]> Git Repo - qemu.git/blob - tests/test-char.c
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
[qemu.git] / tests / test-char.c
1 #include "qemu/osdep.h"
2 #include <glib/gstdio.h>
3
4 #include "qemu/config-file.h"
5 #include "qemu/option.h"
6 #include "qemu/sockets.h"
7 #include "chardev/char-fe.h"
8 #include "chardev/char-mux.h"
9 #include "sysemu/sysemu.h"
10 #include "qapi/error.h"
11 #include "qapi/qapi-commands-char.h"
12 #include "qapi/qmp/qdict.h"
13 #include "qom/qom-qobject.h"
14
15 static bool quit;
16
17 typedef struct FeHandler {
18     int read_count;
19     int last_event;
20     char read_buf[128];
21 } FeHandler;
22
23 static void main_loop(void)
24 {
25     quit = false;
26     do {
27         main_loop_wait(false);
28     } while (!quit);
29 }
30
31 static int fe_can_read(void *opaque)
32 {
33     FeHandler *h = opaque;
34
35     return sizeof(h->read_buf) - h->read_count;
36 }
37
38 static void fe_read(void *opaque, const uint8_t *buf, int size)
39 {
40     FeHandler *h = opaque;
41
42     g_assert_cmpint(size, <=, fe_can_read(opaque));
43
44     memcpy(h->read_buf + h->read_count, buf, size);
45     h->read_count += size;
46     quit = true;
47 }
48
49 static void fe_event(void *opaque, int event)
50 {
51     FeHandler *h = opaque;
52
53     h->last_event = event;
54     if (event != CHR_EVENT_BREAK) {
55         quit = true;
56     }
57 }
58
59 #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
60 #ifdef _WIN32
61 static void char_console_test_subprocess(void)
62 {
63     QemuOpts *opts;
64     Chardev *chr;
65
66     opts = qemu_opts_create(qemu_find_opts("chardev"), "console-label",
67                             1, &error_abort);
68     qemu_opt_set(opts, "backend", "console", &error_abort);
69
70     chr = qemu_chr_new_from_opts(opts, NULL);
71     g_assert_nonnull(chr);
72
73     qemu_chr_write_all(chr, (const uint8_t *)"CONSOLE", 7);
74
75     qemu_opts_del(opts);
76     object_unparent(OBJECT(chr));
77 }
78
79 static void char_console_test(void)
80 {
81     g_test_trap_subprocess("/char/console/subprocess", 0, 0);
82     g_test_trap_assert_passed();
83     g_test_trap_assert_stdout("CONSOLE");
84 }
85 #endif
86 static void char_stdio_test_subprocess(void)
87 {
88     Chardev *chr;
89     CharBackend be;
90     int ret;
91
92     chr = qemu_chr_new("label", "stdio");
93     g_assert_nonnull(chr);
94
95     qemu_chr_fe_init(&be, chr, &error_abort);
96     qemu_chr_fe_set_open(&be, true);
97     ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
98     g_assert_cmpint(ret, ==, 4);
99
100     qemu_chr_fe_deinit(&be, true);
101 }
102
103 static void char_stdio_test(void)
104 {
105     g_test_trap_subprocess("/char/stdio/subprocess", 0, 0);
106     g_test_trap_assert_passed();
107     g_test_trap_assert_stdout("buf");
108 }
109 #endif
110
111 static void char_ringbuf_test(void)
112 {
113     QemuOpts *opts;
114     Chardev *chr;
115     CharBackend be;
116     char *data;
117     int ret;
118
119     opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
120                             1, &error_abort);
121     qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
122
123     qemu_opt_set(opts, "size", "5", &error_abort);
124     chr = qemu_chr_new_from_opts(opts, NULL);
125     g_assert_null(chr);
126     qemu_opts_del(opts);
127
128     opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
129                             1, &error_abort);
130     qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
131     qemu_opt_set(opts, "size", "2", &error_abort);
132     chr = qemu_chr_new_from_opts(opts, &error_abort);
133     g_assert_nonnull(chr);
134     qemu_opts_del(opts);
135
136     qemu_chr_fe_init(&be, chr, &error_abort);
137     ret = qemu_chr_fe_write(&be, (void *)"buff", 4);
138     g_assert_cmpint(ret, ==, 4);
139
140     data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
141     g_assert_cmpstr(data, ==, "ff");
142     g_free(data);
143
144     data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
145     g_assert_cmpstr(data, ==, "");
146     g_free(data);
147
148     qemu_chr_fe_deinit(&be, true);
149
150     /* check alias */
151     opts = qemu_opts_create(qemu_find_opts("chardev"), "memory-label",
152                             1, &error_abort);
153     qemu_opt_set(opts, "backend", "memory", &error_abort);
154     qemu_opt_set(opts, "size", "2", &error_abort);
155     chr = qemu_chr_new_from_opts(opts, NULL);
156     g_assert_nonnull(chr);
157     object_unparent(OBJECT(chr));
158     qemu_opts_del(opts);
159 }
160
161 static void char_mux_test(void)
162 {
163     QemuOpts *opts;
164     Chardev *chr, *base;
165     char *data;
166     FeHandler h1 = { 0, }, h2 = { 0, };
167     CharBackend chr_be1, chr_be2;
168
169     muxes_realized = true; /* done after machine init */
170     opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label",
171                             1, &error_abort);
172     qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
173     qemu_opt_set(opts, "size", "128", &error_abort);
174     qemu_opt_set(opts, "mux", "on", &error_abort);
175     chr = qemu_chr_new_from_opts(opts, &error_abort);
176     g_assert_nonnull(chr);
177     qemu_opts_del(opts);
178
179     qemu_chr_fe_init(&chr_be1, chr, &error_abort);
180     qemu_chr_fe_set_handlers(&chr_be1,
181                              fe_can_read,
182                              fe_read,
183                              fe_event,
184                              NULL,
185                              &h1,
186                              NULL, true);
187
188     qemu_chr_fe_init(&chr_be2, chr, &error_abort);
189     qemu_chr_fe_set_handlers(&chr_be2,
190                              fe_can_read,
191                              fe_read,
192                              fe_event,
193                              NULL,
194                              &h2,
195                              NULL, true);
196     qemu_chr_fe_take_focus(&chr_be2);
197
198     base = qemu_chr_find("mux-label-base");
199     g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0);
200
201     qemu_chr_be_write(base, (void *)"hello", 6);
202     g_assert_cmpint(h1.read_count, ==, 0);
203     g_assert_cmpint(h2.read_count, ==, 6);
204     g_assert_cmpstr(h2.read_buf, ==, "hello");
205     h2.read_count = 0;
206
207     g_assert_cmpint(h1.last_event, !=, 42); /* should be MUX_OUT or OPENED */
208     g_assert_cmpint(h2.last_event, !=, 42); /* should be MUX_IN or OPENED */
209     /* sending event on the base broadcast to all fe, historical reasons? */
210     qemu_chr_be_event(base, 42);
211     g_assert_cmpint(h1.last_event, ==, 42);
212     g_assert_cmpint(h2.last_event, ==, 42);
213     qemu_chr_be_event(chr, -1);
214     g_assert_cmpint(h1.last_event, ==, 42);
215     g_assert_cmpint(h2.last_event, ==, -1);
216
217     /* switch focus */
218     qemu_chr_be_write(base, (void *)"\1c", 2);
219     g_assert_cmpint(h1.last_event, ==, CHR_EVENT_MUX_IN);
220     g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
221     qemu_chr_be_event(chr, -1);
222     g_assert_cmpint(h1.last_event, ==, -1);
223     g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
224
225     qemu_chr_be_write(base, (void *)"hello", 6);
226     g_assert_cmpint(h2.read_count, ==, 0);
227     g_assert_cmpint(h1.read_count, ==, 6);
228     g_assert_cmpstr(h1.read_buf, ==, "hello");
229     h1.read_count = 0;
230
231     /* remove first handler */
232     qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL,
233                              NULL, NULL, true);
234     qemu_chr_be_write(base, (void *)"hello", 6);
235     g_assert_cmpint(h1.read_count, ==, 0);
236     g_assert_cmpint(h2.read_count, ==, 0);
237
238     qemu_chr_be_write(base, (void *)"\1c", 2);
239     qemu_chr_be_write(base, (void *)"hello", 6);
240     g_assert_cmpint(h1.read_count, ==, 0);
241     g_assert_cmpint(h2.read_count, ==, 6);
242     g_assert_cmpstr(h2.read_buf, ==, "hello");
243     h2.read_count = 0;
244
245     /* print help */
246     qemu_chr_be_write(base, (void *)"\1?", 2);
247     data = qmp_ringbuf_read("mux-label-base", 128, false, 0, &error_abort);
248     g_assert_cmpint(strlen(data), !=, 0);
249     g_free(data);
250
251     qemu_chr_fe_deinit(&chr_be1, false);
252     qemu_chr_fe_deinit(&chr_be2, true);
253 }
254
255 typedef struct SocketIdleData {
256     GMainLoop *loop;
257     Chardev *chr;
258     bool conn_expected;
259     CharBackend *be;
260     CharBackend *client_be;
261 } SocketIdleData;
262
263 static gboolean char_socket_test_idle(gpointer user_data)
264 {
265     SocketIdleData *data = user_data;
266
267     if (object_property_get_bool(OBJECT(data->chr), "connected", NULL)
268         == data->conn_expected) {
269         quit = true;
270         return FALSE;
271     }
272
273     return TRUE;
274 }
275
276 static void socket_read(void *opaque, const uint8_t *buf, int size)
277 {
278     SocketIdleData *data = opaque;
279
280     g_assert_cmpint(size, ==, 1);
281     g_assert_cmpint(*buf, ==, 'Z');
282
283     size = qemu_chr_fe_write(data->be, (const uint8_t *)"hello", 5);
284     g_assert_cmpint(size, ==, 5);
285 }
286
287 static int socket_can_read(void *opaque)
288 {
289     return 10;
290 }
291
292 static void socket_read_hello(void *opaque, const uint8_t *buf, int size)
293 {
294     g_assert_cmpint(size, ==, 5);
295     g_assert(strncmp((char *)buf, "hello", 5) == 0);
296
297     quit = true;
298 }
299
300 static int socket_can_read_hello(void *opaque)
301 {
302     return 10;
303 }
304
305 static void char_socket_test(void)
306 {
307     Chardev *chr = qemu_chr_new("server", "tcp:127.0.0.1:0,server,nowait");
308     Chardev *chr_client;
309     QObject *addr;
310     QDict *qdict;
311     const char *port;
312     SocketIdleData d = { .chr = chr };
313     CharBackend be;
314     CharBackend client_be;
315     char *tmp;
316
317     d.be = &be;
318     d.client_be = &be;
319
320     g_assert_nonnull(chr);
321     g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
322
323     addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
324     qdict = qobject_to_qdict(addr);
325     port = qdict_get_str(qdict, "port");
326     tmp = g_strdup_printf("tcp:127.0.0.1:%s", port);
327     QDECREF(qdict);
328
329     qemu_chr_fe_init(&be, chr, &error_abort);
330     qemu_chr_fe_set_handlers(&be, socket_can_read, socket_read,
331                              NULL, NULL, &d, NULL, true);
332
333     chr_client = qemu_chr_new("client", tmp);
334     qemu_chr_fe_init(&client_be, chr_client, &error_abort);
335     qemu_chr_fe_set_handlers(&client_be, socket_can_read_hello,
336                              socket_read_hello,
337                              NULL, NULL, &d, NULL, true);
338     g_free(tmp);
339
340     d.conn_expected = true;
341     guint id = g_idle_add(char_socket_test_idle, &d);
342     g_source_set_name_by_id(id, "test-idle");
343     g_assert_cmpint(id, >, 0);
344     main_loop();
345
346     g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
347     g_assert(object_property_get_bool(OBJECT(chr_client),
348                                       "connected", &error_abort));
349
350     qemu_chr_write_all(chr_client, (const uint8_t *)"Z", 1);
351     main_loop();
352
353     object_unparent(OBJECT(chr_client));
354
355     d.conn_expected = false;
356     g_idle_add(char_socket_test_idle, &d);
357     main_loop();
358
359     object_unparent(OBJECT(chr));
360 }
361
362 #ifndef _WIN32
363 static void char_pipe_test(void)
364 {
365     gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
366     gchar *tmp, *in, *out, *pipe = g_build_filename(tmp_path, "pipe", NULL);
367     Chardev *chr;
368     CharBackend be;
369     int ret, fd;
370     char buf[10];
371     FeHandler fe = { 0, };
372
373     in = g_strdup_printf("%s.in", pipe);
374     if (mkfifo(in, 0600) < 0) {
375         abort();
376     }
377     out = g_strdup_printf("%s.out", pipe);
378     if (mkfifo(out, 0600) < 0) {
379         abort();
380     }
381
382     tmp = g_strdup_printf("pipe:%s", pipe);
383     chr = qemu_chr_new("pipe", tmp);
384     g_assert_nonnull(chr);
385     g_free(tmp);
386
387     qemu_chr_fe_init(&be, chr, &error_abort);
388
389     ret = qemu_chr_fe_write(&be, (void *)"pipe-out", 9);
390     g_assert_cmpint(ret, ==, 9);
391
392     fd = open(out, O_RDWR);
393     ret = read(fd, buf, sizeof(buf));
394     g_assert_cmpint(ret, ==, 9);
395     g_assert_cmpstr(buf, ==, "pipe-out");
396     close(fd);
397
398     fd = open(in, O_WRONLY);
399     ret = write(fd, "pipe-in", 8);
400     g_assert_cmpint(ret, ==, 8);
401     close(fd);
402
403     qemu_chr_fe_set_handlers(&be,
404                              fe_can_read,
405                              fe_read,
406                              fe_event,
407                              NULL,
408                              &fe,
409                              NULL, true);
410
411     main_loop();
412
413     g_assert_cmpint(fe.read_count, ==, 8);
414     g_assert_cmpstr(fe.read_buf, ==, "pipe-in");
415
416     qemu_chr_fe_deinit(&be, true);
417
418     g_assert(g_unlink(in) == 0);
419     g_assert(g_unlink(out) == 0);
420     g_assert(g_rmdir(tmp_path) == 0);
421     g_free(in);
422     g_free(out);
423     g_free(tmp_path);
424     g_free(pipe);
425 }
426 #endif
427
428 static int make_udp_socket(int *port)
429 {
430     struct sockaddr_in addr = { 0, };
431     socklen_t alen = sizeof(addr);
432     int ret, sock = qemu_socket(PF_INET, SOCK_DGRAM, 0);
433
434     g_assert_cmpint(sock, >, 0);
435     addr.sin_family = AF_INET ;
436     addr.sin_addr.s_addr = htonl(INADDR_ANY);
437     addr.sin_port = 0;
438     ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
439     g_assert_cmpint(ret, ==, 0);
440     ret = getsockname(sock, (struct sockaddr *)&addr, &alen);
441     g_assert_cmpint(ret, ==, 0);
442
443     *port = ntohs(addr.sin_port);
444     return sock;
445 }
446
447 static void char_udp_test_internal(Chardev *reuse_chr, int sock)
448 {
449     struct sockaddr_in other;
450     SocketIdleData d = { 0, };
451     Chardev *chr;
452     CharBackend *be;
453     socklen_t alen = sizeof(other);
454     int ret;
455     char buf[10];
456     char *tmp = NULL;
457
458     if (reuse_chr) {
459         chr = reuse_chr;
460         be = chr->be;
461     } else {
462         int port;
463         sock = make_udp_socket(&port);
464         tmp = g_strdup_printf("udp:127.0.0.1:%d", port);
465         chr = qemu_chr_new("client", tmp);
466         g_assert_nonnull(chr);
467
468         be = g_alloca(sizeof(CharBackend));
469         qemu_chr_fe_init(be, chr, &error_abort);
470     }
471
472     d.chr = chr;
473     qemu_chr_fe_set_handlers(be, socket_can_read_hello, socket_read_hello,
474                              NULL, NULL, &d, NULL, true);
475     ret = qemu_chr_write_all(chr, (uint8_t *)"hello", 5);
476     g_assert_cmpint(ret, ==, 5);
477
478     ret = recvfrom(sock, buf, sizeof(buf), 0,
479                    (struct sockaddr *)&other, &alen);
480     g_assert_cmpint(ret, ==, 5);
481     ret = sendto(sock, buf, 5, 0, (struct sockaddr *)&other, alen);
482     g_assert_cmpint(ret, ==, 5);
483
484     main_loop();
485
486     if (!reuse_chr) {
487         close(sock);
488         qemu_chr_fe_deinit(be, true);
489     }
490     g_free(tmp);
491 }
492
493 static void char_udp_test(void)
494 {
495     char_udp_test_internal(NULL, 0);
496 }
497
498 #ifdef HAVE_CHARDEV_SERIAL
499 static void char_serial_test(void)
500 {
501     QemuOpts *opts;
502     Chardev *chr;
503
504     opts = qemu_opts_create(qemu_find_opts("chardev"), "serial-id",
505                             1, &error_abort);
506     qemu_opt_set(opts, "backend", "serial", &error_abort);
507     qemu_opt_set(opts, "path", "/dev/null", &error_abort);
508
509     chr = qemu_chr_new_from_opts(opts, NULL);
510     g_assert_nonnull(chr);
511     /* TODO: add more tests with a pty */
512     object_unparent(OBJECT(chr));
513
514     /* test tty alias */
515     qemu_opt_set(opts, "backend", "tty", &error_abort);
516     chr = qemu_chr_new_from_opts(opts, NULL);
517     g_assert_nonnull(chr);
518     object_unparent(OBJECT(chr));
519
520     qemu_opts_del(opts);
521 }
522 #endif
523
524 #ifndef _WIN32
525 static void char_file_fifo_test(void)
526 {
527     Chardev *chr;
528     CharBackend be;
529     char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
530     char *fifo = g_build_filename(tmp_path, "fifo", NULL);
531     char *out = g_build_filename(tmp_path, "out", NULL);
532     ChardevFile file = { .in = fifo,
533                          .has_in = true,
534                          .out = out };
535     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
536                                .u.file.data = &file };
537     FeHandler fe = { 0, };
538     int fd, ret;
539
540     if (mkfifo(fifo, 0600) < 0) {
541         abort();
542     }
543
544     fd = open(fifo, O_RDWR);
545     ret = write(fd, "fifo-in", 8);
546     g_assert_cmpint(ret, ==, 8);
547
548     chr = qemu_chardev_new("label-file", TYPE_CHARDEV_FILE, &backend,
549                            &error_abort);
550
551     qemu_chr_fe_init(&be, chr, &error_abort);
552     qemu_chr_fe_set_handlers(&be,
553                              fe_can_read,
554                              fe_read,
555                              fe_event,
556                              NULL,
557                              &fe, NULL, true);
558
559     g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
560     qmp_chardev_send_break("label-foo", NULL);
561     g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
562     qmp_chardev_send_break("label-file", NULL);
563     g_assert_cmpint(fe.last_event, ==, CHR_EVENT_BREAK);
564
565     main_loop();
566
567     close(fd);
568
569     g_assert_cmpint(fe.read_count, ==, 8);
570     g_assert_cmpstr(fe.read_buf, ==, "fifo-in");
571
572     qemu_chr_fe_deinit(&be, true);
573
574     g_unlink(fifo);
575     g_free(fifo);
576     g_unlink(out);
577     g_free(out);
578     g_rmdir(tmp_path);
579     g_free(tmp_path);
580 }
581 #endif
582
583 static void char_file_test_internal(Chardev *ext_chr, const char *filepath)
584 {
585     char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
586     char *out;
587     Chardev *chr;
588     char *contents = NULL;
589     ChardevFile file = {};
590     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
591                                .u.file.data = &file };
592     gsize length;
593     int ret;
594
595     if (ext_chr) {
596         chr = ext_chr;
597         out = g_strdup(filepath);
598         file.out = out;
599     } else {
600         out = g_build_filename(tmp_path, "out", NULL);
601         file.out = out;
602         chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &backend,
603                                &error_abort);
604     }
605     ret = qemu_chr_write_all(chr, (uint8_t *)"hello!", 6);
606     g_assert_cmpint(ret, ==, 6);
607
608     ret = g_file_get_contents(out, &contents, &length, NULL);
609     g_assert(ret == TRUE);
610     g_assert_cmpint(length, ==, 6);
611     g_assert(strncmp(contents, "hello!", 6) == 0);
612
613     if (!ext_chr) {
614         object_unref(OBJECT(chr));
615         g_unlink(out);
616     }
617     g_free(contents);
618     g_rmdir(tmp_path);
619     g_free(tmp_path);
620     g_free(out);
621 }
622
623 static void char_file_test(void)
624 {
625     char_file_test_internal(NULL, NULL);
626 }
627
628 static void char_null_test(void)
629 {
630     Error *err = NULL;
631     Chardev *chr;
632     CharBackend be;
633     int ret;
634
635     chr = qemu_chr_find("label-null");
636     g_assert_null(chr);
637
638     chr = qemu_chr_new("label-null", "null");
639     chr = qemu_chr_find("label-null");
640     g_assert_nonnull(chr);
641
642     g_assert(qemu_chr_has_feature(chr,
643                  QEMU_CHAR_FEATURE_FD_PASS) == false);
644     g_assert(qemu_chr_has_feature(chr,
645                  QEMU_CHAR_FEATURE_RECONNECTABLE) == false);
646
647     /* check max avail */
648     qemu_chr_fe_init(&be, chr, &error_abort);
649     qemu_chr_fe_init(&be, chr, &err);
650     error_free_or_abort(&err);
651
652     /* deinit & reinit */
653     qemu_chr_fe_deinit(&be, false);
654     qemu_chr_fe_init(&be, chr, &error_abort);
655
656     qemu_chr_fe_set_open(&be, true);
657
658     qemu_chr_fe_set_handlers(&be,
659                              fe_can_read,
660                              fe_read,
661                              fe_event,
662                              NULL,
663                              NULL, NULL, true);
664
665     ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
666     g_assert_cmpint(ret, ==, 4);
667
668     qemu_chr_fe_deinit(&be, true);
669 }
670
671 static void char_invalid_test(void)
672 {
673     Chardev *chr;
674
675     chr = qemu_chr_new("label-invalid", "invalid");
676     g_assert_null(chr);
677 }
678
679 static int chardev_change(void *opaque)
680 {
681     return 0;
682 }
683
684 static int chardev_change_denied(void *opaque)
685 {
686     return -1;
687 }
688
689 static void char_hotswap_test(void)
690 {
691     char *chr_args;
692     Chardev *chr;
693     CharBackend be;
694
695     gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
696     char *filename = g_build_filename(tmp_path, "file", NULL);
697     ChardevFile file = { .out = filename };
698     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
699                                .u.file.data = &file };
700     ChardevReturn *ret;
701
702     int port;
703     int sock = make_udp_socket(&port);
704     g_assert_cmpint(sock, >, 0);
705
706     chr_args = g_strdup_printf("udp:127.0.0.1:%d", port);
707
708     chr = qemu_chr_new("chardev", chr_args);
709     qemu_chr_fe_init(&be, chr, &error_abort);
710
711     /* check that chardev operates correctly */
712     char_udp_test_internal(chr, sock);
713
714     /* set the handler that denies the hotswap */
715     qemu_chr_fe_set_handlers(&be, NULL, NULL,
716                              NULL, chardev_change_denied, NULL, NULL, true);
717
718     /* now, change is denied and has to keep the old backend operating */
719     ret = qmp_chardev_change("chardev", &backend, NULL);
720     g_assert(!ret);
721     g_assert(be.chr == chr);
722
723     char_udp_test_internal(chr, sock);
724
725     /* now allow the change */
726     qemu_chr_fe_set_handlers(&be, NULL, NULL,
727                              NULL, chardev_change, NULL, NULL, true);
728
729     /* has to succeed now */
730     ret = qmp_chardev_change("chardev", &backend, &error_abort);
731     g_assert(be.chr != chr);
732
733     close(sock);
734     chr = be.chr;
735
736     /* run the file chardev test */
737     char_file_test_internal(chr, filename);
738
739     object_unparent(OBJECT(chr));
740
741     qapi_free_ChardevReturn(ret);
742     g_unlink(filename);
743     g_free(filename);
744     g_rmdir(tmp_path);
745     g_free(tmp_path);
746     g_free(chr_args);
747 }
748
749 int main(int argc, char **argv)
750 {
751     qemu_init_main_loop(&error_abort);
752     socket_init();
753
754     g_test_init(&argc, &argv, NULL);
755
756     module_call_init(MODULE_INIT_QOM);
757     qemu_add_opts(&qemu_chardev_opts);
758
759     g_test_add_func("/char/null", char_null_test);
760     g_test_add_func("/char/invalid", char_invalid_test);
761     g_test_add_func("/char/ringbuf", char_ringbuf_test);
762     g_test_add_func("/char/mux", char_mux_test);
763 #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
764 #ifdef _WIN32
765     g_test_add_func("/char/console/subprocess", char_console_test_subprocess);
766     g_test_add_func("/char/console", char_console_test);
767 #endif
768     g_test_add_func("/char/stdio/subprocess", char_stdio_test_subprocess);
769     g_test_add_func("/char/stdio", char_stdio_test);
770 #endif
771 #ifndef _WIN32
772     g_test_add_func("/char/pipe", char_pipe_test);
773 #endif
774     g_test_add_func("/char/file", char_file_test);
775 #ifndef _WIN32
776     g_test_add_func("/char/file-fifo", char_file_fifo_test);
777 #endif
778     g_test_add_func("/char/socket", char_socket_test);
779     g_test_add_func("/char/udp", char_udp_test);
780 #ifdef HAVE_CHARDEV_SERIAL
781     g_test_add_func("/char/serial", char_serial_test);
782 #endif
783     g_test_add_func("/char/hotswap", char_hotswap_test);
784
785     return g_test_run();
786 }
This page took 0.073064 seconds and 4 git commands to generate.