aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--tests/Makefile.am8
-rw-r--r--tests/stream/stream_test.c309
-rw-r--r--tests/stream/stream_test.err43
-rw-r--r--tests/stream/stream_test.ok51
-rw-r--r--tests/testsuite.at7
6 files changed, 418 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 672708d..e2f2fb9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,3 +56,4 @@ Doxyfile
jibuf_test
jibuf_tool
osmux_test2
+stream_test
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 03a7a3c..c3628ac 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,7 +1,7 @@
AM_CFLAGS = -Wall -I$(top_srcdir)/include $(LIBOSMOCORE_CFLAGS) -g
AM_LDFLAGS = $(LIBOSMOCORE_LDFLAGS)
-check_PROGRAMS = osmux/osmux_test osmux/osmux_test2 jibuf/jibuf_test
+check_PROGRAMS = osmux/osmux_test osmux/osmux_test2 stream/stream_test jibuf/jibuf_test
check_HEADERS =
osmux_osmux_test_SOURCES = osmux/osmux_test.c
@@ -10,6 +10,10 @@ osmux_osmux_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(top_builddir)/
osmux_osmux_test2_SOURCES = osmux/osmux_test2.c
osmux_osmux_test2_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(top_builddir)/src/libosmonetif.la
+stream_stream_test_SOURCES = stream/stream_test.c
+stream_stream_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(top_builddir)/src/libosmonetif.la
+stream_stream_test_LDFLAGS = -no-install
+
jibuf_jibuf_test_SOURCES = jibuf/jibuf_test.c
jibuf_jibuf_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(top_builddir)/src/libosmonetif.la
@@ -57,6 +61,8 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
osmux/osmux_test.ok \
osmux/osmux_test2.ok \
+ stream/stream_test.ok \
+ stream/stream_test.err \
jibuf/jibuf_test.ok
DISTCLEANFILES = atconfig
diff --git a/tests/stream/stream_test.c b/tests/stream/stream_test.c
new file mode 100644
index 0000000..1a0c555
--- /dev/null
+++ b/tests/stream/stream_test.c
@@ -0,0 +1,309 @@
+/*
+ * (C) 2019 by sysmocom - s.f.m.c. GmbH.
+ * Author: Max Suraev
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/application.h>
+
+#include <osmocom/netif/stream.h>
+
+#define DSTREAMTEST 0
+struct log_info_cat osmo_stream_test_cat[] = {
+ [DSTREAMTEST] = {
+ .name = "DSTREAMTEST",
+ .description = "STREAM test",
+ .enabled = 1, .loglevel = LOGL_INFO,
+ },
+};
+
+const struct log_info osmo_stream_test_log_info = {
+ .filter_fn = NULL,
+ .cat = osmo_stream_test_cat,
+ .num_cat = ARRAY_SIZE(osmo_stream_test_cat),
+};
+
+static struct msgb *make_msgb(const char *m)
+{
+ struct msgb *msg = msgb_alloc(512, "STREAM test");
+ if (!msg) {
+ printf("Unable to allocate message\n");
+ return NULL;
+ }
+
+ if (m)
+ msgb_printf(msg, "%s", m);
+
+ return msg;
+}
+
+#define ASTR(rec) ((rec) ? "autoreconnecting" : "non-reconnecting")
+
+/* client defs */
+#define LOGCLI(cli, fmt, args...) \
+ printf("[%s] Client's %s(): " fmt, osmo_stream_cli_get_data(cli) ? "OK" : "NA", __func__, ##args)
+
+#define CLI_SND(cli, m) do { \
+ struct msgb *msg = make_msgb(m); \
+ LOGCLI(cli, "sent %d bytes message: %s\n", \
+ msg->len, msgb_hexdump(msg)); \
+ osmo_stream_cli_send(cli, msg); \
+ } while(0)
+
+/* client callbacks */
+static int connect_cb_cli(struct osmo_stream_cli *cli)
+{
+ void *recon = osmo_stream_cli_get_data(cli);
+ LOGCLI(cli, "callback triggered <%s>\n", recon ? "reconnected" : "initial");
+ if (recon) {
+ LOGCLI(cli, "closing connection\n");
+ osmo_stream_cli_close(cli);
+ } else
+ CLI_SND(cli, "Hi! from connect callback :-P");
+
+ return 0;
+}
+
+static int read_cb_cli(struct osmo_stream_cli *cli)
+{
+ int bytes;
+ void *cli_data = osmo_stream_cli_get_data(cli);
+ struct msgb *msg = make_msgb(NULL);
+ if (!msg)
+ return -ENOMEM;
+
+ LOGCLI(cli, "callback triggered\n");
+
+ bytes = osmo_stream_cli_recv(cli, msg);
+ if (bytes < 0) {
+ LOGCLI(cli, "unable to receive message\n");
+ return -EINVAL;
+ }
+
+ if (bytes)
+ LOGCLI(cli, "received %d(%d) bytes: %s\n", bytes, msg->len, msgb_hexdump(msg));
+ else {
+ /* N. B: normally receiving 0 bytes means that we should close the connection and re-establish it
+ but to test autoreconnection logic we ignore it in here to let the test run till completion */
+ LOGCLI(cli, "0-byte read, auto-reconnect will be triggered if enabled\n");
+ }
+
+ if (!cli_data) {
+ LOGCLI(cli, "initial read, contacting server\n");
+
+ osmo_stream_cli_set_data(cli, msg);
+ CLI_SND(cli, "Doh, responding to server :-D");
+ }
+
+ return 0;
+}
+
+/* client helpers */
+static struct osmo_stream_cli *init_client_reconnection(struct osmo_stream_cli *cli, bool autoreconnect)
+{
+ /* setting negative timeout ensures that we disable reconnection logic */
+ osmo_stream_cli_set_reconnect_timeout(cli, autoreconnect ? 9 : -1);
+
+ if (osmo_stream_cli_open(cli) < 0) {
+ LOGCLI(cli, "unable to open client\n");
+ return NULL;
+ }
+
+ return cli;
+}
+
+static struct osmo_stream_cli *make_client(void *ctx, const char *host, unsigned port, bool autoreconnect)
+{
+ struct osmo_stream_cli *cli = osmo_stream_cli_create(ctx);
+ if (!cli) {
+ printf("Unable to create client\n");
+ return NULL;
+ }
+
+ printf("Prepare %s stream client...\n", ASTR(autoreconnect));
+
+ osmo_stream_cli_set_addr(cli, host);
+ osmo_stream_cli_set_port(cli, port);
+ osmo_stream_cli_set_connect_cb(cli, connect_cb_cli);
+ osmo_stream_cli_set_read_cb(cli, read_cb_cli);
+
+ return init_client_reconnection(cli, autoreconnect);
+}
+
+/* server defs */
+#define LOGLNK(lnk, fmt, args...) \
+ printf("[%s] Server's %s(): " fmt, osmo_stream_srv_link_get_data(lnk) ? "OK" : "NA", __func__, ##args)
+
+#define LOGSRV(srv, fmt, args...) \
+ printf("[%s|%s] Server's %s(): " fmt, osmo_stream_srv_get_data(srv) ? "OK" : "NA", \
+ osmo_stream_srv_link_get_data(osmo_stream_srv_get_master(srv)) ? "OK" : "NA", __func__, ##args)
+
+#define SRV_SND(srv, m) do { \
+ struct msgb *msg = make_msgb(m); \
+ LOGSRV(srv, "sent %d bytes message: %s\n", \
+ msg->len, msgb_hexdump(msg)); \
+ osmo_stream_srv_send(srv, msg); \
+ } while(0)
+
+/* server helpers */
+static bool subsequent_read(struct osmo_stream_srv *srv)
+{
+ if (osmo_stream_srv_get_data(srv))
+ return true;
+
+ osmo_stream_srv_set_data(srv, srv);
+
+ return false;
+}
+
+static void request_test_stop(struct osmo_stream_srv *srv)
+{
+ osmo_stream_srv_link_set_data(osmo_stream_srv_get_master(srv), NULL);
+}
+
+static bool test_stop_requested(struct osmo_stream_srv_link *lnk)
+{
+ if (osmo_stream_srv_link_get_data(lnk))
+ return false;
+ return true;
+}
+
+/* server callbacks */
+int read_cb_srv(struct osmo_stream_srv *srv)
+{
+ int bytes;
+ struct msgb *msg = make_msgb(NULL);
+ if (!msg)
+ return -ENOMEM;
+
+ LOGSRV(srv, "callback triggered\n");
+
+ bytes = osmo_stream_srv_recv(srv, msg);
+ if (bytes <= 0) {
+ if (bytes < 0)
+ LOGSRV(srv, "unable to receive message: %s\n", strerror(-bytes));
+ else {
+ LOGSRV(srv, "client have already closed connection\n");
+
+ /* if client have already closed the connection,
+ than it must be subsequent (after reconnect) call */
+ request_test_stop(srv);
+ }
+ osmo_stream_srv_destroy(srv);
+ return -EINVAL;
+ } else {
+ LOGSRV(srv, "received %d(%d) bytes: %s\n", bytes, msg->len, msgb_hexdump(msg));
+ SRV_SND(srv, __func__);
+ }
+
+ msgb_free(msg);
+
+ if (subsequent_read(srv)) {
+ LOGSRV(srv, "force client disconnect on subsequent call\n");
+ osmo_stream_srv_destroy(srv);
+ } else
+ LOGSRV(srv, "keep initial client connection\n");
+
+ return 0;
+}
+
+static int close_cb_srv(struct osmo_stream_srv *ignored)
+{
+ return 0;
+}
+
+static int accept_cb_srv(struct osmo_stream_srv_link *lnk, int fd)
+{
+ struct osmo_stream_srv *srv = osmo_stream_srv_create(osmo_stream_srv_link_get_data(lnk), lnk, fd,
+ read_cb_srv, close_cb_srv, NULL);
+ if (!srv) {
+ LOGLNK(lnk, "error while creating connection\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static void test_recon(void *ctx, const char *host, unsigned port, unsigned steps, struct osmo_stream_srv_link *lnk,
+ bool autoreconnect)
+{
+ struct osmo_stream_cli *cli = make_client(ctx, host, port, autoreconnect);
+ if (!cli)
+ return;
+
+ printf("=======================================\n");
+ printf("Client/Server entering %s event loop...\n", ASTR(autoreconnect));
+ printf("=======================================\n");
+
+ osmo_stream_srv_link_set_data(lnk, ctx);
+
+ while(steps--) {
+ osmo_select_main(0);
+ fprintf(stderr, "\n%s test step %u [client %s, server %s], FD reg %u\n", ASTR(autoreconnect), steps,
+ osmo_stream_cli_get_data(cli) ? "OK" : "NA",
+ osmo_stream_srv_link_get_data(lnk) ? "OK" : "NA",
+ osmo_fd_is_registered(osmo_stream_cli_get_ofd(cli)));
+
+ if (test_stop_requested(lnk)) {
+ printf("Server requested test termination\n");
+ steps = 0;
+ }
+ }
+
+ osmo_stream_cli_destroy(cli);
+ printf("%s test complete.\n\n", ASTR(autoreconnect));
+}
+
+
+int main(void)
+{
+ struct osmo_stream_srv_link *srv;
+ char *host = "127.0.0.11";
+ unsigned port = 1111;
+ void *tall_test = talloc_named_const(NULL, 1, "osmo_stream_test");
+ msgb_talloc_ctx_init(tall_test, 0);
+ osmo_init_logging2(tall_test, &osmo_stream_test_log_info);
+ log_set_log_level(osmo_stderr_target, LOGL_INFO);
+ log_set_use_color(osmo_stderr_target, 0);
+ log_set_print_category_hex(osmo_stderr_target, 0);
+ log_set_print_filename(osmo_stderr_target, 0);
+
+ printf("Preparing stream server...\n");
+ srv = osmo_stream_srv_link_create(tall_test);
+ if (!srv) {
+ printf("Unable to create server\n");
+ return EXIT_FAILURE;
+ }
+
+ osmo_stream_srv_link_set_addr(srv, host);
+ osmo_stream_srv_link_set_port(srv, port);
+ osmo_stream_srv_link_set_accept_cb(srv, accept_cb_srv);
+
+ if (osmo_stream_srv_link_open(srv) < 0) {
+ printf("Unable to open server\n");
+ return EXIT_FAILURE;
+ }
+
+ test_recon(tall_test, host, port, 12, srv, true);
+ test_recon(tall_test, host, port, 8, srv, false);
+
+ osmo_stream_srv_link_destroy(srv);
+ printf("Stream tests completed\n");
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/stream/stream_test.err b/tests/stream/stream_test.err
new file mode 100644
index 0000000..07cc7b0
--- /dev/null
+++ b/tests/stream/stream_test.err
@@ -0,0 +1,43 @@
+
+autoreconnecting test step 11 [client NA, server OK], FD reg 1
+
+autoreconnecting test step 10 [client NA, server OK], FD reg 1
+
+autoreconnecting test step 9 [client NA, server OK], FD reg 1
+
+autoreconnecting test step 8 [client NA, server OK], FD reg 1
+
+autoreconnecting test step 7 [client OK, server OK], FD reg 1
+
+autoreconnecting test step 6 [client OK, server OK], FD reg 1
+
+autoreconnecting test step 5 [client OK, server OK], FD reg 1
+[ CONNECTED] osmo_stream_cli_recv(): connection closed with srv
+[ NONE] osmo_stream_cli_reconnect(): retrying in 9 seconds...
+
+autoreconnecting test step 4 [client OK, server OK], FD reg 0
+
+autoreconnecting test step 3 [client OK, server OK], FD reg 1
+
+autoreconnecting test step 2 [client OK, server OK], FD reg 0
+connection closed with srv
+
+autoreconnecting test step 1 [client OK, server NA], FD reg 0
+
+non-reconnecting test step 7 [client NA, server OK], FD reg 1
+
+non-reconnecting test step 6 [client NA, server OK], FD reg 1
+
+non-reconnecting test step 5 [client NA, server OK], FD reg 1
+
+non-reconnecting test step 4 [client NA, server OK], FD reg 1
+
+non-reconnecting test step 3 [client OK, server OK], FD reg 1
+
+non-reconnecting test step 2 [client OK, server OK], FD reg 1
+
+non-reconnecting test step 1 [client OK, server OK], FD reg 1
+[ CONNECTED] osmo_stream_cli_recv(): connection closed with srv
+[ NONE] osmo_stream_cli_reconnect(): not reconnecting, disabled.
+
+non-reconnecting test step 0 [client OK, server OK], FD reg 0
diff --git a/tests/stream/stream_test.ok b/tests/stream/stream_test.ok
new file mode 100644
index 0000000..7b6fb95
--- /dev/null
+++ b/tests/stream/stream_test.ok
@@ -0,0 +1,51 @@
+Preparing stream server...
+Prepare autoreconnecting stream client...
+=======================================
+Client/Server entering autoreconnecting event loop...
+=======================================
+[NA] Client's connect_cb_cli(): callback triggered <initial>
+[NA] Client's connect_cb_cli(): sent 29 bytes message: 48 69 21 20 66 72 6f 6d 20 63 6f 6e 6e 65 63 74 20 63 61 6c 6c 62 61 63 6b 20 3a 2d 50
+[NA|OK] Server's read_cb_srv(): callback triggered
+[NA|OK] Server's read_cb_srv(): received 29(29) bytes: 48 69 21 20 66 72 6f 6d 20 63 6f 6e 6e 65 63 74 20 63 61 6c 6c 62 61 63 6b 20 3a 2d 50
+[NA|OK] Server's read_cb_srv(): sent 11 bytes message: 72 65 61 64 5f 63 62 5f 73 72 76
+[OK|OK] Server's read_cb_srv(): keep initial client connection
+[NA] Client's read_cb_cli(): callback triggered
+[NA] Client's read_cb_cli(): received 11(11) bytes: 72 65 61 64 5f 63 62 5f 73 72 76
+[NA] Client's read_cb_cli(): initial read, contacting server
+[OK] Client's read_cb_cli(): sent 29 bytes message: 44 6f 68 2c 20 72 65 73 70 6f 6e 64 69 6e 67 20 74 6f 20 73 65 72 76 65 72 20 3a 2d 44
+[OK|OK] Server's read_cb_srv(): callback triggered
+[OK|OK] Server's read_cb_srv(): received 29(29) bytes: 44 6f 68 2c 20 72 65 73 70 6f 6e 64 69 6e 67 20 74 6f 20 73 65 72 76 65 72 20 3a 2d 44
+[OK|OK] Server's read_cb_srv(): sent 11 bytes message: 72 65 61 64 5f 63 62 5f 73 72 76
+[OK|OK] Server's read_cb_srv(): force client disconnect on subsequent call
+[OK] Client's read_cb_cli(): callback triggered
+[OK] Client's read_cb_cli(): 0-byte read, auto-reconnect will be triggered if enabled
+[OK] Client's connect_cb_cli(): callback triggered <reconnected>
+[OK] Client's connect_cb_cli(): closing connection
+[NA|OK] Server's read_cb_srv(): callback triggered
+[NA|OK] Server's read_cb_srv(): client have already closed connection
+Server requested test termination
+autoreconnecting test complete.
+
+Prepare non-reconnecting stream client...
+=======================================
+Client/Server entering non-reconnecting event loop...
+=======================================
+[NA] Client's connect_cb_cli(): callback triggered <initial>
+[NA] Client's connect_cb_cli(): sent 29 bytes message: 48 69 21 20 66 72 6f 6d 20 63 6f 6e 6e 65 63 74 20 63 61 6c 6c 62 61 63 6b 20 3a 2d 50
+[NA|OK] Server's read_cb_srv(): callback triggered
+[NA|OK] Server's read_cb_srv(): received 29(29) bytes: 48 69 21 20 66 72 6f 6d 20 63 6f 6e 6e 65 63 74 20 63 61 6c 6c 62 61 63 6b 20 3a 2d 50
+[NA|OK] Server's read_cb_srv(): sent 11 bytes message: 72 65 61 64 5f 63 62 5f 73 72 76
+[OK|OK] Server's read_cb_srv(): keep initial client connection
+[NA] Client's read_cb_cli(): callback triggered
+[NA] Client's read_cb_cli(): received 11(11) bytes: 72 65 61 64 5f 63 62 5f 73 72 76
+[NA] Client's read_cb_cli(): initial read, contacting server
+[OK] Client's read_cb_cli(): sent 29 bytes message: 44 6f 68 2c 20 72 65 73 70 6f 6e 64 69 6e 67 20 74 6f 20 73 65 72 76 65 72 20 3a 2d 44
+[OK|OK] Server's read_cb_srv(): callback triggered
+[OK|OK] Server's read_cb_srv(): received 29(29) bytes: 44 6f 68 2c 20 72 65 73 70 6f 6e 64 69 6e 67 20 74 6f 20 73 65 72 76 65 72 20 3a 2d 44
+[OK|OK] Server's read_cb_srv(): sent 11 bytes message: 72 65 61 64 5f 63 62 5f 73 72 76
+[OK|OK] Server's read_cb_srv(): force client disconnect on subsequent call
+[OK] Client's read_cb_cli(): callback triggered
+[OK] Client's read_cb_cli(): 0-byte read, auto-reconnect will be triggered if enabled
+non-reconnecting test complete.
+
+Stream tests completed
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 67b91c6..8eb389d 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -1,6 +1,13 @@
AT_INIT
AT_BANNER([Regression tests.])
+AT_SETUP([stream_test])
+AT_KEYWORDS([stream_test])
+cat $abs_srcdir/stream/stream_test.ok > expout
+cat $abs_srcdir/stream/stream_test.err > experr
+AT_CHECK([$abs_top_builddir/tests/stream/stream_test], [0], [expout], [experr])
+AT_CLEANUP
+
AT_SETUP([osmux_test])
AT_KEYWORDS([osmux_test])
cat $abs_srcdir/osmux/osmux_test.ok > expout