[PATCH] kunit: Cover 'assert.c' with tests

35 views
Skip to first unread message

Ivan Orlov

unread,
Apr 27, 2024, 6:05:01 PMApr 27
to brendan...@linux.dev, davi...@google.com, rm...@google.com, Ivan Orlov, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
There are multiple assertion formatting functions in the `assert.c`
file, which are not covered with tests yet. Implement the KUnit test
for these functions.

The test consists of 11 test cases for the following functions:

1) 'is_literal'
2) 'is_str_literal'
3) 'kunit_assert_prologue', test case for multiple assert types
4) 'kunit_assert_print_msg'
5) 'kunit_unary_assert_format'
6) 'kunit_ptr_not_err_assert_format'
7) 'kunit_binary_assert_format'
8) 'kunit_binary_ptr_assert_format'
9) 'kunit_binary_str_assert_format'
10) 'kunit_assert_hexdump'
11) 'kunit_mem_assert_format'

The test aims at maximizing the branch coverage for the assertion
formatting functions. As you can see, it covers some of the static
helper functions as well, so we have to import the test source in the
`assert.c` file in order to be able to call and validate them.

Signed-off-by: Ivan Orlov <ivan.or...@gmail.com>
---
lib/kunit/assert.c | 4 +
lib/kunit/assert_test.c | 416 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 420 insertions(+)
create mode 100644 lib/kunit/assert_test.c

diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c
index dd1d633d0fe2..ab68c6daf546 100644
--- a/lib/kunit/assert.c
+++ b/lib/kunit/assert.c
@@ -270,3 +270,7 @@ void kunit_mem_assert_format(const struct kunit_assert *assert,
}
}
EXPORT_SYMBOL_GPL(kunit_mem_assert_format);
+
+#if IS_ENABLED(CONFIG_KUNIT_TEST)
+#include "assert_test.c"
+#endif
diff --git a/lib/kunit/assert_test.c b/lib/kunit/assert_test.c
new file mode 100644
index 000000000000..d54841740761
--- /dev/null
+++ b/lib/kunit/assert_test.c
@@ -0,0 +1,416 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * KUnit test for the assertion formatting functions.
+ * Author: Ivan Orlov <ivan.or...@gmail.com>
+ */
+#include <kunit/test.h>
+
+#define TEST_PTR_EXPECTED_BUF_SIZE 128
+
+static void kunit_test_is_literal(struct kunit *test)
+{
+ KUNIT_EXPECT_TRUE(test, is_literal("5", 5));
+ KUNIT_EXPECT_TRUE(test, is_literal("0", 0));
+ KUNIT_EXPECT_TRUE(test, is_literal("1234567890", 1234567890));
+ KUNIT_EXPECT_TRUE(test, is_literal("-1234567890", -1234567890));
+ KUNIT_EXPECT_FALSE(test, is_literal("05", 5));
+ KUNIT_EXPECT_FALSE(test, is_literal("", 0));
+ KUNIT_EXPECT_FALSE(test, is_literal("-0", 0));
+ KUNIT_EXPECT_FALSE(test, is_literal("12#45", 1245));
+}
+
+static void kunit_test_is_str_literal(struct kunit *test)
+{
+ KUNIT_EXPECT_TRUE(test, is_str_literal("\"Hello, World!\"", "Hello, World!"));
+ KUNIT_EXPECT_TRUE(test, is_str_literal("\"\"", ""));
+ KUNIT_EXPECT_TRUE(test, is_str_literal("\"\"\"", "\""));
+ KUNIT_EXPECT_FALSE(test, is_str_literal("", ""));
+ KUNIT_EXPECT_FALSE(test, is_str_literal("\"", "\""));
+ KUNIT_EXPECT_FALSE(test, is_str_literal("\"Abacaba", "Abacaba"));
+ KUNIT_EXPECT_FALSE(test, is_str_literal("Abacaba\"", "Abacaba"));
+ KUNIT_EXPECT_FALSE(test, is_str_literal("\"Abacaba\"", "\"Abacaba\""));
+}
+
+KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
+
+/* this function is used to get a "char *" string from the string stream and defer its cleanup */
+static char *get_str_from_stream(struct kunit *test, struct string_stream *stream)
+{
+ char *str = string_stream_get_string(stream);
+
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str);
+ kunit_add_action(test, kfree_wrapper, (void *)str);
+
+ return str;
+}
+
+static void kunit_test_assert_prologue(struct kunit *test)
+{
+ struct string_stream *stream;
+ const struct kunit_loc location = {
+ .file = "testfile.c",
+ .line = 1337,
+ };
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ /* Test an expectation fail prologue */
+ kunit_assert_prologue(&location, KUNIT_EXPECTATION, stream);
+ KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream),
+ "EXPECTATION FAILED at testfile.c:1337\n");
+
+ /* Test an assertion fail prologue */
+ string_stream_clear(stream);
+ kunit_assert_prologue(&location, KUNIT_ASSERTION, stream);
+ KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream),
+ "ASSERTION FAILED at testfile.c:1337\n");
+}
+
+/*
+ * This function accepts an arbitrary count of parameters and generates a va_format struct,
+ * which can be used to validate kunit_assert_print_msg function
+ */
+static void verify_assert_print_msg(struct kunit *test,
+ struct string_stream *stream,
+ char *expected, const char *format, ...)
+{
+ va_list list;
+ const struct va_format vformat = {
+ .fmt = format,
+ .va = &list,
+ };
+
+ va_start(list, format);
+ string_stream_clear(stream);
+ kunit_assert_print_msg(&vformat, stream);
+ KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream), expected);
+}
+
+static void kunit_test_assert_print_msg(struct kunit *test)
+{
+ struct string_stream *stream;
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ verify_assert_print_msg(test, stream, "\nTest", "Test");
+ verify_assert_print_msg(test, stream, "\nAbacaba -123 234", "%s %d %u",
+ "Abacaba", -123, 234U);
+ verify_assert_print_msg(test, stream, "", NULL);
+}
+
+/*
+ * Further code contains the tests for different assert format functions.
+ * This helper function accepts the assert format function, executes it and
+ * validates the result string from the stream.
+ */
+static void validate_assert(assert_format_t format_func, struct kunit *test,
+ const struct kunit_assert *assert,
+ const char *expected, struct string_stream *stream)
+{
+ struct va_format message = { NULL, NULL };
+
+ string_stream_clear(stream);
+ format_func(assert, &message, stream);
+ KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream), expected);
+}
+
+static void kunit_test_unary_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct kunit_assert assert = {};
+ struct kunit_unary_assert un_assert = {
+ .assert = assert,
+ .condition = "expr",
+ .expected_true = true,
+ };
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ validate_assert(kunit_unary_assert_format, test, &un_assert.assert,
+ KUNIT_SUBTEST_INDENT
+ "Expected expr to be true, but is false\n",
+ stream);
+
+ un_assert.expected_true = false;
+ validate_assert(kunit_unary_assert_format, test, &un_assert.assert,
+ KUNIT_SUBTEST_INDENT
+ "Expected expr to be false, but is true\n",
+ stream);
+}
+
+static void kunit_test_ptr_not_err_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct kunit_assert assert = {};
+ struct kunit_ptr_not_err_assert not_err_assert = {
+ .assert = assert,
+ .text = "expr",
+ .value = NULL,
+ };
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ /* Value is NULL. The corresponding message should be printed out */
+ validate_assert(kunit_ptr_not_err_assert_format, test,
+ &not_err_assert.assert,
+ KUNIT_SUBTEST_INDENT
+ "Expected expr is not null, but is\n",
+ stream);
+
+ /* Value is not NULL, but looks like an error pointer. Error should be printed out */
+ not_err_assert.value = (void *)-12;
+ validate_assert(kunit_ptr_not_err_assert_format, test,
+ &not_err_assert.assert,
+ KUNIT_SUBTEST_INDENT
+ "Expected expr is not error, but is: -12\n",
+ stream);
+}
+
+static void kunit_test_binary_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct kunit_assert assert = {};
+ struct kunit_binary_assert_text text = {
+ .left_text = "1 + 2",
+ .operation = "==",
+ .right_text = "2",
+ };
+ const struct kunit_binary_assert binary_assert = {
+ .assert = assert,
+ .text = &text,
+ .left_value = 3,
+ .right_value = 2,
+ };
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ /*
+ * the right argument is "literal" (see test for `is_literal` above),
+ * so the right argument won't be printed out separately.
+ */
+ validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
+ KUNIT_SUBTEST_INDENT
+ "Expected 1 + 2 == 2, but\n" KUNIT_SUBSUBTEST_INDENT
+ "1 + 2 == 3 (0x3)\n",
+ stream);
+
+ /* Now both arguments are not "literal". They both will be printed out separately */
+ text.right_text = "4 - 2";
+ validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
+ KUNIT_SUBTEST_INDENT
+ "Expected 1 + 2 == 4 - 2, but\n" KUNIT_SUBSUBTEST_INDENT
+ "1 + 2 == 3 (0x3)\n" KUNIT_SUBSUBTEST_INDENT
+ "4 - 2 == 2 (0x2)",
+ stream);
+
+ /* Now the left argument is "literal", so it won't be printed out */
+ text.left_text = "3";
+ validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
+ KUNIT_SUBTEST_INDENT
+ "Expected 3 == 4 - 2, but\n" KUNIT_SUBSUBTEST_INDENT
+ "4 - 2 == 2 (0x2)",
+ stream);
+
+ /* The left and the right arguments are not "literal", so they won't be printed out */
+ text.right_text = "2";
+ validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
+ KUNIT_SUBTEST_INDENT "Expected 3 == 2, but\n", stream);
+}
+
+static void kunit_test_binary_ptr_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct kunit_assert assert = {};
+ char *expected;
+ static const void *var_a = (void *)0xDEADBEEF;
+ static const void *var_b = (void *)0xBADDCAFE;
+ struct kunit_binary_assert_text text = {
+ .left_text = "var_a",
+ .operation = "==",
+ .right_text = "var_b",
+ };
+ struct kunit_binary_ptr_assert binary_ptr_assert = {
+ .assert = assert,
+ .text = &text,
+ .left_value = var_a,
+ .right_value = var_b,
+ };
+
+ expected = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected);
+ /*
+ * Print the expected string to the buffer first.
+ * This is necessary as we may have different count of leading zeros in the pointer
+ * on different architectures.
+ */
+ snprintf(expected, TEST_PTR_EXPECTED_BUF_SIZE,
+ KUNIT_SUBTEST_INDENT
+ "Expected var_a == var_b, but\n" KUNIT_SUBSUBTEST_INDENT
+ "var_a == %px\n" KUNIT_SUBSUBTEST_INDENT "var_b == %px",
+ var_a, var_b);
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+ validate_assert(kunit_binary_ptr_assert_format, test,
+ &binary_ptr_assert.assert, expected, stream);
+}
+
+static void kunit_test_binary_str_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct kunit_assert assert = {};
+ static const char *var_a = "abacaba";
+ static const char *var_b = "kernel";
+ struct kunit_binary_assert_text text = {
+ .left_text = "var_a",
+ .operation = "==",
+ .right_text = "var_b",
+ };
+ struct kunit_binary_str_assert binary_str_assert = {
+ .assert = assert,
+ .text = &text,
+ .left_value = var_a,
+ .right_value = var_b,
+ };
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ /* Both arguments are not "string literals", so they should be printed separately */
+ validate_assert(kunit_binary_str_assert_format, test,
+ &binary_str_assert.assert,
+ KUNIT_SUBTEST_INDENT
+ "Expected var_a == var_b, but\n" KUNIT_SUBSUBTEST_INDENT
+ "var_a == \"abacaba\"\n" KUNIT_SUBSUBTEST_INDENT
+ "var_b == \"kernel\"",
+ stream);
+
+ /* Left argument is a "string literal", so it shouldn't be printed separately */
+ text.left_text = "\"abacaba\"";
+ validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert,
+ KUNIT_SUBTEST_INDENT "Expected \"abacaba\" == var_b, but\n"
+ KUNIT_SUBSUBTEST_INDENT "var_b == \"kernel\"", stream);
+
+ /* Both arguments are "string literals", so they shouldn't be printed separately */
+ text.right_text = "\"kernel\"";
+ validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert,
+ KUNIT_SUBTEST_INDENT "Expected \"abacaba\" == \"kernel\", but\n", stream);
+}
+
+static const u8 hex_testbuf1[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55,
+ 0x45, 0x9d, 0x47, 0xd6, 0x47,
+ 0x1, 0x89, 0x8c, 0x81, 0x94,
+ 0x12, 0xfe, 0x01 };
+static const u8 hex_testbuf2[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55,
+ 0x45, 0x9d, 0x47, 0x21, 0x47,
+ 0xcd, 0x89, 0x24, 0x50, 0x94,
+ 0x12, 0xba, 0x01 };
+static void kunit_test_assert_hexdump(struct kunit *test)
+{
+ struct string_stream *stream;
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+ /*
+ * Check that we are getting numbers like <xx> on the right places.
+ * Also check that we get a newline after 16 bytes
+ */
+ kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf2, sizeof(hex_testbuf1));
+ KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream), KUNIT_SUBSUBTEST_INDENT
+ " 26 74 6b 9c 55 45 9d 47 <d6> 47 <01> 89 <8c><81> 94 12 \n"
+ KUNIT_SUBSUBTEST_INDENT "<fe> 01 ");
+
+ /*
+ * We shouldn't get any <xx> numbers when comparing the buffer with itself.
+ * We still should get a newline after 16 printed bytes
+ */
+ string_stream_clear(stream);
+ kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf1, sizeof(hex_testbuf1));
+ KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream),
+ KUNIT_SUBSUBTEST_INDENT
+ " 26 74 6b 9c 55 45 9d 47 d6 47 01 89 8c 81 94 12 \n"
+ KUNIT_SUBSUBTEST_INDENT " fe 01 ");
+}
+
+static void kunit_test_mem_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct string_stream *expected_stream;
+ struct kunit_assert assert = {};
+ static const struct kunit_binary_assert_text text = {
+ .left_text = "hex_testbuf1",
+ .operation = "==",
+ .right_text = "hex_testbuf2",
+ };
+ struct kunit_mem_assert mem_assert = {
+ .assert = assert,
+ .text = &text,
+ .left_value = NULL,
+ .right_value = hex_testbuf2,
+ .size = sizeof(hex_testbuf1),
+ };
+
+ expected_stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_stream);
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ /* The left value is NULL */
+ validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
+ KUNIT_SUBTEST_INDENT
+ "Expected hex_testbuf1 is not null, but is\n",
+ stream);
+
+ /* The right value is NULL, the left value is not NULL */
+ mem_assert.left_value = hex_testbuf1;
+ mem_assert.right_value = NULL;
+ validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
+ KUNIT_SUBTEST_INDENT
+ "Expected hex_testbuf2 is not null, but is\n",
+ stream);
+
+ /* Both arguments are not null */
+ mem_assert.left_value = hex_testbuf1;
+ mem_assert.right_value = hex_testbuf2;
+
+ /*
+ * Building the expected buffer.
+ */
+ string_stream_add(expected_stream,
+ KUNIT_SUBTEST_INDENT "Expected hex_testbuf1 == hex_testbuf2, but\n");
+ string_stream_add(expected_stream, KUNIT_SUBSUBTEST_INDENT "hex_testbuf1 ==\n");
+ kunit_assert_hexdump(expected_stream, hex_testbuf1, hex_testbuf2, mem_assert.size);
+ string_stream_add(expected_stream,
+ "\n" KUNIT_SUBSUBTEST_INDENT "hex_testbuf2 ==\n");
+ kunit_assert_hexdump(expected_stream, hex_testbuf2, hex_testbuf1, mem_assert.size);
+
+ validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
+ get_str_from_stream(test, expected_stream), stream);
+}
+
+struct kunit_case assert_test_cases[] = {
+ KUNIT_CASE(kunit_test_is_literal),
+ KUNIT_CASE(kunit_test_is_str_literal),
+ KUNIT_CASE(kunit_test_assert_prologue),
+ KUNIT_CASE(kunit_test_assert_print_msg),
+ KUNIT_CASE(kunit_test_unary_assert_format),
+ KUNIT_CASE(kunit_test_ptr_not_err_assert_format),
+ KUNIT_CASE(kunit_test_binary_assert_format),
+ KUNIT_CASE(kunit_test_binary_ptr_assert_format),
+ KUNIT_CASE(kunit_test_binary_str_assert_format),
+ KUNIT_CASE(kunit_test_assert_hexdump),
+ KUNIT_CASE(kunit_test_mem_assert_format),
+ {}
+};
+
+struct kunit_suite assert_test_suite = {
+ .name = "kunit-assert",
+ .test_cases = assert_test_cases,
+};
+
+kunit_test_suites(&assert_test_suite);
--
2.34.1

Rae Moar

unread,
Apr 29, 2024, 5:26:36 PMApr 29
to Ivan Orlov, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
On Sat, Apr 27, 2024 at 6:04 PM Ivan Orlov <ivan.or...@gmail.com> wrote:
>
> There are multiple assertion formatting functions in the `assert.c`
> file, which are not covered with tests yet. Implement the KUnit test
> for these functions.
>
> The test consists of 11 test cases for the following functions:
>
> 1) 'is_literal'
> 2) 'is_str_literal'
> 3) 'kunit_assert_prologue', test case for multiple assert types
> 4) 'kunit_assert_print_msg'
> 5) 'kunit_unary_assert_format'
> 6) 'kunit_ptr_not_err_assert_format'
> 7) 'kunit_binary_assert_format'
> 8) 'kunit_binary_ptr_assert_format'
> 9) 'kunit_binary_str_assert_format'
> 10) 'kunit_assert_hexdump'
> 11) 'kunit_mem_assert_format'
>
> The test aims at maximizing the branch coverage for the assertion
> formatting functions. As you can see, it covers some of the static
> helper functions as well, so we have to import the test source in the
> `assert.c` file in order to be able to call and validate them.
>
> Signed-off-by: Ivan Orlov <ivan.or...@gmail.com>

Hello,

I'll give this a full review tomorrow. But with a quick glance and
test, this is looking good to me.

Tested-by: Rae Moar <rm...@google.com>

Thanks!
-Rae

Ivan Orlov

unread,
Apr 30, 2024, 5:19:14 AMApr 30
to Rae Moar, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
Hi Rae,

Thanks a lot for testing the patch.

Looking forward to seeing your review! :)

--
Kind regards,
Ivan Orlov

Rae Moar

unread,
May 1, 2024, 7:20:28 PMMay 1
to Ivan Orlov, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
On Sat, Apr 27, 2024 at 6:04 PM Ivan Orlov <ivan.or...@gmail.com> wrote:
>
> There are multiple assertion formatting functions in the `assert.c`
> file, which are not covered with tests yet. Implement the KUnit test
> for these functions.
>
> The test consists of 11 test cases for the following functions:
>
> 1) 'is_literal'
> 2) 'is_str_literal'
> 3) 'kunit_assert_prologue', test case for multiple assert types
> 4) 'kunit_assert_print_msg'
> 5) 'kunit_unary_assert_format'
> 6) 'kunit_ptr_not_err_assert_format'
> 7) 'kunit_binary_assert_format'
> 8) 'kunit_binary_ptr_assert_format'
> 9) 'kunit_binary_str_assert_format'
> 10) 'kunit_assert_hexdump'
> 11) 'kunit_mem_assert_format'
>
> The test aims at maximizing the branch coverage for the assertion
> formatting functions. As you can see, it covers some of the static
> helper functions as well, so we have to import the test source in the
> `assert.c` file in order to be able to call and validate them.
>
> Signed-off-by: Ivan Orlov <ivan.or...@gmail.com>

Hello!

This is a great patch and addition of KUnit tests. Happy to see it.
Thank you very much!

I do have a few comments below. But none of them are deal breakers.

Thanks!
-Rae

> ---
> lib/kunit/assert.c | 4 +
> lib/kunit/assert_test.c | 416 ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 420 insertions(+)
> create mode 100644 lib/kunit/assert_test.c
>
> diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c
> index dd1d633d0fe2..ab68c6daf546 100644
> --- a/lib/kunit/assert.c
> +++ b/lib/kunit/assert.c
> @@ -270,3 +270,7 @@ void kunit_mem_assert_format(const struct kunit_assert *assert,
> }
> }
> EXPORT_SYMBOL_GPL(kunit_mem_assert_format);
> +
> +#if IS_ENABLED(CONFIG_KUNIT_TEST)
> +#include "assert_test.c"
> +#endif

I might consider using the macro VISIBLE_IF_KUNIT macro, found in
include/kunit/visibility.h, to make the static functions in assert.c
visible only if KUnit is enabled. To avoid having to add the include
here. What do you think?
My one main concern with some of these tests is that they test for
exact matches to string error messages. I worry that these error
messages are likely to change over time, especially the indentation
and spacing of the messages. This applies more to some of the tests
below that check for the indentation.

I think it is most important that we test for the message containing
the correct information. Is there a way to instead check if the stream
contains each of a list of important information. So for example in
the test above, I think it is important to check the stream contains
the following strings: "ASSERTION" (maybe even not check for case),
"testfile.c", "1337", and "\n" at the end of the stream.

This applies to the tests below as well. Although, I do see how it may
be difficult to change this. If there is a way to at least remove the
checks for indentation and any filler words that would be great.
Similar to above, the exactness of this message worries me slightly,
especially the indentation formatting. And I am not 100 percent sure
if having a hex dump test is worth it. But I am good to keep this in.

Ivan Orlov

unread,
May 3, 2024, 7:10:50 AMMay 3
to Rae Moar, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
Hi Rae,

Thank you so much for the detailed review.

>
>> ---
>> lib/kunit/assert.c | 4 +
>> lib/kunit/assert_test.c | 416 ++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 420 insertions(+)
>> create mode 100644 lib/kunit/assert_test.c
>>
>> diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c
>> index dd1d633d0fe2..ab68c6daf546 100644
>> --- a/lib/kunit/assert.c
>> +++ b/lib/kunit/assert.c
>> @@ -270,3 +270,7 @@ void kunit_mem_assert_format(const struct kunit_assert *assert,
>> }
>> }
>> EXPORT_SYMBOL_GPL(kunit_mem_assert_format);
>> +
>> +#if IS_ENABLED(CONFIG_KUNIT_TEST)
>> +#include "assert_test.c"
>> +#endif
>
> I might consider using the macro VISIBLE_IF_KUNIT macro, found in
> include/kunit/visibility.h, to make the static functions in assert.c
> visible only if KUnit is enabled. To avoid having to add the include
> here. What do you think?
>

Wow, I haven't seen this macro before, thank you for the suggestion!
I'll use it in the V2 of the patch.

I assume we need to use it in combination with EXPORT_SYMBOL_IF_KUNIT,
otherwise GCC will complain on use of functions without definitions, right?

Also, should the assertion test be in a different file in such a case,
or we could merge it with one of the existing test files, for instance
`kunit_test.c`? Having these static functions exported would allow us to
do that.
Yes, I fully agree, checking for the important information would be a
better way of testing these functions.

My initial intention was to check for the format and indentation as well
to be sure that some change won't break any of existing parsers (I
assume there are some parsers for KUnit test output :) ), but in fact
this approach just bloats the test and makes it less readable. I will
fix it in the V2, thanks!

Ivan Orlov

unread,
May 3, 2024, 8:19:05 AMMay 3
to Rae Moar, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
s/definitions/declarations/g :)

Ivan Orlov

unread,
May 4, 2024, 12:45:10 PMMay 4
to Rae Moar, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
On 5/3/24 12:10, Ivan Orlov wrote:
Ah, alright, it seems like GCC is going to complain on missing
prototypes anyway, so we have to declare these static functions in the
header file if CONFIG_KUNIT is defined.

Ivan Orlov

unread,
May 8, 2024, 9:26:03 AMMay 8
to brendan...@linux.dev, davi...@google.com, rm...@google.com, Ivan Orlov, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
There are multiple assertion formatting functions in the `assert.c`
file, which are not covered with tests yet. Implement the KUnit test
for these functions.

The test consists of 11 test cases for the following functions:

1) 'is_literal'
2) 'is_str_literal'
3) 'kunit_assert_prologue', test case for multiple assert types
4) 'kunit_assert_print_msg'
5) 'kunit_unary_assert_format'
6) 'kunit_ptr_not_err_assert_format'
7) 'kunit_binary_assert_format'
8) 'kunit_binary_ptr_assert_format'
9) 'kunit_binary_str_assert_format'
10) 'kunit_assert_hexdump'
11) 'kunit_mem_assert_format'

The test aims at maximizing the branch coverage for the assertion
formatting functions.

As you can see, it covers some of the static helper functions as
well, so mark the static functions in `assert.c` as 'VISIBLE_IF_KUNIT'
and conditionally export them with EXPORT_SYMBOL_IF_KUNIT. Add the
corresponding definitions to `assert.h`.

Build the assert test when CONFIG_KUNIT_TEST is enabled, similar to
how it is done for the string stream test.

Signed-off-by: Ivan Orlov <ivan.or...@gmail.com>
---
V1 -> V2:
- Check the output from the string stream for containing the key parts
instead of comparing the results with expected strings char by char, as
it was suggested by Rae Moar <rm...@google.com>. Define two macros to
make it possible (ASSERT_TEST_EXPECT_CONTAIN and
ASSERT_TEST_EXPECT_NCONTAIN).
- Mark the static functions in `assert.c` as VISIBLE_IF_KUNIT and export
them conditionally if kunit is enabled instead of including the
`assert_test.c` file in the end of `assert.c`. This way we will decouple
the test from the implementation (SUT).
- Update the kunit_assert_hexdump test: now it checks for presense of
the brackets '<>' around the non-matching bytes, instead of comparing
the kunit_assert_hexdump output char by char.

include/kunit/assert.h | 11 ++
lib/kunit/Makefile | 1 +
lib/kunit/assert.c | 24 ++-
lib/kunit/assert_test.c | 389 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 417 insertions(+), 8 deletions(-)
create mode 100644 lib/kunit/assert_test.c

diff --git a/include/kunit/assert.h b/include/kunit/assert.h
index 24c2b9fa61e8..31e655abbce9 100644
--- a/include/kunit/assert.h
+++ b/include/kunit/assert.h
@@ -218,4 +218,15 @@ void kunit_mem_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream);

+#if IS_ENABLED(CONFIG_KUNIT_TEST)
+void kunit_assert_print_msg(const struct va_format *message,
+ struct string_stream *stream);
+bool is_literal(const char *text, long long value);
+bool is_str_literal(const char *text, const char *value);
+void kunit_assert_hexdump(struct string_stream *stream,
+ const void *buf,
+ const void *compared_buf,
+ const size_t len);
+#endif
+
#endif /* _KUNIT_ASSERT_H */
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 309659a32a78..be7c9903936f 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -18,6 +18,7 @@ endif
obj-y += hooks.o

obj-$(CONFIG_KUNIT_TEST) += kunit-test.o
+obj-$(CONFIG_KUNIT_TEST) += assert_test.o

# string-stream-test compiles built-in only.
ifeq ($(CONFIG_KUNIT_TEST),y)
diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c
index dd1d633d0fe2..382eb409d34b 100644
--- a/lib/kunit/assert.c
+++ b/lib/kunit/assert.c
@@ -7,6 +7,7 @@
*/
#include <kunit/assert.h>
#include <kunit/test.h>
+#include <kunit/visibility.h>

#include "string-stream.h"

@@ -30,12 +31,14 @@ void kunit_assert_prologue(const struct kunit_loc *loc,
}
EXPORT_SYMBOL_GPL(kunit_assert_prologue);

-static void kunit_assert_print_msg(const struct va_format *message,
- struct string_stream *stream)
+VISIBLE_IF_KUNIT
+void kunit_assert_print_msg(const struct va_format *message,
+ struct string_stream *stream)
{
if (message->fmt)
string_stream_add(stream, "\n%pV", message);
}
+EXPORT_SYMBOL_IF_KUNIT(kunit_assert_print_msg);

void kunit_fail_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
@@ -89,7 +92,7 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);

/* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */
-static bool is_literal(const char *text, long long value)
+VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
{
char *buffer;
int len;
@@ -110,6 +113,7 @@ static bool is_literal(const char *text, long long value)

return ret;
}
+EXPORT_SYMBOL_IF_KUNIT(is_literal);

void kunit_binary_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
@@ -166,7 +170,7 @@ EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
/* Checks if KUNIT_EXPECT_STREQ() args were string literals.
* Note: `text` will have ""s where as `value` will not.
*/
-static bool is_str_literal(const char *text, const char *value)
+VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
{
int len;

@@ -178,6 +182,7 @@ static bool is_str_literal(const char *text, const char *value)

return strncmp(text + 1, value, len - 2) == 0;
}
+EXPORT_SYMBOL_IF_KUNIT(is_str_literal);

void kunit_binary_str_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
@@ -208,10 +213,11 @@ EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
/* Adds a hexdump of a buffer to a string_stream comparing it with
* a second buffer. The different bytes are marked with <>.
*/
-static void kunit_assert_hexdump(struct string_stream *stream,
- const void *buf,
- const void *compared_buf,
- const size_t len)
+VISIBLE_IF_KUNIT
+void kunit_assert_hexdump(struct string_stream *stream,
+ const void *buf,
+ const void *compared_buf,
+ const size_t len)
{
size_t i;
const u8 *buf1 = buf;
@@ -229,6 +235,7 @@ static void kunit_assert_hexdump(struct string_stream *stream,
string_stream_add(stream, " %02x ", buf1[i]);
}
}
+EXPORT_SYMBOL_IF_KUNIT(kunit_assert_hexdump);

void kunit_mem_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
@@ -269,4 +276,5 @@ void kunit_mem_assert_format(const struct kunit_assert *assert,
kunit_assert_print_msg(message, stream);
}
}
+
EXPORT_SYMBOL_GPL(kunit_mem_assert_format);
diff --git a/lib/kunit/assert_test.c b/lib/kunit/assert_test.c
new file mode 100644
index 000000000000..dd26a82b9fd7
--- /dev/null
+++ b/lib/kunit/assert_test.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * KUnit test for the assertion formatting functions.
+ * Author: Ivan Orlov <ivan.or...@gmail.com>
+ */
+#include <kunit/test.h>
+#include "string-stream.h"
+
+#define TEST_PTR_EXPECTED_BUF_SIZE 32
+#define HEXDUMP_TEST_BUF_LEN 5
+#define ASSERT_TEST_EXPECT_CONTAIN(test, str, substr) KUNIT_EXPECT_TRUE(test, strstr(str, substr))
+#define ASSERT_TEST_EXPECT_NCONTAIN(test, str, substr) KUNIT_EXPECT_FALSE(test, strstr(str, substr))
+ char *str;
+ const struct kunit_loc location = {
+ .file = "testfile.c",
+ .line = 1337,
+ };
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ /* Test an expectation fail prologue */
+ kunit_assert_prologue(&location, KUNIT_EXPECTATION, stream);
+ str = get_str_from_stream(test, stream);
+ ASSERT_TEST_EXPECT_CONTAIN(test, str, "EXPECTATION");
+ ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c");
+ ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337");
+
+ /* Test an assertion fail prologue */
+ string_stream_clear(stream);
+ kunit_assert_prologue(&location, KUNIT_ASSERTION, stream);
+ str = get_str_from_stream(test, stream);
+ ASSERT_TEST_EXPECT_CONTAIN(test, str, "ASSERTION");
+ ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c");
+ ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337");
+}
+
+/*
+ * This function accepts an arbitrary count of parameters and generates a va_format struct,
+ * which can be used to validate kunit_assert_print_msg function
+ */
+static void verify_assert_print_msg(struct kunit *test,
+ struct string_stream *stream,
+ char *expected, const char *format, ...)
+{
+ va_list list;
+ const struct va_format vformat = {
+ .fmt = format,
+ .va = &list,
+ };
+
+ va_start(list, format);
+ string_stream_clear(stream);
+ kunit_assert_print_msg(&vformat, stream);
+ KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream), expected);
+}
+
+static void kunit_test_assert_print_msg(struct kunit *test)
+{
+ struct string_stream *stream;
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ verify_assert_print_msg(test, stream, "\nTest", "Test");
+ verify_assert_print_msg(test, stream, "\nAbacaba -123 234", "%s %d %u",
+ "Abacaba", -123, 234U);
+ verify_assert_print_msg(test, stream, "", NULL);
+}
+
+/*
+ * Further code contains the tests for different assert format functions.
+ * This helper function accepts the assert format function, executes it and
+ * validates the result string from the stream by checking that all of the
+ * substrings exist in the output.
+ */
+static void validate_assert(assert_format_t format_func, struct kunit *test,
+ const struct kunit_assert *assert,
+ struct string_stream *stream, int num_checks, ...)
+{
+ size_t i;
+ va_list checks;
+ char *cur_substr_exp;
+ struct va_format message = { NULL, NULL };
+
+ va_start(checks, num_checks);
+ string_stream_clear(stream);
+ format_func(assert, &message, stream);
+
+ for (i = 0; i < num_checks; i++) {
+ cur_substr_exp = va_arg(checks, char *);
+ ASSERT_TEST_EXPECT_CONTAIN(test, get_str_from_stream(test, stream), cur_substr_exp);
+ }
+}
+
+static void kunit_test_unary_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct kunit_assert assert = {};
+ struct kunit_unary_assert un_assert = {
+ .assert = assert,
+ .condition = "expr",
+ .expected_true = true,
+ };
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ validate_assert(kunit_unary_assert_format, test, &un_assert.assert,
+ stream, 2, "true", "is false");
+
+ un_assert.expected_true = false;
+ validate_assert(kunit_unary_assert_format, test, &un_assert.assert,
+ stream, 2, "false", "is true");
+}
+
+static void kunit_test_ptr_not_err_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct kunit_assert assert = {};
+ struct kunit_ptr_not_err_assert not_err_assert = {
+ .assert = assert,
+ .text = "expr",
+ .value = NULL,
+ };
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ /* Value is NULL. The corresponding message should be printed out */
+ validate_assert(kunit_ptr_not_err_assert_format, test,
+ &not_err_assert.assert,
+ stream, 1, "null");
+
+ /* Value is not NULL, but looks like an error pointer. Error should be printed out */
+ not_err_assert.value = (void *)-12;
+ validate_assert(kunit_ptr_not_err_assert_format, test,
+ &not_err_assert.assert, stream, 2,
+ "error", "-12");
+}
+
+static void kunit_test_binary_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct kunit_assert assert = {};
+ struct kunit_binary_assert_text text = {
+ .left_text = "1 + 2",
+ .operation = "==",
+ .right_text = "2",
+ };
+ const struct kunit_binary_assert binary_assert = {
+ .assert = assert,
+ .text = &text,
+ .left_value = 3,
+ .right_value = 2,
+ };
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ /*
+ * Printed values should depend on the input we provide: the left text, right text, left
+ * value and the right value.
+ */
+ validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
+ stream, 4, "1 + 2", "2", "3", "==");
+
+ text.right_text = "4 - 2";
+ validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
+ stream, 3, "==", "1 + 2", "4 - 2");
+
+ text.left_text = "3";
+ validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
+ stream, 4, "3", "4 - 2", "2", "==");
+
+ text.right_text = "2";
+ validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
+ stream, 3, "3", "2", "==");
+}
+
+static void kunit_test_binary_ptr_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct kunit_assert assert = {};
+ char *addr_var_a, *addr_var_b;
+ static const void *var_a = (void *)0xDEADBEEF;
+ static const void *var_b = (void *)0xBADDCAFE;
+ struct kunit_binary_assert_text text = {
+ .left_text = "var_a",
+ .operation = "==",
+ .right_text = "var_b",
+ };
+ struct kunit_binary_ptr_assert binary_ptr_assert = {
+ .assert = assert,
+ .text = &text,
+ .left_value = var_a,
+ .right_value = var_b,
+ };
+
+ addr_var_a = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_a);
+ addr_var_b = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_b);
+ /*
+ * Print the addresses to the buffers first.
+ * This is necessary as we may have different count of leading zeros in the pointer
+ * on different architectures.
+ */
+ snprintf(addr_var_a, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_a);
+ snprintf(addr_var_b, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_b);
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+ validate_assert(kunit_binary_ptr_assert_format, test, &binary_ptr_assert.assert,
+ stream, 3, addr_var_a, addr_var_b, "==");
+}
+
+static void kunit_test_binary_str_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct kunit_assert assert = {};
+ static const char *var_a = "abacaba";
+ static const char *var_b = "kernel";
+ struct kunit_binary_assert_text text = {
+ .left_text = "var_a",
+ .operation = "==",
+ .right_text = "var_b",
+ };
+ struct kunit_binary_str_assert binary_str_assert = {
+ .assert = assert,
+ .text = &text,
+ .left_value = var_a,
+ .right_value = var_b,
+ };
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ validate_assert(kunit_binary_str_assert_format, test,
+ &binary_str_assert.assert,
+ stream, 5, "var_a", "var_b", "\"abacaba\"",
+ "\"kernel\"", "==");
+
+ text.left_text = "\"abacaba\"";
+ validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert,
+ stream, 4, "\"abacaba\"", "var_b", "\"kernel\"", "==");
+
+ text.right_text = "\"kernel\"";
+ validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert,
+ stream, 3, "\"abacaba\"", "\"kernel\"", "==");
+}
+
+static const u8 hex_testbuf1[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55,
+ 0x45, 0x9d, 0x47, 0xd6, 0x47,
+ 0x2, 0x89, 0x8c, 0x81, 0x94,
+ 0x12, 0xfe, 0x01 };
+static const u8 hex_testbuf2[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55,
+ 0x45, 0x9d, 0x47, 0x21, 0x47,
+ 0xcd, 0x89, 0x24, 0x50, 0x94,
+ 0x12, 0xba, 0x01 };
+static void kunit_test_assert_hexdump(struct kunit *test)
+{
+ struct string_stream *stream;
+ char *str;
+ size_t i;
+ char buf[HEXDUMP_TEST_BUF_LEN];
+
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+ /* Check that we are getting output like <xx> for non-matching numbers. */
+ kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf2, sizeof(hex_testbuf1));
+ str = get_str_from_stream(test, stream);
+ for (i = 0; i < sizeof(hex_testbuf1); i++) {
+ snprintf(buf, HEXDUMP_TEST_BUF_LEN, "<%02x>", hex_testbuf1[i]);
+ if (hex_testbuf1[i] != hex_testbuf2[i])
+ ASSERT_TEST_EXPECT_CONTAIN(test, str, buf);
+ }
+ /* We shouldn't get any <xx> numbers when comparing the buffer with itself. */
+ string_stream_clear(stream);
+ kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf1, sizeof(hex_testbuf1));
+ str = get_str_from_stream(test, stream);
+ ASSERT_TEST_EXPECT_NCONTAIN(test, str, "<");
+ ASSERT_TEST_EXPECT_NCONTAIN(test, str, ">");
+}
+
+static void kunit_test_mem_assert_format(struct kunit *test)
+{
+ struct string_stream *stream;
+ struct string_stream *expected_stream;
+ struct kunit_assert assert = {};
+ static const struct kunit_binary_assert_text text = {
+ .left_text = "hex_testbuf1",
+ .operation = "==",
+ .right_text = "hex_testbuf2",
+ };
+ struct kunit_mem_assert mem_assert = {
+ .assert = assert,
+ .text = &text,
+ .left_value = NULL,
+ .right_value = hex_testbuf2,
+ .size = sizeof(hex_testbuf1),
+ };
+
+ expected_stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_stream);
+ stream = kunit_alloc_string_stream(test, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+ /* The left value is NULL */
+ validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
+ stream, 2, "hex_testbuf1", "is not null");
+
+ /* The right value is NULL, the left value is not NULL */
+ mem_assert.left_value = hex_testbuf1;
+ mem_assert.right_value = NULL;
+ validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
+ stream, 2, "hex_testbuf2", "is not null");
+
+ /* Both arguments are not null */
+ mem_assert.left_value = hex_testbuf1;
+ mem_assert.right_value = hex_testbuf2;
+
+ validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
+ stream, 3, "hex_testbuf1", "hex_testbuf2", "==");
+}
+
+struct kunit_case assert_test_cases[] = {
+ KUNIT_CASE(kunit_test_is_literal),
+ KUNIT_CASE(kunit_test_is_str_literal),
+ KUNIT_CASE(kunit_test_assert_prologue),
+ KUNIT_CASE(kunit_test_assert_print_msg),
+ KUNIT_CASE(kunit_test_unary_assert_format),
+ KUNIT_CASE(kunit_test_ptr_not_err_assert_format),
+ KUNIT_CASE(kunit_test_binary_assert_format),
+ KUNIT_CASE(kunit_test_binary_ptr_assert_format),
+ KUNIT_CASE(kunit_test_binary_str_assert_format),
+ KUNIT_CASE(kunit_test_assert_hexdump),
+ KUNIT_CASE(kunit_test_mem_assert_format),
+ {}
+};
+
+struct kunit_suite assert_test_suite = {
+ .name = "kunit-assert",
+ .test_cases = assert_test_cases,
+};
+
+MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+kunit_test_suites(&assert_test_suite);
--
2.34.1

kernel test robot

unread,
May 8, 2024, 11:34:01 PMMay 8
to Ivan Orlov, brendan...@linux.dev, davi...@google.com, rm...@google.com, oe-kbu...@lists.linux.dev, Ivan Orlov, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
Hi Ivan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on shuah-kselftest/kunit]
[also build test WARNING on linus/master v6.9-rc7 next-20240508]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Ivan-Orlov/kunit-Cover-assert-c-with-tests/20240508-212654
base: https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git kunit
patch link: https://lore.kernel.org/r/20240508132557.599213-1-ivan.orlov0322%40gmail.com
patch subject: [PATCH v2] kunit: Cover 'assert.c' with tests
config: x86_64-randconfig-121-20240509 (https://download.01.org/0day-ci/archive/20240509/202405091128...@intel.com/config)
compiler: clang version 18.1.4 (https://github.com/llvm/llvm-project e6c3289804a67ea0bb6a86fadbe454dd93b8d855)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240509/202405091128...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <l...@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405091128...@intel.com/

sparse warnings: (new ones prefixed by >>)
>> lib/kunit/assert_test.c:368:19: sparse: sparse: symbol 'assert_test_cases' was not declared. Should it be static?
>> lib/kunit/assert_test.c:383:20: sparse: sparse: symbol 'assert_test_suite' was not declared. Should it be static?

vim +/assert_test_cases +368 lib/kunit/assert_test.c

367
> 368 struct kunit_case assert_test_cases[] = {
369 KUNIT_CASE(kunit_test_is_literal),
370 KUNIT_CASE(kunit_test_is_str_literal),
371 KUNIT_CASE(kunit_test_assert_prologue),
372 KUNIT_CASE(kunit_test_assert_print_msg),
373 KUNIT_CASE(kunit_test_unary_assert_format),
374 KUNIT_CASE(kunit_test_ptr_not_err_assert_format),
375 KUNIT_CASE(kunit_test_binary_assert_format),
376 KUNIT_CASE(kunit_test_binary_ptr_assert_format),
377 KUNIT_CASE(kunit_test_binary_str_assert_format),
378 KUNIT_CASE(kunit_test_assert_hexdump),
379 KUNIT_CASE(kunit_test_mem_assert_format),
380 {}
381 };
382
> 383 struct kunit_suite assert_test_suite = {
384 .name = "kunit-assert",
385 .test_cases = assert_test_cases,
386 };
387

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

kernel test robot

unread,
May 9, 2024, 12:48:04 AMMay 9
to Ivan Orlov, brendan...@linux.dev, davi...@google.com, rm...@google.com, ll...@lists.linux.dev, oe-kbu...@lists.linux.dev, Ivan Orlov, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
Hi Ivan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on shuah-kselftest/kunit]
[also build test WARNING on shuah-kselftest/kunit-fixes linus/master v6.9-rc7 next-20240508]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Ivan-Orlov/kunit-Cover-assert-c-with-tests/20240508-212654
base: https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git kunit
patch link: https://lore.kernel.org/r/20240508132557.599213-1-ivan.orlov0322%40gmail.com
patch subject: [PATCH v2] kunit: Cover 'assert.c' with tests
config: i386-randconfig-001-20240509 (https://download.01.org/0day-ci/archive/20240509/202405091253...@intel.com/config)
compiler: clang version 18.1.4 (https://github.com/llvm/llvm-project e6c3289804a67ea0bb6a86fadbe454dd93b8d855)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240509/202405091253...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <l...@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405091253...@intel.com/

All warnings (new ones prefixed by >>):

>> lib/kunit/assert.c:35:6: warning: no previous prototype for function 'kunit_assert_print_msg' [-Wmissing-prototypes]
35 | void kunit_assert_print_msg(const struct va_format *message,
| ^
lib/kunit/assert.c:35:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
35 | void kunit_assert_print_msg(const struct va_format *message,
| ^
| static
>> lib/kunit/assert.c:95:23: warning: no previous prototype for function 'is_literal' [-Wmissing-prototypes]
95 | VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
| ^
lib/kunit/assert.c:95:18: note: declare 'static' if the function is not intended to be used outside of this translation unit
95 | VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
| ^
| static
>> lib/kunit/assert.c:173:23: warning: no previous prototype for function 'is_str_literal' [-Wmissing-prototypes]
173 | VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
| ^
lib/kunit/assert.c:173:18: note: declare 'static' if the function is not intended to be used outside of this translation unit
173 | VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
| ^
| static
>> lib/kunit/assert.c:217:6: warning: no previous prototype for function 'kunit_assert_hexdump' [-Wmissing-prototypes]
217 | void kunit_assert_hexdump(struct string_stream *stream,
| ^
lib/kunit/assert.c:217:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
217 | void kunit_assert_hexdump(struct string_stream *stream,
| ^
| static
4 warnings generated.


vim +/kunit_assert_print_msg +35 lib/kunit/assert.c

33
34 VISIBLE_IF_KUNIT
> 35 void kunit_assert_print_msg(const struct va_format *message,
36 struct string_stream *stream)
37 {
38 if (message->fmt)
39 string_stream_add(stream, "\n%pV", message);
40 }
41 EXPORT_SYMBOL_IF_KUNIT(kunit_assert_print_msg);
42
43 void kunit_fail_assert_format(const struct kunit_assert *assert,
44 const struct va_format *message,
45 struct string_stream *stream)
46 {
47 string_stream_add(stream, "%pV", message);
48 }
49 EXPORT_SYMBOL_GPL(kunit_fail_assert_format);
50
51 void kunit_unary_assert_format(const struct kunit_assert *assert,
52 const struct va_format *message,
53 struct string_stream *stream)
54 {
55 struct kunit_unary_assert *unary_assert;
56
57 unary_assert = container_of(assert, struct kunit_unary_assert, assert);
58
59 if (unary_assert->expected_true)
60 string_stream_add(stream,
61 KUNIT_SUBTEST_INDENT "Expected %s to be true, but is false\n",
62 unary_assert->condition);
63 else
64 string_stream_add(stream,
65 KUNIT_SUBTEST_INDENT "Expected %s to be false, but is true\n",
66 unary_assert->condition);
67 kunit_assert_print_msg(message, stream);
68 }
69 EXPORT_SYMBOL_GPL(kunit_unary_assert_format);
70
71 void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
72 const struct va_format *message,
73 struct string_stream *stream)
74 {
75 struct kunit_ptr_not_err_assert *ptr_assert;
76
77 ptr_assert = container_of(assert, struct kunit_ptr_not_err_assert,
78 assert);
79
80 if (!ptr_assert->value) {
81 string_stream_add(stream,
82 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
83 ptr_assert->text);
84 } else if (IS_ERR(ptr_assert->value)) {
85 string_stream_add(stream,
86 KUNIT_SUBTEST_INDENT "Expected %s is not error, but is: %ld\n",
87 ptr_assert->text,
88 PTR_ERR(ptr_assert->value));
89 }
90 kunit_assert_print_msg(message, stream);
91 }
92 EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);
93
94 /* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */
> 95 VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
96 {
97 char *buffer;
98 int len;
99 bool ret;
100
101 len = snprintf(NULL, 0, "%lld", value);
102 if (strlen(text) != len)
103 return false;
104
105 buffer = kmalloc(len+1, GFP_KERNEL);
106 if (!buffer)
107 return false;
108
109 snprintf(buffer, len+1, "%lld", value);
110 ret = strncmp(buffer, text, len) == 0;
111
112 kfree(buffer);
113
114 return ret;
115 }
116 EXPORT_SYMBOL_IF_KUNIT(is_literal);
117
118 void kunit_binary_assert_format(const struct kunit_assert *assert,
119 const struct va_format *message,
120 struct string_stream *stream)
121 {
122 struct kunit_binary_assert *binary_assert;
123
124 binary_assert = container_of(assert, struct kunit_binary_assert,
125 assert);
126
127 string_stream_add(stream,
128 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
129 binary_assert->text->left_text,
130 binary_assert->text->operation,
131 binary_assert->text->right_text);
132 if (!is_literal(binary_assert->text->left_text, binary_assert->left_value))
133 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)\n",
134 binary_assert->text->left_text,
135 binary_assert->left_value,
136 binary_assert->left_value);
137 if (!is_literal(binary_assert->text->right_text, binary_assert->right_value))
138 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)",
139 binary_assert->text->right_text,
140 binary_assert->right_value,
141 binary_assert->right_value);
142 kunit_assert_print_msg(message, stream);
143 }
144 EXPORT_SYMBOL_GPL(kunit_binary_assert_format);
145
146 void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
147 const struct va_format *message,
148 struct string_stream *stream)
149 {
150 struct kunit_binary_ptr_assert *binary_assert;
151
152 binary_assert = container_of(assert, struct kunit_binary_ptr_assert,
153 assert);
154
155 string_stream_add(stream,
156 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
157 binary_assert->text->left_text,
158 binary_assert->text->operation,
159 binary_assert->text->right_text);
160 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px\n",
161 binary_assert->text->left_text,
162 binary_assert->left_value);
163 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px",
164 binary_assert->text->right_text,
165 binary_assert->right_value);
166 kunit_assert_print_msg(message, stream);
167 }
168 EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
169
170 /* Checks if KUNIT_EXPECT_STREQ() args were string literals.
171 * Note: `text` will have ""s where as `value` will not.
172 */
> 173 VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
174 {
175 int len;
176
177 len = strlen(text);
178 if (len < 2)
179 return false;
180 if (text[0] != '\"' || text[len - 1] != '\"')
181 return false;
182
183 return strncmp(text + 1, value, len - 2) == 0;
184 }
185 EXPORT_SYMBOL_IF_KUNIT(is_str_literal);
186
187 void kunit_binary_str_assert_format(const struct kunit_assert *assert,
188 const struct va_format *message,
189 struct string_stream *stream)
190 {
191 struct kunit_binary_str_assert *binary_assert;
192
193 binary_assert = container_of(assert, struct kunit_binary_str_assert,
194 assert);
195
196 string_stream_add(stream,
197 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
198 binary_assert->text->left_text,
199 binary_assert->text->operation,
200 binary_assert->text->right_text);
201 if (!is_str_literal(binary_assert->text->left_text, binary_assert->left_value))
202 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"\n",
203 binary_assert->text->left_text,
204 binary_assert->left_value);
205 if (!is_str_literal(binary_assert->text->right_text, binary_assert->right_value))
206 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"",
207 binary_assert->text->right_text,
208 binary_assert->right_value);
209 kunit_assert_print_msg(message, stream);
210 }
211 EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
212
213 /* Adds a hexdump of a buffer to a string_stream comparing it with
214 * a second buffer. The different bytes are marked with <>.
215 */
216 VISIBLE_IF_KUNIT
> 217 void kunit_assert_hexdump(struct string_stream *stream,
218 const void *buf,
219 const void *compared_buf,
220 const size_t len)
221 {
222 size_t i;
223 const u8 *buf1 = buf;
224 const u8 *buf2 = compared_buf;
225
226 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT);
227
228 for (i = 0; i < len; ++i) {
229 if (!(i % 16) && i)
230 string_stream_add(stream, "\n" KUNIT_SUBSUBTEST_INDENT);
231
232 if (buf1[i] != buf2[i])
233 string_stream_add(stream, "<%02x>", buf1[i]);
234 else
235 string_stream_add(stream, " %02x ", buf1[i]);
236 }
237 }
238 EXPORT_SYMBOL_IF_KUNIT(kunit_assert_hexdump);
239

kernel test robot

unread,
May 9, 2024, 2:22:09 AMMay 9
to Ivan Orlov, brendan...@linux.dev, davi...@google.com, rm...@google.com, ll...@lists.linux.dev, oe-kbu...@lists.linux.dev, Ivan Orlov, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
Hi Ivan,

kernel test robot noticed the following build errors:

[auto build test ERROR on shuah-kselftest/kunit]
[also build test ERROR on shuah-kselftest/kunit-fixes linus/master v6.9-rc7 next-20240508]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Ivan-Orlov/kunit-Cover-assert-c-with-tests/20240508-212654
base: https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git kunit
patch link: https://lore.kernel.org/r/20240508132557.599213-1-ivan.orlov0322%40gmail.com
patch subject: [PATCH v2] kunit: Cover 'assert.c' with tests
config: i386-buildonly-randconfig-003-20240509 (https://download.01.org/0day-ci/archive/20240509/202405091439...@intel.com/config)
compiler: clang version 18.1.4 (https://github.com/llvm/llvm-project e6c3289804a67ea0bb6a86fadbe454dd93b8d855)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240509/202405091439...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <l...@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405091439...@intel.com/

All errors (new ones prefixed by >>, old ones prefixed by <<):

WARNING: modpost: missing MODULE_DESCRIPTION() in fs/unicode/utf8-selftest.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/isofs/isofs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/hfs/hfs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/sysv/sysv.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/hpfs/hpfs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/efs/efs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/qnx6/qnx6.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/adfs/adfs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/bcachefs/mean_and_variance_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in crypto/xor.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/kunit/kunit.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/kunit/kunit-test.o
ERROR: modpost: missing MODULE_LICENSE() in lib/kunit/assert_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/kunit/assert_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/kunit/kunit-example-test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/zlib_deflate/zlib_deflate.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/pinctrl/pinctrl-mcp23s08_i2c.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/pinctrl/pinctrl-mcp23s08.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpio/gpio-gw-pld.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpio/gpio-pcf857x.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/video/console/mdacon.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/clk/clk_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/clk/clk-fractional-divider_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/regulator/da9121-regulator.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/regulator/rt4831-regulator.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/regulator/tps6286x-regulator.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/tty/serial/8250/serial_cs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/tty/goldfish.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/char/dtlk.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/char/tlclk.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-kunit.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-i2c.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-ram.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-raw-ram.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/block/floppy.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/misc/open-dice.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mfd/arizona.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mfd/rt4831.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mfd/qcom-pm8008.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/scsi/aha1542.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/scsi/g_NCR5380.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/cdrom/cdrom.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/pcmcia/i82365.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/misc/ezusb.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/misc/isight_firmware.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/mon/usbmon.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/serial/ch341.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/serial/usb_debug.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/serial/navman.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/serial/usb-serial-simple.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/input/matrix-keymap.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/input/vivaldi-fmap.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/input/tests/input_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mmc/core/mmc_core.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mmc/core/sdio_uart.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/firmware/google/cbmem.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-apple.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-belkin.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-bigbenff.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-cherry.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-chicony.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-elecom.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-elo.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-ezkey.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-vivaldi-common.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-google-hammer.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-kensington.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-logitech.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-lg-g15.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-logitech-dj.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-logitech-hidpp.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-maltron.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-mf.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-ntrig.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-petalynx.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-retrode.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-saitek.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-samsung.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-semitek.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-sjoy.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-sunplus.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-topseed.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-twinhan.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hid/hid-xinmo.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/greybus/gb-es2.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-bootrom.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-log.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-loopback.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-power-supply.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-gpio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-i2c.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-sdio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/staging/greybus/gb-uart.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/platform/chrome/cros_kunit_proto_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/nvmem/nvmem_u-boot-env.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/fsi/fsi-scom.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/uio/uio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hwmon/mr75203.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/vfio-mdev/mtty.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/configfs/configfs_sample.o
>> ERROR: modpost: "kunit_alloc_string_stream" [lib/kunit/assert_test.ko] undefined!
>> ERROR: modpost: "string_stream_get_string" [lib/kunit/assert_test.ko] undefined!
>> ERROR: modpost: "string_stream_clear" [lib/kunit/assert_test.ko] undefined!

kernel test robot

unread,
May 9, 2024, 3:45:11 AMMay 9
to Ivan Orlov, brendan...@linux.dev, davi...@google.com, rm...@google.com, oe-kbu...@lists.linux.dev, Ivan Orlov, linux-k...@vger.kernel.org, kuni...@googlegroups.com, linux-...@vger.kernel.org, sk...@linuxfoundation.org
Hi Ivan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on shuah-kselftest/kunit]
[also build test WARNING on shuah-kselftest/kunit-fixes linus/master v6.9-rc7 next-20240508]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Ivan-Orlov/kunit-Cover-assert-c-with-tests/20240508-212654
base: https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git kunit
patch link: https://lore.kernel.org/r/20240508132557.599213-1-ivan.orlov0322%40gmail.com
patch subject: [PATCH v2] kunit: Cover 'assert.c' with tests
config: i386-randconfig-004-20240509 (https://download.01.org/0day-ci/archive/20240509/202405091540...@intel.com/config)
compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240509/202405091540...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <l...@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405091540...@intel.com/

All warnings (new ones prefixed by >>):

>> lib/kunit/assert.c:35:6: warning: no previous prototype for 'kunit_assert_print_msg' [-Wmissing-prototypes]
35 | void kunit_assert_print_msg(const struct va_format *message,
| ^~~~~~~~~~~~~~~~~~~~~~
>> lib/kunit/assert.c:95:23: warning: no previous prototype for 'is_literal' [-Wmissing-prototypes]
95 | VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
| ^~~~~~~~~~
>> lib/kunit/assert.c:173:23: warning: no previous prototype for 'is_str_literal' [-Wmissing-prototypes]
173 | VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
| ^~~~~~~~~~~~~~
>> lib/kunit/assert.c:217:6: warning: no previous prototype for 'kunit_assert_hexdump' [-Wmissing-prototypes]
217 | void kunit_assert_hexdump(struct string_stream *stream,
| ^~~~~~~~~~~~~~~~~~~~

Ivan Orlov

unread,
May 9, 2024, 5:05:53 AMMay 9
to brendan...@linux.dev, davi...@google.com, rm...@google.com, Ivan Orlov, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
V2 -> V3:
- Make test case array and test suite definitions static
- Change the condition in `assert.h`: we should declare VISIBLE_IF_KUNIT
functions in the header file when CONFIG_KUNIT is enabled, not
CONFIG_KUNIT_TEST. Otherwise, if CONFIG_KUNIT_TEST is disabled,
VISIBLE_IF_KUNIT functions in the `assert.c` are not static, and
prototypes for them can't be found.
- Add MODULE_LICENSE and MODULE_DESCRIPTION macros

include/kunit/assert.h | 11 ++
lib/kunit/Makefile | 1 +
lib/kunit/assert.c | 24 ++-
lib/kunit/assert_test.c | 391 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 419 insertions(+), 8 deletions(-)
create mode 100644 lib/kunit/assert_test.c

diff --git a/include/kunit/assert.h b/include/kunit/assert.h
index 24c2b9fa61e8..7e7490a74b13 100644
--- a/include/kunit/assert.h
+++ b/include/kunit/assert.h
@@ -218,4 +218,15 @@ void kunit_mem_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream);

+#if IS_ENABLED(CONFIG_KUNIT)
void kunit_fail_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
@@ -89,7 +92,7 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);

/* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */
-static bool is_literal(const char *text, long long value)
+VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
{
char *buffer;
int len;
@@ -110,6 +113,7 @@ static bool is_literal(const char *text, long long value)

return ret;
}
+EXPORT_SYMBOL_IF_KUNIT(is_literal);

void kunit_binary_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
@@ -166,7 +170,7 @@ EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
/* Checks if KUNIT_EXPECT_STREQ() args were string literals.
* Note: `text` will have ""s where as `value` will not.
*/
-static bool is_str_literal(const char *text, const char *value)
+VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
{
int len;

@@ -178,6 +182,7 @@ static bool is_str_literal(const char *text, const char *value)

return strncmp(text + 1, value, len - 2) == 0;
}
+EXPORT_SYMBOL_IF_KUNIT(is_str_literal);

void kunit_binary_str_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
@@ -208,10 +213,11 @@ EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
/* Adds a hexdump of a buffer to a string_stream comparing it with
* a second buffer. The different bytes are marked with <>.
*/
-static void kunit_assert_hexdump(struct string_stream *stream,
- const void *buf,
- const void *compared_buf,
- const size_t len)
+VISIBLE_IF_KUNIT
+void kunit_assert_hexdump(struct string_stream *stream,
+ const void *buf,
+ const void *compared_buf,
+ const size_t len)
{
size_t i;
const u8 *buf1 = buf;
@@ -229,6 +235,7 @@ static void kunit_assert_hexdump(struct string_stream *stream,
string_stream_add(stream, " %02x ", buf1[i]);
}
}
+EXPORT_SYMBOL_IF_KUNIT(kunit_assert_hexdump);

void kunit_mem_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
@@ -269,4 +276,5 @@ void kunit_mem_assert_format(const struct kunit_assert *assert,
kunit_assert_print_msg(message, stream);
}
}
+
EXPORT_SYMBOL_GPL(kunit_mem_assert_format);
diff --git a/lib/kunit/assert_test.c b/lib/kunit/assert_test.c
new file mode 100644
index 000000000000..1347a964204b
--- /dev/null
+++ b/lib/kunit/assert_test.c
@@ -0,0 +1,391 @@
+static struct kunit_case assert_test_cases[] = {
+ KUNIT_CASE(kunit_test_is_literal),
+ KUNIT_CASE(kunit_test_is_str_literal),
+ KUNIT_CASE(kunit_test_assert_prologue),
+ KUNIT_CASE(kunit_test_assert_print_msg),
+ KUNIT_CASE(kunit_test_unary_assert_format),
+ KUNIT_CASE(kunit_test_ptr_not_err_assert_format),
+ KUNIT_CASE(kunit_test_binary_assert_format),
+ KUNIT_CASE(kunit_test_binary_ptr_assert_format),
+ KUNIT_CASE(kunit_test_binary_str_assert_format),
+ KUNIT_CASE(kunit_test_assert_hexdump),
+ KUNIT_CASE(kunit_test_mem_assert_format),
+ {}
+};
+
+static struct kunit_suite assert_test_suite = {
+ .name = "kunit-assert",
+ .test_cases = assert_test_cases,
+};
+
+MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+kunit_test_suites(&assert_test_suite);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Test for the KUnit assertion format functions.");
--
2.34.1

Rae Moar

unread,
May 13, 2024, 8:17:49 PMMay 13
to Ivan Orlov, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
On Thu, May 9, 2024 at 5:05 AM Ivan Orlov <ivan.or...@gmail.com> wrote:
>
> There are multiple assertion formatting functions in the `assert.c`
> file, which are not covered with tests yet. Implement the KUnit test
> for these functions.
>
> The test consists of 11 test cases for the following functions:
>
> 1) 'is_literal'
> 2) 'is_str_literal'
> 3) 'kunit_assert_prologue', test case for multiple assert types
> 4) 'kunit_assert_print_msg'
> 5) 'kunit_unary_assert_format'
> 6) 'kunit_ptr_not_err_assert_format'
> 7) 'kunit_binary_assert_format'
> 8) 'kunit_binary_ptr_assert_format'
> 9) 'kunit_binary_str_assert_format'
> 10) 'kunit_assert_hexdump'
> 11) 'kunit_mem_assert_format'
>
> The test aims at maximizing the branch coverage for the assertion
> formatting functions.
>
> As you can see, it covers some of the static helper functions as
> well, so mark the static functions in `assert.c` as 'VISIBLE_IF_KUNIT'
> and conditionally export them with EXPORT_SYMBOL_IF_KUNIT. Add the
> corresponding definitions to `assert.h`.
>
> Build the assert test when CONFIG_KUNIT_TEST is enabled, similar to
> how it is done for the string stream test.

Hello!

This looks great to me! Thanks for all your work on this! There is
just one comment I have below. Once that is fixed up, I am happy to
add a reviewed-by.

Thanks!
-Rae
When trying to make the kernel with this test loaded in, I am getting
an error that string_stream_get_string, string_stream_clear, and
kunit_alloc_string_stream are undefined.

So either these three methods will have to be exported using
EXPORT_SYMBOL_KUNIT or this test cannot be loaded and run as a module.

But once this is fixed up this should be good to go.

Ivan Orlov

unread,
May 14, 2024, 10:31:40 AMMay 14
to Rae Moar, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
Hi Rae,

Thank you so much for the review.

At the moment, I believe the best approach would be to make this test
depend on CONFIG_KUNIT_TEST=y (as it is done for string-stream-test).

However, I assume that every (standalone) test should be able to run as
a module, and I'd like to add EXPORT_SYMBOL_IF_KUNIT to all of the
non-static string-stream functions in a separate patch series. It will
require updating string-stream-test.c as well (adding MODULE_IMPORT_NS).
What do you think?

Thank you once again,

Rae Moar

unread,
May 14, 2024, 3:55:34 PMMay 14
to Ivan Orlov, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
Hello!

This sounds like a great approach! Happy to review the new patch
series when it comes in.

Thanks,
Rae

>

Ivan Orlov

unread,
May 14, 2024, 4:00:33 PMMay 14
to Rae Moar, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
On 5/14/24 20:55, 'Rae Moar' via KUnit Development wrote:
>> Thank you once again,
>> --
>> Kind regards,
>> Ivan Orlov
>
> Hello!
>
> This sounds like a great approach! Happy to review the new patch
> series when it comes in.
>
> Thanks,
> Rae
>


Awesome, thank you!

Ivan Orlov

unread,
May 15, 2024, 10:21:02 AMMay 15
to brendan...@linux.dev, davi...@google.com, rm...@google.com, Ivan Orlov, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
There are multiple assertion formatting functions in the `assert.c`
file, which are not covered with tests yet. Implement the KUnit test
for these functions.

The test consists of 11 test cases for the following functions:

1) 'is_literal'
2) 'is_str_literal'
3) 'kunit_assert_prologue', test case for multiple assert types
4) 'kunit_assert_print_msg'
5) 'kunit_unary_assert_format'
6) 'kunit_ptr_not_err_assert_format'
7) 'kunit_binary_assert_format'
8) 'kunit_binary_ptr_assert_format'
9) 'kunit_binary_str_assert_format'
10) 'kunit_assert_hexdump'
11) 'kunit_mem_assert_format'

The test aims at maximizing the branch coverage for the assertion
formatting functions.

As you can see, it covers some of the static helper functions as
well, so mark the static functions in `assert.c` as 'VISIBLE_IF_KUNIT'
and conditionally export them with EXPORT_SYMBOL_IF_KUNIT. Add the
corresponding definitions to `assert.h`.

Build the assert test when CONFIG_KUNIT_TEST is enabled, similar to
how it is done for the string stream test.

Signed-off-by: Ivan Orlov <ivan.or...@gmail.com>
---
V1 -> V2:
- Check the output from the string stream for containing the key parts
instead of comparing the results with expected strings char by char, as
it was suggested by Rae Moar <rm...@google.com>. Define two macros to
make it possible (ASSERT_TEST_EXPECT_CONTAIN and
ASSERT_TEST_EXPECT_NCONTAIN).
- Mark the static functions in `assert.c` as VISIBLE_IF_KUNIT and export
them conditionally if kunit is enabled instead of including the
`assert_test.c` file in the end of `assert.c`. This way we will decouple
the test from the implementation (SUT).
- Update the kunit_assert_hexdump test: now it checks for presense of
the brackets '<>' around the non-matching bytes, instead of comparing
the kunit_assert_hexdump output char by char.
V2 -> V3:
- Make test case array and test suite definitions static
- Change the condition in `assert.h`: we should declare VISIBLE_IF_KUNIT
functions in the header file when CONFIG_KUNIT is enabled, not
CONFIG_KUNIT_TEST. Otherwise, if CONFIG_KUNIT_TEST is disabled,
VISIBLE_IF_KUNIT functions in the `assert.c` are not static, and
prototypes for them can't be found.
- Add MODULE_LICENSE and MODULE_DESCRIPTION macros
V3 -> V4:
- Compile the assertion test only when CONFIG_KUNIT_TEST is set to 'y',
as it is done for the string-stream test. It is necessary since
functions from the string-stream are not exported into the public
namespace, and therefore they are not accessible when linking and
loading the test module.
index 309659a32a78..900e6447c8e8 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_KUNIT_TEST) += kunit-test.o
# string-stream-test compiles built-in only.
ifeq ($(CONFIG_KUNIT_TEST),y)
obj-$(CONFIG_KUNIT_TEST) += string-stream-test.o
+obj-$(CONFIG_KUNIT_TEST) += assert_test.o
endif

obj-$(CONFIG_KUNIT_EXAMPLE_TEST) += kunit-example-test.o

Rae Moar

unread,
May 16, 2024, 2:57:23 PMMay 16
to Ivan Orlov, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
Hi Ivan!

This looks great! Just one last thing, since this test is no longer
loadable as a module, could you remove the exporting of new symbols
and adding of the module license. Those can be part of the next patch,
where we convert these tests to modules.

Thanks!
-Rae
This symbol does not have to be exported because the test is not
loadable as a module.

>
> void kunit_fail_assert_format(const struct kunit_assert *assert,
> const struct va_format *message,
> @@ -89,7 +92,7 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
> EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);
>
> /* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */
> -static bool is_literal(const char *text, long long value)
> +VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
> {
> char *buffer;
> int len;
> @@ -110,6 +113,7 @@ static bool is_literal(const char *text, long long value)
>
> return ret;
> }
> +EXPORT_SYMBOL_IF_KUNIT(is_literal);

Same here.

>
> void kunit_binary_assert_format(const struct kunit_assert *assert,
> const struct va_format *message,
> @@ -166,7 +170,7 @@ EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
> /* Checks if KUNIT_EXPECT_STREQ() args were string literals.
> * Note: `text` will have ""s where as `value` will not.
> */
> -static bool is_str_literal(const char *text, const char *value)
> +VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
> {
> int len;
>
> @@ -178,6 +182,7 @@ static bool is_str_literal(const char *text, const char *value)
>
> return strncmp(text + 1, value, len - 2) == 0;
> }
> +EXPORT_SYMBOL_IF_KUNIT(is_str_literal);

Same here.

>
> void kunit_binary_str_assert_format(const struct kunit_assert *assert,
> const struct va_format *message,
> @@ -208,10 +213,11 @@ EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
> /* Adds a hexdump of a buffer to a string_stream comparing it with
> * a second buffer. The different bytes are marked with <>.
> */
> -static void kunit_assert_hexdump(struct string_stream *stream,
> - const void *buf,
> - const void *compared_buf,
> - const size_t len)
> +VISIBLE_IF_KUNIT
> +void kunit_assert_hexdump(struct string_stream *stream,
> + const void *buf,
> + const void *compared_buf,
> + const size_t len)
> {
> size_t i;
> const u8 *buf1 = buf;
> @@ -229,6 +235,7 @@ static void kunit_assert_hexdump(struct string_stream *stream,
> string_stream_add(stream, " %02x ", buf1[i]);
> }
> }
> +EXPORT_SYMBOL_IF_KUNIT(kunit_assert_hexdump);

Same here.
This is not needed as this test cannot be loaded as a module.

> +kunit_test_suites(&assert_test_suite);
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("Test for the KUnit assertion format functions.");

Same here with the license and description.

> --
> 2.34.1
>

Ivan Orlov

unread,
May 16, 2024, 4:14:27 PMMay 16
to Rae Moar, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
Hi Rae,

Ah, sorry, I completely forgot to remove the module-related part. Thank
you for the review, and I'll try to be more attentive next time :)

Ivan Orlov

unread,
May 16, 2024, 5:17:40 PMMay 16
to brendan...@linux.dev, davi...@google.com, rm...@google.com, Ivan Orlov, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
V4 -> V5:
- Remove EXPORT_SYMBOL_IF_KUNIT from the assert.c and all of the
module-related macros from the test source since the test can't
be used as a loadable module for now (see V3 -> V4).

include/kunit/assert.h | 11 ++
lib/kunit/Makefile | 1 +
lib/kunit/assert.c | 19 +-
lib/kunit/assert_test.c | 388 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 411 insertions(+), 8 deletions(-)
index dd1d633d0fe2..867aa5c4bccf 100644
--- a/lib/kunit/assert.c
+++ b/lib/kunit/assert.c
@@ -7,6 +7,7 @@
*/
#include <kunit/assert.h>
#include <kunit/test.h>
+#include <kunit/visibility.h>

#include "string-stream.h"

@@ -30,8 +31,9 @@ void kunit_assert_prologue(const struct kunit_loc *loc,
}
EXPORT_SYMBOL_GPL(kunit_assert_prologue);

-static void kunit_assert_print_msg(const struct va_format *message,
- struct string_stream *stream)
+VISIBLE_IF_KUNIT
+void kunit_assert_print_msg(const struct va_format *message,
+ struct string_stream *stream)
{
if (message->fmt)
string_stream_add(stream, "\n%pV", message);
@@ -89,7 +91,7 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);

/* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */
-static bool is_literal(const char *text, long long value)
+VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
{
char *buffer;
int len;
@@ -166,7 +168,7 @@ EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
/* Checks if KUNIT_EXPECT_STREQ() args were string literals.
* Note: `text` will have ""s where as `value` will not.
*/
-static bool is_str_literal(const char *text, const char *value)
+VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
{
int len;

@@ -208,10 +210,11 @@ EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
/* Adds a hexdump of a buffer to a string_stream comparing it with
* a second buffer. The different bytes are marked with <>.
*/
-static void kunit_assert_hexdump(struct string_stream *stream,
- const void *buf,
- const void *compared_buf,
- const size_t len)
+VISIBLE_IF_KUNIT
+void kunit_assert_hexdump(struct string_stream *stream,
+ const void *buf,
+ const void *compared_buf,
+ const size_t len)
{
size_t i;
const u8 *buf1 = buf;
diff --git a/lib/kunit/assert_test.c b/lib/kunit/assert_test.c
new file mode 100644
index 000000000000..4a5967712186
--- /dev/null
+++ b/lib/kunit/assert_test.c
@@ -0,0 +1,388 @@
+kunit_test_suites(&assert_test_suite);
--
2.34.1

Rae Moar

unread,
May 20, 2024, 5:12:36 PMMay 20
to Ivan Orlov, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
Hi! This looks great to me!

Reviewed-by: Rae Moar <rm...@google.com>

Thanks!
-Rae

Ivan Orlov

unread,
May 29, 2024, 9:27:57 AMMay 29
to Rae Moar, brendan...@linux.dev, davi...@google.com, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
Hi Rae,

Thank you so much for the review and sorry for the late reply :)

David Gow

unread,
May 30, 2024, 12:22:46 AMMay 30
to Ivan Orlov, brendan...@linux.dev, rm...@google.com, linux-k...@vger.kernel.org, linux-...@vger.kernel.org, kuni...@googlegroups.com, sk...@linuxfoundation.org
This looks good to me, and passes all of my tests locally.

Note that this does have some checkpatch warnings:

WARNING: Using vsprintf specifier '%px' potentially exposes the kernel
memory layout, if you don't really need the address please consider
using '%p'.
#426: FILE: lib/kunit/assert_test.c:250:
+ snprintf(addr_var_a, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_a);

WARNING: Using vsprintf specifier '%px' potentially exposes the kernel
memory layout, if you don't really need the address please consider
using '%p'.
#427: FILE: lib/kunit/assert_test.c:251:
+ snprintf(addr_var_b, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_b);

These are necessary, as KUnit _does_ expose the kernel memory layout
(on purpose), as it's useful for debugging. This is one of the reasons
why KUnit tests taint the kernel: to make it clear that this could be
a problem.

Acked-by: David Gow <davi...@google.com>

Cheers,
-- David
Reply all
Reply to author
Forward
0 new messages