From 6dcd539f062d89127cb3a84a7da373a9bd28ba7b Mon Sep 17 00:00:00 2001 From: Ryota Sakamoto Date: Mon, 15 Dec 2025 13:43:22 +0000 Subject: lib/tests: convert test_uuid module to KUnit Move lib/test_uuid.c to lib/tests/uuid_kunit.c and convert it to use KUnit. This change switches the ad-hoc test code to standard KUnit test cases. The test data remains the same, but the verification logic is updated to use KUNIT_EXPECT_* macros. Also remove CONFIG_TEST_UUID from arch/*/configs/* because it is no longer used. The new CONFIG_UUID_KUNIT_TEST will be automatically enabled by CONFIG_KUNIT_ALL_TESTS. [lukas.bulwahn@redhat.com: MAINTAINERS: adjust file entry in UUID HELPERS] Link: https://lkml.kernel.org/r/20251217053907.2778515-1-lukas.bulwahn@redhat.com Link: https://lkml.kernel.org/r/20251215134322.12949-1-sakamo.ryota@gmail.com Signed-off-by: Ryota Sakamoto Signed-off-by: Lukas Bulwahn Acked-by: Geert Uytterhoeven Reviewed-by: David Gow Cc: Andriy Shevchenko Cc: Brendan Higgins Cc: Lukas Bulwahn Signed-off-by: Andrew Morton --- lib/Makefile | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/Makefile') diff --git a/lib/Makefile b/lib/Makefile index aaf677cf4527..586a9f9b27a9 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -89,7 +89,6 @@ ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_KASAN),yy) GCOV_PROFILE_test_bitmap.o := n endif -obj-$(CONFIG_TEST_UUID) += test_uuid.o obj-$(CONFIG_TEST_XARRAY) += test_xarray.o obj-$(CONFIG_TEST_MAPLE_TREE) += test_maple_tree.o obj-$(CONFIG_TEST_PARMAN) += test_parman.o -- cgit v1.2.3 From d30aca3eeffc18452e5cc5c4e59f1a4da2bd2f12 Mon Sep 17 00:00:00 2001 From: Ryota Sakamoto Date: Sun, 21 Dec 2025 13:35:16 +0000 Subject: lib/tests: convert test_min_heap module to KUnit Move lib/test_min_heap.c to lib/tests/min_heap_kunit.c and convert it to use KUnit. This change switches the ad-hoc test code to standard KUnit test cases. The test data remains the same, but the verification logic is updated to use KUNIT_EXPECT_* macros. Also remove CONFIG_TEST_MIN_HEAP from arch/*/configs/* because it is no longer used. The new CONFIG_MIN_HEAP_KUNIT_TEST will be automatically enabled by CONFIG_KUNIT_ALL_TESTS. The reasons for converting to KUnit are: 1. Standardization: Switching from ad-hoc printk-based reporting to the standard KTAP format makes it easier for CI systems to parse and report test results 2. Better Diagnostics: Using KUNIT_EXPECT_* macros automatically provides detailed diagnostics on failure. 3. Tooling Integration: It allows the test to be managed and executed using standard KUnit tools. Link: https://lkml.kernel.org/r/20251221133516.321846-1-sakamo.ryota@gmail.com Signed-off-by: Ryota Sakamoto Acked-by: Kuan-Wei Chiu Cc: Alexander Gordeev Cc: Christian Borntraeger Cc: David Gow Cc: Geert Uytterhoeven Cc: Heiko Carstens Cc: Madhavan Srinivasan Cc: Michael Ellerman Cc: Nicholas Piggin Cc: Sven Schnelle Cc: Vasily Gorbik Signed-off-by: Andrew Morton --- MAINTAINERS | 2 +- arch/m68k/configs/amiga_defconfig | 1 - arch/m68k/configs/apollo_defconfig | 1 - arch/m68k/configs/atari_defconfig | 1 - arch/m68k/configs/bvme6000_defconfig | 1 - arch/m68k/configs/hp300_defconfig | 1 - arch/m68k/configs/mac_defconfig | 1 - arch/m68k/configs/multi_defconfig | 1 - arch/m68k/configs/mvme147_defconfig | 1 - arch/m68k/configs/mvme16x_defconfig | 1 - arch/m68k/configs/q40_defconfig | 1 - arch/m68k/configs/sun3_defconfig | 1 - arch/m68k/configs/sun3x_defconfig | 1 - arch/powerpc/configs/ppc64_defconfig | 1 - arch/s390/configs/debug_defconfig | 2 +- lib/Kconfig.debug | 21 ++-- lib/Makefile | 1 - lib/test_min_heap.c | 222 ----------------------------------- lib/tests/Makefile | 1 + lib/tests/min_heap_kunit.c | 209 +++++++++++++++++++++++++++++++++ 20 files changed, 223 insertions(+), 248 deletions(-) delete mode 100644 lib/test_min_heap.c create mode 100644 lib/tests/min_heap_kunit.c (limited to 'lib/Makefile') diff --git a/MAINTAINERS b/MAINTAINERS index 99407c4c0095..4dcbcb5c14f0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17456,7 +17456,7 @@ S: Maintained F: Documentation/core-api/min_heap.rst F: include/linux/min_heap.h F: lib/min_heap.c -F: lib/test_min_heap.c +F: lib/tests/min_heap_kunit.c MIPI CCS, SMIA AND SMIA++ IMAGE SENSOR DRIVER M: Sakari Ailus diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index 1439abb69f73..46598efbea54 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -609,7 +609,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 6a4e71866f60..63bef7a6d858 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -566,7 +566,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 46ad7d57b4fc..1342adfbd855 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -586,7 +586,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index 867bfa13a44c..484f21a2da37 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -558,7 +558,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 5dfe602cafd4..ce97c816aa21 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -568,7 +568,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index f5d30310a349..f5b57ea2d681 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -585,7 +585,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index fe54e9222cc0..85efdb31c898 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -672,7 +672,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index 4ff2ff0993ad..7102579b83d3 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -558,7 +558,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 6bb4738a65aa..18c0493ed0ff 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -559,7 +559,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index 14166c8fe234..1b3a34ab1c74 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -575,7 +575,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 5db924e3caf7..1a41a1c6bde1 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -555,7 +555,6 @@ CONFIG_WW_MUTEX_SELFTEST=m CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 318c9fe42f46..8f182684e54b 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -556,7 +556,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 684b3ea80f39..f1e937222a83 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -426,7 +426,6 @@ CONFIG_BOOTX_TEXT=y CONFIG_KUNIT=m CONFIG_KUNIT_ALL_TESTS=m CONFIG_LKDTM=m -CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m CONFIG_BACKTRACE_SELF_TEST=m CONFIG_TEST_REF_TRACKER=m diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index 0713914b25b4..4be3a7540909 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -921,7 +921,7 @@ CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION_CONFIGFS=y CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y CONFIG_LKDTM=m -CONFIG_TEST_MIN_HEAP=y +CONFIG_MIN_HEAP_KUNIT_TEST=m CONFIG_KPROBES_SANITY_TEST=m CONFIG_RBTREE_TEST=y CONFIG_INTERVAL_TREE_TEST=m diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 947e62e92da8..3a31bbf53425 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2278,16 +2278,6 @@ config TEST_LIST_SORT If unsure, say N. -config TEST_MIN_HEAP - tristate "Min heap test" - depends on DEBUG_KERNEL || m - help - Enable this to turn on min heap function tests. This test is - executed only once during system boot (so affects only boot time), - or at module load time. - - If unsure, say N. - config TEST_SORT tristate "Array-based sort test" if !KUNIT_ALL_TESTS depends on KUNIT @@ -2878,6 +2868,17 @@ config MEMCPY_KUNIT_TEST If unsure, say N. +config MIN_HEAP_KUNIT_TEST + tristate "Min heap test" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + This option enables the KUnit test suite for the min heap library + which provides functions for creating and managing min heaps. + The test suite checks the functionality of the min heap library. + + If unsure, say N + config IS_SIGNED_TYPE_KUNIT_TEST tristate "Test is_signed_type() macro" if !KUNIT_ALL_TESTS depends on KUNIT diff --git a/lib/Makefile b/lib/Makefile index 586a9f9b27a9..1f87a174a317 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -75,7 +75,6 @@ obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o CFLAGS_test_ubsan.o += $(call cc-disable-warning, unused-but-set-variable) UBSAN_SANITIZE_test_ubsan.o := y obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o -obj-$(CONFIG_TEST_MIN_HEAP) += test_min_heap.o obj-$(CONFIG_TEST_LKM) += test_module.o obj-$(CONFIG_TEST_VMALLOC) += test_vmalloc.o obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o diff --git a/lib/test_min_heap.c b/lib/test_min_heap.c deleted file mode 100644 index a9c4a74d3898..000000000000 --- a/lib/test_min_heap.c +++ /dev/null @@ -1,222 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -#define pr_fmt(fmt) "min_heap_test: " fmt - -/* - * Test cases for the min max heap. - */ - -#include -#include -#include -#include -#include - -DEFINE_MIN_HEAP(int, min_heap_test); - -static __init bool less_than(const void *lhs, const void *rhs, void __always_unused *args) -{ - return *(int *)lhs < *(int *)rhs; -} - -static __init bool greater_than(const void *lhs, const void *rhs, void __always_unused *args) -{ - return *(int *)lhs > *(int *)rhs; -} - -static __init int pop_verify_heap(bool min_heap, - struct min_heap_test *heap, - const struct min_heap_callbacks *funcs) -{ - int *values = heap->data; - int err = 0; - int last; - - last = values[0]; - min_heap_pop_inline(heap, funcs, NULL); - while (heap->nr > 0) { - if (min_heap) { - if (last > values[0]) { - pr_err("error: expected %d <= %d\n", last, - values[0]); - err++; - } - } else { - if (last < values[0]) { - pr_err("error: expected %d >= %d\n", last, - values[0]); - err++; - } - } - last = values[0]; - min_heap_pop_inline(heap, funcs, NULL); - } - return err; -} - -static __init int test_heapify_all(bool min_heap) -{ - int values[] = { 3, 1, 2, 4, 0x8000000, 0x7FFFFFF, 0, - -3, -1, -2, -4, 0x8000000, 0x7FFFFFF }; - struct min_heap_test heap = { - .data = values, - .nr = ARRAY_SIZE(values), - .size = ARRAY_SIZE(values), - }; - struct min_heap_callbacks funcs = { - .less = min_heap ? less_than : greater_than, - .swp = NULL, - }; - int i, err; - - /* Test with known set of values. */ - min_heapify_all_inline(&heap, &funcs, NULL); - err = pop_verify_heap(min_heap, &heap, &funcs); - - - /* Test with randomly generated values. */ - heap.nr = ARRAY_SIZE(values); - for (i = 0; i < heap.nr; i++) - values[i] = get_random_u32(); - - min_heapify_all_inline(&heap, &funcs, NULL); - err += pop_verify_heap(min_heap, &heap, &funcs); - - return err; -} - -static __init int test_heap_push(bool min_heap) -{ - const int data[] = { 3, 1, 2, 4, 0x80000000, 0x7FFFFFFF, 0, - -3, -1, -2, -4, 0x80000000, 0x7FFFFFFF }; - int values[ARRAY_SIZE(data)]; - struct min_heap_test heap = { - .data = values, - .nr = 0, - .size = ARRAY_SIZE(values), - }; - struct min_heap_callbacks funcs = { - .less = min_heap ? less_than : greater_than, - .swp = NULL, - }; - int i, temp, err; - - /* Test with known set of values copied from data. */ - for (i = 0; i < ARRAY_SIZE(data); i++) - min_heap_push_inline(&heap, &data[i], &funcs, NULL); - - err = pop_verify_heap(min_heap, &heap, &funcs); - - /* Test with randomly generated values. */ - while (heap.nr < heap.size) { - temp = get_random_u32(); - min_heap_push_inline(&heap, &temp, &funcs, NULL); - } - err += pop_verify_heap(min_heap, &heap, &funcs); - - return err; -} - -static __init int test_heap_pop_push(bool min_heap) -{ - const int data[] = { 3, 1, 2, 4, 0x80000000, 0x7FFFFFFF, 0, - -3, -1, -2, -4, 0x80000000, 0x7FFFFFFF }; - int values[ARRAY_SIZE(data)]; - struct min_heap_test heap = { - .data = values, - .nr = 0, - .size = ARRAY_SIZE(values), - }; - struct min_heap_callbacks funcs = { - .less = min_heap ? less_than : greater_than, - .swp = NULL, - }; - int i, temp, err; - - /* Fill values with data to pop and replace. */ - temp = min_heap ? 0x80000000 : 0x7FFFFFFF; - for (i = 0; i < ARRAY_SIZE(data); i++) - min_heap_push_inline(&heap, &temp, &funcs, NULL); - - /* Test with known set of values copied from data. */ - for (i = 0; i < ARRAY_SIZE(data); i++) - min_heap_pop_push_inline(&heap, &data[i], &funcs, NULL); - - err = pop_verify_heap(min_heap, &heap, &funcs); - - heap.nr = 0; - for (i = 0; i < ARRAY_SIZE(data); i++) - min_heap_push_inline(&heap, &temp, &funcs, NULL); - - /* Test with randomly generated values. */ - for (i = 0; i < ARRAY_SIZE(data); i++) { - temp = get_random_u32(); - min_heap_pop_push_inline(&heap, &temp, &funcs, NULL); - } - err += pop_verify_heap(min_heap, &heap, &funcs); - - return err; -} - -static __init int test_heap_del(bool min_heap) -{ - int values[] = { 3, 1, 2, 4, 0x8000000, 0x7FFFFFF, 0, - -3, -1, -2, -4, 0x8000000, 0x7FFFFFF }; - struct min_heap_test heap; - - min_heap_init_inline(&heap, values, ARRAY_SIZE(values)); - heap.nr = ARRAY_SIZE(values); - struct min_heap_callbacks funcs = { - .less = min_heap ? less_than : greater_than, - .swp = NULL, - }; - int i, err; - - /* Test with known set of values. */ - min_heapify_all_inline(&heap, &funcs, NULL); - for (i = 0; i < ARRAY_SIZE(values) / 2; i++) - min_heap_del_inline(&heap, get_random_u32() % heap.nr, &funcs, NULL); - err = pop_verify_heap(min_heap, &heap, &funcs); - - - /* Test with randomly generated values. */ - heap.nr = ARRAY_SIZE(values); - for (i = 0; i < heap.nr; i++) - values[i] = get_random_u32(); - min_heapify_all_inline(&heap, &funcs, NULL); - - for (i = 0; i < ARRAY_SIZE(values) / 2; i++) - min_heap_del_inline(&heap, get_random_u32() % heap.nr, &funcs, NULL); - err += pop_verify_heap(min_heap, &heap, &funcs); - - return err; -} - -static int __init test_min_heap_init(void) -{ - int err = 0; - - err += test_heapify_all(true); - err += test_heapify_all(false); - err += test_heap_push(true); - err += test_heap_push(false); - err += test_heap_pop_push(true); - err += test_heap_pop_push(false); - err += test_heap_del(true); - err += test_heap_del(false); - if (err) { - pr_err("test failed with %d errors\n", err); - return -EINVAL; - } - pr_info("test passed\n"); - return 0; -} -module_init(test_min_heap_init); - -static void __exit test_min_heap_exit(void) -{ - /* do nothing */ -} -module_exit(test_min_heap_exit); - -MODULE_DESCRIPTION("Test cases for the min max heap"); -MODULE_LICENSE("GPL"); diff --git a/lib/tests/Makefile b/lib/tests/Makefile index 9a20608f65f5..088b80d16383 100644 --- a/lib/tests/Makefile +++ b/lib/tests/Makefile @@ -33,6 +33,7 @@ CFLAGS_longest_symbol_kunit.o += $(call cc-disable-warning, missing-prototypes) obj-$(CONFIG_LONGEST_SYM_KUNIT_TEST) += longest_symbol_kunit.o obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o +obj-$(CONFIG_MIN_HEAP_KUNIT_TEST) += min_heap_kunit.o CFLAGS_overflow_kunit.o = $(call cc-disable-warning, tautological-constant-out-of-range-compare) obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o obj-$(CONFIG_PRINTF_KUNIT_TEST) += printf_kunit.o diff --git a/lib/tests/min_heap_kunit.c b/lib/tests/min_heap_kunit.c new file mode 100644 index 000000000000..9c1122661698 --- /dev/null +++ b/lib/tests/min_heap_kunit.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Test cases for the min max heap. + */ + +#include +#include +#include +#include + +struct min_heap_test_case { + const char *str; + bool min_heap; +}; + +static struct min_heap_test_case min_heap_cases[] = { + { + .str = "min", + .min_heap = true, + }, + { + .str = "max", + .min_heap = false, + }, +}; + +KUNIT_ARRAY_PARAM_DESC(min_heap, min_heap_cases, str); + +DEFINE_MIN_HEAP(int, min_heap_test); + +static bool less_than(const void *lhs, const void *rhs, void __always_unused *args) +{ + return *(int *)lhs < *(int *)rhs; +} + +static bool greater_than(const void *lhs, const void *rhs, void __always_unused *args) +{ + return *(int *)lhs > *(int *)rhs; +} + +static void pop_verify_heap(struct kunit *test, + bool min_heap, + struct min_heap_test *heap, + const struct min_heap_callbacks *funcs) +{ + int *values = heap->data; + int last; + + last = values[0]; + min_heap_pop_inline(heap, funcs, NULL); + while (heap->nr > 0) { + if (min_heap) + KUNIT_EXPECT_LE(test, last, values[0]); + else + KUNIT_EXPECT_GE(test, last, values[0]); + last = values[0]; + min_heap_pop_inline(heap, funcs, NULL); + } +} + +static void test_heapify_all(struct kunit *test) +{ + const struct min_heap_test_case *params = test->param_value; + int values[] = { 3, 1, 2, 4, 0x8000000, 0x7FFFFFF, 0, + -3, -1, -2, -4, 0x8000000, 0x7FFFFFF }; + struct min_heap_test heap = { + .data = values, + .nr = ARRAY_SIZE(values), + .size = ARRAY_SIZE(values), + }; + struct min_heap_callbacks funcs = { + .less = params->min_heap ? less_than : greater_than, + .swp = NULL, + }; + int i; + + /* Test with known set of values. */ + min_heapify_all_inline(&heap, &funcs, NULL); + pop_verify_heap(test, params->min_heap, &heap, &funcs); + + /* Test with randomly generated values. */ + heap.nr = ARRAY_SIZE(values); + for (i = 0; i < heap.nr; i++) + values[i] = get_random_u32(); + + min_heapify_all_inline(&heap, &funcs, NULL); + pop_verify_heap(test, params->min_heap, &heap, &funcs); +} + +static void test_heap_push(struct kunit *test) +{ + const struct min_heap_test_case *params = test->param_value; + const int data[] = { 3, 1, 2, 4, 0x80000000, 0x7FFFFFFF, 0, + -3, -1, -2, -4, 0x80000000, 0x7FFFFFFF }; + int values[ARRAY_SIZE(data)]; + struct min_heap_test heap = { + .data = values, + .nr = 0, + .size = ARRAY_SIZE(values), + }; + struct min_heap_callbacks funcs = { + .less = params->min_heap ? less_than : greater_than, + .swp = NULL, + }; + int i, temp; + + /* Test with known set of values copied from data. */ + for (i = 0; i < ARRAY_SIZE(data); i++) + min_heap_push_inline(&heap, &data[i], &funcs, NULL); + + pop_verify_heap(test, params->min_heap, &heap, &funcs); + + /* Test with randomly generated values. */ + while (heap.nr < heap.size) { + temp = get_random_u32(); + min_heap_push_inline(&heap, &temp, &funcs, NULL); + } + pop_verify_heap(test, params->min_heap, &heap, &funcs); +} + +static void test_heap_pop_push(struct kunit *test) +{ + const struct min_heap_test_case *params = test->param_value; + const int data[] = { 3, 1, 2, 4, 0x80000000, 0x7FFFFFFF, 0, + -3, -1, -2, -4, 0x80000000, 0x7FFFFFFF }; + int values[ARRAY_SIZE(data)]; + struct min_heap_test heap = { + .data = values, + .nr = 0, + .size = ARRAY_SIZE(values), + }; + struct min_heap_callbacks funcs = { + .less = params->min_heap ? less_than : greater_than, + .swp = NULL, + }; + int i, temp; + + /* Fill values with data to pop and replace. */ + temp = params->min_heap ? 0x80000000 : 0x7FFFFFFF; + for (i = 0; i < ARRAY_SIZE(data); i++) + min_heap_push_inline(&heap, &temp, &funcs, NULL); + + /* Test with known set of values copied from data. */ + for (i = 0; i < ARRAY_SIZE(data); i++) + min_heap_pop_push_inline(&heap, &data[i], &funcs, NULL); + + pop_verify_heap(test, params->min_heap, &heap, &funcs); + + heap.nr = 0; + for (i = 0; i < ARRAY_SIZE(data); i++) + min_heap_push_inline(&heap, &temp, &funcs, NULL); + + /* Test with randomly generated values. */ + for (i = 0; i < ARRAY_SIZE(data); i++) { + temp = get_random_u32(); + min_heap_pop_push_inline(&heap, &temp, &funcs, NULL); + } + pop_verify_heap(test, params->min_heap, &heap, &funcs); +} + +static void test_heap_del(struct kunit *test) +{ + const struct min_heap_test_case *params = test->param_value; + int values[] = { 3, 1, 2, 4, 0x8000000, 0x7FFFFFF, 0, + -3, -1, -2, -4, 0x8000000, 0x7FFFFFF }; + struct min_heap_test heap; + + min_heap_init_inline(&heap, values, ARRAY_SIZE(values)); + heap.nr = ARRAY_SIZE(values); + struct min_heap_callbacks funcs = { + .less = params->min_heap ? less_than : greater_than, + .swp = NULL, + }; + int i; + + /* Test with known set of values. */ + min_heapify_all_inline(&heap, &funcs, NULL); + for (i = 0; i < ARRAY_SIZE(values) / 2; i++) + min_heap_del_inline(&heap, get_random_u32() % heap.nr, &funcs, NULL); + pop_verify_heap(test, params->min_heap, &heap, &funcs); + + /* Test with randomly generated values. */ + heap.nr = ARRAY_SIZE(values); + for (i = 0; i < heap.nr; i++) + values[i] = get_random_u32(); + min_heapify_all_inline(&heap, &funcs, NULL); + + for (i = 0; i < ARRAY_SIZE(values) / 2; i++) + min_heap_del_inline(&heap, get_random_u32() % heap.nr, &funcs, NULL); + pop_verify_heap(test, params->min_heap, &heap, &funcs); +} + +static struct kunit_case min_heap_test_cases[] = { + KUNIT_CASE_PARAM(test_heapify_all, min_heap_gen_params), + KUNIT_CASE_PARAM(test_heap_push, min_heap_gen_params), + KUNIT_CASE_PARAM(test_heap_pop_push, min_heap_gen_params), + KUNIT_CASE_PARAM(test_heap_del, min_heap_gen_params), + {}, +}; + +static struct kunit_suite min_heap_test_suite = { + .name = "min_heap", + .test_cases = min_heap_test_cases, +}; + +kunit_test_suite(min_heap_test_suite); + +MODULE_DESCRIPTION("Test cases for the min max heap"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From bf45794244ca1fb1c135754f36ff765eea01f9e6 Mon Sep 17 00:00:00 2001 From: Kir Chou Date: Thu, 8 Jan 2026 21:07:53 +0900 Subject: lib/glob: convert selftest to KUnit This patch converts the existing glob selftest (lib/globtest.c) to use the KUnit framework (lib/tests/glob_kunit.c). The new test: - Migrates all 64 test cases from the original test to the KUnit suite. - Removes the custom 'verbose' module parameter as KUnit handles logging. - Updates Kconfig.debug and Makefile to support the new KUnit test. - Updates Kconfig and Makefile to remove the original selftest. - Updates GLOB_SELFTEST to GLOB_KUNIT_TEST for arch/m68k/configs. This commit is verified by `./tools/testing/kunit/kunit.py run' with the .kunit/.kunitconfig: CONFIG_KUNIT=y CONFIG_GLOB_KUNIT_TEST=y Link: https://lkml.kernel.org/r/20260108120753.27339-1-note351@hotmail.com Signed-off-by: Kir Chou Acked-by: Geert Uytterhoeven Reviewed-by: David Gow Reviewed-by: Kuan-Wei Chiu Cc: Signed-off-by: Andrew Morton --- arch/m68k/configs/amiga_defconfig | 1 - arch/m68k/configs/apollo_defconfig | 1 - arch/m68k/configs/atari_defconfig | 1 - arch/m68k/configs/bvme6000_defconfig | 1 - arch/m68k/configs/hp300_defconfig | 1 - arch/m68k/configs/mac_defconfig | 1 - arch/m68k/configs/multi_defconfig | 1 - arch/m68k/configs/mvme147_defconfig | 1 - arch/m68k/configs/mvme16x_defconfig | 1 - arch/m68k/configs/q40_defconfig | 1 - arch/m68k/configs/sun3_defconfig | 1 - arch/m68k/configs/sun3x_defconfig | 1 - lib/Kconfig | 13 --- lib/Kconfig.debug | 13 +++ lib/Makefile | 1 - lib/globtest.c | 167 ----------------------------------- lib/tests/Makefile | 1 + lib/tests/glob_kunit.c | 125 ++++++++++++++++++++++++++ 18 files changed, 139 insertions(+), 193 deletions(-) delete mode 100644 lib/globtest.c create mode 100644 lib/tests/glob_kunit.c (limited to 'lib/Makefile') diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index 46598efbea54..3c87c1d181a6 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -600,7 +600,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 63bef7a6d858..03eaace46fe7 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -557,7 +557,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 1342adfbd855..61228b9d2c2a 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -577,7 +577,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index 484f21a2da37..83fcc12916c5 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -549,7 +549,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index ce97c816aa21..84d477e95fe8 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -559,7 +559,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index f5b57ea2d681..b1e911a138a0 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -576,7 +576,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 85efdb31c898..0a2c3ac6dc7f 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -663,7 +663,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index 7102579b83d3..2087fe4af3d6 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -549,7 +549,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 18c0493ed0ff..4af83b643da1 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -550,7 +550,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index 1b3a34ab1c74..56c303097050 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -566,7 +566,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 1a41a1c6bde1..de2a5b27d408 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -547,7 +547,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 8f182684e54b..297b8edcff6d 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -547,7 +547,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_PRIME_NUMBERS=m CONFIG_CRC_BENCHMARK=y CONFIG_XZ_DEC_TEST=m -CONFIG_GLOB_SELFTEST=m # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_TEST_LOCKUP=m diff --git a/lib/Kconfig b/lib/Kconfig index 2923924bea78..0f2fb9610647 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -430,19 +430,6 @@ config GLOB are compiling an out-of tree driver which tells you that it depends on this. -config GLOB_SELFTEST - tristate "glob self-test on init" - depends on GLOB - help - This option enables a simple self-test of the glob_match - function on startup. It is primarily useful for people - working on the code to ensure they haven't introduced any - regressions. - - It only adds a little bit of code and slows kernel boot (or - module load) by a small amount, so you're welcome to play with - it, but you probably don't need it. - # # Netlink attribute parsing support is select'ed if needed # diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 2122d5cec34d..17d759a04021 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -3364,6 +3364,19 @@ config PRIME_NUMBERS_KUNIT_TEST If unsure, say N +config GLOB_KUNIT_TEST + tristate "Glob matching test" if !KUNIT_ALL_TESTS + depends on GLOB + depends on KUNIT + default KUNIT_ALL_TESTS + help + Enable this option to test the glob functions at runtime. + + This test suite verifies the correctness of glob_match() across various + scenarios, including edge cases. + + If unsure, say N + endif # RUNTIME_TESTING_MENU config ARCH_USE_MEMTEST diff --git a/lib/Makefile b/lib/Makefile index 1f87a174a317..9839f40af5dc 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -224,7 +224,6 @@ obj-$(CONFIG_CLOSURES) += closure.o obj-$(CONFIG_DQL) += dynamic_queue_limits.o obj-$(CONFIG_GLOB) += glob.o -obj-$(CONFIG_GLOB_SELFTEST) += globtest.o obj-$(CONFIG_DIMLIB) += dim/ obj-$(CONFIG_SIGNATURE) += digsig.o diff --git a/lib/globtest.c b/lib/globtest.c deleted file mode 100644 index d8e97d43b905..000000000000 --- a/lib/globtest.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Extracted fronm glob.c - */ - -#include -#include -#include -#include - -/* Boot with "glob.verbose=1" to show successful tests, too */ -static bool verbose = false; -module_param(verbose, bool, 0); - -struct glob_test { - char const *pat, *str; - bool expected; -}; - -static bool __pure __init test(char const *pat, char const *str, bool expected) -{ - bool match = glob_match(pat, str); - bool success = match == expected; - - /* Can't get string literals into a particular section, so... */ - static char const msg_error[] __initconst = - KERN_ERR "glob: \"%s\" vs. \"%s\": %s *** ERROR ***\n"; - static char const msg_ok[] __initconst = - KERN_DEBUG "glob: \"%s\" vs. \"%s\": %s OK\n"; - static char const mismatch[] __initconst = "mismatch"; - char const *message; - - if (!success) - message = msg_error; - else if (verbose) - message = msg_ok; - else - return success; - - printk(message, pat, str, mismatch + 3*match); - return success; -} - -/* - * The tests are all jammed together in one array to make it simpler - * to place that array in the .init.rodata section. The obvious - * "array of structures containing char *" has no way to force the - * pointed-to strings to be in a particular section. - * - * Anyway, a test consists of: - * 1. Expected glob_match result: '1' or '0'. - * 2. Pattern to match: null-terminated string - * 3. String to match against: null-terminated string - * - * The list of tests is terminated with a final '\0' instead of - * a glob_match result character. - */ -static char const glob_tests[] __initconst = - /* Some basic tests */ - "1" "a\0" "a\0" - "0" "a\0" "b\0" - "0" "a\0" "aa\0" - "0" "a\0" "\0" - "1" "\0" "\0" - "0" "\0" "a\0" - /* Simple character class tests */ - "1" "[a]\0" "a\0" - "0" "[a]\0" "b\0" - "0" "[!a]\0" "a\0" - "1" "[!a]\0" "b\0" - "1" "[ab]\0" "a\0" - "1" "[ab]\0" "b\0" - "0" "[ab]\0" "c\0" - "1" "[!ab]\0" "c\0" - "1" "[a-c]\0" "b\0" - "0" "[a-c]\0" "d\0" - /* Corner cases in character class parsing */ - "1" "[a-c-e-g]\0" "-\0" - "0" "[a-c-e-g]\0" "d\0" - "1" "[a-c-e-g]\0" "f\0" - "1" "[]a-ceg-ik[]\0" "a\0" - "1" "[]a-ceg-ik[]\0" "]\0" - "1" "[]a-ceg-ik[]\0" "[\0" - "1" "[]a-ceg-ik[]\0" "h\0" - "0" "[]a-ceg-ik[]\0" "f\0" - "0" "[!]a-ceg-ik[]\0" "h\0" - "0" "[!]a-ceg-ik[]\0" "]\0" - "1" "[!]a-ceg-ik[]\0" "f\0" - /* Simple wild cards */ - "1" "?\0" "a\0" - "0" "?\0" "aa\0" - "0" "??\0" "a\0" - "1" "?x?\0" "axb\0" - "0" "?x?\0" "abx\0" - "0" "?x?\0" "xab\0" - /* Asterisk wild cards (backtracking) */ - "0" "*??\0" "a\0" - "1" "*??\0" "ab\0" - "1" "*??\0" "abc\0" - "1" "*??\0" "abcd\0" - "0" "??*\0" "a\0" - "1" "??*\0" "ab\0" - "1" "??*\0" "abc\0" - "1" "??*\0" "abcd\0" - "0" "?*?\0" "a\0" - "1" "?*?\0" "ab\0" - "1" "?*?\0" "abc\0" - "1" "?*?\0" "abcd\0" - "1" "*b\0" "b\0" - "1" "*b\0" "ab\0" - "0" "*b\0" "ba\0" - "1" "*b\0" "bb\0" - "1" "*b\0" "abb\0" - "1" "*b\0" "bab\0" - "1" "*bc\0" "abbc\0" - "1" "*bc\0" "bc\0" - "1" "*bc\0" "bbc\0" - "1" "*bc\0" "bcbc\0" - /* Multiple asterisks (complex backtracking) */ - "1" "*ac*\0" "abacadaeafag\0" - "1" "*ac*ae*ag*\0" "abacadaeafag\0" - "1" "*a*b*[bc]*[ef]*g*\0" "abacadaeafag\0" - "0" "*a*b*[ef]*[cd]*g*\0" "abacadaeafag\0" - "1" "*abcd*\0" "abcabcabcabcdefg\0" - "1" "*ab*cd*\0" "abcabcabcabcdefg\0" - "1" "*abcd*abcdef*\0" "abcabcdabcdeabcdefg\0" - "0" "*abcd*\0" "abcabcabcabcefg\0" - "0" "*ab*cd*\0" "abcabcabcabcefg\0"; - -static int __init glob_init(void) -{ - unsigned successes = 0; - unsigned n = 0; - char const *p = glob_tests; - static char const message[] __initconst = - KERN_INFO "glob: %u self-tests passed, %u failed\n"; - - /* - * Tests are jammed together in a string. The first byte is '1' - * or '0' to indicate the expected outcome, or '\0' to indicate the - * end of the tests. Then come two null-terminated strings: the - * pattern and the string to match it against. - */ - while (*p) { - bool expected = *p++ & 1; - char const *pat = p; - - p += strlen(p) + 1; - successes += test(pat, p, expected); - p += strlen(p) + 1; - n++; - } - - n -= successes; - printk(message, successes, n); - - /* What's the errno for "kernel bug detected"? Guess... */ - return n ? -ECANCELED : 0; -} - -/* We need a dummy exit function to allow unload */ -static void __exit glob_fini(void) { } - -module_init(glob_init); -module_exit(glob_fini); - -MODULE_DESCRIPTION("glob(7) matching tests"); -MODULE_LICENSE("Dual MIT/GPL"); diff --git a/lib/tests/Makefile b/lib/tests/Makefile index 088b80d16383..ab3e74d0da9e 100644 --- a/lib/tests/Makefile +++ b/lib/tests/Makefile @@ -19,6 +19,7 @@ CFLAGS_fortify_kunit.o += $(DISABLE_STRUCTLEAK_PLUGIN) obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o CFLAGS_test_fprobe.o += $(CC_FLAGS_FTRACE) obj-$(CONFIG_FPROBE_SANITY_TEST) += test_fprobe.o +obj-$(CONFIG_GLOB_KUNIT_TEST) += glob_kunit.o obj-$(CONFIG_HASHTABLE_KUNIT_TEST) += hashtable_test.o obj-$(CONFIG_HASH_KUNIT_TEST) += test_hash.o obj-$(CONFIG_TEST_IOV_ITER) += kunit_iov_iter.o diff --git a/lib/tests/glob_kunit.c b/lib/tests/glob_kunit.c new file mode 100644 index 000000000000..362b1eda8e5b --- /dev/null +++ b/lib/tests/glob_kunit.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT OR GPL-2.0 +/* + * Test cases for glob functions. + */ + +#include +#include +#include + +/** + * struct glob_test_case - Test case for glob matching. + * @pat: Pattern to match. + * @str: String to match against. + * @expected: Expected glob_match result, true if matched. + */ +struct glob_test_case { + const char *pat; + const char *str; + bool expected; +}; + +static const struct glob_test_case glob_test_cases[] = { + /* Some basic tests */ + { .pat = "a", .str = "a", .expected = true }, + { .pat = "a", .str = "b", .expected = false }, + { .pat = "a", .str = "aa", .expected = false }, + { .pat = "a", .str = "", .expected = false }, + { .pat = "", .str = "", .expected = true }, + { .pat = "", .str = "a", .expected = false }, + /* Simple character class tests */ + { .pat = "[a]", .str = "a", .expected = true }, + { .pat = "[a]", .str = "b", .expected = false }, + { .pat = "[!a]", .str = "a", .expected = false }, + { .pat = "[!a]", .str = "b", .expected = true }, + { .pat = "[ab]", .str = "a", .expected = true }, + { .pat = "[ab]", .str = "b", .expected = true }, + { .pat = "[ab]", .str = "c", .expected = false }, + { .pat = "[!ab]", .str = "c", .expected = true }, + { .pat = "[a-c]", .str = "b", .expected = true }, + { .pat = "[a-c]", .str = "d", .expected = false }, + /* Corner cases in character class parsing */ + { .pat = "[a-c-e-g]", .str = "-", .expected = true }, + { .pat = "[a-c-e-g]", .str = "d", .expected = false }, + { .pat = "[a-c-e-g]", .str = "f", .expected = true }, + { .pat = "[]a-ceg-ik[]", .str = "a", .expected = true }, + { .pat = "[]a-ceg-ik[]", .str = "]", .expected = true }, + { .pat = "[]a-ceg-ik[]", .str = "[", .expected = true }, + { .pat = "[]a-ceg-ik[]", .str = "h", .expected = true }, + { .pat = "[]a-ceg-ik[]", .str = "f", .expected = false }, + { .pat = "[!]a-ceg-ik[]", .str = "h", .expected = false }, + { .pat = "[!]a-ceg-ik[]", .str = "]", .expected = false }, + { .pat = "[!]a-ceg-ik[]", .str = "f", .expected = true }, + /* Simple wild cards */ + { .pat = "?", .str = "a", .expected = true }, + { .pat = "?", .str = "aa", .expected = false }, + { .pat = "??", .str = "a", .expected = false }, + { .pat = "?x?", .str = "axb", .expected = true }, + { .pat = "?x?", .str = "abx", .expected = false }, + { .pat = "?x?", .str = "xab", .expected = false }, + /* Asterisk wild cards (backtracking) */ + { .pat = "*??", .str = "a", .expected = false }, + { .pat = "*??", .str = "ab", .expected = true }, + { .pat = "*??", .str = "abc", .expected = true }, + { .pat = "*??", .str = "abcd", .expected = true }, + { .pat = "??*", .str = "a", .expected = false }, + { .pat = "??*", .str = "ab", .expected = true }, + { .pat = "??*", .str = "abc", .expected = true }, + { .pat = "??*", .str = "abcd", .expected = true }, + { .pat = "?*?", .str = "a", .expected = false }, + { .pat = "?*?", .str = "ab", .expected = true }, + { .pat = "?*?", .str = "abc", .expected = true }, + { .pat = "?*?", .str = "abcd", .expected = true }, + { .pat = "*b", .str = "b", .expected = true }, + { .pat = "*b", .str = "ab", .expected = true }, + { .pat = "*b", .str = "ba", .expected = false }, + { .pat = "*b", .str = "bb", .expected = true }, + { .pat = "*b", .str = "abb", .expected = true }, + { .pat = "*b", .str = "bab", .expected = true }, + { .pat = "*bc", .str = "abbc", .expected = true }, + { .pat = "*bc", .str = "bc", .expected = true }, + { .pat = "*bc", .str = "bbc", .expected = true }, + { .pat = "*bc", .str = "bcbc", .expected = true }, + /* Multiple asterisks (complex backtracking) */ + { .pat = "*ac*", .str = "abacadaeafag", .expected = true }, + { .pat = "*ac*ae*ag*", .str = "abacadaeafag", .expected = true }, + { .pat = "*a*b*[bc]*[ef]*g*", .str = "abacadaeafag", .expected = true }, + { .pat = "*a*b*[ef]*[cd]*g*", .str = "abacadaeafag", .expected = false }, + { .pat = "*abcd*", .str = "abcabcabcabcdefg", .expected = true }, + { .pat = "*ab*cd*", .str = "abcabcabcabcdefg", .expected = true }, + { .pat = "*abcd*abcdef*", .str = "abcabcdabcdeabcdefg", .expected = true }, + { .pat = "*abcd*", .str = "abcabcabcabcefg", .expected = false }, + { .pat = "*ab*cd*", .str = "abcabcabcabcefg", .expected = false }, +}; + +static void glob_case_to_desc(const struct glob_test_case *t, char *desc) +{ + snprintf(desc, KUNIT_PARAM_DESC_SIZE, "pat:\"%s\" str:\"%s\"", t->pat, t->str); +} + +KUNIT_ARRAY_PARAM(glob, glob_test_cases, glob_case_to_desc); + +static void glob_test_match(struct kunit *test) +{ + const struct glob_test_case *params = test->param_value; + + KUNIT_EXPECT_EQ_MSG(test, + glob_match(params->pat, params->str), + params->expected, + "Pattern: \"%s\", String: \"%s\", Expected: %d", + params->pat, params->str, params->expected); +} + +static struct kunit_case glob_kunit_test_cases[] = { + KUNIT_CASE_PARAM(glob_test_match, glob_gen_params), + {} +}; + +static struct kunit_suite glob_test_suite = { + .name = "glob", + .test_cases = glob_kunit_test_cases, +}; + +kunit_test_suite(glob_test_suite); +MODULE_DESCRIPTION("Test cases for glob functions"); +MODULE_LICENSE("Dual MIT/GPL"); -- cgit v1.2.3