This switches the test to using the GTest API, and add several tests related to https://bugzilla.redhat.com/show_bug.cgi?id=1411194 This uses some API not available in glib 2.28, so this checks we have a new enough glib before building this test, and disables warnings when using too new glib API when building it. The "multiple-vmc-devices" is based off code written by Frediano Ziglio. Signed-off-by: Christophe Fergeau <cfergeau@xxxxxxxxxx> --- server/tests/Makefile.am | 10 ++- server/tests/test-vdagent.c | 173 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 166 insertions(+), 17 deletions(-) diff --git a/server/tests/Makefile.am b/server/tests/Makefile.am index af0bd20..816546c 100644 --- a/server/tests/Makefile.am +++ b/server/tests/Makefile.am @@ -45,6 +45,7 @@ check_PROGRAMS = \ test-loop \ test-qxl-parsing \ test-stat-file \ + test-vdagent \ $(NULL) noinst_PROGRAMS = \ @@ -56,7 +57,6 @@ noinst_PROGRAMS = \ test-playback \ test-display-resolution-changes \ test-two-servers \ - test-vdagent \ test-display-width-stride \ spice-server-replay \ $(check_PROGRAMS) \ @@ -112,6 +112,14 @@ libtest_stat4_a_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_COMPRESS_STAT=1 -DTEST_RED_WORK test_qxl_parsing_LDADD = ../libserver.la $(LDADD) +# Fallback implementations are provided for older glibs for the recent glib +# methods this test is using, so no need to warn about them +test_vdagent_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -UGLIB_VERSION_MIN_REQUIRED \ + -UGLIB_VERSION_MAX_ALLOWED \ + $(NULL) + if HAVE_GSTREAMER test_gst_SOURCES = test-gst.c \ $(NULL) diff --git a/server/tests/test-vdagent.c b/server/tests/test-vdagent.c index e06229e..a4d48ee 100644 --- a/server/tests/test-vdagent.c +++ b/server/tests/test-vdagent.c @@ -37,14 +37,98 @@ int ping_ms = 100; #define MIN(a, b) ((a) > (b) ? (b) : (a)) #endif -static void pinger(SPICE_GNUC_UNUSED void *opaque) +#if !GLIB_CHECK_VERSION(2, 34, 0) + +/* The code in this #ifdef block is taken from glib and is licensed under the + * GNU Lesser General Public License version 2 or later. + * + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * Modified by the GLib Team and others 1997-2000. See GLib AUTHORS + * file for a list of people on the GLib Team. + */ + +typedef struct { + gchar *log_domain; + GLogLevelFlags log_level; + gchar *pattern; +} GTestExpectedMessage; + +static GSList *expected_messages = NULL; + +static gboolean fatal_log_filter(const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *msg, + gpointer user_data) +{ + GTestExpectedMessage *expected = expected_messages->data; + + if ((g_strcmp0(expected->log_domain, log_domain) == 0) + && ((log_level & expected->log_level) == expected->log_level) + && (g_pattern_match_simple(expected->pattern, msg))) { + expected_messages = g_slist_delete_link(expected_messages, + expected_messages); + g_free (expected->log_domain); + g_free (expected->pattern); + g_free (expected); + + return FALSE; + } + return TRUE; +} + +static void +g_test_assert_expected_messages_internal (const char *domain, + const char *file, + int line, + const char *func) +{ + if (expected_messages) + { + GTestExpectedMessage *expected; + gchar *message; + + expected = expected_messages->data; + + message = g_strdup_printf ("Did not see expected message %s: %s", + expected->log_domain ? expected->log_domain : "**", + expected->pattern); + g_error ("%s", message); + g_free (message); + } +} + +#define g_test_assert_expected_messages() g_test_assert_expected_messages_internal (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC) + +static void +g_test_expect_message (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *pattern) { - // show_channels is not thread safe - fails if disconnections / connections occur - //show_channels(server); + GTestExpectedMessage *expected; - core->timer_start(ping_timer, ping_ms); + g_return_if_fail (log_level != 0); + g_return_if_fail (pattern != NULL); + g_return_if_fail (~log_level & G_LOG_LEVEL_ERROR); + + if (expected_messages == NULL) + { + g_test_log_set_fatal_handler(fatal_log_filter, NULL); + } + + expected = g_new (GTestExpectedMessage, 1); + expected->log_domain = g_strdup (log_domain); + expected->log_level = log_level; + expected->pattern = g_strdup (pattern); + + if ((log_level & G_LOG_LEVEL_MASK) <= G_LOG_LEVEL_WARNING) + { + expected_messages = g_slist_append (expected_messages, expected); + } } +#endif /* GLIB_CHECK_VERSION(2, 34, 0) */ + + static int vmc_write(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, SPICE_GNUC_UNUSED const uint8_t *buf, int len) @@ -62,6 +146,13 @@ static int vmc_read(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, static unsigned message_size; int ret; + if (pos == sizeof(message)) { + g_message("sent whole message"); + pos++; /* Only print message once */ + } + if (pos > sizeof(message)) { + return 0; + } if (pos == 0) { VDIChunkHeader *hdr = (VDIChunkHeader *)message; VDAgentMessage *msg = (VDAgentMessage *)&hdr[1]; @@ -83,9 +174,6 @@ static int vmc_read(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, ret = MIN(message_size - pos, len); memcpy(buf, &message[pos], ret); pos += ret; - if (pos == message_size) { - pos = 0; - } //printf("vmc_read %d (ret %d)\n", len, ret); return ret; } @@ -105,24 +193,77 @@ static SpiceCharDeviceInterface vmc_interface = { .read = vmc_read, }; -SpiceCharDeviceInstance vmc_instance = { +static SpiceCharDeviceInstance vmc_instance = { .subtype = "vdagent", }; -int main(void) +static void test_multiple_vmc_devices(void) { - Test *test; + SpiceCharDeviceInstance vmc_instances[2] = { + { .subtype = "vdagent", }, + { .subtype = "vdagent", } + }; + int status; - core = basic_event_loop_init(); - test = test_new(core); + SpiceCoreInterface *core = basic_event_loop_init(); + Test *test = test_new(core); + g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, + "*spice_server_char_device_add_interface: vdagent already attached"); + g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*spice_server_remove_interface: assertion ?char_device->st != NULL'*"); + vmc_instances[0].base.sif = &vmc_interface.base; + spice_server_add_interface(test->server, &vmc_instances[0].base); + vmc_instances[1].base.sif = &vmc_interface.base; + spice_server_add_interface(test->server, &vmc_instances[1].base); + status = spice_server_remove_interface(&vmc_instances[1].base); + g_assert_cmpint(status, ==, -1); + status = spice_server_remove_interface(&vmc_instances[0].base); + g_assert_cmpint(status, ==, 0); + g_test_assert_expected_messages(); + test_destroy(test); + basic_event_loop_destroy(); +} + +static void test_duplicate_removal(void) +{ + SpiceCoreInterface *core = basic_event_loop_init(); + Test *test = test_new(core); + int status; + + g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*spice_server_remove_interface: assertion ?char_device->st != NULL'*"); + vmc_instance.base.sif = &vmc_interface.base; + spice_server_add_interface(test->server, &vmc_instance.base); + status = spice_server_remove_interface(&vmc_instance.base); + g_assert_cmpint(status, ==, 0); + status = spice_server_remove_interface(&vmc_instance.base); + g_assert_cmpint(status, ==, -1); + g_test_assert_expected_messages(); + test_destroy(test); + basic_event_loop_destroy(); +} + +static void test_agent_to_server(void) +{ + SpiceCoreInterface *core = basic_event_loop_init(); + Test *test = test_new(core); + + g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, "sent whole message"); vmc_instance.base.sif = &vmc_interface.base; spice_server_add_interface(test->server, &vmc_instance.base); + g_test_assert_expected_messages(); + test_destroy(test); + basic_event_loop_destroy(); +} - ping_timer = core->timer_add(pinger, NULL); - core->timer_start(ping_timer, ping_ms); +int main(int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); - basic_event_loop_mainloop(); + g_test_add_func("/server/vdagent/agent-to-server", test_agent_to_server); + g_test_add_func("/server/vdagent/duplicate-removal", test_duplicate_removal); + g_test_add_func("/server/vdagent/multiple-vmc-devices", test_multiple_vmc_devices); - return 0; + return g_test_run(); } -- 2.9.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel