From 2f5d45a150b2f20f7423aed185c1e99e1d4d23cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 14 Dec 2016 15:23:36 +0300 Subject: char: add a /chardevs container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a /chardevs container object to hold the list of chardevs. (Note: QTAILQ chardevs is going away in the following commits) Signed-off-by: Marc-André Lureau --- tests/test-char.c | 8 ++++---- tests/vhost-user-test.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'tests') diff --git a/tests/test-char.c b/tests/test-char.c index da69f11..71de4b3 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -53,7 +53,7 @@ static void char_stdio_test_subprocess(void) g_assert_cmpint(ret, ==, 4); qemu_chr_fe_deinit(&be); - qemu_chr_delete(chr); + object_unparent(OBJECT(chr)); } static void char_stdio_test(void) @@ -103,7 +103,7 @@ static void char_ringbuf_test(void) g_free(data); qemu_chr_fe_deinit(&be); - qemu_chr_delete(chr); + object_unparent(OBJECT(chr)); } static void char_mux_test(void) @@ -179,7 +179,7 @@ static void char_mux_test(void) qemu_chr_fe_deinit(&chr_be1); qemu_chr_fe_deinit(&chr_be2); - qemu_chr_delete(chr); + object_unparent(OBJECT(chr)); } static void char_null_test(void) @@ -222,7 +222,7 @@ static void char_null_test(void) g_assert_cmpint(ret, ==, 4); qemu_chr_fe_deinit(&be); - qemu_chr_delete(chr); + object_unparent(OBJECT(chr)); } static void char_invalid_test(void) diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c index a61896c..9095af2 100644 --- a/tests/vhost-user-test.c +++ b/tests/vhost-user-test.c @@ -491,7 +491,7 @@ static gboolean _test_server_free(TestServer *server) Chardev *chr = qemu_chr_fe_get_driver(&server->chr); qemu_chr_fe_deinit(&server->chr); - qemu_chr_delete(chr); + object_unparent(OBJECT(chr)); for (i = 0; i < server->fds_num; i++) { close(server->fds[i]); -- cgit v1.1 From e24ef0db4fabfe1f64854cfd2a2b5aaddc90f379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 3 Jan 2017 19:21:09 +0100 Subject: tests: add alias check in /char/ringbuf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- tests/test-char.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'tests') diff --git a/tests/test-char.c b/tests/test-char.c index 71de4b3..2811644 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -104,6 +104,16 @@ static void char_ringbuf_test(void) qemu_chr_fe_deinit(&be); object_unparent(OBJECT(chr)); + + /* check alias */ + opts = qemu_opts_create(qemu_find_opts("chardev"), "memory-label", + 1, &error_abort); + qemu_opt_set(opts, "backend", "memory", &error_abort); + qemu_opt_set(opts, "size", "2", &error_abort); + chr = qemu_chr_new_from_opts(opts, NULL); + g_assert_nonnull(chr); + object_unparent(OBJECT(chr)); + qemu_opts_del(opts); } static void char_mux_test(void) -- cgit v1.1 From a86c83d704c379ac54b6121def389acb49f042a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 3 Jan 2017 19:20:05 +0100 Subject: tests: add /char/pipe test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- tests/test-char.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'tests') diff --git a/tests/test-char.c b/tests/test-char.c index 2811644..2b155ff 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -1,4 +1,5 @@ #include "qemu/osdep.h" +#include #include "qemu-common.h" #include "qemu/config-file.h" @@ -7,12 +8,28 @@ #include "qapi/error.h" #include "qmp-commands.h" +static bool quit; + typedef struct FeHandler { int read_count; int last_event; char read_buf[128]; } FeHandler; +#ifndef _WIN32 +static void main_loop(void) +{ + bool nonblocking; + int last_io = 0; + + quit = false; + do { + nonblocking = last_io > 0; + last_io = main_loop_wait(nonblocking); + } while (!quit); +} +#endif + static int fe_can_read(void *opaque) { FeHandler *h = opaque; @@ -28,6 +45,7 @@ static void fe_read(void *opaque, const uint8_t *buf, int size) memcpy(h->read_buf + h->read_count, buf, size); h->read_count += size; + quit = true; } static void fe_event(void *opaque, int event) @@ -35,6 +53,7 @@ static void fe_event(void *opaque, int event) FeHandler *h = opaque; h->last_event = event; + quit = true; } #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS @@ -192,6 +211,72 @@ static void char_mux_test(void) object_unparent(OBJECT(chr)); } +#ifndef _WIN32 +static void char_pipe_test(void) +{ + gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL); + gchar *tmp, *in, *out, *pipe = g_build_filename(tmp_path, "pipe", NULL); + Chardev *chr; + CharBackend be; + int ret, fd; + char buf[10]; + FeHandler fe = { 0, }; + + in = g_strdup_printf("%s.in", pipe); + if (mkfifo(in, 0600) < 0) { + abort(); + } + out = g_strdup_printf("%s.out", pipe); + if (mkfifo(out, 0600) < 0) { + abort(); + } + + tmp = g_strdup_printf("pipe:%s", pipe); + chr = qemu_chr_new("pipe", tmp); + g_assert_nonnull(chr); + g_free(tmp); + + qemu_chr_fe_init(&be, chr, &error_abort); + + ret = qemu_chr_fe_write(&be, (void *)"pipe-out", 9); + g_assert_cmpint(ret, ==, 9); + + fd = open(out, O_RDWR); + ret = read(fd, buf, sizeof(buf)); + g_assert_cmpint(ret, ==, 9); + g_assert_cmpstr(buf, ==, "pipe-out"); + close(fd); + + fd = open(in, O_WRONLY); + ret = write(fd, "pipe-in", 8); + g_assert_cmpint(ret, ==, 8); + close(fd); + + qemu_chr_fe_set_handlers(&be, + fe_can_read, + fe_read, + fe_event, + &fe, + NULL, true); + + main_loop(); + + g_assert_cmpint(fe.read_count, ==, 8); + g_assert_cmpstr(fe.read_buf, ==, "pipe-in"); + + qemu_chr_fe_deinit(&be); + object_unparent(OBJECT(chr)); + + g_assert(g_unlink(in) == 0); + g_assert(g_unlink(out) == 0); + g_assert(g_rmdir(tmp_path) == 0); + g_free(in); + g_free(out); + g_free(tmp_path); + g_free(pipe); +} +#endif + static void char_null_test(void) { Error *err = NULL; @@ -245,6 +330,8 @@ static void char_invalid_test(void) int main(int argc, char **argv) { + qemu_init_main_loop(&error_abort); + g_test_init(&argc, &argv, NULL); module_call_init(MODULE_INIT_QOM); @@ -258,6 +345,9 @@ int main(int argc, char **argv) g_test_add_func("/char/stdio/subprocess", char_stdio_test_subprocess); g_test_add_func("/char/stdio", char_stdio_test); #endif +#ifndef _WIN32 + g_test_add_func("/char/pipe", char_pipe_test); +#endif return g_test_run(); } -- cgit v1.1 From 9dbaa4ce58e9fad263b1dc8e88bb782f544b5a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 3 Jan 2017 19:21:39 +0100 Subject: tests: add /char/file test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- tests/test-char.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'tests') diff --git a/tests/test-char.c b/tests/test-char.c index 2b155ff..87a4e29 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -277,6 +277,76 @@ static void char_pipe_test(void) } #endif +static void char_file_test(void) +{ + char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL); + char *out = g_build_filename(tmp_path, "out", NULL); + char *contents = NULL; + ChardevFile file = { .out = out }; + ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE, + .u.file.data = &file }; + Chardev *chr; + gsize length; + int ret; + + chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &backend, + &error_abort); + ret = qemu_chr_write_all(chr, (uint8_t *)"hello!", 6); + g_assert_cmpint(ret, ==, 6); + object_unref(OBJECT(chr)); + + ret = g_file_get_contents(out, &contents, &length, NULL); + g_assert(ret == TRUE); + g_assert_cmpint(length, ==, 6); + g_assert(strncmp(contents, "hello!", 6) == 0); + g_free(contents); + +#ifndef _WIN32 + { + CharBackend be; + FeHandler fe = { 0, }; + char *fifo = g_build_filename(tmp_path, "fifo", NULL); + int fd; + + if (mkfifo(fifo, 0600) < 0) { + abort(); + } + + fd = open(fifo, O_RDWR); + ret = write(fd, "fifo-in", 8); + g_assert_cmpint(ret, ==, 8); + + file.in = fifo; + file.has_in = true; + chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &backend, + &error_abort); + + qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_set_handlers(&be, + fe_can_read, + fe_read, + fe_event, + &fe, NULL, true); + + main_loop(); + + close(fd); + + g_assert_cmpint(fe.read_count, ==, 8); + g_assert_cmpstr(fe.read_buf, ==, "fifo-in"); + qemu_chr_fe_deinit(&be); + object_unref(OBJECT(chr)); + g_unlink(fifo); + g_free(fifo); + } +#endif + + g_unlink(out); + g_rmdir(tmp_path); + g_free(tmp_path); + g_free(out); +} + static void char_null_test(void) { Error *err = NULL; @@ -348,6 +418,7 @@ int main(int argc, char **argv) #ifndef _WIN32 g_test_add_func("/char/pipe", char_pipe_test); #endif + g_test_add_func("/char/file", char_file_test); return g_test_run(); } -- cgit v1.1 From d47fb5d17c049b7add784c088f327d506097a970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 3 Jan 2017 19:22:03 +0100 Subject: tests: add /char/socket test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- tests/test-char.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/test-char.c b/tests/test-char.c index 87a4e29..9971498 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -3,9 +3,11 @@ #include "qemu-common.h" #include "qemu/config-file.h" +#include "qemu/sockets.h" #include "sysemu/char.h" #include "sysemu/sysemu.h" #include "qapi/error.h" +#include "qom/qom-qobject.h" #include "qmp-commands.h" static bool quit; @@ -16,7 +18,6 @@ typedef struct FeHandler { char read_buf[128]; } FeHandler; -#ifndef _WIN32 static void main_loop(void) { bool nonblocking; @@ -28,7 +29,6 @@ static void main_loop(void) last_io = main_loop_wait(nonblocking); } while (!quit); } -#endif static int fe_can_read(void *opaque) { @@ -211,6 +211,114 @@ static void char_mux_test(void) object_unparent(OBJECT(chr)); } +typedef struct SocketIdleData { + GMainLoop *loop; + Chardev *chr; + bool conn_expected; + CharBackend *be; + CharBackend *client_be; +} SocketIdleData; + +static gboolean char_socket_test_idle(gpointer user_data) +{ + SocketIdleData *data = user_data; + + if (object_property_get_bool(OBJECT(data->chr), "connected", NULL) + == data->conn_expected) { + quit = true; + return FALSE; + } + + return TRUE; +} + +static void socket_read(void *opaque, const uint8_t *buf, int size) +{ + SocketIdleData *data = opaque; + + g_assert_cmpint(size, ==, 1); + g_assert_cmpint(*buf, ==, 'Z'); + + size = qemu_chr_fe_write(data->be, (const uint8_t *)"hello", 5); + g_assert_cmpint(size, ==, 5); +} + +static int socket_can_read(void *opaque) +{ + return 10; +} + +static void socket_read_hello(void *opaque, const uint8_t *buf, int size) +{ + g_assert_cmpint(size, ==, 5); + g_assert(strncmp((char *)buf, "hello", 5) == 0); + + quit = true; +} + +static int socket_can_read_hello(void *opaque) +{ + return 10; +} + +static void char_socket_test(void) +{ + Chardev *chr = qemu_chr_new("server", "tcp:127.0.0.1:0,server,nowait"); + Chardev *chr_client; + QObject *addr; + QDict *qdict, *data; + const char *port; + SocketIdleData d = { .chr = chr }; + CharBackend be; + CharBackend client_be; + char *tmp; + + d.be = &be; + d.client_be = &be; + + g_assert_nonnull(chr); + g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort)); + + addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort); + qdict = qobject_to_qdict(addr); + data = qdict_get_qdict(qdict, "data"); + port = qdict_get_str(data, "port"); + tmp = g_strdup_printf("tcp:127.0.0.1:%s", port); + QDECREF(qdict); + + qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_set_handlers(&be, socket_can_read, socket_read, + NULL, &d, NULL, true); + + chr_client = qemu_chr_new("client", tmp); + qemu_chr_fe_init(&client_be, chr_client, &error_abort); + qemu_chr_fe_set_handlers(&client_be, socket_can_read_hello, + socket_read_hello, + NULL, &d, NULL, true); + g_free(tmp); + + d.conn_expected = true; + guint id = g_idle_add(char_socket_test_idle, &d); + g_source_set_name_by_id(id, "test-idle"); + g_assert_cmpint(id, >, 0); + main_loop(); + + g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort)); + g_assert(object_property_get_bool(OBJECT(chr_client), + "connected", &error_abort)); + + qemu_chr_write_all(chr_client, (const uint8_t *)"Z", 1); + main_loop(); + + object_unparent(OBJECT(chr_client)); + + d.conn_expected = false; + g_idle_add(char_socket_test_idle, &d); + main_loop(); + + object_unparent(OBJECT(chr)); +} + #ifndef _WIN32 static void char_pipe_test(void) { @@ -401,6 +509,7 @@ static void char_invalid_test(void) int main(int argc, char **argv) { qemu_init_main_loop(&error_abort); + socket_init(); g_test_init(&argc, &argv, NULL); @@ -419,6 +528,7 @@ int main(int argc, char **argv) g_test_add_func("/char/pipe", char_pipe_test); #endif g_test_add_func("/char/file", char_file_test); + g_test_add_func("/char/socket", char_socket_test); return g_test_run(); } -- cgit v1.1 From bb1490486df2ea60c57a1d72c6a779ab1652b429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 3 Jan 2017 19:22:19 +0100 Subject: tests: add /char/udp test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- tests/test-char.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'tests') diff --git a/tests/test-char.c b/tests/test-char.c index 9971498..19707bf 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -385,6 +385,51 @@ static void char_pipe_test(void) } #endif +static void char_udp_test(void) +{ + struct sockaddr_in addr = { 0, }, other; + SocketIdleData d = { 0, }; + Chardev *chr; + CharBackend be; + socklen_t alen = sizeof(addr); + int ret, sock = qemu_socket(PF_INET, SOCK_DGRAM, 0); + char buf[10]; + char *tmp; + + g_assert_cmpint(sock, >, 0); + addr.sin_family = AF_INET ; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = 0; + ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); + g_assert_cmpint(ret, ==, 0); + ret = getsockname(sock, (struct sockaddr *)&addr, &alen); + g_assert_cmpint(ret, ==, 0); + + tmp = g_strdup_printf("udp:127.0.0.1:%d", + ntohs(addr.sin_port)); + chr = qemu_chr_new("client", tmp); + g_assert_nonnull(chr); + + d.chr = chr; + qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_set_handlers(&be, socket_can_read_hello, socket_read_hello, + NULL, &d, NULL, true); + ret = qemu_chr_write_all(chr, (uint8_t *)"hello", 5); + g_assert_cmpint(ret, ==, 5); + + alen = sizeof(addr); + ret = recvfrom(sock, buf, sizeof(buf), 0, + (struct sockaddr *)&other, &alen); + g_assert_cmpint(ret, ==, 5); + ret = sendto(sock, buf, 5, 0, (struct sockaddr *)&other, alen); + g_assert_cmpint(ret, ==, 5); + + main_loop(); + + close(sock); + g_free(tmp); +} + static void char_file_test(void) { char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL); @@ -529,6 +574,7 @@ int main(int argc, char **argv) #endif g_test_add_func("/char/file", char_file_test); g_test_add_func("/char/socket", char_socket_test); + g_test_add_func("/char/udp", char_udp_test); return g_test_run(); } -- cgit v1.1 From 79c8db5a13c0f4b73f930be0fcff9bbc1237c258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 3 Jan 2017 19:55:55 +0100 Subject: tests: add /char/console test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- tests/test-char.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/test-char.c b/tests/test-char.c index 19707bf..773a1c3 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -57,6 +57,32 @@ static void fe_event(void *opaque, int event) } #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS +#ifdef _WIN32 +static void char_console_test_subprocess(void) +{ + QemuOpts *opts; + Chardev *chr; + + opts = qemu_opts_create(qemu_find_opts("chardev"), "console-label", + 1, &error_abort); + qemu_opt_set(opts, "backend", "console", &error_abort); + + chr = qemu_chr_new_from_opts(opts, NULL); + g_assert_nonnull(chr); + + qemu_chr_write_all(chr, (const uint8_t *)"CONSOLE", 7); + + qemu_opts_del(opts); + object_unparent(OBJECT(chr)); +} + +static void char_console_test(void) +{ + g_test_trap_subprocess("/char/console/subprocess", 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stdout("CONSOLE"); +} +#endif static void char_stdio_test_subprocess(void) { Chardev *chr; @@ -83,7 +109,6 @@ static void char_stdio_test(void) } #endif - static void char_ringbuf_test(void) { QemuOpts *opts; @@ -566,6 +591,10 @@ int main(int argc, char **argv) g_test_add_func("/char/ringbuf", char_ringbuf_test); g_test_add_func("/char/mux", char_mux_test); #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS +#ifdef _WIN32 + g_test_add_func("/char/console/subprocess", char_console_test_subprocess); + g_test_add_func("/char/console", char_console_test); +#endif g_test_add_func("/char/stdio/subprocess", char_stdio_test_subprocess); g_test_add_func("/char/stdio", char_stdio_test); #endif -- cgit v1.1