[libsoup/autobahn-test-client] tests: add a autobahn test client




commit 7d2f39695bf9bd4a502d24a8a58197750ce60a15
Author: Claudio Saavedra <csaavedra igalia com>
Date:   Wed Oct 28 17:07:04 2020 +0200

    tests: add a autobahn test client
    
    Autobahn is a WebSockets test suite that allows us to test libsoup's
    implementation. With the files added it should be possible to start
    running WebSocket tests in the CI in gitlab, but it will probably
    still need some further work to integrate it nicely.
    
    autobahn-server.sh will start a docker container that runs the
    Autobahn fuzzing server. It uses fuzzingserver.json for the server
    settings.
    
    soup-autobahn-test-client is a simple client that can run Autobahn
    tests by connecting to said server.

 tests/autobahn/autobahn-server.sh          |  14 ++
 tests/autobahn/fuzzingserver.json          |   8 ++
 tests/autobahn/meson.build                 |   6 +
 tests/autobahn/soup-autobahn-test-client.c | 216 +++++++++++++++++++++++++++++
 4 files changed, 244 insertions(+)
---
diff --git a/tests/autobahn/autobahn-server.sh b/tests/autobahn/autobahn-server.sh
new file mode 100755
index 00000000..b634a767
--- /dev/null
+++ b/tests/autobahn/autobahn-server.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+REPORTS_DIR="${PWD}/reports"
+
+cd "$(dirname "$0")"
+
+[ ! -d "${REPORTS_DIR}" ] && mkdir "${REPORTS_DIR}"
+
+docker run -it --rm \
+       -v "${PWD}:/config" \
+       -v "${REPORTS_DIR}:/reports" \
+       -p 9001:9001 \
+       --name fuzzingserver \
+       crossbario/autobahn-testsuite
diff --git a/tests/autobahn/fuzzingserver.json b/tests/autobahn/fuzzingserver.json
new file mode 100644
index 00000000..4b7fe3bd
--- /dev/null
+++ b/tests/autobahn/fuzzingserver.json
@@ -0,0 +1,8 @@
+{
+    "url": "ws://127.0.0.1:9001",
+    "outdir": "./reports/clients",
+    "cases": ["*"],
+    "exclude-cases": [],
+    "exclude-agent-cases": {}
+}
+
diff --git a/tests/autobahn/meson.build b/tests/autobahn/meson.build
new file mode 100644
index 00000000..20370b0b
--- /dev/null
+++ b/tests/autobahn/meson.build
@@ -0,0 +1,6 @@
+deps = [
+  glib_deps,
+  libsoup_dep
+]
+
+executable('soup-autobahn-test-client', 'soup-autobahn-test-client.c', dependencies: deps)
diff --git a/tests/autobahn/soup-autobahn-test-client.c b/tests/autobahn/soup-autobahn-test-client.c
new file mode 100644
index 00000000..4aa0c58b
--- /dev/null
+++ b/tests/autobahn/soup-autobahn-test-client.c
@@ -0,0 +1,216 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ */
+
+#include <stdio.h>
+#include <libsoup/soup.h>
+
+GMainLoop *loop;
+static char *address = "ws://localhost:9001";
+static char *agent = "libsoup";
+static unsigned int total_num_cases = 0;
+gboolean running_tests = FALSE;
+
+typedef void (*ConnectionFunc) (SoupWebsocketConnection *socket_connection,
+                                gint type,
+                                GBytes *message,
+                                gpointer data);
+
+typedef struct {
+    ConnectionFunc method;
+    gpointer data;
+} ConnectionContext;
+
+static void run_case (SoupSession *session, const unsigned int test_case);
+
+static gboolean option_run_all = FALSE;
+static int option_run_test = -1;
+static gboolean option_number_of_tests = FALSE;
+static gboolean option_update_report = FALSE;
+static gboolean option_debug = FALSE;
+
+static GOptionEntry entries[] =
+{
+    { "run-all",         'a', 0, G_OPTION_ARG_NONE, &option_run_all,         "Run all tests", NULL },
+    { "test",            't', 0, G_OPTION_ARG_INT,  &option_run_test,        "Run TEST only", "TEST" },
+    { "number-of-tests", 'n', 0, G_OPTION_ARG_NONE, &option_number_of_tests, "Queries the Autobahn server 
for the number of test cases", NULL },
+    { "update-report",   'r', 0, G_OPTION_ARG_NONE, &option_update_report,   "Requests the Autobahn server 
to update the report for tests", NULL },
+    { "debug",           'd', 0, G_OPTION_ARG_NONE, &option_debug,           "Enables extra debug output", 
NULL },
+    { NULL }
+};
+
+static void
+on_message_received (SoupWebsocketConnection *socket_connection,
+                     gint type, GBytes *message,
+                     gpointer data)
+{
+    ConnectionContext *ctx = (ConnectionContext*) data;
+
+    if (option_debug)
+        fprintf (stderr, "<- ");
+
+    if (ctx && ctx->method)
+        ctx->method (socket_connection, type, message, ctx->data);
+}
+
+static void
+on_connection_closed (SoupWebsocketConnection *socket_connection,
+                      gpointer data)
+{
+    ConnectionContext *ctx = (ConnectionContext*) data;
+
+    if (option_debug)
+        fprintf (stderr, "\nConnection closed\n");
+
+    if (running_tests)
+        fprintf (stderr, " DONE\n");
+
+    g_free (ctx);
+
+    g_object_unref (socket_connection);
+    g_main_loop_quit (loop);
+}
+
+static void
+on_connect (GObject *session,
+            GAsyncResult *res,
+            gpointer ctx)
+{
+    SoupWebsocketConnection *socket_connection = soup_session_websocket_connect_finish 
(SOUP_SESSION(session), res, NULL);
+    if (!socket_connection) {
+        g_free (ctx);
+        return;
+    }
+
+    /* The performance tests increase the size of the payload up to 16 MB, let's disable
+       the limit to see what happens. */
+    soup_websocket_connection_set_max_incoming_payload_size (socket_connection, 0);
+
+    g_signal_connect (socket_connection, "message", G_CALLBACK(on_message_received), ctx);
+    g_signal_connect (socket_connection, "closed", G_CALLBACK(on_connection_closed), ctx);
+}
+
+static void
+connect_and_run (SoupSession *session, char *path, ConnectionFunc method, gpointer data)
+{
+    char *uri = g_strconcat (address, path, NULL);
+    SoupMessage *message = soup_message_new (SOUP_METHOD_GET, uri);
+    ConnectionContext *ctx  = g_new0 (ConnectionContext, 1);
+
+    ctx->method = method;
+    ctx->data = data;
+
+    if (option_debug)
+        fprintf (stderr, "About to connect to %s\n", uri);
+    soup_session_websocket_connect_async (session, message, NULL, NULL, NULL, on_connect, ctx);
+
+    g_object_unref (message);
+    g_free (uri);
+
+    g_main_loop_run (loop);
+}
+
+static void
+test_case_message_received (SoupWebsocketConnection *socket_connection,
+                            gint type,
+                            GBytes *message,
+                            gpointer data)
+{
+    /* Cannot send messages if we're not in an open state. */
+    if (soup_websocket_connection_get_state (socket_connection) != SOUP_WEBSOCKET_STATE_OPEN)
+        return;
+
+    if (option_debug)
+        fprintf (stderr, "-> ");
+
+    soup_websocket_connection_send_message (socket_connection, type, message);
+}
+
+static void
+run_case (SoupSession *session, const unsigned int test_case)
+{
+    char *path = g_strdup_printf ("/runCase?case=%u&agent=%s", test_case, agent);
+
+    running_tests = TRUE;
+    fprintf (stderr, "Running test case %u:", test_case);
+    connect_and_run (session, path, test_case_message_received, GUINT_TO_POINTER (test_case));
+    g_free (path);
+}
+
+static void
+run_all_cases (SoupSession *session)
+{
+    int i;
+    for (i = 0; i < total_num_cases; i++)
+        run_case (session, i + 1);
+}
+
+static void
+got_case_count (SoupWebsocketConnection *socket_connection,
+                gint type,
+                GBytes *message,
+                gpointer data)
+{
+    total_num_cases = g_ascii_strtoull (g_bytes_get_data (message, NULL), NULL, 10);
+
+    fprintf (stderr, "Total number of cases: %u\n", total_num_cases);
+}
+
+static void
+get_case_count (SoupSession *session)
+{
+    connect_and_run (session, "/getCaseCount", got_case_count, NULL);
+}
+
+static void
+update_reports (SoupSession *session)
+{
+    char *path = g_strdup_printf ("/updateReports?agent=%s", agent);
+    fprintf (stderr, "Updating reports..\n");
+    connect_and_run (session, path, NULL, NULL);
+    g_free (path);
+}
+
+int main (int argc, char* argv[])
+{
+    GOptionContext *context;
+    GError *error = NULL;
+    SoupSession *session;
+
+    context = g_option_context_new ("- libsoup test runner for Autobahn WebSocket client tests.");
+    g_option_context_add_main_entries (context, entries, NULL);
+
+    if (!g_option_context_parse (context, &argc, &argv, &error)) {
+        g_warning ("Option parsing failed: %s\n", error->message);
+        g_error_free (error);
+        g_option_context_free (context);
+        exit (1);
+    }
+    g_option_context_free (context);
+
+    if (option_run_test >= 0 || option_number_of_tests)
+        option_run_all = FALSE;
+
+    session = soup_session_new ();
+    soup_session_add_feature_by_type (session, SOUP_TYPE_WEBSOCKET_EXTENSION_MANAGER);
+    loop = g_main_loop_new (g_main_context_default (), FALSE);
+
+    if (!(option_run_all || option_number_of_tests || option_update_report || option_run_test > 0))
+        option_run_all = TRUE;
+
+    if (option_run_all || option_number_of_tests)
+        get_case_count (session);
+
+    if (option_run_test >= 0)
+        run_case (session, option_run_test);
+    else if (option_run_all)
+        run_all_cases (session);
+
+    if (option_update_report)
+        update_reports (session);
+
+    g_object_unref (session);
+
+    return 0;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]