[Spice-devel] [spice-server 4/8] test-listen: Add test case port/address configuration
Christophe Fergeau
cfergeau at redhat.com
Tue Mar 6 13:53:18 UTC 2018
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, ...
---
server/tests/Makefile.am | 1 +
server/tests/test-listen.c | 146 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 147 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..052dc0b8f
--- /dev/null
+++ b/server/tests/test-listen.c
@@ -0,0 +1,146 @@
+/* -*- 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>
+
+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 GThread *fake_client_new(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", check_magic_thread, 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, 5701);
+ result = spice_server_init(server, core);
+ g_assert_cmpint(result, ==, 0);
+
+ /* fake client */
+ thread = fake_client_new("localhost", 5701);
+
+ 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);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/server/listen/connect_plain", test_connect_plain);
+
+ return g_test_run();
+}
--
2.14.3
More information about the Spice-devel
mailing list