summaryrefslogtreecommitdiff
path: root/ctdb
diff options
context:
space:
mode:
authorAmitay Isaacs <amitay@gmail.com>2017-01-05 00:48:32 +1100
committerMartin Schwenke <martins@samba.org>2017-01-06 08:37:28 +0100
commit1dc1689e7402f6f90af3ddd4c7d33d140892ff2a (patch)
treeb8cff16714905321dc5d4ddf01f33dcf2a1f22bf /ctdb
parente3440d2bbc0e8f2cb09c94a1d77a60524017cfa0 (diff)
downloadsamba-1dc1689e7402f6f90af3ddd4c7d33d140892ff2a.tar.gz
ctdb-tests: Add tests for generic socket I/O
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12500 Signed-off-by: Amitay Isaacs <amitay@gmail.com> Reviewed-by: Martin Schwenke <martin@meltin.net>
Diffstat (limited to 'ctdb')
-rwxr-xr-xctdb/tests/cunit/sock_io_test_001.sh9
-rw-r--r--ctdb/tests/src/sock_io_test.c283
-rw-r--r--ctdb/wscript1
3 files changed, 293 insertions, 0 deletions
diff --git a/ctdb/tests/cunit/sock_io_test_001.sh b/ctdb/tests/cunit/sock_io_test_001.sh
new file mode 100755
index 00000000000..1ead2f37508
--- /dev/null
+++ b/ctdb/tests/cunit/sock_io_test_001.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+. "${TEST_SCRIPTS_DIR}/unit.sh"
+
+sockpath="${TEST_VAR_DIR}/sock_daemon_test.sock.$$"
+
+ok_null
+
+unit_test sock_io_test "$sockpath"
diff --git a/ctdb/tests/src/sock_io_test.c b/ctdb/tests/src/sock_io_test.c
new file mode 100644
index 00000000000..d0048c18220
--- /dev/null
+++ b/ctdb/tests/src/sock_io_test.c
@@ -0,0 +1,283 @@
+/*
+ sock I/O tests
+
+ Copyright (C) Amitay Isaacs 2017
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/network.h"
+#include "system/wait.h"
+
+#include <assert.h>
+
+#include "common/sock_io.c"
+
+static int socket_init(const char *sockpath)
+{
+ struct sockaddr_un addr;
+ int fd, ret;
+ size_t len;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+
+ len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
+ assert(len < sizeof(addr.sun_path));
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ assert(fd != -1);
+
+ ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+ assert(ret != -1);
+
+ ret = listen(fd, 10);
+ assert(ret != -1);
+
+ return fd;
+}
+
+static void test1_writer(int fd)
+{
+ uint8_t buf[1024];
+ ssize_t nwritten;
+ uint32_t len;
+
+ for (len = 10; len < 1000; len += 10) {
+ int value = len / 10;
+ uint32_t buflen = len + sizeof(uint32_t);
+
+ memset(buf, value, buflen);
+ memcpy(buf, &buflen, sizeof(uint32_t));
+
+ nwritten = sys_write(fd, buf, buflen);
+ assert(nwritten == buflen);
+ }
+}
+
+struct test1_reader_state {
+ size_t pkt_len;
+ bool done;
+};
+
+static void test1_reader(uint8_t *buf, size_t buflen, void *private_data)
+{
+ struct test1_reader_state *state =
+ (struct test1_reader_state *)private_data;
+
+ if (buflen == 0) {
+ state->done = true;
+ return;
+ }
+
+ assert(buflen == state->pkt_len);
+
+ state->pkt_len += 10;
+}
+
+static void test1(TALLOC_CTX *mem_ctx, const char *sockpath)
+{
+ struct test1_reader_state state;
+ struct tevent_context *ev;
+ struct sock_queue *queue;
+ pid_t pid;
+ int pfd[2], fd, ret;
+ ssize_t n;
+
+ ret = pipe(pfd);
+ assert(ret == 0);
+
+ pid = fork();
+ assert(pid != -1);
+
+ if (pid == 0) {
+ int newfd;
+
+ close(pfd[0]);
+
+ fd = socket_init(sockpath);
+ assert(fd != -1);
+
+ ret = 1;
+ n = sys_write(pfd[1], &ret, sizeof(int));
+ assert(n == sizeof(int));
+
+ newfd = accept(fd, NULL, NULL);
+ assert(newfd != -1);
+
+ test1_writer(newfd);
+ close(newfd);
+ unlink(sockpath);
+
+ exit(0);
+ }
+
+ close(pfd[1]);
+
+ n = sys_read(pfd[0], &ret, sizeof(int));
+ assert(n == sizeof(int));
+ assert(ret == 1);
+
+ close(pfd[0]);
+
+ fd = sock_connect(sockpath);
+ assert(fd != -1);
+
+ ev = tevent_context_init(mem_ctx);
+ assert(ev != NULL);
+
+ state.pkt_len = 10 + sizeof(uint32_t);
+ state.done = false;
+
+ queue = sock_queue_setup(mem_ctx, ev, fd, test1_reader, &state);
+ assert(queue != NULL);
+
+ while (! state.done) {
+ tevent_loop_once(ev);
+ }
+
+ talloc_free(queue);
+ talloc_free(ev);
+
+ pid = wait(&ret);
+ assert(pid != -1);
+}
+
+static void test2_reader(int fd)
+{
+ uint8_t buf[1024];
+ size_t pkt_len = 10 + sizeof(uint32_t);
+ ssize_t n;
+
+ while (1) {
+ n = sys_read(fd, buf, 1024);
+ assert(n != -1);
+
+ if (n == 0) {
+ return;
+ }
+
+ assert(n == pkt_len);
+ pkt_len += 10;
+ }
+}
+
+static void test2_dummy_reader(uint8_t *buf, size_t buflen,
+ void *private_data)
+{
+ assert(buflen == -1);
+}
+
+static void test2_writer(struct sock_queue *queue)
+{
+ uint8_t buf[1024];
+ uint32_t len;
+ int ret;
+
+ for (len = 10; len < 1000; len += 10) {
+ int value = len / 10;
+ uint32_t buflen = len + sizeof(uint32_t);
+
+ memset(buf, value, buflen);
+ memcpy(buf, &buflen, sizeof(uint32_t));
+
+ ret = sock_queue_write(queue, buf, buflen);
+ assert(ret == 0);
+ }
+}
+
+static void test2(TALLOC_CTX *mem_ctx, const char *sockpath)
+{
+ struct tevent_context *ev;
+ struct sock_queue *queue;
+ pid_t pid;
+ int pfd[2], fd, ret;
+ ssize_t n;
+
+ ret = pipe(pfd);
+ assert(ret == 0);
+
+ pid = fork();
+ assert(pid != -1);
+
+ if (pid == 0) {
+ int newfd;
+
+ close(pfd[0]);
+
+ fd = socket_init(sockpath);
+ assert(fd != -1);
+
+ ret = 1;
+ n = sys_write(pfd[1], &ret, sizeof(int));
+ assert(n == sizeof(int));
+
+ newfd = accept(fd, NULL, NULL);
+ assert(newfd != -1);
+
+ test2_reader(newfd);
+ close(newfd);
+ unlink(sockpath);
+
+ exit(0);
+ }
+
+ close(pfd[1]);
+
+ n = sys_read(pfd[0], &ret, sizeof(int));
+ assert(n == sizeof(int));
+ assert(ret == 1);
+
+ close(pfd[0]);
+
+ fd = sock_connect(sockpath);
+ assert(fd != -1);
+
+ ev = tevent_context_init(mem_ctx);
+ assert(ev != NULL);
+
+ queue = sock_queue_setup(mem_ctx, ev, fd, test2_dummy_reader, NULL);
+ assert(queue != NULL);
+
+ test2_writer(queue);
+
+ talloc_free(queue);
+ talloc_free(ev);
+
+ pid = wait(&ret);
+ assert(pid != -1);
+}
+
+int main(int argc, const char **argv)
+{
+ TALLOC_CTX *mem_ctx;
+ const char *sockpath;
+
+ if (argc != 2) {
+ fprintf(stderr, "%s <sockpath>\n", argv[0]);
+ exit(1);
+ }
+
+ sockpath = argv[1];
+
+ mem_ctx = talloc_new(NULL);
+ assert(mem_ctx != NULL);
+
+ test1(mem_ctx, sockpath);
+ test2(mem_ctx, sockpath);
+
+ return 0;
+}
diff --git a/ctdb/wscript b/ctdb/wscript
index b951dd69f6c..4bd7d6692c9 100644
--- a/ctdb/wscript
+++ b/ctdb/wscript
@@ -736,6 +736,7 @@ def build(bld):
'pidfile_test',
'run_proc_test',
'sock_daemon_test',
+ 'sock_io_test',
]
for target in ctdb_unit_tests: