diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 8 | ||||
-rw-r--r-- | tests/stream/stream_test.c | 309 | ||||
-rw-r--r-- | tests/stream/stream_test.err | 43 | ||||
-rw-r--r-- | tests/stream/stream_test.ok | 51 | ||||
-rw-r--r-- | tests/testsuite.at | 7 |
5 files changed, 417 insertions, 1 deletions
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 |