Skip to contentSkip to conversation

test: Add compression tests to pytest

PATCH New Simon Glass 3 participants 13 messages Nov 25, 2017 – Dec 4, 2017

lore
Share & tools
lore
#0 lore raw

cover test: Add compression tests to pytest

At present the compression tests do not use the unit test framework, nor are they executed by the 'make tests' command. This series converts these tests to use the unit test framework, adding a few other minor improvements along the way.

The overlay tests do not currently run for me, and we lack instructions on how to run them.

./b/sandbox/u-boot -c "ut overlay"

did not work:

Running 9 overlay tests
Test: fdt_overlay_add_node_by_path
Segmentation fault (core dumped)

It would be useful to have instructions for how to run these somewhere, along with a README for the feature. The tests should run with 'make tests'.

Simon Glass (5):
test: Add a command function for test execution
test: overlay: Use cmd_ut_category()
test: compression: Put test variables in a struct test/py: Allow any unit test suite to be found
test: compression: Convert to unit test framework

 include/test/compression.h    |  17 +++
 include/test/suites.h         |  17 +++
 test/cmd_ut.c                 |  32 +++++
 test/compression.c            | 295 ++++++++++++++++++++++++++----------------
 test/env/cmd_ut_env.c         |  19 +--
 test/overlay/cmd_ut_overlay.c |  21 +--
 test/py/conftest.py           |   2 +-
 7 files changed, 251 insertions(+), 152 deletions(-)
 create mode 100644 include/test/compression.h
Signature · 1 line
2.15.0.417.g466bffb3ac-goog
#1 lore raw

PATCH 1/5 test: Add a command function for test execution

The logic to either iterate through a list of tests or pick a named test is common to at lest two test suits. Move this logic into a new function and call it from the environment tests.

---

 include/test/suites.h | 16 ++++++++++++++++
 test/cmd_ut.c         | 25 +++++++++++++++++++++++++
 test/env/cmd_ut_env.c | 19 +------------------
 3 files changed, 42 insertions(+), 18 deletions(-)
include/test/suites.h +16 -0
index 0e94feb07a7..6b900a8f594 100644
@@ -8,6 +8,22 @@
 #ifndef __TEST_SUITES_H__
 #define __TEST_SUITES_H__
 
+struct unit_test;
+
+/**
+ * cmd_ut_category() - Run a category of unit tests
+ *
+ * @name:	Category name
+ * @tests:	List of tests to run
+ * @n_ents:	Number of tests in @tests
+ * @argc:	Argument count provided. Must be <= 1. If this is 1 then all
+ *		tests are run, otherwise only the one named @argv[1] is run.
+ * @argv:	Arguments: argv[1] is the test to run (if @argc >= 2)
+ * @return 0 if OK, CMD_RET_FAILURE on failure
+ */
+int cmd_ut_category(const char *name, struct unit_test *tests, int n_ents,
+		    int argc, char * const argv[]);
+
 int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
test/cmd_ut.c +25 -0
index 14333423a17..d860dd72f0b 100644
@@ -8,9 +8,34 @@
 #include <common.h>
 #include <command.h>
 #include <test/suites.h>
+#include <test/test.h>
 
 static int do_ut_all(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 
+int cmd_ut_category(const char *name, struct unit_test *tests, int n_ents,
+		    int argc, char * const argv[])
+{
+	struct unit_test_state uts = { .fail_count = 0 };
+	struct unit_test *test;
+
+	if (argc == 1)
+		printf("Running %d %s tests\n", n_ents, name);
+
+	for (test = tests; test < tests + n_ents; test++) {
+		if (argc > 1 && strcmp(argv[1], test->name))
+			continue;
+		printf("Test: %s\n", test->name);
+
+		uts.start = mallinfo();
+
+		test->func(&uts);
+	}
+
+	printf("Failures: %d\n", uts.fail_count);
+
+	return uts.fail_count ? CMD_RET_FAILURE : 0;
+}
+
 static cmd_tbl_t cmd_ut_sub[] = {
 	U_BOOT_CMD_MKENT(all, CONFIG_SYS_MAXARGS, 1, do_ut_all, "", ""),
 #if defined(CONFIG_UT_DM)
test/env/cmd_ut_env.c +1 -18
index 893e5e6a6d6..096afa83dde 100644
@@ -15,23 +15,6 @@ int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	struct unit_test *tests = ll_entry_start(struct unit_test, env_test);
 	const int n_ents = ll_entry_count(struct unit_test, env_test);
-	struct unit_test_state uts = { .fail_count = 0 };
-	struct unit_test *test;
 
-	if (argc == 1)
-		printf("Running %d environment tests\n", n_ents);
-
-	for (test = tests; test < tests + n_ents; test++) {
-		if (argc > 1 && strcmp(argv[1], test->name))
-			continue;
-		printf("Test: %s\n", test->name);
-
-		uts.start = mallinfo();
-
-		test->func(&uts);
-	}
-
-	printf("Failures: %d\n", uts.fail_count);
-
-	return uts.fail_count ? CMD_RET_FAILURE : 0;
+	return cmd_ut_category("environment", tests, n_ents, argc, argv);
 }
Signature · 1 line
2.15.0.417.g466bffb3ac-goog
#2 lore raw

PATCH 1/5 test: Add a command function for test execution

Quoted 5 lines · Simon Glass

The logic to either iterate through a list of tests or pick a named test is common to at lest two test suits. Move this logic into a new function and call it from the environment tests.

Applied to u-boot/master, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20171204/cef73217/attachment.sig>
#3 lore raw

PATCH 2/5 test: overlay: Use cmd_ut_category()

In reply to Simon Glass

Adjust the code to use the common test-execution function.

---

 test/overlay/cmd_ut_overlay.c | 21 ++-------------------
 1 file changed, 2 insertions(+), 19 deletions(-)
test/overlay/cmd_ut_overlay.c +2 -19
index c730a11f518..6279e6d0c20 100644
@@ -14,6 +14,7 @@
 
 #include <test/ut.h>
 #include <test/overlay.h>
+#include <test/suites.h>
 
 /* 4k ought to be enough for anybody */
 #define FDT_COPY_SIZE	(4 * SZ_1K)
@@ -221,7 +222,6 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 						 overlay_test);
 	const int n_ents = ll_entry_count(struct unit_test, overlay_test);
 	struct unit_test_state *uts;
-	struct unit_test *test;
 	void *fdt_base = &__dtb_test_fdt_base_begin;
 	void *fdt_overlay = &__dtb_test_fdt_overlay_begin;
 	void *fdt_overlay_stacked = &__dtb_test_fdt_overlay_stacked_begin;
@@ -280,24 +280,7 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	/* Apply the stacked overlay */
 	ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_stacked_copy));
 
-	if (argc == 1)
-		printf("Running %d environment tests\n", n_ents);
-
-	for (test = tests; test < tests + n_ents; test++) {
-		if (argc > 1 && strcmp(argv[1], test->name))
-			continue;
-		printf("Test: %s\n", test->name);
-
-		uts->start = mallinfo();
-
-		test->func(uts);
-	}
-
-	printf("Failures: %d\n", uts->fail_count);
-	if (!uts->fail_count)
-		ret = 0;
-	else
-		ret = CMD_RET_FAILURE;
+	ret = cmd_ut_category("overlay", tests, n_ents, argc, argv);
 
 	free(fdt_overlay_stacked_copy);
 err3:
Signature · 1 line
2.15.0.417.g466bffb3ac-goog
#4 lore raw

PATCH 2/5 test: overlay: Use cmd_ut_category()

Quoted 3 lines · Simon Glass

Adjust the code to use the common test-execution function.

Applied to u-boot/master, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20171204/4514ddef/attachment.sig>
#5 lore raw

PATCH 2/5 test: overlay: Use cmd_ut_category()

In reply to Simon Glass
Quoted 3 lines · Simon Glass

Adjust the code to use the common test-execution function.

Applied to u-boot/master, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20171204/6424b31c/attachment.sig>
#6 lore raw

PATCH 3/5 test: compression: Put test variables in a struct

In reply to Simon Glass

At present the test setup is somewhat mixed with the test itself. But if the test setup fails (which it should not) then the test is actually invalid. Put all the test buffers and sizes in a struct and separate out the core code into a function.

This will make it easier to move the code to use the unit test framework.

---

 test/compression.c | 128 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 74 insertions(+), 54 deletions(-)
test/compression.c +74 -54
index be4e04e6cc0..82eed846a94 100644
@@ -288,85 +288,105 @@ static int uncompress_using_lz4(void *in, unsigned long in_size,
 	goto out; \
 }
 
-static int run_test(char *name, mutate_func compress, mutate_func uncompress)
-{
-	ulong orig_size, compressed_size, uncompressed_size;
+struct buf_state {
+	ulong orig_size;
+	ulong compressed_size;
+	ulong uncompressed_size;
 	void *orig_buf;
-	void *compressed_buf = NULL;
-	void *uncompressed_buf = NULL;
-	void *compare_buf = NULL;
+	void *compressed_buf;
+	void *uncompressed_buf;
+	void *compare_buf;
+};
+
+static int run_test_internal(char *name,
+			     mutate_func compress, mutate_func uncompress,
+			     struct buf_state *buf)
+{
 	int ret;
 
-	printf(" testing %s ...\n", name);
-
-	orig_buf = (void *)plain;
-	orig_size = strlen(orig_buf); /* Trailing NULL not included. */
-	errcheck(orig_size > 0);
-
-	compressed_size = uncompressed_size = TEST_BUFFER_SIZE;
-	compressed_buf = malloc(compressed_size);
-	errcheck(compressed_buf != NULL);
-	uncompressed_buf = malloc(uncompressed_size);
-	errcheck(uncompressed_buf != NULL);
-	compare_buf = malloc(uncompressed_size);
-	errcheck(compare_buf != NULL);
-
 	/* Compress works as expected. */
-	printf("\torig_size:%lu\n", orig_size);
-	memset(compressed_buf, 'A', TEST_BUFFER_SIZE);
-	errcheck(compress(orig_buf, orig_size,
-			compressed_buf, compressed_size,
-			&compressed_size) == 0);
-	printf("\tcompressed_size:%lu\n", compressed_size);
-	errcheck(compressed_size > 0);
-	errcheck(compressed_size < orig_size);
-	errcheck(((char *)compressed_buf)[compressed_size-1] != 'A');
-	errcheck(((char *)compressed_buf)[compressed_size] == 'A');
+	printf("\torig_size:%lu\n", buf->orig_size);
+	memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
+	errcheck(compress(buf->orig_buf, buf->orig_size, buf->compressed_buf,
+			  buf->compressed_size, &buf->compressed_size) == 0);
+	printf("\tcompressed_size:%lu\n", buf->compressed_size);
+	errcheck(buf->compressed_size > 0);
+	errcheck(buf->compressed_size < buf->orig_size);
+	errcheck(((char *)buf->compressed_buf)[buf->compressed_size - 1] !=
+			'A');
+	errcheck(((char *)buf->compressed_buf)[buf->compressed_size] == 'A');
 
 	/* Uncompresses with space remaining. */
-	errcheck(uncompress(compressed_buf, compressed_size,
-			  uncompressed_buf, uncompressed_size,
-			  &uncompressed_size) == 0);
-	printf("\tuncompressed_size:%lu\n", uncompressed_size);
-	errcheck(uncompressed_size == orig_size);
-	errcheck(memcmp(orig_buf, uncompressed_buf, orig_size) == 0);
+	errcheck(uncompress(buf->compressed_buf, buf->compressed_size,
+			    buf->uncompressed_buf, buf->uncompressed_size,
+			    &buf->uncompressed_size) == 0);
+	printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
+	errcheck(buf->uncompressed_size == buf->orig_size);
+	errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
+			buf->orig_size) == 0);
 
 	/* Uncompresses with exactly the right size output buffer. */
-	memset(uncompressed_buf, 'A', TEST_BUFFER_SIZE);
-	errcheck(uncompress(compressed_buf, compressed_size,
-			  uncompressed_buf, orig_size,
-			  &uncompressed_size) == 0);
-	errcheck(uncompressed_size == orig_size);
-	errcheck(memcmp(orig_buf, uncompressed_buf, orig_size) == 0);
-	errcheck(((char *)uncompressed_buf)[orig_size] == 'A');
+	memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
+	errcheck(uncompress(buf->compressed_buf, buf->compressed_size,
+			    buf->uncompressed_buf, buf->orig_size,
+			    &buf->uncompressed_size) == 0);
+	errcheck(buf->uncompressed_size == buf->orig_size);
+	errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
+			buf->orig_size) == 0);
+	errcheck(((char *)buf->uncompressed_buf)[buf->orig_size] == 'A');
 
 	/* Make sure compression does not over-run. */
-	memset(compare_buf, 'A', TEST_BUFFER_SIZE);
-	ret = compress(orig_buf, orig_size,
-		       compare_buf, compressed_size - 1,
+	memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
+	ret = compress(buf->orig_buf, buf->orig_size,
+		       buf->compare_buf, buf->compressed_size - 1,
 		       NULL);
-	errcheck(((char *)compare_buf)[compressed_size] == 'A');
+	errcheck(((char *)buf->compare_buf)[buf->compressed_size] == 'A');
 	errcheck(ret != 0);
 	printf("\tcompress does not overrun\n");
 
 	/* Make sure decompression does not over-run. */
-	memset(compare_buf, 'A', TEST_BUFFER_SIZE);
-	ret = uncompress(compressed_buf, compressed_size,
-			 compare_buf, uncompressed_size - 1,
+	memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
+	ret = uncompress(buf->compressed_buf, buf->compressed_size,
+			 buf->compare_buf, buf->uncompressed_size - 1,
 			 NULL);
-	errcheck(((char *)compare_buf)[uncompressed_size - 1] == 'A');
+	errcheck(((char *)buf->compare_buf)[buf->uncompressed_size - 1] == 'A');
 	errcheck(ret != 0);
 	printf("\tuncompress does not overrun\n");
 
 	/* Got here, everything is fine. */
 	ret = 0;
 
+out:
+	return ret;
+}
+
+static int run_test(char *name, mutate_func compress, mutate_func uncompress)
+{
+	struct buf_state sbuf, *buf = &sbuf;
+	int ret;
+
+	printf(" testing %s ...\n", name);
+
+	buf->orig_buf = (void *)plain;
+	buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
+	errcheck(buf->orig_size > 0);
+
+	buf->compressed_size = TEST_BUFFER_SIZE;
+	buf->uncompressed_size = TEST_BUFFER_SIZE;
+	buf->compressed_buf = malloc(buf->compressed_size);
+	errcheck(buf->compressed_buf);
+	buf->uncompressed_buf = malloc(buf->uncompressed_size);
+	errcheck(buf->uncompressed_buf);
+	buf->compare_buf = malloc(buf->uncompressed_size);
+	errcheck(buf->compare_buf);
+
+	ret = run_test_internal(name, compress, uncompress, buf);
 out:
 	printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
 
-	free(compare_buf);
-	free(uncompressed_buf);
-	free(compressed_buf);
+	free(buf->compare_buf);
+	free(buf->uncompressed_buf);
+	free(buf->compressed_buf);
 
 	return ret;
 }
Signature · 1 line
2.15.0.417.g466bffb3ac-goog
#7 lore raw

PATCH 3/5 test: compression: Put test variables in a struct

Quoted 8 lines · Simon Glass

At present the test setup is somewhat mixed with the test itself. But if the test setup fails (which it should not) then the test is actually invalid. Put all the test buffers and sizes in a struct and separate out the core code into a function.

This will make it easier to move the code to use the unit test framework.

Applied to u-boot/master, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20171204/f395a819/attachment.sig>
#8 lore raw

PATCH 4/5 test/py: Allow any unit test suite to be found

In reply to Simon Glass

The u-boot.sym file is scanned to find unit test suites for execution. At present it only finds those whose names start with 'dm' or 'env'. This code is buried in the bowels of the test code so when adding a new suite it is not easy to discover why it is ignored by the test framework.

There seems to be no need to make this restriction. Drop it.

---

 test/py/conftest.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
test/py/conftest.py +1 -1
index 6e66a48c15f..3fe91e87460 100644
@@ -200,7 +200,7 @@ def pytest_configure(config):
         import u_boot_console_exec_attach
         console = u_boot_console_exec_attach.ConsoleExecAttach(log, ubconfig)
 
-re_ut_test_list = re.compile(r'_u_boot_list_2_(dm|env)_test_2_\1_test_(.*)\s*$')
+re_ut_test_list = re.compile(r'_u_boot_list_2_(.*)_test_2_\1_test_(.*)\s*$')
 def generate_ut_subtest(metafunc, fixture_name):
     """Provide parametrization for a ut_subtest fixture.
 
Signature · 1 line
2.15.0.417.g466bffb3ac-goog
#9 lore raw

PATCH 4/5 test/py: Allow any unit test suite to be found

Quoted 6 lines · Simon Glass

The u-boot.sym file is scanned to find unit test suites for execution. At present it only finds those whose names start with 'dm' or 'env'. This code is buried in the bowels of the test code so when adding a new suite it is not easy to discover why it is ignored by the test framework.

There seems to be no need to make this restriction. Drop it.

test/py/conftest.py def pytest_configure(config): · line 203

Quoted 4 lines
test/py/conftest.py +1 -1
 
-re_ut_test_list = re.compile(r'_u_boot_list_2_(dm|env)_test_2_\1_test_(.*)\s*$')
+re_ut_test_list = re.compile(r'_u_boot_list_2_(.*)_test_2_\1_test_(.*)\s*$')

I think I made this regex restrictive to avoid accidentally matching lists (symbols) with "test" in the name that weren't known unit tests. Or maybe there were some unit tests that didn't work yet when I wrote it? If we're confident that won't happen, this change seems fine. If we do have a problem in the future, I guess we could just rename the symbol to s/test/unit_test/ or something to make matching more explicit.

#10 lore raw

PATCH 4/5 test/py: Allow any unit test suite to be found

In reply to Simon Glass
Quoted 9 lines · Simon Glass

The u-boot.sym file is scanned to find unit test suites for execution. At present it only finds those whose names start with 'dm' or 'env'. This code is buried in the bowels of the test code so when adding a new suite it is not easy to discover why it is ignored by the test framework.

There seems to be no need to make this restriction. Drop it.

Applied to u-boot/master, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20171204/bd52ff22/attachment.sig>
#11 lore raw

PATCH 5/5 test: compression: Convert to unit test framework

In reply to Simon Glass

Adjust this test to use the unit test framework. Drop the two existing commands for running the tests and replace them with a single 'ut compression' command, with sub-commands.

---

 include/test/compression.h |  17 +++++
 include/test/suites.h      |   1 +
 test/cmd_ut.c              |   7 ++
 test/compression.c         | 185 ++++++++++++++++++++++++++++-----------------
 4 files changed, 141 insertions(+), 69 deletions(-)
 create mode 100644 include/test/compression.h
include/test/compression.h new file +17 -0
new file mode 100644
index 00000000000..646f117ed81
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <[email protected]>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __TEST_COMPRESSION_H__
+#define __TEST_COMPRESSION_H__
+
+#include <test/test.h>
+
+/* Declare a new compression test */
+#define COMPRESSION_TEST(_name, _flags) \
+		UNIT_TEST(_name, _flags, compression_test)
+
+#endif /* __TEST_ENV_H__ */
include/test/suites.h +1 -0
index 6b900a8f594..5f2e519084f 100644
@@ -28,5 +28,6 @@ int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_time(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);
 
 #endif /* __TEST_SUITES_H__ */
test/cmd_ut.c +7 -0
index d860dd72f0b..6b24f463f33 100644
@@ -50,6 +50,10 @@ static cmd_tbl_t cmd_ut_sub[] = {
 #ifdef CONFIG_UT_TIME
 	U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""),
 #endif
+#ifdef CONFIG_SANDBOX
+	U_BOOT_CMD_MKENT(compression, CONFIG_SYS_MAXARGS, 1, do_ut_compression,
+			 "", ""),
+#endif
 };
 
 static int do_ut_all(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -101,6 +105,9 @@ static char ut_help_text[] =
 #endif
 #ifdef CONFIG_UT_TIME
 	"ut time - Very basic test of time functions\n"
+#endif
+#ifdef CONFIG_SANDBOX
+	"ut compression - Test compressors and bootm decompression\n"
 #endif
 	;
 #endif
test/compression.c +116 -69

369 lines not on this page · raw message

Signature · 1 line
2.15.0.417.g466bffb3ac-goog
#12 lore raw

PATCH 5/5 test: compression: Convert to unit test framework

Quoted 5 lines · Simon Glass

Adjust this test to use the unit test framework. Drop the two existing commands for running the tests and replace them with a single 'ut compression' command, with sub-commands.

Applied to u-boot/master, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20171204/b3304bef/attachment.sig>