aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-07-16 17:42:14 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2024-07-16 17:42:14 -0700
commitf8d22a3195b8e2eaacbc5073ae1d5d5bb7386de9 (patch)
tree6c345750b684e137b06c63e40000111f365ae8fc
parent9de4ad3bde144b55b8451fc280c18107c139481c (diff)
parentebf51e460e488511d9ee60b07d00dac68883facf (diff)
Merge tag 'linux_kselftest-kunit-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull KUnit updates from Shuah Khan: - add vm_mmap() allocation resource manager - convert usercopy kselftest to KUnit - disable usercopy testing on !CONFIG_MMU - add MODULE_DESCRIPTION() to core, list, and usercopy tests - add tests for assertion formatting functions - assert.c - introduce KUNIT_ASSERT_MEMEQ and KUNIT_ASSERT_MEMNEQ macros - fix KUNIT_ASSERT_STRNEQ comments to make it clear that it is an assertion - rename KUNIT_ASSERT_FAILURE to KUNIT_FAIL_AND_ABORT * tag 'linux_kselftest-kunit-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: kunit: Introduce KUNIT_ASSERT_MEMEQ and KUNIT_ASSERT_MEMNEQ macros kunit: Rename KUNIT_ASSERT_FAILURE to KUNIT_FAIL_AND_ABORT for readability kunit: Fix the comment of KUNIT_ASSERT_STRNEQ as assertion kunit: executor: Simplify string allocation handling kunit/usercopy: Add missing MODULE_DESCRIPTION() kunit/usercopy: Disable testing on !CONFIG_MMU usercopy: Convert test_user_copy to KUnit test kunit: test: Add vm_mmap() allocation resource manager list: test: add the missing MODULE_DESCRIPTION() macro kunit: add missing MODULE_DESCRIPTION() macros to core modules list: test: remove unused struct 'klist_test_struct' kunit: Cover 'assert.c' with tests
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/input/tests/input_test.c2
-rw-r--r--include/kunit/assert.h13
-rw-r--r--include/kunit/test.h88
-rw-r--r--kernel/fork.c3
-rw-r--r--lib/Kconfig.debug21
-rw-r--r--lib/Makefile2
-rw-r--r--lib/kunit/Makefile2
-rw-r--r--lib/kunit/assert.c19
-rw-r--r--lib/kunit/assert_test.c388
-rw-r--r--lib/kunit/executor.c12
-rw-r--r--lib/kunit/executor_test.c2
-rw-r--r--lib/kunit/kunit-example-test.c1
-rw-r--r--lib/kunit/kunit-test.c1
-rw-r--r--lib/kunit/test.c1
-rw-r--r--lib/kunit/user_alloc.c117
-rw-r--r--lib/list-test.c7
-rw-r--r--lib/test_user_copy.c331
-rw-r--r--lib/usercopy_kunit.c335
-rw-r--r--mm/util.c5
20 files changed, 978 insertions, 373 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 8377529c9b95..788ee9b4dd80 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12034,6 +12034,7 @@ F: arch/*/configs/hardening.config
F: include/linux/overflow.h
F: include/linux/randomize_kstack.h
F: kernel/configs/hardening.config
+F: lib/usercopy_kunit.c
F: mm/usercopy.c
K: \b(add|choose)_random_kstack_offset\b
K: \b__check_(object_size|heap_object)\b
diff --git a/drivers/input/tests/input_test.c b/drivers/input/tests/input_test.c
index 2fa5b725ae0a..9711ced180b8 100644
--- a/drivers/input/tests/input_test.c
+++ b/drivers/input/tests/input_test.c
@@ -31,7 +31,7 @@ static int input_test_init(struct kunit *test)
ret = input_register_device(input_dev);
if (ret) {
input_free_device(input_dev);
- KUNIT_ASSERT_FAILURE(test, "Register device failed: %d", ret);
+ KUNIT_FAIL_AND_ABORT(test, "Register device failed: %d", ret);
}
test->priv = input_dev;
diff --git a/include/kunit/assert.h b/include/kunit/assert.h
index 24c2b9fa61e8..bb879389f11d 100644
--- a/include/kunit/assert.h
+++ b/include/kunit/assert.h
@@ -60,7 +60,7 @@ void kunit_assert_prologue(const struct kunit_loc *loc,
* struct kunit_fail_assert - Represents a plain fail expectation/assertion.
* @assert: The parent of this type.
*
- * Represents a simple KUNIT_FAIL/KUNIT_ASSERT_FAILURE that always fails.
+ * Represents a simple KUNIT_FAIL/KUNIT_FAIL_AND_ABORT that always fails.
*/
struct kunit_fail_assert {
struct kunit_assert assert;
@@ -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_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/include/kunit/test.h b/include/kunit/test.h
index e32b4cb7afa2..e2a1f0928e8b 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -480,6 +480,23 @@ static inline void *kunit_kcalloc(struct kunit *test, size_t n, size_t size, gfp
return kunit_kmalloc_array(test, n, size, gfp | __GFP_ZERO);
}
+/**
+ * kunit_vm_mmap() - Allocate KUnit-tracked vm_mmap() area
+ * @test: The test context object.
+ * @file: struct file pointer to map from, if any
+ * @addr: desired address, if any
+ * @len: how many bytes to allocate
+ * @prot: mmap PROT_* bits
+ * @flag: mmap flags
+ * @offset: offset into @file to start mapping from.
+ *
+ * See vm_mmap() for more information.
+ */
+unsigned long kunit_vm_mmap(struct kunit *test, struct file *file,
+ unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flag,
+ unsigned long offset);
+
void kunit_cleanup(struct kunit *test);
void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt, ...);
@@ -1211,7 +1228,18 @@ do { \
fmt, \
##__VA_ARGS__)
-#define KUNIT_ASSERT_FAILURE(test, fmt, ...) \
+/**
+ * KUNIT_FAIL_AND_ABORT() - Always causes a test to fail and abort when evaluated.
+ * @test: The test context object.
+ * @fmt: an informational message to be printed when the assertion is made.
+ * @...: string format arguments.
+ *
+ * The opposite of KUNIT_SUCCEED(), it is an assertion that always fails. In
+ * other words, it always results in a failed assertion, and consequently
+ * always causes the test case to fail and abort when evaluated.
+ * See KUNIT_ASSERT_TRUE() for more information.
+ */
+#define KUNIT_FAIL_AND_ABORT(test, fmt, ...) \
KUNIT_FAIL_ASSERTION(test, KUNIT_ASSERTION, fmt, ##__VA_ARGS__)
/**
@@ -1438,12 +1466,12 @@ do { \
##__VA_ARGS__)
/**
- * KUNIT_ASSERT_STRNEQ() - Expects that strings @left and @right are not equal.
+ * KUNIT_ASSERT_STRNEQ() - An assertion that strings @left and @right are not equal.
* @test: The test context object.
* @left: an arbitrary expression that evaluates to a null terminated string.
* @right: an arbitrary expression that evaluates to a null terminated string.
*
- * Sets an expectation that the values that @left and @right evaluate to are
+ * Sets an assertion that the values that @left and @right evaluate to are
* not equal. This is semantically equivalent to
* KUNIT_ASSERT_TRUE(@test, strcmp((@left), (@right))). See KUNIT_ASSERT_TRUE()
* for more information.
@@ -1459,6 +1487,60 @@ do { \
##__VA_ARGS__)
/**
+ * KUNIT_ASSERT_MEMEQ() - Asserts that the first @size bytes of @left and @right are equal.
+ * @test: The test context object.
+ * @left: An arbitrary expression that evaluates to the specified size.
+ * @right: An arbitrary expression that evaluates to the specified size.
+ * @size: Number of bytes compared.
+ *
+ * Sets an assertion that the values that @left and @right evaluate to are
+ * equal. This is semantically equivalent to
+ * KUNIT_ASSERT_TRUE(@test, !memcmp((@left), (@right), (@size))). See
+ * KUNIT_ASSERT_TRUE() for more information.
+ *
+ * Although this assertion works for any memory block, it is not recommended
+ * for comparing more structured data, such as structs. This assertion is
+ * recommended for comparing, for example, data arrays.
+ */
+#define KUNIT_ASSERT_MEMEQ(test, left, right, size) \
+ KUNIT_ASSERT_MEMEQ_MSG(test, left, right, size, NULL)
+
+#define KUNIT_ASSERT_MEMEQ_MSG(test, left, right, size, fmt, ...) \
+ KUNIT_MEM_ASSERTION(test, \
+ KUNIT_ASSERTION, \
+ left, ==, right, \
+ size, \
+ fmt, \
+ ##__VA_ARGS__)
+
+/**
+ * KUNIT_ASSERT_MEMNEQ() - Asserts that the first @size bytes of @left and @right are not equal.
+ * @test: The test context object.
+ * @left: An arbitrary expression that evaluates to the specified size.
+ * @right: An arbitrary expression that evaluates to the specified size.
+ * @size: Number of bytes compared.
+ *
+ * Sets an assertion that the values that @left and @right evaluate to are
+ * not equal. This is semantically equivalent to
+ * KUNIT_ASSERT_TRUE(@test, memcmp((@left), (@right), (@size))). See
+ * KUNIT_ASSERT_TRUE() for more information.
+ *
+ * Although this assertion works for any memory block, it is not recommended
+ * for comparing more structured data, such as structs. This assertion is
+ * recommended for comparing, for example, data arrays.
+ */
+#define KUNIT_ASSERT_MEMNEQ(test, left, right, size) \
+ KUNIT_ASSERT_MEMNEQ_MSG(test, left, right, size, NULL)
+
+#define KUNIT_ASSERT_MEMNEQ_MSG(test, left, right, size, fmt, ...) \
+ KUNIT_MEM_ASSERTION(test, \
+ KUNIT_ASSERTION, \
+ left, !=, right, \
+ size, \
+ fmt, \
+ ##__VA_ARGS__)
+
+/**
* KUNIT_ASSERT_NULL() - Asserts that pointers @ptr is null.
* @test: The test context object.
* @ptr: an arbitrary pointer.
diff --git a/kernel/fork.c b/kernel/fork.c
index 63a76166497a..942e3d8617bf 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -115,6 +115,8 @@
#define CREATE_TRACE_POINTS
#include <trace/events/task.h>
+#include <kunit/visibility.h>
+
/*
* Minimum number of threads to boot the kernel
*/
@@ -1328,6 +1330,7 @@ struct mm_struct *mm_alloc(void)
memset(mm, 0, sizeof(*mm));
return mm_init(mm, current, current_user_ns());
}
+EXPORT_SYMBOL_IF_KUNIT(mm_alloc);
static inline void __mmput(struct mm_struct *mm)
{
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 59b6765d86b8..561e346f5cb0 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2505,18 +2505,6 @@ config TEST_VMALLOC
If unsure, say N.
-config TEST_USER_COPY
- tristate "Test user/kernel boundary protections"
- depends on m
- help
- This builds the "test_user_copy" module that runs sanity checks
- on the copy_to/from_user infrastructure, making sure basic
- user/kernel boundary testing is working. If it fails to load,
- a regression has been detected in the user/kernel memory boundary
- protections.
-
- If unsure, say N.
-
config TEST_BPF
tristate "Test BPF filter functionality"
depends on m && NET
@@ -2814,6 +2802,15 @@ config SIPHASH_KUNIT_TEST
This is intended to help people writing architecture-specific
optimized versions. If unsure, say N.
+config USERCOPY_KUNIT_TEST
+ tristate "KUnit Test for user/kernel boundary protections"
+ depends on KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ This builds the "usercopy_kunit" module that runs sanity checks
+ on the copy_to/from_user infrastructure, making sure basic
+ user/kernel boundary testing is working.
+
config TEST_UDELAY
tristate "udelay test driver"
help
diff --git a/lib/Makefile b/lib/Makefile
index 30337431d10e..322bb127b4dc 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -78,7 +78,6 @@ obj-$(CONFIG_TEST_LKM) += test_module.o
obj-$(CONFIG_TEST_VMALLOC) += test_vmalloc.o
obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
obj-$(CONFIG_TEST_SORT) += test_sort.o
-obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
obj-$(CONFIG_TEST_DYNAMIC_DEBUG) += test_dynamic_debug.o
@@ -388,6 +387,7 @@ CFLAGS_fortify_kunit.o += $(call cc-disable-warning, stringop-truncation)
CFLAGS_fortify_kunit.o += $(DISABLE_STRUCTLEAK_PLUGIN)
obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o
obj-$(CONFIG_SIPHASH_KUNIT_TEST) += siphash_kunit.o
+obj-$(CONFIG_USERCOPY_KUNIT_TEST) += usercopy_kunit.o
obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 309659a32a78..30f6bbf04a4a 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_KUNIT) += kunit.o
kunit-objs += test.o \
resource.o \
+ user_alloc.o \
static_stub.o \
string-stream.o \
assert.o \
@@ -22,6 +23,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
diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c
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 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * KUnit test for the assertion formatting functions.
+ * Author: Ivan Orlov <ivan.orlov0322@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))
+
+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;
+ 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", "==");
+}
+
+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,
+};
+
+kunit_test_suites(&assert_test_suite);
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
index 70b9a43cd257..34b7b6833df3 100644
--- a/lib/kunit/executor.c
+++ b/lib/kunit/executor.c
@@ -70,32 +70,26 @@ struct kunit_glob_filter {
static int kunit_parse_glob_filter(struct kunit_glob_filter *parsed,
const char *filter_glob)
{
- const int len = strlen(filter_glob);
const char *period = strchr(filter_glob, '.');
if (!period) {
- parsed->suite_glob = kzalloc(len + 1, GFP_KERNEL);
+ parsed->suite_glob = kstrdup(filter_glob, GFP_KERNEL);
if (!parsed->suite_glob)
return -ENOMEM;
-
parsed->test_glob = NULL;
- strcpy(parsed->suite_glob, filter_glob);
return 0;
}
- parsed->suite_glob = kzalloc(period - filter_glob + 1, GFP_KERNEL);
+ parsed->suite_glob = kstrndup(filter_glob, period - filter_glob, GFP_KERNEL);
if (!parsed->suite_glob)
return -ENOMEM;
- parsed->test_glob = kzalloc(len - (period - filter_glob) + 1, GFP_KERNEL);
+ parsed->test_glob = kstrdup(period + 1, GFP_KERNEL);
if (!parsed->test_glob) {
kfree(parsed->suite_glob);
return -ENOMEM;
}
- strncpy(parsed->suite_glob, filter_glob, period - filter_glob);
- strncpy(parsed->test_g