Skip to content

Commit

Permalink
Merge tag 'linux_kselftest-kunit-6.11-rc1' of git://git.kernel.org/pu…
Browse files Browse the repository at this point in the history
…b/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
  • Loading branch information
torvalds committed Jul 17, 2024
2 parents 9de4ad3 + ebf51e4 commit f8d22a3
Show file tree
Hide file tree
Showing 20 changed files with 978 additions and 373 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion drivers/input/tests/input_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 12 additions & 1 deletion include/kunit/assert.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
88 changes: 85 additions & 3 deletions include/kunit/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, ...);
Expand Down Expand Up @@ -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__)

/**
Expand Down Expand Up @@ -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.
Expand All @@ -1458,6 +1486,60 @@ do { \
fmt, \
##__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.
Expand Down
3 changes: 3 additions & 0 deletions kernel/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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)
{
Expand Down
21 changes: 9 additions & 12 deletions lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions lib/kunit/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -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
19 changes: 11 additions & 8 deletions lib/kunit/assert.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
#include <kunit/assert.h>
#include <kunit/test.h>
#include <kunit/visibility.h>

#include "string-stream.h"

Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit f8d22a3

Please sign in to comment.