> > 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> Acked-by: Frediano Ziglio <fziglio@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(); > } _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel