qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio
at master 362 lines 9.2 kB view raw
1/* 2 * Tests for util/qemu-sockets.c 3 * 4 * Copyright 2018 Red Hat, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this library; if not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21#include "qemu/osdep.h" 22#include "qemu-common.h" 23#include "qemu/sockets.h" 24#include "qapi/error.h" 25#include "socket-helpers.h" 26#include "monitor/monitor.h" 27 28static void test_fd_is_socket_bad(void) 29{ 30 char *tmp = g_strdup("qemu-test-util-sockets-XXXXXX"); 31 int fd = mkstemp(tmp); 32 if (fd != 0) { 33 unlink(tmp); 34 } 35 g_free(tmp); 36 37 g_assert(fd >= 0); 38 39 g_assert(!fd_is_socket(fd)); 40 close(fd); 41} 42 43static void test_fd_is_socket_good(void) 44{ 45 int fd = qemu_socket(PF_INET, SOCK_STREAM, 0); 46 47 g_assert(fd >= 0); 48 49 g_assert(fd_is_socket(fd)); 50 close(fd); 51} 52 53static int mon_fd = -1; 54static const char *mon_fdname; 55 56int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp) 57{ 58 g_assert(cur_mon); 59 g_assert(mon == cur_mon); 60 if (mon_fd == -1 || !g_str_equal(mon_fdname, fdname)) { 61 error_setg(errp, "No fd named %s", fdname); 62 return -1; 63 } 64 return dup(mon_fd); 65} 66 67/* Syms in libqemustub.a are discarded at .o file granularity. 68 * To replace monitor_get_fd() we must ensure everything in 69 * stubs/monitor.c is defined, to make sure monitor.o is discarded 70 * otherwise we get duplicate syms at link time. 71 */ 72__thread Monitor *cur_mon; 73int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); } 74void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) {} 75void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp) {} 76 77 78static void test_socket_fd_pass_name_good(void) 79{ 80 SocketAddress addr; 81 int fd; 82 83 cur_mon = g_malloc(1); /* Fake a monitor */ 84 mon_fdname = "myfd"; 85 mon_fd = qemu_socket(AF_INET, SOCK_STREAM, 0); 86 g_assert_cmpint(mon_fd, >, STDERR_FILENO); 87 88 addr.type = SOCKET_ADDRESS_TYPE_FD; 89 addr.u.fd.str = g_strdup(mon_fdname); 90 91 fd = socket_connect(&addr, &error_abort); 92 g_assert_cmpint(fd, !=, -1); 93 g_assert_cmpint(fd, !=, mon_fd); 94 close(fd); 95 96 fd = socket_listen(&addr, 1, &error_abort); 97 g_assert_cmpint(fd, !=, -1); 98 g_assert_cmpint(fd, !=, mon_fd); 99 close(fd); 100 101 g_free(addr.u.fd.str); 102 mon_fdname = NULL; 103 close(mon_fd); 104 mon_fd = -1; 105 g_free(cur_mon); 106 cur_mon = NULL; 107} 108 109static void test_socket_fd_pass_name_bad(void) 110{ 111 SocketAddress addr; 112 Error *err = NULL; 113 int fd; 114 115 cur_mon = g_malloc(1); /* Fake a monitor */ 116 mon_fdname = "myfd"; 117 mon_fd = dup(STDOUT_FILENO); 118 g_assert_cmpint(mon_fd, >, STDERR_FILENO); 119 120 addr.type = SOCKET_ADDRESS_TYPE_FD; 121 addr.u.fd.str = g_strdup(mon_fdname); 122 123 fd = socket_connect(&addr, &err); 124 g_assert_cmpint(fd, ==, -1); 125 error_free_or_abort(&err); 126 127 fd = socket_listen(&addr, 1, &err); 128 g_assert_cmpint(fd, ==, -1); 129 error_free_or_abort(&err); 130 131 g_free(addr.u.fd.str); 132 mon_fdname = NULL; 133 close(mon_fd); 134 mon_fd = -1; 135 g_free(cur_mon); 136 cur_mon = NULL; 137} 138 139static void test_socket_fd_pass_name_nomon(void) 140{ 141 SocketAddress addr; 142 Error *err = NULL; 143 int fd; 144 145 g_assert(cur_mon == NULL); 146 147 addr.type = SOCKET_ADDRESS_TYPE_FD; 148 addr.u.fd.str = g_strdup("myfd"); 149 150 fd = socket_connect(&addr, &err); 151 g_assert_cmpint(fd, ==, -1); 152 error_free_or_abort(&err); 153 154 fd = socket_listen(&addr, 1, &err); 155 g_assert_cmpint(fd, ==, -1); 156 error_free_or_abort(&err); 157 158 g_free(addr.u.fd.str); 159} 160 161 162static void test_socket_fd_pass_num_good(void) 163{ 164 SocketAddress addr; 165 int fd, sfd; 166 167 g_assert(cur_mon == NULL); 168 sfd = qemu_socket(AF_INET, SOCK_STREAM, 0); 169 g_assert_cmpint(sfd, >, STDERR_FILENO); 170 171 addr.type = SOCKET_ADDRESS_TYPE_FD; 172 addr.u.fd.str = g_strdup_printf("%d", sfd); 173 174 fd = socket_connect(&addr, &error_abort); 175 g_assert_cmpint(fd, ==, sfd); 176 177 fd = socket_listen(&addr, 1, &error_abort); 178 g_assert_cmpint(fd, ==, sfd); 179 180 g_free(addr.u.fd.str); 181 close(sfd); 182} 183 184static void test_socket_fd_pass_num_bad(void) 185{ 186 SocketAddress addr; 187 Error *err = NULL; 188 int fd, sfd; 189 190 g_assert(cur_mon == NULL); 191 sfd = dup(STDOUT_FILENO); 192 193 addr.type = SOCKET_ADDRESS_TYPE_FD; 194 addr.u.fd.str = g_strdup_printf("%d", sfd); 195 196 fd = socket_connect(&addr, &err); 197 g_assert_cmpint(fd, ==, -1); 198 error_free_or_abort(&err); 199 200 fd = socket_listen(&addr, 1, &err); 201 g_assert_cmpint(fd, ==, -1); 202 error_free_or_abort(&err); 203 204 g_free(addr.u.fd.str); 205 close(sfd); 206} 207 208static void test_socket_fd_pass_num_nocli(void) 209{ 210 SocketAddress addr; 211 Error *err = NULL; 212 int fd; 213 214 cur_mon = g_malloc(1); /* Fake a monitor */ 215 216 addr.type = SOCKET_ADDRESS_TYPE_FD; 217 addr.u.fd.str = g_strdup_printf("%d", STDOUT_FILENO); 218 219 fd = socket_connect(&addr, &err); 220 g_assert_cmpint(fd, ==, -1); 221 error_free_or_abort(&err); 222 223 fd = socket_listen(&addr, 1, &err); 224 g_assert_cmpint(fd, ==, -1); 225 error_free_or_abort(&err); 226 227 g_free(addr.u.fd.str); 228} 229 230#ifdef __linux__ 231static gchar *abstract_sock_name; 232 233static gpointer unix_server_thread_func(gpointer user_data) 234{ 235 SocketAddress addr; 236 Error *err = NULL; 237 int fd = -1; 238 int connfd = -1; 239 struct sockaddr_un un; 240 socklen_t len = sizeof(un); 241 242 addr.type = SOCKET_ADDRESS_TYPE_UNIX; 243 addr.u.q_unix.path = abstract_sock_name; 244 addr.u.q_unix.tight = user_data != NULL; 245 addr.u.q_unix.abstract = true; 246 247 fd = socket_listen(&addr, 1, &err); 248 g_assert_cmpint(fd, >=, 0); 249 g_assert(fd_is_socket(fd)); 250 251 connfd = accept(fd, (struct sockaddr *)&un, &len); 252 g_assert_cmpint(connfd, !=, -1); 253 254 close(fd); 255 256 return NULL; 257} 258 259static gpointer unix_client_thread_func(gpointer user_data) 260{ 261 SocketAddress addr; 262 Error *err = NULL; 263 int fd = -1; 264 265 addr.type = SOCKET_ADDRESS_TYPE_UNIX; 266 addr.u.q_unix.path = abstract_sock_name; 267 addr.u.q_unix.tight = user_data != NULL; 268 addr.u.q_unix.abstract = true; 269 270 fd = socket_connect(&addr, &err); 271 272 g_assert_cmpint(fd, >=, 0); 273 274 close(fd); 275 276 return NULL; 277} 278 279static void test_socket_unix_abstract_good(void) 280{ 281 GRand *r = g_rand_new(); 282 283 abstract_sock_name = g_strdup_printf("unix-%d-%d", getpid(), 284 g_rand_int_range(r, 100, 1000)); 285 286 /* non tight socklen serv and cli */ 287 GThread *serv = g_thread_new("abstract_unix_server", 288 unix_server_thread_func, 289 NULL); 290 291 sleep(1); 292 293 GThread *cli = g_thread_new("abstract_unix_client", 294 unix_client_thread_func, 295 NULL); 296 297 g_thread_join(cli); 298 g_thread_join(serv); 299 300 /* tight socklen serv and cli */ 301 serv = g_thread_new("abstract_unix_server", 302 unix_server_thread_func, 303 (gpointer)1); 304 305 sleep(1); 306 307 cli = g_thread_new("abstract_unix_client", 308 unix_client_thread_func, 309 (gpointer)1); 310 311 g_thread_join(cli); 312 g_thread_join(serv); 313 314 g_free(abstract_sock_name); 315} 316#endif 317 318int main(int argc, char **argv) 319{ 320 bool has_ipv4, has_ipv6; 321 322 socket_init(); 323 324 g_test_init(&argc, &argv, NULL); 325 326 /* We're creating actual IPv4/6 sockets, so we should 327 * check if the host running tests actually supports 328 * each protocol to avoid breaking tests on machines 329 * with either IPv4 or IPv6 disabled. 330 */ 331 if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) { 332 g_printerr("socket_check_protocol_support() failed\n"); 333 goto end; 334 } 335 336 if (has_ipv4) { 337 g_test_add_func("/util/socket/is-socket/bad", 338 test_fd_is_socket_bad); 339 g_test_add_func("/util/socket/is-socket/good", 340 test_fd_is_socket_good); 341 g_test_add_func("/socket/fd-pass/name/good", 342 test_socket_fd_pass_name_good); 343 g_test_add_func("/socket/fd-pass/name/bad", 344 test_socket_fd_pass_name_bad); 345 g_test_add_func("/socket/fd-pass/name/nomon", 346 test_socket_fd_pass_name_nomon); 347 g_test_add_func("/socket/fd-pass/num/good", 348 test_socket_fd_pass_num_good); 349 g_test_add_func("/socket/fd-pass/num/bad", 350 test_socket_fd_pass_num_bad); 351 g_test_add_func("/socket/fd-pass/num/nocli", 352 test_socket_fd_pass_num_nocli); 353 } 354 355#ifdef __linux__ 356 g_test_add_func("/util/socket/unix-abstract/good", 357 test_socket_unix_abstract_good); 358#endif 359 360end: 361 return g_test_run(); 362}