[PATCH 6/8] membuf: Add some tests

Simon Glass sjg at chromium.org
Fri Oct 18 05:00:25 CEST 2024


Add tests for the membuf implementation.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 test/lib/Makefile |   1 +
 test/lib/membuf.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 240 insertions(+)
 create mode 100644 test/lib/membuf.c

diff --git a/test/lib/Makefile b/test/lib/Makefile
index a54387a058e..014cd42efe1 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -12,6 +12,7 @@ obj-y += hexdump.o
 obj-$(CONFIG_SANDBOX) += kconfig.o
 obj-y += lmb.o
 obj-y += longjmp.o
+obj-$(CONFIG_SANDBOX) += membuf.o
 obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
 obj-$(CONFIG_SSCANF) += sscanf.o
 obj-y += string.o
diff --git a/test/lib/membuf.c b/test/lib/membuf.c
new file mode 100644
index 00000000000..3f268a422d5
--- /dev/null
+++ b/test/lib/membuf.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 Google LLC
+ * Written by Simon Glass <sjg at chromium.org>
+ */
+
+#include <membuf.h>
+#include <os.h>
+#include <rand.h>
+#include <string.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define TEST_SIZE	16
+#define TEST_COUNT	10000
+
+static void membuf_zero(struct membuf *mb)
+{
+	memset(mb->start, '\0', mb->end - mb->start);
+}
+
+static int membuf_check(struct unit_test_state *uts, struct membuf *mb,
+			int value)
+{
+	/* head is out of range */
+	ut_assert(!(mb->head < mb->start || mb->head >= mb->end));
+
+	/* tail is out of range */
+	ut_assert(!(mb->tail < mb->start || mb->tail >= mb->end));
+
+	return 0;
+}
+
+/* write from 1 to test_size bytes, and check they come back OK */
+static int lib_test_membuf_one(struct unit_test_state *uts)
+{
+	char in[TEST_SIZE * 2], out[TEST_SIZE * 2];
+	struct membuf mb;
+	int size, ret, test_size, i;
+
+	ut_assertok(membuf_new(&mb, TEST_SIZE));
+
+	/* setup in test */
+	for (i = 0; i < TEST_SIZE; i++) {
+		in[i] = (i & 63) + '0';
+		in[i + TEST_SIZE] = in[i];
+	}
+
+	test_size = TEST_SIZE;
+
+	for (i = 1; i < TEST_COUNT; i++) {
+		membuf_zero(&mb);
+		size = rand() % test_size;
+
+		// now write patterns and check they come back OK
+		ret = membuf_put(&mb, in, 0);
+		ret = membuf_put(&mb, in, size);
+		ut_asserteq(size, ret);
+
+		ret = membuf_put(&mb, in, 0);
+		ut_assertok(membuf_check(uts, &mb, i));
+
+		ret = membuf_get(&mb, out, 0);
+		ret = membuf_get(&mb, out, size);
+		ut_asserteq(size, ret);
+
+		ret = membuf_get(&mb, out, 0);
+		ut_assertok(membuf_check(uts, &mb, i));
+
+		ut_asserteq_mem(in, out, size);
+	}
+
+	return 0;
+}
+LIB_TEST(lib_test_membuf_one, 0);
+
+/* write random number of bytes, and check they come back OK */
+static int lib_test_membuf_random(struct unit_test_state *uts)
+{
+	char in[TEST_SIZE * 2];
+	char buf[TEST_SIZE * 2];
+	struct membuf mb;
+	int size, ret, test_size, i;
+	char *inptr, *outptr;
+	int max_avail, min_free;
+
+	ut_assertok(membuf_new(&mb, TEST_SIZE));
+
+	for (i = 0; i < TEST_SIZE; i++) {
+		in[i] = (i & 63) + '0';
+		in[i + TEST_SIZE] = in[i];
+	}
+
+	test_size = TEST_SIZE;
+
+	inptr = in;
+	outptr = in;
+	min_free = TEST_COUNT;
+	max_avail = 0;
+	membuf_zero(&mb);
+	for (i = 0; i < TEST_COUNT; i++) {
+		size = rand() % test_size;
+
+		if (membuf_free(&mb) < min_free)
+			min_free = membuf_free(&mb);
+
+		ret = membuf_put(&mb, inptr, size);
+		ut_assertok(membuf_check(uts, &mb, i));
+		inptr += ret;
+		if (inptr >= in + TEST_SIZE)
+			inptr -= TEST_SIZE;
+
+		size = rand() % (test_size - 1);
+
+		if (membuf_avail(&mb) > max_avail)
+			max_avail = membuf_avail(&mb);
+
+		ret = membuf_get(&mb, buf, size);
+		ut_assertok(membuf_check(uts, &mb, i));
+		ut_asserteq_mem(buf, outptr, ret);
+
+		outptr += ret;
+		if (outptr >= in + TEST_SIZE)
+			outptr -= TEST_SIZE;
+	}
+
+	return 0;
+}
+LIB_TEST(lib_test_membuf_random, 0);
+
+/* test membuf_extend() with split segments */
+static int lib_test_membuf_extend(struct unit_test_state *uts)
+{
+	char in[TEST_SIZE * 2];
+	char buf[TEST_SIZE * 2];
+	struct membuf mb;
+	int ret, test_size, i, cur;
+	char *data;
+
+	ut_assertok(membuf_new(&mb, TEST_SIZE));
+
+	for (i = 0; i < TEST_SIZE; i++) {
+		in[i] = (i & 63) + '0';
+		in[i + TEST_SIZE] = in[i];
+	}
+
+	test_size = TEST_SIZE - 1;
+
+	for (cur = 0; cur <= test_size; cur++) {
+		ut_assertok(membuf_new(&mb, TEST_SIZE));
+
+		membuf_zero(&mb);
+
+		/*
+		 * add some bytes, then remove them - this will force the membuf
+		 * to have data split into two segments when we fill it
+		 */
+		ret = membuf_putraw(&mb, TEST_SIZE / 2, true, &data);
+		membuf_getraw(&mb, ret, true, &data);
+		ut_asserteq(TEST_SIZE / 2, ret);
+
+		/* fill it */
+		ret = membuf_put(&mb, in, cur);
+		ut_assertok(membuf_check(uts, &mb, cur));
+		ut_asserteq(cur, ret);
+
+		/* extend the buffer */
+		ut_assertok(membuf_extend_by(&mb, TEST_SIZE, -1));
+		ut_assertok(membuf_check(uts, &mb, cur));
+
+		/* check our data is still there */
+		ret = membuf_get(&mb, buf, TEST_SIZE * 2);
+		ut_assertok(membuf_check(uts, &mb, cur));
+		ut_asserteq(cur, ret);
+		ut_asserteq_mem(in, buf, cur);
+		membuf_uninit(&mb);
+	}
+
+	return 0;
+}
+LIB_TEST(lib_test_membuf_extend, 0);
+
+/* test membuf_readline() with generated data */
+static int lib_test_membuf_readline(struct unit_test_state *uts)
+{
+	char *buf;
+	int size, cur, i, ret, readptr, cmpptr;
+	struct membuf mb;
+	char *data;
+	char str[256];
+	char *s;
+
+	ut_assertok(membuf_new(&mb, 1024));
+	membuf_zero(&mb);
+
+	/* Use the README as test data */
+	ut_assertok(os_read_file("README", (void **)&buf, &size));
+
+	cur = 0;
+	readptr = 0;
+	cmpptr = 0;
+	for (i = 0; i < 100000; i++, cur += 1) {
+		/* fill the buffer with up to 'cur' bytes */
+		ret = membuf_putraw(&mb, cur, false, &data);
+
+		if (ret > 0) {
+			int can_read = min(ret, size - readptr);
+
+			memcpy(data, &buf[readptr], can_read);
+			readptr += can_read;
+
+			membuf_putraw(&mb, can_read, true, &data);
+			ut_assertok(membuf_check(uts, &mb, i));
+		}
+
+		/* read a line and compare */
+		ret = membuf_readline(&mb, str, 256, 0, true);
+		ut_assertok(membuf_check(uts, &mb, i));
+		if (ret) {
+			char *ptr;
+
+			s = &buf[cmpptr];
+			ptr = strchr(s, '\n');
+			*ptr = '\0';
+
+			ut_asserteq_str(s, str);
+			cmpptr += strlen(s) + 1;
+			*ptr = '\n';
+		} else {
+			ut_assert(membuf_free(&mb));
+		}
+	}
+	membuf_dispose(&mb);
+	os_free(buf);
+
+	return 0;
+}
+LIB_TEST(lib_test_membuf_readline, 0);
-- 
2.34.1



More information about the U-Boot mailing list