[PATCH] ctdb-test: Add tests to verify queue processing

swen swen at linux.ibm.com
Thu Mar 7 12:03:15 UTC 2019


Followed Christof's good example and created a test verifying
the correct processing of CTDB's queue buffer.

Please review and push if happy.

Thanks for your support in advance.

Cheers Swen
-------------- next part --------------
From 0819b09e6e261464c787e6ef0d5775bb27461b9a Mon Sep 17 00:00:00 2001
From: Swen Schillig <swen at linux.ibm.com>
Date: Thu, 7 Mar 2019 12:51:49 +0100
Subject: [PATCH] ctdb-test: Add tests to verify queue processing

Adding two more test to verify CTDB's queue buffer processing.
The first test verifies that a move of the already read data
is only performed if required, here, to make some room to read in
the remaining packet data.
The second test verifes that the appropriate re-sizing of the
buffer is performed depending on the packet size.
This includes the re-sizing to standard size.

Signed-off-by: Swen Schillig <swen at linux.ibm.com>
---
 ctdb/tests/src/ctdb_queue_processing_test.c | 221 ++++++++++++++++++++
 ctdb/wscript                                |   4 +
 2 files changed, 225 insertions(+)
 create mode 100644 ctdb/tests/src/ctdb_queue_processing_test.c

diff --git a/ctdb/tests/src/ctdb_queue_processing_test.c b/ctdb/tests/src/ctdb_queue_processing_test.c
new file mode 100644
index 00000000000..746cae5afd5
--- /dev/null
+++ b/ctdb/tests/src/ctdb_queue_processing_test.c
@@ -0,0 +1,221 @@
+/*
+   ctdb queue processing tests
+
+   Copyright (C) Swen Schillig 2019
+
+   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 <assert.h>
+
+#include "common/ctdb_io.c"
+
+void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       assert(false);
+}
+
+static struct ctdb_queue *test_init(ctdb_queue_cb_fn_t cb, int *fd)
+{
+	struct ctdb_context *ctdb;
+	struct ctdb_queue *queue;
+	int tmp_fd[2];
+	int ret;
+
+	ret = pipe(tmp_fd);
+	assert(ret == 0);
+
+	ctdb = talloc_zero(NULL, struct ctdb_context);
+	assert(ctdb != NULL);
+
+	ctdb->ev = tevent_context_init(NULL);
+
+	queue = ctdb_queue_setup(ctdb, ctdb, tmp_fd[0], 0, cb, NULL, "tq_1");
+	assert(queue != NULL);
+
+	*fd = tmp_fd[1];
+	return queue;
+}
+
+static void test_cb(uint8_t *data, size_t length, void *private_data)
+{
+	/* dummy handler, not verifying anything */
+	TALLOC_FREE(data);
+}
+
+static void test1(void)
+{
+	struct ctdb_queue *queue;
+	uint32_t pkt_size;
+	char *request;
+	size_t req_len;
+	int fd;
+	int ret;
+
+	queue = test_init(test_cb, &fd);
+	request = talloc_zero_size(queue, queue->buffer_size);
+
+	/*
+	 * calculate a request length which will fit into the buffer
+	 * but not twice. Because we need to write the size integer
+	 * as well (4-bytes) we're guaranteed that no 2 packets will fit.
+	 */
+	req_len = queue->buffer_size >> 1;
+
+	/* writing first packet */
+	pkt_size = sizeof(uint32_t) + req_len;
+
+	ret = write(fd, &pkt_size, sizeof(pkt_size));
+	assert(ret == sizeof(pkt_size));
+
+	ret = write(fd, request, req_len);
+	assert(ret == req_len);
+
+	/* writing second, incomplete packet */
+	pkt_size = sizeof(uint32_t) + req_len;
+
+	ret = write(fd, &pkt_size, sizeof(pkt_size));
+	assert(ret == sizeof(pkt_size));
+
+	ret = write(fd, request, req_len >> 1);
+	assert(ret == req_len >> 1);
+
+	/* process...only 1st packet can be processed */
+	tevent_loop_once(queue->ctdb->ev);
+
+	/* we should see a progressed offset of req_len + sizeof(pkt_size) */
+	assert(queue->buffer.offset == req_len + sizeof(pkt_size));
+
+	/* writing another few bytes of the still incomplete packet */
+	ret = write(fd, request, (req_len >> 1) - 1);
+	assert(ret == (req_len >> 1) - 1);
+
+	/*
+	 * the packet is still incomplete and connot be processed
+	 * but the packet data had to be moved in the buffer in order
+	 * to fetch the new 199 bytes -> offset must be 0 now.
+	 */
+	tevent_loop_once(queue->ctdb->ev);
+	/*
+	 * needs to be called twice as an incomplete packet
+	 * does not trigger a schedule_immediate
+	 */
+	tevent_loop_once(queue->ctdb->ev);
+
+	assert(queue->buffer.offset == 0);
+
+	TALLOC_FREE(queue->ctdb);
+}
+
+static void test2(void)
+{
+	struct ctdb_queue *queue;
+	uint32_t pkt_size;
+	char *request;
+	size_t req_len;
+	int fd;
+	int ret;
+
+	queue = test_init(test_cb, &fd);
+
+	req_len = queue->buffer_size << 1; /* double the buffer size */
+	request = talloc_zero_size(queue, req_len);
+
+	/* writing first part of packet exceeding standard buffer size */
+	pkt_size = sizeof(uint32_t) + req_len;
+
+	ret = write(fd, &pkt_size, sizeof(pkt_size));
+	assert(ret == sizeof(pkt_size));
+
+	ret = write(fd, request, req_len - (queue->buffer_size >> 1));
+	assert(ret == req_len - (queue->buffer_size >> 1));
+
+	/*
+	 * process...
+	 * this needs to be done to have things changed
+	 */
+	tevent_loop_once(queue->ctdb->ev);
+	/*
+	 * needs to be called twice as an initial incomplete packet
+	 * does not trigger a schedule_immediate
+	 */
+	tevent_loop_once(queue->ctdb->ev);
+
+	/* the buffer should be resized to packet size now */
+	assert(queue->buffer.size == pkt_size);
+
+	/* writing remaining data */
+	ret = write(fd, request, queue->buffer_size >> 1);
+	assert(ret == (queue->buffer_size >> 1));
+
+	/* process... */
+	tevent_loop_once(queue->ctdb->ev);
+
+	/*
+	 * the buffer was increased beyond its standard size.
+	 * once packet got processed, the buffer has to be free'd
+	 * and will be re-allocated with standard size on new request arrival.
+	 */
+
+	assert(queue->buffer.size == 0);
+
+	/* writing new packet to verify standard buffer size */
+	pkt_size = sizeof(uint32_t) + (queue->buffer_size >> 1);
+
+	ret = write(fd, &pkt_size, sizeof(pkt_size));
+	assert(ret == sizeof(pkt_size));
+
+	ret = write(fd, request, (queue->buffer_size >> 1));
+	assert(ret == (queue->buffer_size >> 1));
+
+	/* process... */
+	tevent_loop_once(queue->ctdb->ev);
+
+	/* back to standard buffer size */
+	assert(queue->buffer.size == queue->buffer_size);
+
+	TALLOC_FREE(queue->ctdb);
+}
+
+int main(int argc, const char **argv)
+{
+	int num;
+
+	if (argc != 2) {
+		fprintf(stderr, "%s <testnum>\n", argv[0]);
+		exit(1);
+	}
+
+	num = atoi(argv[1]);
+	switch (num) {
+	case 1:
+		test1();
+		break;
+
+	case 2:
+		test2();
+		break;
+
+	default:
+		fprintf(stderr, "Unknown test number %s\n", argv[1]);
+	}
+
+	return 0;
+}
diff --git a/ctdb/wscript b/ctdb/wscript
index c2f1956a916..75809def8dc 100644
--- a/ctdb/wscript
+++ b/ctdb/wscript
@@ -948,6 +948,10 @@ def build(bld):
                      deps='''talloc tevent tdb samba-util sys_rw''',
                      install_path='${CTDB_TEST_LIBEXECDIR}')
 
+    bld.SAMBA_BINARY('ctdb_queue_processing_test',
+                     source='tests/src/ctdb_queue_processing_test.c',
+                     deps='''talloc tevent tdb samba-util sys_rw''',
+                     install_path='${CTDB_TEST_LIBEXECDIR}')
 
     bld.SAMBA_SUBSYSTEM('ctdb-protocol-tests-basic',
                         source=bld.SUBDIR('tests/src',
-- 
2.20.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20190307/0895a0e1/signature.sig>


More information about the samba-technical mailing list