diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-12 16:42:57 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-12 16:42:57 -0800 |
commit | e2ed78d5d9ca07a2b9d158ebac366170a2d3083d (patch) | |
tree | 1c5e722706ca862849c149c39431f63c1a0f6cf5 /include | |
parent | 23a68d14def8247735b66a14b370b42d8fcedb47 (diff) | |
parent | 054be257f28ca8eeb8e3620766501b81ceb4b293 (diff) |
Merge tag 'linux-kselftest-kunit-next-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull KUnit updates from Shuah Khan:
"Several enhancements, fixes, clean-ups, documentation updates,
improvements to logging and KTAP compliance of KUnit test output:
- log numbers in decimal and hex
- parse KTAP compliant test output
- allow conditionally exposing static symbols to tests when KUNIT is
enabled
- make static symbols visible during kunit testing
- clean-ups to remove unused structure definition"
* tag 'linux-kselftest-kunit-next-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (29 commits)
Documentation: dev-tools: Clarify requirements for result description
apparmor: test: make static symbols visible during kunit testing
kunit: add macro to allow conditionally exposing static symbols to tests
kunit: tool: make parser preserve whitespace when printing test log
Documentation: kunit: Fix "How Do I Use This" / "Next Steps" sections
kunit: tool: don't include KTAP headers and the like in the test log
kunit: improve KTAP compliance of KUnit test output
kunit: tool: parse KTAP compliant test output
mm: slub: test: Use the kunit_get_current_test() function
kunit: Use the static key when retrieving the current test
kunit: Provide a static key to check if KUnit is actively running tests
kunit: tool: make --json do nothing if --raw_ouput is set
kunit: tool: tweak error message when no KTAP found
kunit: remove KUNIT_INIT_MEM_ASSERTION macro
Documentation: kunit: Remove redundant 'tips.rst' page
Documentation: KUnit: reword description of assertions
Documentation: KUnit: make usage.rst a superset of tips.rst, remove duplication
kunit: eliminate KUNIT_INIT_*_ASSERT_STRUCT macros
kunit: tool: remove redundant file.close() call in unit test
kunit: tool: unit tests all check parser errors, standardize formatting a bit
...
Diffstat (limited to 'include')
-rw-r--r-- | include/kunit/assert.h | 74 | ||||
-rw-r--r-- | include/kunit/test-bug.h | 53 | ||||
-rw-r--r-- | include/kunit/test.h | 118 | ||||
-rw-r--r-- | include/kunit/visibility.h | 33 |
4 files changed, 215 insertions, 63 deletions
diff --git a/include/kunit/assert.h b/include/kunit/assert.h index ace3de8d1ee7..24c2b9fa61e8 100644 --- a/include/kunit/assert.h +++ b/include/kunit/assert.h @@ -91,19 +91,6 @@ void kunit_unary_assert_format(const struct kunit_assert *assert, struct string_stream *stream); /** - * KUNIT_INIT_UNARY_ASSERT_STRUCT() - Initializes &struct kunit_unary_assert. - * @cond: A string representation of the expression asserted true or false. - * @expect_true: True if of type KUNIT_{EXPECT|ASSERT}_TRUE, false otherwise. - * - * Initializes a &struct kunit_unary_assert. Intended to be used in - * KUNIT_EXPECT_* and KUNIT_ASSERT_* macros. - */ -#define KUNIT_INIT_UNARY_ASSERT_STRUCT(cond, expect_true) { \ - .condition = cond, \ - .expected_true = expect_true \ -} - -/** * struct kunit_ptr_not_err_assert - An expectation/assertion that a pointer is * not NULL and not a -errno. * @assert: The parent of this type. @@ -124,20 +111,6 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert, struct string_stream *stream); /** - * KUNIT_INIT_PTR_NOT_ERR_ASSERT_STRUCT() - Initializes a - * &struct kunit_ptr_not_err_assert. - * @txt: A string representation of the expression passed to the expectation. - * @val: The actual evaluated pointer value of the expression. - * - * Initializes a &struct kunit_ptr_not_err_assert. Intended to be used in - * KUNIT_EXPECT_* and KUNIT_ASSERT_* macros. - */ -#define KUNIT_INIT_PTR_NOT_ERR_STRUCT(txt, val) { \ - .text = txt, \ - .value = val \ -} - -/** * struct kunit_binary_assert_text - holds strings for &struct * kunit_binary_assert and friends to try and make the structs smaller. * @operation: A string representation of the comparison operator (e.g. "=="). @@ -174,27 +147,6 @@ void kunit_binary_assert_format(const struct kunit_assert *assert, struct string_stream *stream); /** - * KUNIT_INIT_BINARY_ASSERT_STRUCT() - Initializes a binary assert like - * kunit_binary_assert, kunit_binary_ptr_assert, etc. - * - * @text_: Pointer to a kunit_binary_assert_text. - * @left_val: The actual evaluated value of the expression in the left slot. - * @right_val: The actual evaluated value of the expression in the right slot. - * - * Initializes a binary assert like kunit_binary_assert, - * kunit_binary_ptr_assert, etc. This relies on these structs having the same - * fields but with different types for left_val/right_val. - * This is ultimately used by binary assertion macros like KUNIT_EXPECT_EQ, etc. - */ -#define KUNIT_INIT_BINARY_ASSERT_STRUCT(text_, \ - left_val, \ - right_val) { \ - .text = text_, \ - .left_value = left_val, \ - .right_value = right_val \ -} - -/** * struct kunit_binary_ptr_assert - An expectation/assertion that compares two * pointer values (for example, KUNIT_EXPECT_PTR_EQ(test, foo, bar)). * @assert: The parent of this type. @@ -240,4 +192,30 @@ void kunit_binary_str_assert_format(const struct kunit_assert *assert, const struct va_format *message, struct string_stream *stream); +/** + * struct kunit_mem_assert - An expectation/assertion that compares two + * memory blocks. + * @assert: The parent of this type. + * @text: Holds the textual representations of the operands and comparator. + * @left_value: The actual evaluated value of the expression in the left slot. + * @right_value: The actual evaluated value of the expression in the right slot. + * @size: Size of the memory block analysed in bytes. + * + * Represents an expectation/assertion that compares two memory blocks. For + * example, to expect that the first three bytes of foo is equal to the + * first three bytes of bar, you can use the expectation + * KUNIT_EXPECT_MEMEQ(test, foo, bar, 3); + */ +struct kunit_mem_assert { + struct kunit_assert assert; + const struct kunit_binary_assert_text *text; + const void *left_value; + const void *right_value; + const size_t size; +}; + +void kunit_mem_assert_format(const struct kunit_assert *assert, + const struct va_format *message, + struct string_stream *stream); + #endif /* _KUNIT_ASSERT_H */ diff --git a/include/kunit/test-bug.h b/include/kunit/test-bug.h index 5fc58081d511..c1b2e14eab64 100644 --- a/include/kunit/test-bug.h +++ b/include/kunit/test-bug.h @@ -9,16 +9,63 @@ #ifndef _KUNIT_TEST_BUG_H #define _KUNIT_TEST_BUG_H -#define kunit_fail_current_test(fmt, ...) \ - __kunit_fail_current_test(__FILE__, __LINE__, fmt, ##__VA_ARGS__) - #if IS_BUILTIN(CONFIG_KUNIT) +#include <linux/jump_label.h> /* For static branch */ +#include <linux/sched.h> + +/* Static key if KUnit is running any tests. */ +DECLARE_STATIC_KEY_FALSE(kunit_running); + +/** + * kunit_get_current_test() - Return a pointer to the currently running + * KUnit test. + * + * If a KUnit test is running in the current task, returns a pointer to its + * associated struct kunit. This pointer can then be passed to any KUnit + * function or assertion. If no test is running (or a test is running in a + * different task), returns NULL. + * + * This function is safe to call even when KUnit is disabled. If CONFIG_KUNIT + * is not enabled, it will compile down to nothing and will return quickly no + * test is running. + */ +static inline struct kunit *kunit_get_current_test(void) +{ + if (!static_branch_unlikely(&kunit_running)) + return NULL; + + return current->kunit_test; +} + + +/** + * kunit_fail_current_test() - If a KUnit test is running, fail it. + * + * If a KUnit test is running in the current task, mark that test as failed. + * + * This macro will only work if KUnit is built-in (though the tests + * themselves can be modules). Otherwise, it compiles down to nothing. + */ +#define kunit_fail_current_test(fmt, ...) do { \ + if (static_branch_unlikely(&kunit_running)) { \ + __kunit_fail_current_test(__FILE__, __LINE__, \ + fmt, ##__VA_ARGS__); \ + } \ + } while (0) + + extern __printf(3, 4) void __kunit_fail_current_test(const char *file, int line, const char *fmt, ...); #else +static inline struct kunit *kunit_get_current_test(void) { return NULL; } + +/* We define this with an empty helper function so format string warnings work */ +#define kunit_fail_current_test(fmt, ...) \ + __kunit_fail_current_test(__FILE__, __LINE__, fmt, ##__VA_ARGS__) + static inline __printf(3, 4) void __kunit_fail_current_test(const char *file, int line, const char *fmt, ...) { diff --git a/include/kunit/test.h b/include/kunit/test.h index b1ab6b32216d..87ea90576b50 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -16,6 +16,7 @@ #include <linux/container_of.h> #include <linux/err.h> #include <linux/init.h> +#include <linux/jump_label.h> #include <linux/kconfig.h> #include <linux/kref.h> #include <linux/list.h> @@ -27,6 +28,9 @@ #include <asm/rwonce.h> +/* Static key: true if any KUnit tests are currently running */ +DECLARE_STATIC_KEY_FALSE(kunit_running); + struct kunit; /* Size of log associated with test. */ @@ -515,22 +519,25 @@ void kunit_do_failed_assertion(struct kunit *test, fmt, \ ##__VA_ARGS__) +/* Helper to safely pass around an initializer list to other macros. */ +#define KUNIT_INIT_ASSERT(initializers...) { initializers } + #define KUNIT_UNARY_ASSERTION(test, \ assert_type, \ - condition, \ - expected_true, \ + condition_, \ + expected_true_, \ fmt, \ ...) \ do { \ - if (likely(!!(condition) == !!expected_true)) \ + if (likely(!!(condition_) == !!expected_true_)) \ break; \ \ _KUNIT_FAILED(test, \ assert_type, \ kunit_unary_assert, \ kunit_unary_assert_format, \ - KUNIT_INIT_UNARY_ASSERT_STRUCT(#condition, \ - expected_true), \ + KUNIT_INIT_ASSERT(.condition = #condition_, \ + .expected_true = expected_true_), \ fmt, \ ##__VA_ARGS__); \ } while (0) @@ -590,9 +597,9 @@ do { \ assert_type, \ assert_class, \ format_func, \ - KUNIT_INIT_BINARY_ASSERT_STRUCT(&__text, \ - __left, \ - __right), \ + KUNIT_INIT_ASSERT(.text = &__text, \ + .left_value = __left, \ + .right_value = __right), \ fmt, \ ##__VA_ARGS__); \ } while (0) @@ -651,9 +658,42 @@ do { \ assert_type, \ kunit_binary_str_assert, \ kunit_binary_str_assert_format, \ - KUNIT_INIT_BINARY_ASSERT_STRUCT(&__text, \ - __left, \ - __right), \ + KUNIT_INIT_ASSERT(.text = &__text, \ + .left_value = __left, \ + .right_value = __right), \ + fmt, \ + ##__VA_ARGS__); \ +} while (0) + +#define KUNIT_MEM_ASSERTION(test, \ + assert_type, \ + left, \ + op, \ + right, \ + size_, \ + fmt, \ + ...) \ +do { \ + const void *__left = (left); \ + const void *__right = (right); \ + const size_t __size = (size_); \ + static const struct kunit_binary_assert_text __text = { \ + .operation = #op, \ + .left_text = #left, \ + .right_text = #right, \ + }; \ + \ + if (likely(memcmp(__left, __right, __size) op 0)) \ + break; \ + \ + _KUNIT_FAILED(test, \ + assert_type, \ + kunit_mem_assert, \ + kunit_mem_assert_format, \ + KUNIT_INIT_ASSERT(.text = &__text, \ + .left_value = __left, \ + .right_value = __right, \ + .size = __size), \ fmt, \ ##__VA_ARGS__); \ } while (0) @@ -673,7 +713,7 @@ do { \ assert_type, \ kunit_ptr_not_err_assert, \ kunit_ptr_not_err_assert_format, \ - KUNIT_INIT_PTR_NOT_ERR_STRUCT(#ptr, __ptr), \ + KUNIT_INIT_ASSERT(.text = #ptr, .value = __ptr), \ fmt, \ ##__VA_ARGS__); \ } while (0) @@ -929,6 +969,60 @@ do { \ ##__VA_ARGS__) /** + * KUNIT_EXPECT_MEMEQ() - Expects 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 expectation that the values that @left and @right evaluate to are + * equal. This is semantically equivalent to + * KUNIT_EXPECT_TRUE(@test, !memcmp((@left), (@right), (@size))). See + * KUNIT_EXPECT_TRUE() for more information. + * + * Although this expectation works for any memory block, it is not recommended + * for comparing more structured data, such as structs. This expectation is + * recommended for comparing, for example, data arrays. + */ +#define KUNIT_EXPECT_MEMEQ(test, left, right, size) \ + KUNIT_EXPECT_MEMEQ_MSG(test, left, right, size, NULL) + +#define KUNIT_EXPECT_MEMEQ_MSG(test, left, right, size, fmt, ...) \ + KUNIT_MEM_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, ==, right, \ + size, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_EXPECT_MEMNEQ() - Expects 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 expectation that the values that @left and @right evaluate to are + * not equal. This is semantically equivalent to + * KUNIT_EXPECT_TRUE(@test, memcmp((@left), (@right), (@size))). See + * KUNIT_EXPECT_TRUE() for more information. + * + * Although this expectation works for any memory block, it is not recommended + * for comparing more structured data, such as structs. This expectation is + * recommended for comparing, for example, data arrays. + */ +#define KUNIT_EXPECT_MEMNEQ(test, left, right, size) \ + KUNIT_EXPECT_MEMNEQ_MSG(test, left, right, size, NULL) + +#define KUNIT_EXPECT_MEMNEQ_MSG(test, left, right, size, fmt, ...) \ + KUNIT_MEM_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, !=, right, \ + size, \ + fmt, \ + ##__VA_ARGS__) + +/** * KUNIT_EXPECT_NULL() - Expects that @ptr is null. * @test: The test context object. * @ptr: an arbitrary pointer. diff --git a/include/kunit/visibility.h b/include/kunit/visibility.h new file mode 100644 index 000000000000..0dfe35feeec6 --- /dev/null +++ b/include/kunit/visibility.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * KUnit API to allow symbols to be conditionally visible during KUnit + * testing + * + * Copyright (C) 2022, Google LLC. + * Author: Rae Moar <rmoar@google.com> + */ + +#ifndef _KUNIT_VISIBILITY_H +#define _KUNIT_VISIBILITY_H + +#if IS_ENABLED(CONFIG_KUNIT) + /** + * VISIBLE_IF_KUNIT - A macro that sets symbols to be static if + * CONFIG_KUNIT is not enabled. Otherwise if CONFIG_KUNIT is enabled + * there is no change to the symbol definition. + */ + #define VISIBLE_IF_KUNIT + /** + * EXPORT_SYMBOL_IF_KUNIT(symbol) - Exports symbol into + * EXPORTED_FOR_KUNIT_TESTING namespace only if CONFIG_KUNIT is + * enabled. Must use MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING) + * in test file in order to use symbols. + */ + #define EXPORT_SYMBOL_IF_KUNIT(symbol) EXPORT_SYMBOL_NS(symbol, \ + EXPORTED_FOR_KUNIT_TESTING) +#else + #define VISIBLE_IF_KUNIT static + #define EXPORT_SYMBOL_IF_KUNIT(symbol) +#endif + +#endif /* _KUNIT_VISIBILITY_H */ |