xref: /openbmc/qemu/tests/unit/test-char.c (revision 7d87775f)
1 #include "qemu/osdep.h"
2 #include <glib/gstdio.h>
3 
4 #include "qapi/error.h"
5 #include "qemu/config-file.h"
6 #include "qemu/module.h"
7 #include "qemu/option.h"
8 #include "qemu/sockets.h"
9 #include "chardev/char-fe.h"
10 #include "sysemu/sysemu.h"
11 #include "qapi/error.h"
12 #include "qapi/qapi-commands-char.h"
13 #include "qapi/qmp/qdict.h"
14 #include "qom/qom-qobject.h"
15 #include "io/channel-socket.h"
16 #include "qapi/qobject-input-visitor.h"
17 #include "qapi/qapi-visit-sockets.h"
18 #include "socket-helpers.h"
19 
20 static bool quit;
21 
22 typedef struct FeHandler {
23     int read_count;
24     bool is_open;
25     int openclose_count;
26     bool openclose_mismatch;
27     int last_event;
28     char read_buf[128];
29 } FeHandler;
30 
31 static void main_loop(void)
32 {
33     quit = false;
34     do {
35         main_loop_wait(false);
36     } while (!quit);
37 }
38 
39 static int fe_can_read(void *opaque)
40 {
41     FeHandler *h = opaque;
42 
43     return sizeof(h->read_buf) - h->read_count;
44 }
45 
46 static void fe_read(void *opaque, const uint8_t *buf, int size)
47 {
48     FeHandler *h = opaque;
49 
50     g_assert_cmpint(size, <=, fe_can_read(opaque));
51 
52     memcpy(h->read_buf + h->read_count, buf, size);
53     h->read_count += size;
54     quit = true;
55 }
56 
57 static void fe_event(void *opaque, QEMUChrEvent event)
58 {
59     FeHandler *h = opaque;
60     bool new_open_state;
61 
62     h->last_event = event;
63     switch (event) {
64     case CHR_EVENT_BREAK:
65         break;
66     case CHR_EVENT_OPENED:
67     case CHR_EVENT_CLOSED:
68         h->openclose_count++;
69         new_open_state = (event == CHR_EVENT_OPENED);
70         if (h->is_open == new_open_state) {
71             h->openclose_mismatch = true;
72         }
73         h->is_open = new_open_state;
74         /* fallthrough */
75     default:
76         quit = true;
77         break;
78     }
79 }
80 
81 #ifdef _WIN32
82 static void char_console_test_subprocess(void)
83 {
84     QemuOpts *opts;
85     Chardev *chr;
86 
87     opts = qemu_opts_create(qemu_find_opts("chardev"), "console-label",
88                             1, &error_abort);
89     qemu_opt_set(opts, "backend", "console", &error_abort);
90 
91     chr = qemu_chr_new_from_opts(opts, NULL, NULL);
92     g_assert_nonnull(chr);
93 
94     qemu_chr_write_all(chr, (const uint8_t *)"CONSOLE", 7);
95 
96     qemu_opts_del(opts);
97     object_unparent(OBJECT(chr));
98 }
99 
100 static void char_console_test(void)
101 {
102     g_test_trap_subprocess("/char/console/subprocess", 0, 0);
103     g_test_trap_assert_passed();
104     g_test_trap_assert_stdout("CONSOLE");
105 }
106 #endif
107 static void char_stdio_test_subprocess(void)
108 {
109     Chardev *chr;
110     CharBackend be;
111     int ret;
112 
113     chr = qemu_chr_new("label", "stdio", NULL);
114     g_assert_nonnull(chr);
115 
116     qemu_chr_fe_init(&be, chr, &error_abort);
117     qemu_chr_fe_set_open(&be, true);
118     ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
119     g_assert_cmpint(ret, ==, 4);
120 
121     qemu_chr_fe_deinit(&be, true);
122 }
123 
124 static void char_stdio_test(void)
125 {
126     g_test_trap_subprocess("/char/stdio/subprocess", 0, 0);
127     g_test_trap_assert_passed();
128     g_test_trap_assert_stdout("buf");
129 }
130 
131 static void char_ringbuf_test(void)
132 {
133     QemuOpts *opts;
134     Chardev *chr;
135     CharBackend be;
136     char *data;
137     int ret;
138 
139     opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
140                             1, &error_abort);
141     qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
142 
143     qemu_opt_set(opts, "size", "5", &error_abort);
144     chr = qemu_chr_new_from_opts(opts, NULL, NULL);
145     g_assert_null(chr);
146     qemu_opts_del(opts);
147 
148     opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
149                             1, &error_abort);
150     qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
151     qemu_opt_set(opts, "size", "2", &error_abort);
152     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
153     g_assert_nonnull(chr);
154     qemu_opts_del(opts);
155 
156     qemu_chr_fe_init(&be, chr, &error_abort);
157     ret = qemu_chr_fe_write(&be, (void *)"buff", 4);
158     g_assert_cmpint(ret, ==, 4);
159 
160     data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
161     g_assert_cmpstr(data, ==, "ff");
162     g_free(data);
163 
164     data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
165     g_assert_cmpstr(data, ==, "");
166     g_free(data);
167 
168     qemu_chr_fe_deinit(&be, true);
169 
170     /* check alias */
171     opts = qemu_opts_create(qemu_find_opts("chardev"), "memory-label",
172                             1, &error_abort);
173     qemu_opt_set(opts, "backend", "memory", &error_abort);
174     qemu_opt_set(opts, "size", "2", &error_abort);
175     chr = qemu_chr_new_from_opts(opts, NULL, NULL);
176     g_assert_nonnull(chr);
177     object_unparent(OBJECT(chr));
178     qemu_opts_del(opts);
179 }
180 
181 static void char_mux_test(void)
182 {
183     QemuOpts *opts;
184     Chardev *chr, *base;
185     char *data;
186     FeHandler h1 = { 0, false, 0, false, }, h2 = { 0, false, 0, false, };
187     CharBackend chr_be1, chr_be2;
188     Error *error = NULL;
189 
190     /* Create mux and chardev to be immediately removed */
191     opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label",
192                             1, &error_abort);
193     qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
194     qemu_opt_set(opts, "size", "128", &error_abort);
195     qemu_opt_set(opts, "mux", "on", &error_abort);
196     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
197     g_assert_nonnull(chr);
198     qemu_opts_del(opts);
199 
200     /* Remove just created mux and chardev */
201     qmp_chardev_remove("mux-label", &error_abort);
202     qmp_chardev_remove("mux-label-base", &error_abort);
203 
204     opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label",
205                             1, &error_abort);
206     qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
207     qemu_opt_set(opts, "size", "128", &error_abort);
208     qemu_opt_set(opts, "mux", "on", &error_abort);
209     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
210     g_assert_nonnull(chr);
211     qemu_opts_del(opts);
212 
213     qemu_chr_fe_init(&chr_be1, chr, &error_abort);
214     qemu_chr_fe_set_handlers(&chr_be1,
215                              fe_can_read,
216                              fe_read,
217                              fe_event,
218                              NULL,
219                              &h1,
220                              NULL, true);
221 
222     qemu_chr_fe_init(&chr_be2, chr, &error_abort);
223     qemu_chr_fe_set_handlers(&chr_be2,
224                              fe_can_read,
225                              fe_read,
226                              fe_event,
227                              NULL,
228                              &h2,
229                              NULL, true);
230     qemu_chr_fe_take_focus(&chr_be2);
231 
232     base = qemu_chr_find("mux-label-base");
233     g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0);
234 
235     qemu_chr_be_write(base, (void *)"hello", 6);
236     g_assert_cmpint(h1.read_count, ==, 0);
237     g_assert_cmpint(h2.read_count, ==, 6);
238     g_assert_cmpstr(h2.read_buf, ==, "hello");
239     h2.read_count = 0;
240 
241     g_assert_cmpint(h1.last_event, !=, 42); /* should be MUX_OUT or OPENED */
242     g_assert_cmpint(h2.last_event, !=, 42); /* should be MUX_IN or OPENED */
243     /* sending event on the base broadcast to all fe, historical reasons? */
244     qemu_chr_be_event(base, 42);
245     g_assert_cmpint(h1.last_event, ==, 42);
246     g_assert_cmpint(h2.last_event, ==, 42);
247     qemu_chr_be_event(chr, -1);
248     g_assert_cmpint(h1.last_event, ==, 42);
249     g_assert_cmpint(h2.last_event, ==, -1);
250 
251     /* switch focus */
252     qemu_chr_be_write(base, (void *)"\1b", 2);
253     g_assert_cmpint(h1.last_event, ==, 42);
254     g_assert_cmpint(h2.last_event, ==, CHR_EVENT_BREAK);
255 
256     qemu_chr_be_write(base, (void *)"\1c", 2);
257     g_assert_cmpint(h1.last_event, ==, CHR_EVENT_MUX_IN);
258     g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
259     qemu_chr_be_event(chr, -1);
260     g_assert_cmpint(h1.last_event, ==, -1);
261     g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
262 
263     qemu_chr_be_write(base, (void *)"hello", 6);
264     g_assert_cmpint(h2.read_count, ==, 0);
265     g_assert_cmpint(h1.read_count, ==, 6);
266     g_assert_cmpstr(h1.read_buf, ==, "hello");
267     h1.read_count = 0;
268 
269     qemu_chr_be_write(base, (void *)"\1b", 2);
270     g_assert_cmpint(h1.last_event, ==, CHR_EVENT_BREAK);
271     g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
272 
273     /* open/close state and corresponding events */
274     g_assert_true(qemu_chr_fe_backend_open(&chr_be1));
275     g_assert_true(qemu_chr_fe_backend_open(&chr_be2));
276     g_assert_true(h1.is_open);
277     g_assert_false(h1.openclose_mismatch);
278     g_assert_true(h2.is_open);
279     g_assert_false(h2.openclose_mismatch);
280 
281     h1.openclose_count = h2.openclose_count = 0;
282 
283     qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL,
284                              NULL, NULL, false);
285     qemu_chr_fe_set_handlers(&chr_be2, NULL, NULL, NULL, NULL,
286                              NULL, NULL, false);
287     g_assert_cmpint(h1.openclose_count, ==, 0);
288     g_assert_cmpint(h2.openclose_count, ==, 0);
289 
290     h1.is_open = h2.is_open = false;
291     qemu_chr_fe_set_handlers(&chr_be1,
292                              NULL,
293                              NULL,
294                              fe_event,
295                              NULL,
296                              &h1,
297                              NULL, false);
298     qemu_chr_fe_set_handlers(&chr_be2,
299                              NULL,
300                              NULL,
301                              fe_event,
302                              NULL,
303                              &h2,
304                              NULL, false);
305     g_assert_cmpint(h1.openclose_count, ==, 1);
306     g_assert_false(h1.openclose_mismatch);
307     g_assert_cmpint(h2.openclose_count, ==, 1);
308     g_assert_false(h2.openclose_mismatch);
309 
310     qemu_chr_be_event(base, CHR_EVENT_CLOSED);
311     qemu_chr_be_event(base, CHR_EVENT_OPENED);
312     g_assert_cmpint(h1.openclose_count, ==, 3);
313     g_assert_false(h1.openclose_mismatch);
314     g_assert_cmpint(h2.openclose_count, ==, 3);
315     g_assert_false(h2.openclose_mismatch);
316 
317     qemu_chr_fe_set_handlers(&chr_be2,
318                              fe_can_read,
319                              fe_read,
320                              fe_event,
321                              NULL,
322                              &h2,
323                              NULL, false);
324     qemu_chr_fe_set_handlers(&chr_be1,
325                              fe_can_read,
326                              fe_read,
327                              fe_event,
328                              NULL,
329                              &h1,
330                              NULL, false);
331 
332     /* remove first handler */
333     qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL,
334                              NULL, NULL, true);
335     qemu_chr_be_write(base, (void *)"hello", 6);
336     g_assert_cmpint(h1.read_count, ==, 0);
337     g_assert_cmpint(h2.read_count, ==, 0);
338 
339     qemu_chr_be_write(base, (void *)"\1c", 2);
340     qemu_chr_be_write(base, (void *)"hello", 6);
341     g_assert_cmpint(h1.read_count, ==, 0);
342     g_assert_cmpint(h2.read_count, ==, 6);
343     g_assert_cmpstr(h2.read_buf, ==, "hello");
344     h2.read_count = 0;
345 
346     /* print help */
347     qemu_chr_be_write(base, (void *)"\1?", 2);
348     data = qmp_ringbuf_read("mux-label-base", 128, false, 0, &error_abort);
349     g_assert_cmpint(strlen(data), !=, 0);
350     g_free(data);
351 
352     qemu_chr_fe_deinit(&chr_be1, false);
353 
354     qmp_chardev_remove("mux-label", &error);
355     g_assert_cmpstr(error_get_pretty(error), ==, "Chardev 'mux-label' is busy");
356     error_free(error);
357 
358     qemu_chr_fe_deinit(&chr_be2, false);
359     qmp_chardev_remove("mux-label", &error_abort);
360 }
361 
362 
363 static void websock_server_read(void *opaque, const uint8_t *buf, int size)
364 {
365     g_assert_cmpint(size, ==, 5);
366     g_assert(memcmp(buf, "world", size) == 0);
367     quit = true;
368 }
369 
370 
371 static int websock_server_can_read(void *opaque)
372 {
373     return 10;
374 }
375 
376 
377 static bool websock_check_http_headers(char *buf, int size)
378 {
379     int i;
380     const char *ans[] = { "HTTP/1.1 101 Switching Protocols\r\n",
381                           "Server: QEMU VNC\r\n",
382                           "Upgrade: websocket\r\n",
383                           "Connection: Upgrade\r\n",
384                           "Sec-WebSocket-Accept:",
385                           "Sec-WebSocket-Protocol: binary\r\n" };
386 
387     for (i = 0; i < 6; i++) {
388         if (g_strstr_len(buf, size, ans[i]) == NULL) {
389             return false;
390         }
391     }
392 
393     return true;
394 }
395 
396 
397 static void websock_client_read(void *opaque, const uint8_t *buf, int size)
398 {
399     const uint8_t ping[] = { 0x89, 0x85,                  /* Ping header */
400                              0x07, 0x77, 0x9e, 0xf9,      /* Masking key */
401                              0x6f, 0x12, 0xf2, 0x95, 0x68 /* "hello" */ };
402 
403     const uint8_t binary[] = { 0x82, 0x85,                  /* Binary header */
404                                0x74, 0x90, 0xb9, 0xdf,      /* Masking key */
405                                0x03, 0xff, 0xcb, 0xb3, 0x10 /* "world" */ };
406     Chardev *chr_client = opaque;
407 
408     if (websock_check_http_headers((char *) buf, size)) {
409         qemu_chr_fe_write(chr_client->be, ping, sizeof(ping));
410     } else if (buf[0] == 0x8a && buf[1] == 0x05) {
411         g_assert(strncmp((char *) buf + 2, "hello", 5) == 0);
412         qemu_chr_fe_write(chr_client->be, binary, sizeof(binary));
413     } else {
414         g_assert(buf[0] == 0x88 && buf[1] == 0x16);
415         g_assert(strncmp((char *) buf + 4, "peer requested close", 10) == 0);
416         quit = true;
417     }
418 }
419 
420 
421 static int websock_client_can_read(void *opaque)
422 {
423     return 4096;
424 }
425 
426 
427 static void char_websock_test(void)
428 {
429     QObject *addr;
430     QDict *qdict;
431     const char *port;
432     char *tmp;
433     char *handshake_port;
434     CharBackend be;
435     CharBackend client_be;
436     Chardev *chr_client;
437     Chardev *chr = qemu_chr_new("server",
438                                 "websocket:127.0.0.1:0,server=on,wait=off", NULL);
439     const char handshake[] = "GET / HTTP/1.1\r\n"
440                              "Upgrade: websocket\r\n"
441                              "Connection: Upgrade\r\n"
442                              "Host: localhost:%s\r\n"
443                              "Origin: http://localhost:%s\r\n"
444                              "Sec-WebSocket-Key: o9JHNiS3/0/0zYE1wa3yIw==\r\n"
445                              "Sec-WebSocket-Version: 13\r\n"
446                              "Sec-WebSocket-Protocol: binary\r\n\r\n";
447     const uint8_t close[] = { 0x88, 0x82,             /* Close header */
448                               0xef, 0xaa, 0xc5, 0x97, /* Masking key */
449                               0xec, 0x42              /* Status code */ };
450 
451     addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
452     qdict = qobject_to(QDict, addr);
453     port = qdict_get_str(qdict, "port");
454     tmp = g_strdup_printf("tcp:127.0.0.1:%s", port);
455     handshake_port = g_strdup_printf(handshake, port, port);
456     qobject_unref(qdict);
457 
458     qemu_chr_fe_init(&be, chr, &error_abort);
459     qemu_chr_fe_set_handlers(&be, websock_server_can_read, websock_server_read,
460                              NULL, NULL, chr, NULL, true);
461 
462     chr_client = qemu_chr_new("client", tmp, NULL);
463     qemu_chr_fe_init(&client_be, chr_client, &error_abort);
464     qemu_chr_fe_set_handlers(&client_be, websock_client_can_read,
465                              websock_client_read,
466                              NULL, NULL, chr_client, NULL, true);
467     g_free(tmp);
468 
469     qemu_chr_write_all(chr_client,
470                        (uint8_t *) handshake_port,
471                        strlen(handshake_port));
472     g_free(handshake_port);
473     main_loop();
474 
475     g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
476     g_assert(object_property_get_bool(OBJECT(chr_client),
477                                       "connected", &error_abort));
478 
479     qemu_chr_write_all(chr_client, close, sizeof(close));
480     main_loop();
481 
482     object_unparent(OBJECT(chr_client));
483     object_unparent(OBJECT(chr));
484 }
485 
486 
487 #ifndef _WIN32
488 static void char_pipe_test(void)
489 {
490     gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
491     gchar *tmp, *in, *out, *pipe = g_build_filename(tmp_path, "pipe", NULL);
492     Chardev *chr;
493     CharBackend be;
494     int ret, fd;
495     char buf[10];
496     FeHandler fe = { 0, };
497 
498     in = g_strdup_printf("%s.in", pipe);
499     if (mkfifo(in, 0600) < 0) {
500         abort();
501     }
502     out = g_strdup_printf("%s.out", pipe);
503     if (mkfifo(out, 0600) < 0) {
504         abort();
505     }
506 
507     tmp = g_strdup_printf("pipe:%s", pipe);
508     chr = qemu_chr_new("pipe", tmp, NULL);
509     g_assert_nonnull(chr);
510     g_free(tmp);
511 
512     qemu_chr_fe_init(&be, chr, &error_abort);
513 
514     ret = qemu_chr_fe_write(&be, (void *)"pipe-out", 9);
515     g_assert_cmpint(ret, ==, 9);
516 
517     fd = open(out, O_RDWR);
518     ret = read(fd, buf, sizeof(buf));
519     g_assert_cmpint(ret, ==, 9);
520     g_assert_cmpstr(buf, ==, "pipe-out");
521     close(fd);
522 
523     fd = open(in, O_WRONLY);
524     ret = write(fd, "pipe-in", 8);
525     g_assert_cmpint(ret, ==, 8);
526     close(fd);
527 
528     qemu_chr_fe_set_handlers(&be,
529                              fe_can_read,
530                              fe_read,
531                              fe_event,
532                              NULL,
533                              &fe,
534                              NULL, true);
535 
536     main_loop();
537 
538     g_assert_cmpint(fe.read_count, ==, 8);
539     g_assert_cmpstr(fe.read_buf, ==, "pipe-in");
540 
541     qemu_chr_fe_deinit(&be, true);
542 
543     g_assert(g_unlink(in) == 0);
544     g_assert(g_unlink(out) == 0);
545     g_assert(g_rmdir(tmp_path) == 0);
546     g_free(in);
547     g_free(out);
548     g_free(tmp_path);
549     g_free(pipe);
550 }
551 #endif
552 
553 typedef struct SocketIdleData {
554     GMainLoop *loop;
555     Chardev *chr;
556     bool conn_expected;
557     CharBackend *be;
558     CharBackend *client_be;
559 } SocketIdleData;
560 
561 
562 static void socket_read_hello(void *opaque, const uint8_t *buf, int size)
563 {
564     g_assert_cmpint(size, ==, 5);
565     g_assert(strncmp((char *)buf, "hello", 5) == 0);
566 
567     quit = true;
568 }
569 
570 static int socket_can_read_hello(void *opaque)
571 {
572     return 10;
573 }
574 
575 static int make_udp_socket(int *port)
576 {
577     struct sockaddr_in addr = { 0, };
578     socklen_t alen = sizeof(addr);
579     int ret, sock = qemu_socket(PF_INET, SOCK_DGRAM, 0);
580 
581     g_assert_cmpint(sock, >=, 0);
582     addr.sin_family = AF_INET ;
583     addr.sin_addr.s_addr = htonl(INADDR_ANY);
584     addr.sin_port = 0;
585     ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
586     g_assert_cmpint(ret, ==, 0);
587     ret = getsockname(sock, (struct sockaddr *)&addr, &alen);
588     g_assert_cmpint(ret, ==, 0);
589 
590     *port = ntohs(addr.sin_port);
591     return sock;
592 }
593 
594 static void char_udp_test_internal(Chardev *reuse_chr, int sock)
595 {
596     struct sockaddr_in other;
597     SocketIdleData d = { 0, };
598     Chardev *chr;
599     CharBackend *be;
600     socklen_t alen = sizeof(other);
601     int ret;
602     char buf[10];
603     char *tmp = NULL;
604 
605     if (reuse_chr) {
606         chr = reuse_chr;
607         be = chr->be;
608     } else {
609         int port;
610         sock = make_udp_socket(&port);
611         tmp = g_strdup_printf("udp:127.0.0.1:%d", port);
612         chr = qemu_chr_new("client", tmp, NULL);
613         g_assert_nonnull(chr);
614 
615         be = g_alloca(sizeof(CharBackend));
616         qemu_chr_fe_init(be, chr, &error_abort);
617     }
618 
619     d.chr = chr;
620     qemu_chr_fe_set_handlers(be, socket_can_read_hello, socket_read_hello,
621                              NULL, NULL, &d, NULL, true);
622     ret = qemu_chr_write_all(chr, (uint8_t *)"hello", 5);
623     g_assert_cmpint(ret, ==, 5);
624 
625     ret = recvfrom(sock, buf, sizeof(buf), 0,
626                    (struct sockaddr *)&other, &alen);
627     g_assert_cmpint(ret, ==, 5);
628     ret = sendto(sock, buf, 5, 0, (struct sockaddr *)&other, alen);
629     g_assert_cmpint(ret, ==, 5);
630 
631     main_loop();
632 
633     if (!reuse_chr) {
634         close(sock);
635         qemu_chr_fe_deinit(be, true);
636     }
637     g_free(tmp);
638 }
639 
640 static void char_udp_test(void)
641 {
642     char_udp_test_internal(NULL, 0);
643 }
644 
645 
646 typedef struct {
647     int event;
648     bool got_pong;
649     CharBackend *be;
650 } CharSocketTestData;
651 
652 
653 #define SOCKET_PING "Hello"
654 #define SOCKET_PONG "World"
655 
656 typedef void (*char_socket_cb)(void *opaque, QEMUChrEvent event);
657 
658 static void
659 char_socket_event(void *opaque, QEMUChrEvent event)
660 {
661     CharSocketTestData *data = opaque;
662     data->event = event;
663 }
664 
665 static void
666 char_socket_event_with_error(void *opaque, QEMUChrEvent event)
667 {
668     static bool first_error;
669     CharSocketTestData *data = opaque;
670     CharBackend *be = data->be;
671     data->event = event;
672     switch (event) {
673     case CHR_EVENT_OPENED:
674         if (!first_error) {
675             first_error = true;
676             qemu_chr_fe_disconnect(be);
677         }
678         return;
679     case CHR_EVENT_CLOSED:
680         return;
681     default:
682         return;
683     }
684 }
685 
686 
687 static void
688 char_socket_read(void *opaque, const uint8_t *buf, int size)
689 {
690     CharSocketTestData *data = opaque;
691     g_assert_cmpint(size, ==, sizeof(SOCKET_PONG));
692     g_assert(memcmp(buf, SOCKET_PONG, size) == 0);
693     data->got_pong = true;
694 }
695 
696 
697 static int
698 char_socket_can_read(void *opaque)
699 {
700     return sizeof(SOCKET_PONG);
701 }
702 
703 
704 static char *
705 char_socket_addr_to_opt_str(SocketAddress *addr, bool fd_pass,
706                             const char *reconnect, bool is_listen)
707 {
708     if (fd_pass) {
709         QIOChannelSocket *ioc = qio_channel_socket_new();
710         int fd;
711         char *optstr;
712         g_assert(!reconnect);
713         if (is_listen) {
714             qio_channel_socket_listen_sync(ioc, addr, 1, &error_abort);
715         } else {
716             qio_channel_socket_connect_sync(ioc, addr, &error_abort);
717         }
718         fd = ioc->fd;
719         ioc->fd = -1;
720         optstr = g_strdup_printf("socket,id=cdev0,fd=%d%s",
721                                  fd, is_listen ? ",server=on,wait=off" : "");
722         object_unref(OBJECT(ioc));
723         return optstr;
724     } else {
725         switch (addr->type) {
726         case SOCKET_ADDRESS_TYPE_INET:
727             return g_strdup_printf("socket,id=cdev0,host=%s,port=%s%s%s",
728                                    addr->u.inet.host,
729                                    addr->u.inet.port,
730                                    reconnect ? reconnect : "",
731                                    is_listen ? ",server=on,wait=off" : "");
732 
733         case SOCKET_ADDRESS_TYPE_UNIX:
734             return g_strdup_printf("socket,id=cdev0,path=%s%s%s",
735                                    addr->u.q_unix.path,
736                                    reconnect ? reconnect : "",
737                                    is_listen ? ",server=on,wait=off" : "");
738 
739         default:
740             g_assert_not_reached();
741         }
742     }
743 }
744 
745 
746 static int
747 char_socket_ping_pong(QIOChannel *ioc, Error **errp)
748 {
749     char greeting[sizeof(SOCKET_PING)];
750     const char *response = SOCKET_PONG;
751 
752     int ret;
753     ret = qio_channel_read_all(ioc, greeting, sizeof(greeting), errp);
754     if (ret != 0) {
755         object_unref(OBJECT(ioc));
756         return -1;
757     }
758 
759     g_assert(memcmp(greeting, SOCKET_PING, sizeof(greeting)) == 0);
760 
761     qio_channel_write_all(ioc, response, sizeof(SOCKET_PONG), errp);
762     object_unref(OBJECT(ioc));
763     return 0;
764 }
765 
766 
767 static gpointer
768 char_socket_server_client_thread(gpointer data)
769 {
770     SocketAddress *addr = data;
771     QIOChannelSocket *ioc = qio_channel_socket_new();
772 
773     qio_channel_socket_connect_sync(ioc, addr, &error_abort);
774 
775     char_socket_ping_pong(QIO_CHANNEL(ioc), &error_abort);
776 
777     return NULL;
778 }
779 
780 
781 typedef struct {
782     SocketAddress *addr;
783     bool wait_connected;
784     bool fd_pass;
785 } CharSocketServerTestConfig;
786 
787 
788 static void char_socket_server_test(gconstpointer opaque)
789 {
790     const CharSocketServerTestConfig *config = opaque;
791     Chardev *chr;
792     CharBackend be = {0};
793     CharSocketTestData data = {0};
794     QObject *qaddr;
795     SocketAddress *addr;
796     Visitor *v;
797     QemuThread thread;
798     int ret;
799     bool reconnected = false;
800     char *optstr;
801     QemuOpts *opts;
802 
803     g_setenv("QTEST_SILENT_ERRORS", "1", 1);
804     /*
805      * We rely on config->addr containing "wait=off", otherwise
806      * qemu_chr_new() will block until a client connects. We
807      * can't spawn our client thread though, because until
808      * qemu_chr_new() returns we don't know what TCP port was
809      * allocated by the OS
810      */
811     optstr = char_socket_addr_to_opt_str(config->addr,
812                                          config->fd_pass,
813                                          NULL,
814                                          true);
815     opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
816                                    optstr, true);
817     g_assert_nonnull(opts);
818     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
819     qemu_opts_del(opts);
820     g_assert_nonnull(chr);
821     g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
822 
823     qaddr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
824     g_assert_nonnull(qaddr);
825 
826     v = qobject_input_visitor_new(qaddr);
827     visit_type_SocketAddress(v, "addr", &addr, &error_abort);
828     visit_free(v);
829     qobject_unref(qaddr);
830 
831     qemu_chr_fe_init(&be, chr, &error_abort);
832 
833  reconnect:
834     data.event = -1;
835     data.be = &be;
836     qemu_chr_fe_set_handlers(&be, NULL, NULL,
837                              char_socket_event, NULL,
838                              &data, NULL, true);
839     g_assert(data.event == -1);
840 
841     /*
842      * Kick off a thread to act as the "remote" client
843      * which just plays ping-pong with us
844      */
845     qemu_thread_create(&thread, "client",
846                        char_socket_server_client_thread,
847                        addr, QEMU_THREAD_JOINABLE);
848     g_assert(data.event == -1);
849 
850     if (config->wait_connected) {
851         /* Synchronously accept a connection */
852         qemu_chr_wait_connected(chr, &error_abort);
853     } else {
854         /*
855          * Asynchronously accept a connection when the evnt
856          * loop reports the listener socket as readable
857          */
858         while (data.event == -1) {
859             main_loop_wait(false);
860         }
861     }
862     g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
863     g_assert(data.event == CHR_EVENT_OPENED);
864     data.event = -1;
865 
866     /* Send a greeting to the client */
867     ret = qemu_chr_fe_write_all(&be, (const uint8_t *)SOCKET_PING,
868                                 sizeof(SOCKET_PING));
869     g_assert_cmpint(ret, ==, sizeof(SOCKET_PING));
870     g_assert(data.event == -1);
871 
872     /* Setup a callback to receive the reply to our greeting */
873     qemu_chr_fe_set_handlers(&be, char_socket_can_read,
874                              char_socket_read,
875                              char_socket_event, NULL,
876                              &data, NULL, true);
877     g_assert(data.event == CHR_EVENT_OPENED);
878     data.event = -1;
879 
880     /* Wait for the client to go away */
881     while (data.event == -1) {
882         main_loop_wait(false);
883     }
884     g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
885     g_assert(data.event == CHR_EVENT_CLOSED);
886     g_assert(data.got_pong);
887 
888     qemu_thread_join(&thread);
889 
890     if (!reconnected) {
891         reconnected = true;
892         goto reconnect;
893     }
894 
895     qapi_free_SocketAddress(addr);
896     object_unparent(OBJECT(chr));
897     g_free(optstr);
898     g_unsetenv("QTEST_SILENT_ERRORS");
899 }
900 
901 
902 static gpointer
903 char_socket_client_server_thread(gpointer data)
904 {
905     QIOChannelSocket *ioc = data;
906     QIOChannelSocket *cioc;
907 
908 retry:
909     cioc = qio_channel_socket_accept(ioc, &error_abort);
910     g_assert_nonnull(cioc);
911 
912     if (char_socket_ping_pong(QIO_CHANNEL(cioc), NULL) != 0) {
913         goto retry;
914     }
915 
916     return NULL;
917 }
918 
919 
920 typedef struct {
921     SocketAddress *addr;
922     const char *reconnect;
923     bool wait_connected;
924     bool fd_pass;
925     char_socket_cb event_cb;
926 } CharSocketClientTestConfig;
927 
928 static void char_socket_client_dupid_test(gconstpointer opaque)
929 {
930     const CharSocketClientTestConfig *config = opaque;
931     QIOChannelSocket *ioc;
932     char *optstr;
933     Chardev *chr1, *chr2;
934     SocketAddress *addr;
935     QemuOpts *opts;
936     Error *local_err = NULL;
937 
938     /*
939      * Setup a listener socket and determine get its address
940      * so we know the TCP port for the client later
941      */
942     ioc = qio_channel_socket_new();
943     g_assert_nonnull(ioc);
944     qio_channel_socket_listen_sync(ioc, config->addr, 1, &error_abort);
945     addr = qio_channel_socket_get_local_address(ioc, &error_abort);
946     g_assert_nonnull(addr);
947 
948     /*
949      * Populate the chardev address based on what the server
950      * is actually listening on
951      */
952     optstr = char_socket_addr_to_opt_str(addr,
953                                          config->fd_pass,
954                                          config->reconnect,
955                                          false);
956 
957     opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
958                                    optstr, true);
959     g_assert_nonnull(opts);
960     chr1 = qemu_chr_new_from_opts(opts, NULL, &error_abort);
961     g_assert_nonnull(chr1);
962     qemu_chr_wait_connected(chr1, &error_abort);
963 
964     chr2 = qemu_chr_new_from_opts(opts, NULL, &local_err);
965     g_assert_null(chr2);
966     error_free_or_abort(&local_err);
967 
968     object_unref(OBJECT(ioc));
969     qemu_opts_del(opts);
970     object_unparent(OBJECT(chr1));
971     qapi_free_SocketAddress(addr);
972     g_free(optstr);
973 }
974 
975 static void char_socket_client_test(gconstpointer opaque)
976 {
977     const CharSocketClientTestConfig *config = opaque;
978     const char_socket_cb event_cb = config->event_cb;
979     QIOChannelSocket *ioc;
980     char *optstr;
981     Chardev *chr;
982     CharBackend be = {0};
983     CharSocketTestData data = {0};
984     SocketAddress *addr;
985     QemuThread thread;
986     int ret;
987     bool reconnected = false;
988     QemuOpts *opts;
989 
990     /*
991      * Setup a listener socket and determine get its address
992      * so we know the TCP port for the client later
993      */
994     ioc = qio_channel_socket_new();
995     g_assert_nonnull(ioc);
996     qio_channel_socket_listen_sync(ioc, config->addr, 1, &error_abort);
997     addr = qio_channel_socket_get_local_address(ioc, &error_abort);
998     g_assert_nonnull(addr);
999 
1000     /*
1001      * Kick off a thread to act as the "remote" client
1002      * which just plays ping-pong with us
1003      */
1004     qemu_thread_create(&thread, "client",
1005                        char_socket_client_server_thread,
1006                        ioc, QEMU_THREAD_JOINABLE);
1007 
1008     /*
1009      * Populate the chardev address based on what the server
1010      * is actually listening on
1011      */
1012     optstr = char_socket_addr_to_opt_str(addr,
1013                                          config->fd_pass,
1014                                          config->reconnect,
1015                                          false);
1016 
1017     opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
1018                                    optstr, true);
1019     g_assert_nonnull(opts);
1020     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
1021     qemu_opts_del(opts);
1022     g_assert_nonnull(chr);
1023 
1024     if (config->reconnect) {
1025         /*
1026          * If reconnect is set, the connection will be
1027          * established in a background thread and we won't
1028          * see the "connected" status updated until we
1029          * run the main event loop, or call qemu_chr_wait_connected
1030          */
1031         g_assert(!object_property_get_bool(OBJECT(chr), "connected",
1032                                            &error_abort));
1033     } else {
1034         g_assert(object_property_get_bool(OBJECT(chr), "connected",
1035                                           &error_abort));
1036     }
1037 
1038     qemu_chr_fe_init(&be, chr, &error_abort);
1039 
1040  reconnect:
1041     data.event = -1;
1042     data.be = &be;
1043     qemu_chr_fe_set_handlers(&be, NULL, NULL,
1044                              event_cb, NULL,
1045                              &data, NULL, true);
1046     if (config->reconnect) {
1047         g_assert(data.event == -1);
1048     } else {
1049         g_assert(data.event == CHR_EVENT_OPENED);
1050     }
1051 
1052     if (config->wait_connected) {
1053         /*
1054          * Synchronously wait for the connection to complete
1055          * This should be a no-op if reconnect is not set.
1056          */
1057         qemu_chr_wait_connected(chr, &error_abort);
1058     } else {
1059         /*
1060          * Asynchronously wait for the connection to be reported
1061          * as complete when the background thread reports its
1062          * status.
1063          * The loop will short-circuit if reconnect was set
1064          */
1065         while (data.event == -1) {
1066             main_loop_wait(false);
1067         }
1068     }
1069     g_assert(data.event == CHR_EVENT_OPENED);
1070     data.event = -1;
1071     g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
1072 
1073     /* Send a greeting to the server */
1074     ret = qemu_chr_fe_write_all(&be, (const uint8_t *)SOCKET_PING,
1075                                 sizeof(SOCKET_PING));
1076     g_assert_cmpint(ret, ==, sizeof(SOCKET_PING));
1077     g_assert(data.event == -1);
1078 
1079     /* Setup a callback to receive the reply to our greeting */
1080     qemu_chr_fe_set_handlers(&be, char_socket_can_read,
1081                              char_socket_read,
1082                              event_cb, NULL,
1083                              &data, NULL, true);
1084     g_assert(data.event == CHR_EVENT_OPENED);
1085     data.event = -1;
1086 
1087     /* Wait for the server to go away */
1088     while (data.event == -1) {
1089         main_loop_wait(false);
1090     }
1091     g_assert(data.event == CHR_EVENT_CLOSED);
1092     g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
1093     g_assert(data.got_pong);
1094     qemu_thread_join(&thread);
1095 
1096     if (config->reconnect && !reconnected) {
1097         reconnected = true;
1098         qemu_thread_create(&thread, "client",
1099                            char_socket_client_server_thread,
1100                            ioc, QEMU_THREAD_JOINABLE);
1101         goto reconnect;
1102     }
1103 
1104     object_unref(OBJECT(ioc));
1105     object_unparent(OBJECT(chr));
1106     qapi_free_SocketAddress(addr);
1107     g_free(optstr);
1108 }
1109 
1110 static void
1111 count_closed_event(void *opaque, QEMUChrEvent event)
1112 {
1113     int *count = opaque;
1114     if (event == CHR_EVENT_CLOSED) {
1115         (*count)++;
1116     }
1117 }
1118 
1119 static void
1120 char_socket_discard_read(void *opaque, const uint8_t *buf, int size)
1121 {
1122 }
1123 
1124 static void char_socket_server_two_clients_test(gconstpointer opaque)
1125 {
1126     SocketAddress *incoming_addr = (gpointer) opaque;
1127     Chardev *chr;
1128     CharBackend be = {0};
1129     QObject *qaddr;
1130     SocketAddress *addr;
1131     Visitor *v;
1132     char *optstr;
1133     QemuOpts *opts;
1134     QIOChannelSocket *ioc1, *ioc2;
1135     int closed = 0;
1136 
1137     g_setenv("QTEST_SILENT_ERRORS", "1", 1);
1138     /*
1139      * We rely on addr containing "wait=off", otherwise
1140      * qemu_chr_new() will block until a client connects. We
1141      * can't spawn our client thread though, because until
1142      * qemu_chr_new() returns we don't know what TCP port was
1143      * allocated by the OS
1144      */
1145     optstr = char_socket_addr_to_opt_str(incoming_addr,
1146                                          false,
1147                                          NULL,
1148                                          true);
1149     opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
1150                                    optstr, true);
1151     g_assert_nonnull(opts);
1152     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
1153     qemu_opts_del(opts);
1154     g_assert_nonnull(chr);
1155     g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
1156 
1157     qaddr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
1158     g_assert_nonnull(qaddr);
1159 
1160     v = qobject_input_visitor_new(qaddr);
1161     visit_type_SocketAddress(v, "addr", &addr, &error_abort);
1162     visit_free(v);
1163     qobject_unref(qaddr);
1164 
1165     qemu_chr_fe_init(&be, chr, &error_abort);
1166 
1167     qemu_chr_fe_set_handlers(&be, char_socket_can_read, char_socket_discard_read,
1168                              count_closed_event, NULL,
1169                              &closed, NULL, true);
1170 
1171     ioc1 = qio_channel_socket_new();
1172     qio_channel_socket_connect_sync(ioc1, addr, &error_abort);
1173     qemu_chr_wait_connected(chr, &error_abort);
1174 
1175     /* switch the chardev to another context */
1176     GMainContext *ctx = g_main_context_new();
1177     qemu_chr_fe_set_handlers(&be, char_socket_can_read, char_socket_discard_read,
1178                              count_closed_event, NULL,
1179                              &closed, ctx, true);
1180 
1181     /* Start a second connection while the first is still connected.
1182      * It will be placed in the listen() backlog, and connect() will
1183      * succeed immediately.
1184      */
1185     ioc2 = qio_channel_socket_new();
1186     qio_channel_socket_connect_sync(ioc2, addr, &error_abort);
1187 
1188     object_unref(OBJECT(ioc1));
1189     /* The two connections should now be processed serially.  */
1190     while (g_main_context_iteration(ctx, TRUE)) {
1191         if (closed == 1 && ioc2) {
1192             object_unref(OBJECT(ioc2));
1193             ioc2 = NULL;
1194         }
1195         if (closed == 2) {
1196             break;
1197         }
1198     }
1199 
1200     qapi_free_SocketAddress(addr);
1201     object_unparent(OBJECT(chr));
1202     g_main_context_unref(ctx);
1203     g_free(optstr);
1204     g_unsetenv("QTEST_SILENT_ERRORS");
1205 }
1206 
1207 
1208 #if defined(HAVE_CHARDEV_SERIAL) && !defined(WIN32)
1209 static void char_serial_test(void)
1210 {
1211     QemuOpts *opts;
1212     Chardev *chr;
1213 
1214     opts = qemu_opts_create(qemu_find_opts("chardev"), "serial-id",
1215                             1, &error_abort);
1216     qemu_opt_set(opts, "backend", "serial", &error_abort);
1217     qemu_opt_set(opts, "path", "/dev/null", &error_abort);
1218 
1219     chr = qemu_chr_new_from_opts(opts, NULL, NULL);
1220     g_assert_nonnull(chr);
1221     /* TODO: add more tests with a pty */
1222     object_unparent(OBJECT(chr));
1223 
1224     qemu_opts_del(opts);
1225 }
1226 #endif
1227 
1228 #if defined(HAVE_CHARDEV_PARALLEL) && !defined(WIN32)
1229 static void char_parallel_test(void)
1230 {
1231     QemuOpts *opts;
1232     Chardev *chr;
1233 
1234     opts = qemu_opts_create(qemu_find_opts("chardev"), "parallel-id",
1235                             1, &error_abort);
1236     qemu_opt_set(opts, "backend", "parallel", &error_abort);
1237     qemu_opt_set(opts, "path", "/dev/null", &error_abort);
1238 
1239     chr = qemu_chr_new_from_opts(opts, NULL, NULL);
1240 #ifdef __linux__
1241     /* fails to PPCLAIM, see qemu_chr_open_pp_fd() */
1242     g_assert_null(chr);
1243 #else
1244     g_assert_nonnull(chr);
1245     object_unparent(OBJECT(chr));
1246 #endif
1247 
1248     qemu_opts_del(opts);
1249 }
1250 #endif
1251 
1252 #ifndef _WIN32
1253 static void char_file_fifo_test(void)
1254 {
1255     Chardev *chr;
1256     CharBackend be;
1257     char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
1258     char *fifo = g_build_filename(tmp_path, "fifo", NULL);
1259     char *out = g_build_filename(tmp_path, "out", NULL);
1260     ChardevFile file = { .in = fifo,
1261                          .out = out };
1262     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
1263                                .u.file.data = &file };
1264     FeHandler fe = { 0, };
1265     int fd, ret;
1266 
1267     if (mkfifo(fifo, 0600) < 0) {
1268         abort();
1269     }
1270 
1271     fd = open(fifo, O_RDWR);
1272     ret = write(fd, "fifo-in", 8);
1273     g_assert_cmpint(ret, ==, 8);
1274 
1275     chr = qemu_chardev_new("label-file", TYPE_CHARDEV_FILE, &backend,
1276                            NULL, &error_abort);
1277 
1278     qemu_chr_fe_init(&be, chr, &error_abort);
1279     qemu_chr_fe_set_handlers(&be,
1280                              fe_can_read,
1281                              fe_read,
1282                              fe_event,
1283                              NULL,
1284                              &fe, NULL, true);
1285 
1286     g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
1287     qmp_chardev_send_break("label-foo", NULL);
1288     g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
1289     qmp_chardev_send_break("label-file", NULL);
1290     g_assert_cmpint(fe.last_event, ==, CHR_EVENT_BREAK);
1291 
1292     main_loop();
1293 
1294     close(fd);
1295 
1296     g_assert_cmpint(fe.read_count, ==, 8);
1297     g_assert_cmpstr(fe.read_buf, ==, "fifo-in");
1298 
1299     qemu_chr_fe_deinit(&be, true);
1300 
1301     g_unlink(fifo);
1302     g_free(fifo);
1303     g_unlink(out);
1304     g_free(out);
1305     g_rmdir(tmp_path);
1306     g_free(tmp_path);
1307 }
1308 #endif
1309 
1310 static void char_file_test_internal(Chardev *ext_chr, const char *filepath)
1311 {
1312     char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
1313     char *out;
1314     Chardev *chr;
1315     char *contents = NULL;
1316     ChardevFile file = {};
1317     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
1318                                .u.file.data = &file };
1319     gsize length;
1320     int ret;
1321 
1322     if (ext_chr) {
1323         chr = ext_chr;
1324         out = g_strdup(filepath);
1325         file.out = out;
1326     } else {
1327         out = g_build_filename(tmp_path, "out", NULL);
1328         file.out = out;
1329         chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &backend,
1330                                NULL, &error_abort);
1331     }
1332     ret = qemu_chr_write_all(chr, (uint8_t *)"hello!", 6);
1333     g_assert_cmpint(ret, ==, 6);
1334 
1335     ret = g_file_get_contents(out, &contents, &length, NULL);
1336     g_assert(ret == TRUE);
1337     g_assert_cmpint(length, ==, 6);
1338     g_assert(strncmp(contents, "hello!", 6) == 0);
1339 
1340     if (!ext_chr) {
1341         object_unparent(OBJECT(chr));
1342         g_unlink(out);
1343     }
1344     g_free(contents);
1345     g_rmdir(tmp_path);
1346     g_free(tmp_path);
1347     g_free(out);
1348 }
1349 
1350 static void char_file_test(void)
1351 {
1352     char_file_test_internal(NULL, NULL);
1353 }
1354 
1355 static void char_null_test(void)
1356 {
1357     Error *err = NULL;
1358     Chardev *chr;
1359     CharBackend be;
1360     int ret;
1361 
1362     chr = qemu_chr_find("label-null");
1363     g_assert_null(chr);
1364 
1365     chr = qemu_chr_new("label-null", "null", NULL);
1366     chr = qemu_chr_find("label-null");
1367     g_assert_nonnull(chr);
1368 
1369     g_assert(qemu_chr_has_feature(chr,
1370                  QEMU_CHAR_FEATURE_FD_PASS) == false);
1371     g_assert(qemu_chr_has_feature(chr,
1372                  QEMU_CHAR_FEATURE_RECONNECTABLE) == false);
1373 
1374     /* check max avail */
1375     qemu_chr_fe_init(&be, chr, &error_abort);
1376     qemu_chr_fe_init(&be, chr, &err);
1377     error_free_or_abort(&err);
1378 
1379     /* deinit & reinit */
1380     qemu_chr_fe_deinit(&be, false);
1381     qemu_chr_fe_init(&be, chr, &error_abort);
1382 
1383     qemu_chr_fe_set_open(&be, true);
1384 
1385     qemu_chr_fe_set_handlers(&be,
1386                              fe_can_read,
1387                              fe_read,
1388                              fe_event,
1389                              NULL,
1390                              NULL, NULL, true);
1391 
1392     ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
1393     g_assert_cmpint(ret, ==, 4);
1394 
1395     qemu_chr_fe_deinit(&be, true);
1396 }
1397 
1398 static void char_invalid_test(void)
1399 {
1400     Chardev *chr;
1401     g_setenv("QTEST_SILENT_ERRORS", "1", 1);
1402     chr = qemu_chr_new("label-invalid", "invalid", NULL);
1403     g_assert_null(chr);
1404     g_unsetenv("QTEST_SILENT_ERRORS");
1405 }
1406 
1407 static int chardev_change(void *opaque)
1408 {
1409     return 0;
1410 }
1411 
1412 static int chardev_change_denied(void *opaque)
1413 {
1414     return -1;
1415 }
1416 
1417 static void char_hotswap_test(void)
1418 {
1419     char *chr_args;
1420     Chardev *chr;
1421     CharBackend be;
1422 
1423     gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
1424     char *filename = g_build_filename(tmp_path, "file", NULL);
1425     ChardevFile file = { .out = filename };
1426     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
1427                                .u.file.data = &file };
1428     ChardevReturn *ret;
1429 
1430     int port;
1431     int sock = make_udp_socket(&port);
1432     g_assert_cmpint(sock, >=, 0);
1433 
1434     chr_args = g_strdup_printf("udp:127.0.0.1:%d", port);
1435 
1436     chr = qemu_chr_new("chardev", chr_args, NULL);
1437     qemu_chr_fe_init(&be, chr, &error_abort);
1438 
1439     /* check that chardev operates correctly */
1440     char_udp_test_internal(chr, sock);
1441 
1442     /* set the handler that denies the hotswap */
1443     qemu_chr_fe_set_handlers(&be, NULL, NULL,
1444                              NULL, chardev_change_denied, NULL, NULL, true);
1445 
1446     /* now, change is denied and has to keep the old backend operating */
1447     ret = qmp_chardev_change("chardev", &backend, NULL);
1448     g_assert(!ret);
1449     g_assert(be.chr == chr);
1450 
1451     char_udp_test_internal(chr, sock);
1452 
1453     /* now allow the change */
1454     qemu_chr_fe_set_handlers(&be, NULL, NULL,
1455                              NULL, chardev_change, NULL, NULL, true);
1456 
1457     /* has to succeed now */
1458     ret = qmp_chardev_change("chardev", &backend, &error_abort);
1459     g_assert(be.chr != chr);
1460 
1461     close(sock);
1462     chr = be.chr;
1463 
1464     /* run the file chardev test */
1465     char_file_test_internal(chr, filename);
1466 
1467     object_unparent(OBJECT(chr));
1468 
1469     qapi_free_ChardevReturn(ret);
1470     g_unlink(filename);
1471     g_free(filename);
1472     g_rmdir(tmp_path);
1473     g_free(tmp_path);
1474     g_free(chr_args);
1475 }
1476 
1477 static SocketAddress tcpaddr = {
1478     .type = SOCKET_ADDRESS_TYPE_INET,
1479     .u.inet.host = (char *)"127.0.0.1",
1480     .u.inet.port = (char *)"0",
1481 };
1482 #ifndef WIN32
1483 static SocketAddress unixaddr = {
1484     .type = SOCKET_ADDRESS_TYPE_UNIX,
1485     .u.q_unix.path = (char *)"test-char.sock",
1486 };
1487 #endif
1488 
1489 int main(int argc, char **argv)
1490 {
1491     bool has_ipv4, has_ipv6;
1492 
1493     qemu_init_main_loop(&error_abort);
1494     socket_init();
1495 
1496     g_test_init(&argc, &argv, NULL);
1497 
1498     if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
1499         g_printerr("socket_check_protocol_support() failed\n");
1500         goto end;
1501     }
1502 
1503     module_call_init(MODULE_INIT_QOM);
1504     qemu_add_opts(&qemu_chardev_opts);
1505 
1506     g_test_add_func("/char/null", char_null_test);
1507     g_test_add_func("/char/invalid", char_invalid_test);
1508     g_test_add_func("/char/ringbuf", char_ringbuf_test);
1509     g_test_add_func("/char/mux", char_mux_test);
1510 #ifdef _WIN32
1511     g_test_add_func("/char/console/subprocess", char_console_test_subprocess);
1512     g_test_add_func("/char/console", char_console_test);
1513 #endif
1514     g_test_add_func("/char/stdio/subprocess", char_stdio_test_subprocess);
1515     g_test_add_func("/char/stdio", char_stdio_test);
1516 #ifndef _WIN32
1517     g_test_add_func("/char/pipe", char_pipe_test);
1518 #endif
1519     g_test_add_func("/char/file", char_file_test);
1520 #ifndef _WIN32
1521     g_test_add_func("/char/file-fifo", char_file_fifo_test);
1522 #endif
1523 
1524 #define SOCKET_SERVER_TEST(name, addr)                                  \
1525     static CharSocketServerTestConfig server1 ## name =                 \
1526         { addr, false, false };                                         \
1527     static CharSocketServerTestConfig server2 ## name =                 \
1528         { addr, true, false };                                          \
1529     static CharSocketServerTestConfig server3 ## name =                 \
1530         { addr, false, true };                                          \
1531     static CharSocketServerTestConfig server4 ## name =                 \
1532         { addr, true, true };                                           \
1533     g_test_add_data_func("/char/socket/server/mainloop/" # name,        \
1534                          &server1 ##name, char_socket_server_test);     \
1535     g_test_add_data_func("/char/socket/server/wait-conn/" # name,       \
1536                          &server2 ##name, char_socket_server_test);     \
1537     g_test_add_data_func("/char/socket/server/mainloop-fdpass/" # name, \
1538                          &server3 ##name, char_socket_server_test);     \
1539     g_test_add_data_func("/char/socket/server/wait-conn-fdpass/" # name, \
1540                          &server4 ##name, char_socket_server_test)
1541 
1542 #define SOCKET_CLIENT_TEST(name, addr)                                  \
1543     static CharSocketClientTestConfig client1 ## name =                 \
1544         { addr, NULL, false, false, char_socket_event };                \
1545     static CharSocketClientTestConfig client2 ## name =                 \
1546         { addr, NULL, true, false, char_socket_event };                 \
1547     static CharSocketClientTestConfig client3 ## name =                 \
1548         { addr, ",reconnect-ms=1000", false, false, char_socket_event }; \
1549     static CharSocketClientTestConfig client4 ## name =                 \
1550         { addr, ",reconnect-ms=1000", true, false, char_socket_event }; \
1551     static CharSocketClientTestConfig client5 ## name =                 \
1552         { addr, NULL, false, true, char_socket_event };                 \
1553     static CharSocketClientTestConfig client6 ## name =                 \
1554         { addr, NULL, true, true, char_socket_event };                  \
1555     static CharSocketClientTestConfig client7 ## name =                 \
1556         { addr, ",reconnect-ms=1000", true, false,                      \
1557             char_socket_event_with_error };                             \
1558     static CharSocketClientTestConfig client8 ## name =                 \
1559         { addr, ",reconnect-ms=1000", false, false, char_socket_event };\
1560     g_test_add_data_func("/char/socket/client/mainloop/" # name,        \
1561                          &client1 ##name, char_socket_client_test);     \
1562     g_test_add_data_func("/char/socket/client/wait-conn/" # name,       \
1563                          &client2 ##name, char_socket_client_test);     \
1564     g_test_add_data_func("/char/socket/client/mainloop-reconnect/" # name, \
1565                          &client3 ##name, char_socket_client_test);     \
1566     g_test_add_data_func("/char/socket/client/wait-conn-reconnect/" # name, \
1567                          &client4 ##name, char_socket_client_test);     \
1568     g_test_add_data_func("/char/socket/client/mainloop-fdpass/" # name, \
1569                          &client5 ##name, char_socket_client_test);     \
1570     g_test_add_data_func("/char/socket/client/wait-conn-fdpass/" # name, \
1571                          &client6 ##name, char_socket_client_test);     \
1572     g_test_add_data_func("/char/socket/client/reconnect-error/" # name, \
1573                          &client7 ##name, char_socket_client_test);     \
1574     g_test_add_data_func("/char/socket/client/dupid-reconnect/" # name, \
1575                          &client8 ##name, char_socket_client_dupid_test)
1576 
1577     if (has_ipv4) {
1578         SOCKET_SERVER_TEST(tcp, &tcpaddr);
1579         SOCKET_CLIENT_TEST(tcp, &tcpaddr);
1580         g_test_add_data_func("/char/socket/server/two-clients/tcp", &tcpaddr,
1581                              char_socket_server_two_clients_test);
1582     }
1583 #ifndef WIN32
1584     SOCKET_SERVER_TEST(unix, &unixaddr);
1585     SOCKET_CLIENT_TEST(unix, &unixaddr);
1586     g_test_add_data_func("/char/socket/server/two-clients/unix", &unixaddr,
1587                          char_socket_server_two_clients_test);
1588 #endif
1589 
1590     g_test_add_func("/char/udp", char_udp_test);
1591 #if defined(HAVE_CHARDEV_SERIAL) && !defined(WIN32)
1592     g_test_add_func("/char/serial", char_serial_test);
1593 #endif
1594 #if defined(HAVE_CHARDEV_PARALLEL) && !defined(WIN32)
1595     g_test_add_func("/char/parallel", char_parallel_test);
1596 #endif
1597     g_test_add_func("/char/hotswap", char_hotswap_test);
1598     g_test_add_func("/char/websocket", char_websock_test);
1599 
1600 end:
1601     return g_test_run();
1602 }
1603