xref: /openbmc/qemu/tests/unit/test-char.c (revision 58d49b5895f2e0b5cfe4b2901bf24f3320b74f29)
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  
main_loop(void)31  static void main_loop(void)
32  {
33      quit = false;
34      do {
35          main_loop_wait(false);
36      } while (!quit);
37  }
38  
fe_can_read(void * opaque)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  
fe_read(void * opaque,const uint8_t * buf,int size)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  
fe_event(void * opaque,QEMUChrEvent event)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
char_console_test_subprocess(void)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  
char_console_test(void)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
char_stdio_test_subprocess(void)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  
char_stdio_test(void)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  
char_ringbuf_test(void)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  
char_mux_test(void)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  
websock_server_read(void * opaque,const uint8_t * buf,int size)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  
websock_server_can_read(void * opaque)371  static int websock_server_can_read(void *opaque)
372  {
373      return 10;
374  }
375  
376  
websock_check_http_headers(char * buf,int size)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  
websock_client_read(void * opaque,const uint8_t * buf,int size)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  
websock_client_can_read(void * opaque)421  static int websock_client_can_read(void *opaque)
422  {
423      return 4096;
424  }
425  
426  
char_websock_test(void)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
char_pipe_test(void)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  
socket_read_hello(void * opaque,const uint8_t * buf,int size)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  
socket_can_read_hello(void * opaque)570  static int socket_can_read_hello(void *opaque)
571  {
572      return 10;
573  }
574  
make_udp_socket(int * port)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  
char_udp_test_internal(Chardev * reuse_chr,int sock)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  
char_udp_test(void)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
char_socket_event(void * opaque,QEMUChrEvent event)659  char_socket_event(void *opaque, QEMUChrEvent event)
660  {
661      CharSocketTestData *data = opaque;
662      data->event = event;
663  }
664  
665  static void
char_socket_event_with_error(void * opaque,QEMUChrEvent event)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
char_socket_read(void * opaque,const uint8_t * buf,int size)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
char_socket_can_read(void * opaque)698  char_socket_can_read(void *opaque)
699  {
700      return sizeof(SOCKET_PONG);
701  }
702  
703  
704  static char *
char_socket_addr_to_opt_str(SocketAddress * addr,bool fd_pass,const char * reconnect,bool is_listen)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
char_socket_ping_pong(QIOChannel * ioc,Error ** errp)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
char_socket_server_client_thread(gpointer data)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  
char_socket_server_test(gconstpointer opaque)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
char_socket_client_server_thread(gpointer data)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  
char_socket_client_dupid_test(gconstpointer opaque)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  
char_socket_client_test(gconstpointer opaque)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
count_closed_event(void * opaque,QEMUChrEvent event)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
char_socket_discard_read(void * opaque,const uint8_t * buf,int size)1120  char_socket_discard_read(void *opaque, const uint8_t *buf, int size)
1121  {
1122  }
1123  
char_socket_server_two_clients_test(gconstpointer opaque)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)
char_serial_test(void)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)
char_parallel_test(void)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
char_file_fifo_test(void)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  
char_file_test_internal(Chardev * ext_chr,const char * filepath)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  
char_file_test(void)1350  static void char_file_test(void)
1351  {
1352      char_file_test_internal(NULL, NULL);
1353  }
1354  
char_null_test(void)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  
char_invalid_test(void)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  
chardev_change(void * opaque)1407  static int chardev_change(void *opaque)
1408  {
1409      return 0;
1410  }
1411  
chardev_change_denied(void * opaque)1412  static int chardev_change_denied(void *opaque)
1413  {
1414      return -1;
1415  }
1416  
char_hotswap_test(void)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  
main(int argc,char ** argv)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