This test case will be testing the external spice-server API to configure the address/port it's listening on. For now it sets up a listening server, spawns a thread which is going to connect to that port, and check it gets the REDQ magic upon connection. It will be extended to test for Unix sockets, TLS sockets, ... Signed-off-by: Christophe Fergeau <cfergeau@xxxxxxxxxx> --- server/tests/Makefile.am | 1 + server/tests/test-listen.c | 191 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 server/tests/test-listen.c diff --git a/server/tests/Makefile.am b/server/tests/Makefile.am index 2ff06d7a5..0aae1fd61 100644 --- a/server/tests/Makefile.am +++ b/server/tests/Makefile.am @@ -59,6 +59,7 @@ check_PROGRAMS = \ test-empty-success \ test-channel \ test-stream-device \ + test-listen \ $(NULL) noinst_PROGRAMS = \ diff --git a/server/tests/test-listen.c b/server/tests/test-listen.c new file mode 100644 index 000000000..ee0073cce --- /dev/null +++ b/server/tests/test-listen.c @@ -0,0 +1,191 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2018 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +/* + * This tests the external API entry points to configure the address/port + * spice-server is listening on + */ +#include <config.h> + +#include "basic-event-loop.h" + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> +#include <gio/gio.h> + +/* Arbitrary base port, we want a port which is not in use by the system, and + * by another of our tests (in case of parallel runs) + */ +#define BASE_PORT 5728 + +static SpiceCoreInterface *core; + +static bool error_is_set(GError **error) +{ + return ((error != NULL) && (*error != NULL)); +} + +static GIOStream *fake_client_connect(GSocketConnectable *connectable, GError **error) +{ + GSocketClient *client; + GSocketConnection *connection; + + client = g_socket_client_new(); + connection = g_socket_client_connect(client, connectable, NULL, error); + + g_object_unref(client); + + return G_IO_STREAM(connection); +} + +static void check_magic(GIOStream *io_stream, GError **error) +{ + uint8_t buffer[4]; + gsize bytes_read; + gsize bytes_written; + GInputStream *input_stream; + GOutputStream *output_stream; + + /* send dummy data to trigger a response from the server */ + output_stream = g_io_stream_get_output_stream(io_stream); + memset(buffer, 0xa5, G_N_ELEMENTS(buffer)); + g_output_stream_write_all(output_stream, buffer, G_N_ELEMENTS(buffer), &bytes_written, NULL, error); + if (error_is_set(error)) { + return; + } + + input_stream = g_io_stream_get_input_stream(io_stream); + g_input_stream_read_all(input_stream, buffer, G_N_ELEMENTS(buffer), &bytes_read, NULL, error); + if (error_is_set(error)) { + return; + } + g_assert_cmpuint(bytes_read, ==, G_N_ELEMENTS(buffer)); + g_assert_cmpint(memcmp(buffer, "REDQ", 4), ==, 0); +} + +static void exit_mainloop_cb(SPICE_GNUC_UNUSED void *opaque) +{ + basic_event_loop_quit(); +} + +static gpointer check_magic_thread(gpointer data) +{ + GError *error = NULL; + GSocketConnectable *connectable = G_SOCKET_CONNECTABLE(data); + GIOStream *stream; + SpiceTimer *exit_mainloop_timer; + + stream = fake_client_connect(connectable, &error); + g_assert_no_error(error); + check_magic(stream, &error); + g_assert_no_error(error); + + g_object_unref(stream); + g_object_unref(connectable); + exit_mainloop_timer = core->timer_add(exit_mainloop_cb, NULL); + core->timer_start(exit_mainloop_timer, 0); + + return NULL; +} + +static gpointer check_no_connect_thread(gpointer data) +{ + GError *error = NULL; + GSocketConnectable *connectable = G_SOCKET_CONNECTABLE(data); + GIOStream *stream; + SpiceTimer *exit_mainloop_timer; + + stream = fake_client_connect(connectable, &error); + g_assert(error != NULL); + g_assert(stream == NULL); + g_clear_error(&error); + + g_object_unref(connectable); + exit_mainloop_timer = core->timer_add(exit_mainloop_cb, NULL); + core->timer_start(exit_mainloop_timer, 0); + + return NULL; +} + + +static GThread *fake_client_new(GThreadFunc thread_func, const char *hostname, int port) +{ + GSocketConnectable *connectable; + + g_assert_cmpuint(port, >, 0); + g_assert_cmpuint(port, <, 65536); + connectable = g_network_address_new(hostname, port); + + /* check_magic_thread will assume ownership of 'connectable' */ + return g_thread_new("fake-client-thread", thread_func, connectable); +} + +static void test_connect_plain(void) +{ + GThread *thread; + int result; + + /* server */ + SpiceServer *server = spice_server_new(); + core = basic_event_loop_init(); + spice_server_set_name(server, "SPICE listen test"); + spice_server_set_noauth(server); + spice_server_set_port(server, BASE_PORT); + result = spice_server_init(server, core); + g_assert_cmpint(result, ==, 0); + + /* fake client */ + thread = fake_client_new(check_magic_thread, "localhost", BASE_PORT); + + basic_event_loop_mainloop(); + + g_assert_null(g_thread_join(thread)); + + g_thread_unref(thread); + basic_event_loop_destroy(); + core = NULL; + spice_server_destroy(server); +} + +static void test_connect_ko(void) +{ + GThread *thread; + + core = basic_event_loop_init(); + + /* fake client */ + thread = fake_client_new(check_no_connect_thread, "localhost", BASE_PORT); + + basic_event_loop_mainloop(); + + g_assert_null(g_thread_join(thread)); + + g_thread_unref(thread); + basic_event_loop_destroy(); + core = NULL; +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/server/listen/connect_plain", test_connect_plain); + g_test_add_func("/server/listen/connect_ko", test_connect_ko); + + return g_test_run(); +} -- 2.14.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel