Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <note351@hotmail.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Reviewed-by: David Gow <davidgow@google.com>
Reviewed-by: Kuan-Wei Chiu <visitorckw@gmail.com>
Cc: <kirchou@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Kir Chou and committed by
Andrew Morton
bf457942 105ddfb2

+139 -193
-1
arch/m68k/configs/amiga_defconfig
··· 600 600 CONFIG_PRIME_NUMBERS=m 601 601 CONFIG_CRC_BENCHMARK=y 602 602 CONFIG_XZ_DEC_TEST=m 603 - CONFIG_GLOB_SELFTEST=m 604 603 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 605 604 CONFIG_MAGIC_SYSRQ=y 606 605 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/apollo_defconfig
··· 557 557 CONFIG_PRIME_NUMBERS=m 558 558 CONFIG_CRC_BENCHMARK=y 559 559 CONFIG_XZ_DEC_TEST=m 560 - CONFIG_GLOB_SELFTEST=m 561 560 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 562 561 CONFIG_MAGIC_SYSRQ=y 563 562 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/atari_defconfig
··· 577 577 CONFIG_PRIME_NUMBERS=m 578 578 CONFIG_CRC_BENCHMARK=y 579 579 CONFIG_XZ_DEC_TEST=m 580 - CONFIG_GLOB_SELFTEST=m 581 580 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 582 581 CONFIG_MAGIC_SYSRQ=y 583 582 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/bvme6000_defconfig
··· 549 549 CONFIG_PRIME_NUMBERS=m 550 550 CONFIG_CRC_BENCHMARK=y 551 551 CONFIG_XZ_DEC_TEST=m 552 - CONFIG_GLOB_SELFTEST=m 553 552 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 554 553 CONFIG_MAGIC_SYSRQ=y 555 554 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/hp300_defconfig
··· 559 559 CONFIG_PRIME_NUMBERS=m 560 560 CONFIG_CRC_BENCHMARK=y 561 561 CONFIG_XZ_DEC_TEST=m 562 - CONFIG_GLOB_SELFTEST=m 563 562 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 564 563 CONFIG_MAGIC_SYSRQ=y 565 564 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/mac_defconfig
··· 576 576 CONFIG_PRIME_NUMBERS=m 577 577 CONFIG_CRC_BENCHMARK=y 578 578 CONFIG_XZ_DEC_TEST=m 579 - CONFIG_GLOB_SELFTEST=m 580 579 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 581 580 CONFIG_MAGIC_SYSRQ=y 582 581 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/multi_defconfig
··· 663 663 CONFIG_PRIME_NUMBERS=m 664 664 CONFIG_CRC_BENCHMARK=y 665 665 CONFIG_XZ_DEC_TEST=m 666 - CONFIG_GLOB_SELFTEST=m 667 666 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 668 667 CONFIG_MAGIC_SYSRQ=y 669 668 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/mvme147_defconfig
··· 549 549 CONFIG_PRIME_NUMBERS=m 550 550 CONFIG_CRC_BENCHMARK=y 551 551 CONFIG_XZ_DEC_TEST=m 552 - CONFIG_GLOB_SELFTEST=m 553 552 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 554 553 CONFIG_MAGIC_SYSRQ=y 555 554 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/mvme16x_defconfig
··· 550 550 CONFIG_PRIME_NUMBERS=m 551 551 CONFIG_CRC_BENCHMARK=y 552 552 CONFIG_XZ_DEC_TEST=m 553 - CONFIG_GLOB_SELFTEST=m 554 553 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 555 554 CONFIG_MAGIC_SYSRQ=y 556 555 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/q40_defconfig
··· 566 566 CONFIG_PRIME_NUMBERS=m 567 567 CONFIG_CRC_BENCHMARK=y 568 568 CONFIG_XZ_DEC_TEST=m 569 - CONFIG_GLOB_SELFTEST=m 570 569 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 571 570 CONFIG_MAGIC_SYSRQ=y 572 571 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/sun3_defconfig
··· 547 547 CONFIG_PRIME_NUMBERS=m 548 548 CONFIG_CRC_BENCHMARK=y 549 549 CONFIG_XZ_DEC_TEST=m 550 - CONFIG_GLOB_SELFTEST=m 551 550 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 552 551 CONFIG_MAGIC_SYSRQ=y 553 552 CONFIG_TEST_LOCKUP=m
-1
arch/m68k/configs/sun3x_defconfig
··· 547 547 CONFIG_PRIME_NUMBERS=m 548 548 CONFIG_CRC_BENCHMARK=y 549 549 CONFIG_XZ_DEC_TEST=m 550 - CONFIG_GLOB_SELFTEST=m 551 550 # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 552 551 CONFIG_MAGIC_SYSRQ=y 553 552 CONFIG_TEST_LOCKUP=m
-13
lib/Kconfig
··· 430 430 are compiling an out-of tree driver which tells you that it 431 431 depends on this. 432 432 433 - config GLOB_SELFTEST 434 - tristate "glob self-test on init" 435 - depends on GLOB 436 - help 437 - This option enables a simple self-test of the glob_match 438 - function on startup. It is primarily useful for people 439 - working on the code to ensure they haven't introduced any 440 - regressions. 441 - 442 - It only adds a little bit of code and slows kernel boot (or 443 - module load) by a small amount, so you're welcome to play with 444 - it, but you probably don't need it. 445 - 446 433 # 447 434 # Netlink attribute parsing support is select'ed if needed 448 435 #
+13
lib/Kconfig.debug
··· 3364 3364 3365 3365 If unsure, say N 3366 3366 3367 + config GLOB_KUNIT_TEST 3368 + tristate "Glob matching test" if !KUNIT_ALL_TESTS 3369 + depends on GLOB 3370 + depends on KUNIT 3371 + default KUNIT_ALL_TESTS 3372 + help 3373 + Enable this option to test the glob functions at runtime. 3374 + 3375 + This test suite verifies the correctness of glob_match() across various 3376 + scenarios, including edge cases. 3377 + 3378 + If unsure, say N 3379 + 3367 3380 endif # RUNTIME_TESTING_MENU 3368 3381 3369 3382 config ARCH_USE_MEMTEST
-1
lib/Makefile
··· 224 224 obj-$(CONFIG_DQL) += dynamic_queue_limits.o 225 225 226 226 obj-$(CONFIG_GLOB) += glob.o 227 - obj-$(CONFIG_GLOB_SELFTEST) += globtest.o 228 227 229 228 obj-$(CONFIG_DIMLIB) += dim/ 230 229 obj-$(CONFIG_SIGNATURE) += digsig.o
-167
lib/globtest.c
··· 1 - /* 2 - * Extracted fronm glob.c 3 - */ 4 - 5 - #include <linux/module.h> 6 - #include <linux/moduleparam.h> 7 - #include <linux/glob.h> 8 - #include <linux/printk.h> 9 - 10 - /* Boot with "glob.verbose=1" to show successful tests, too */ 11 - static bool verbose = false; 12 - module_param(verbose, bool, 0); 13 - 14 - struct glob_test { 15 - char const *pat, *str; 16 - bool expected; 17 - }; 18 - 19 - static bool __pure __init test(char const *pat, char const *str, bool expected) 20 - { 21 - bool match = glob_match(pat, str); 22 - bool success = match == expected; 23 - 24 - /* Can't get string literals into a particular section, so... */ 25 - static char const msg_error[] __initconst = 26 - KERN_ERR "glob: \"%s\" vs. \"%s\": %s *** ERROR ***\n"; 27 - static char const msg_ok[] __initconst = 28 - KERN_DEBUG "glob: \"%s\" vs. \"%s\": %s OK\n"; 29 - static char const mismatch[] __initconst = "mismatch"; 30 - char const *message; 31 - 32 - if (!success) 33 - message = msg_error; 34 - else if (verbose) 35 - message = msg_ok; 36 - else 37 - return success; 38 - 39 - printk(message, pat, str, mismatch + 3*match); 40 - return success; 41 - } 42 - 43 - /* 44 - * The tests are all jammed together in one array to make it simpler 45 - * to place that array in the .init.rodata section. The obvious 46 - * "array of structures containing char *" has no way to force the 47 - * pointed-to strings to be in a particular section. 48 - * 49 - * Anyway, a test consists of: 50 - * 1. Expected glob_match result: '1' or '0'. 51 - * 2. Pattern to match: null-terminated string 52 - * 3. String to match against: null-terminated string 53 - * 54 - * The list of tests is terminated with a final '\0' instead of 55 - * a glob_match result character. 56 - */ 57 - static char const glob_tests[] __initconst = 58 - /* Some basic tests */ 59 - "1" "a\0" "a\0" 60 - "0" "a\0" "b\0" 61 - "0" "a\0" "aa\0" 62 - "0" "a\0" "\0" 63 - "1" "\0" "\0" 64 - "0" "\0" "a\0" 65 - /* Simple character class tests */ 66 - "1" "[a]\0" "a\0" 67 - "0" "[a]\0" "b\0" 68 - "0" "[!a]\0" "a\0" 69 - "1" "[!a]\0" "b\0" 70 - "1" "[ab]\0" "a\0" 71 - "1" "[ab]\0" "b\0" 72 - "0" "[ab]\0" "c\0" 73 - "1" "[!ab]\0" "c\0" 74 - "1" "[a-c]\0" "b\0" 75 - "0" "[a-c]\0" "d\0" 76 - /* Corner cases in character class parsing */ 77 - "1" "[a-c-e-g]\0" "-\0" 78 - "0" "[a-c-e-g]\0" "d\0" 79 - "1" "[a-c-e-g]\0" "f\0" 80 - "1" "[]a-ceg-ik[]\0" "a\0" 81 - "1" "[]a-ceg-ik[]\0" "]\0" 82 - "1" "[]a-ceg-ik[]\0" "[\0" 83 - "1" "[]a-ceg-ik[]\0" "h\0" 84 - "0" "[]a-ceg-ik[]\0" "f\0" 85 - "0" "[!]a-ceg-ik[]\0" "h\0" 86 - "0" "[!]a-ceg-ik[]\0" "]\0" 87 - "1" "[!]a-ceg-ik[]\0" "f\0" 88 - /* Simple wild cards */ 89 - "1" "?\0" "a\0" 90 - "0" "?\0" "aa\0" 91 - "0" "??\0" "a\0" 92 - "1" "?x?\0" "axb\0" 93 - "0" "?x?\0" "abx\0" 94 - "0" "?x?\0" "xab\0" 95 - /* Asterisk wild cards (backtracking) */ 96 - "0" "*??\0" "a\0" 97 - "1" "*??\0" "ab\0" 98 - "1" "*??\0" "abc\0" 99 - "1" "*??\0" "abcd\0" 100 - "0" "??*\0" "a\0" 101 - "1" "??*\0" "ab\0" 102 - "1" "??*\0" "abc\0" 103 - "1" "??*\0" "abcd\0" 104 - "0" "?*?\0" "a\0" 105 - "1" "?*?\0" "ab\0" 106 - "1" "?*?\0" "abc\0" 107 - "1" "?*?\0" "abcd\0" 108 - "1" "*b\0" "b\0" 109 - "1" "*b\0" "ab\0" 110 - "0" "*b\0" "ba\0" 111 - "1" "*b\0" "bb\0" 112 - "1" "*b\0" "abb\0" 113 - "1" "*b\0" "bab\0" 114 - "1" "*bc\0" "abbc\0" 115 - "1" "*bc\0" "bc\0" 116 - "1" "*bc\0" "bbc\0" 117 - "1" "*bc\0" "bcbc\0" 118 - /* Multiple asterisks (complex backtracking) */ 119 - "1" "*ac*\0" "abacadaeafag\0" 120 - "1" "*ac*ae*ag*\0" "abacadaeafag\0" 121 - "1" "*a*b*[bc]*[ef]*g*\0" "abacadaeafag\0" 122 - "0" "*a*b*[ef]*[cd]*g*\0" "abacadaeafag\0" 123 - "1" "*abcd*\0" "abcabcabcabcdefg\0" 124 - "1" "*ab*cd*\0" "abcabcabcabcdefg\0" 125 - "1" "*abcd*abcdef*\0" "abcabcdabcdeabcdefg\0" 126 - "0" "*abcd*\0" "abcabcabcabcefg\0" 127 - "0" "*ab*cd*\0" "abcabcabcabcefg\0"; 128 - 129 - static int __init glob_init(void) 130 - { 131 - unsigned successes = 0; 132 - unsigned n = 0; 133 - char const *p = glob_tests; 134 - static char const message[] __initconst = 135 - KERN_INFO "glob: %u self-tests passed, %u failed\n"; 136 - 137 - /* 138 - * Tests are jammed together in a string. The first byte is '1' 139 - * or '0' to indicate the expected outcome, or '\0' to indicate the 140 - * end of the tests. Then come two null-terminated strings: the 141 - * pattern and the string to match it against. 142 - */ 143 - while (*p) { 144 - bool expected = *p++ & 1; 145 - char const *pat = p; 146 - 147 - p += strlen(p) + 1; 148 - successes += test(pat, p, expected); 149 - p += strlen(p) + 1; 150 - n++; 151 - } 152 - 153 - n -= successes; 154 - printk(message, successes, n); 155 - 156 - /* What's the errno for "kernel bug detected"? Guess... */ 157 - return n ? -ECANCELED : 0; 158 - } 159 - 160 - /* We need a dummy exit function to allow unload */ 161 - static void __exit glob_fini(void) { } 162 - 163 - module_init(glob_init); 164 - module_exit(glob_fini); 165 - 166 - MODULE_DESCRIPTION("glob(7) matching tests"); 167 - MODULE_LICENSE("Dual MIT/GPL");
+1
lib/tests/Makefile
··· 19 19 obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o 20 20 CFLAGS_test_fprobe.o += $(CC_FLAGS_FTRACE) 21 21 obj-$(CONFIG_FPROBE_SANITY_TEST) += test_fprobe.o 22 + obj-$(CONFIG_GLOB_KUNIT_TEST) += glob_kunit.o 22 23 obj-$(CONFIG_HASHTABLE_KUNIT_TEST) += hashtable_test.o 23 24 obj-$(CONFIG_HASH_KUNIT_TEST) += test_hash.o 24 25 obj-$(CONFIG_TEST_IOV_ITER) += kunit_iov_iter.o
+125
lib/tests/glob_kunit.c
··· 1 + // SPDX-License-Identifier: MIT OR GPL-2.0 2 + /* 3 + * Test cases for glob functions. 4 + */ 5 + 6 + #include <kunit/test.h> 7 + #include <linux/glob.h> 8 + #include <linux/module.h> 9 + 10 + /** 11 + * struct glob_test_case - Test case for glob matching. 12 + * @pat: Pattern to match. 13 + * @str: String to match against. 14 + * @expected: Expected glob_match result, true if matched. 15 + */ 16 + struct glob_test_case { 17 + const char *pat; 18 + const char *str; 19 + bool expected; 20 + }; 21 + 22 + static const struct glob_test_case glob_test_cases[] = { 23 + /* Some basic tests */ 24 + { .pat = "a", .str = "a", .expected = true }, 25 + { .pat = "a", .str = "b", .expected = false }, 26 + { .pat = "a", .str = "aa", .expected = false }, 27 + { .pat = "a", .str = "", .expected = false }, 28 + { .pat = "", .str = "", .expected = true }, 29 + { .pat = "", .str = "a", .expected = false }, 30 + /* Simple character class tests */ 31 + { .pat = "[a]", .str = "a", .expected = true }, 32 + { .pat = "[a]", .str = "b", .expected = false }, 33 + { .pat = "[!a]", .str = "a", .expected = false }, 34 + { .pat = "[!a]", .str = "b", .expected = true }, 35 + { .pat = "[ab]", .str = "a", .expected = true }, 36 + { .pat = "[ab]", .str = "b", .expected = true }, 37 + { .pat = "[ab]", .str = "c", .expected = false }, 38 + { .pat = "[!ab]", .str = "c", .expected = true }, 39 + { .pat = "[a-c]", .str = "b", .expected = true }, 40 + { .pat = "[a-c]", .str = "d", .expected = false }, 41 + /* Corner cases in character class parsing */ 42 + { .pat = "[a-c-e-g]", .str = "-", .expected = true }, 43 + { .pat = "[a-c-e-g]", .str = "d", .expected = false }, 44 + { .pat = "[a-c-e-g]", .str = "f", .expected = true }, 45 + { .pat = "[]a-ceg-ik[]", .str = "a", .expected = true }, 46 + { .pat = "[]a-ceg-ik[]", .str = "]", .expected = true }, 47 + { .pat = "[]a-ceg-ik[]", .str = "[", .expected = true }, 48 + { .pat = "[]a-ceg-ik[]", .str = "h", .expected = true }, 49 + { .pat = "[]a-ceg-ik[]", .str = "f", .expected = false }, 50 + { .pat = "[!]a-ceg-ik[]", .str = "h", .expected = false }, 51 + { .pat = "[!]a-ceg-ik[]", .str = "]", .expected = false }, 52 + { .pat = "[!]a-ceg-ik[]", .str = "f", .expected = true }, 53 + /* Simple wild cards */ 54 + { .pat = "?", .str = "a", .expected = true }, 55 + { .pat = "?", .str = "aa", .expected = false }, 56 + { .pat = "??", .str = "a", .expected = false }, 57 + { .pat = "?x?", .str = "axb", .expected = true }, 58 + { .pat = "?x?", .str = "abx", .expected = false }, 59 + { .pat = "?x?", .str = "xab", .expected = false }, 60 + /* Asterisk wild cards (backtracking) */ 61 + { .pat = "*??", .str = "a", .expected = false }, 62 + { .pat = "*??", .str = "ab", .expected = true }, 63 + { .pat = "*??", .str = "abc", .expected = true }, 64 + { .pat = "*??", .str = "abcd", .expected = true }, 65 + { .pat = "??*", .str = "a", .expected = false }, 66 + { .pat = "??*", .str = "ab", .expected = true }, 67 + { .pat = "??*", .str = "abc", .expected = true }, 68 + { .pat = "??*", .str = "abcd", .expected = true }, 69 + { .pat = "?*?", .str = "a", .expected = false }, 70 + { .pat = "?*?", .str = "ab", .expected = true }, 71 + { .pat = "?*?", .str = "abc", .expected = true }, 72 + { .pat = "?*?", .str = "abcd", .expected = true }, 73 + { .pat = "*b", .str = "b", .expected = true }, 74 + { .pat = "*b", .str = "ab", .expected = true }, 75 + { .pat = "*b", .str = "ba", .expected = false }, 76 + { .pat = "*b", .str = "bb", .expected = true }, 77 + { .pat = "*b", .str = "abb", .expected = true }, 78 + { .pat = "*b", .str = "bab", .expected = true }, 79 + { .pat = "*bc", .str = "abbc", .expected = true }, 80 + { .pat = "*bc", .str = "bc", .expected = true }, 81 + { .pat = "*bc", .str = "bbc", .expected = true }, 82 + { .pat = "*bc", .str = "bcbc", .expected = true }, 83 + /* Multiple asterisks (complex backtracking) */ 84 + { .pat = "*ac*", .str = "abacadaeafag", .expected = true }, 85 + { .pat = "*ac*ae*ag*", .str = "abacadaeafag", .expected = true }, 86 + { .pat = "*a*b*[bc]*[ef]*g*", .str = "abacadaeafag", .expected = true }, 87 + { .pat = "*a*b*[ef]*[cd]*g*", .str = "abacadaeafag", .expected = false }, 88 + { .pat = "*abcd*", .str = "abcabcabcabcdefg", .expected = true }, 89 + { .pat = "*ab*cd*", .str = "abcabcabcabcdefg", .expected = true }, 90 + { .pat = "*abcd*abcdef*", .str = "abcabcdabcdeabcdefg", .expected = true }, 91 + { .pat = "*abcd*", .str = "abcabcabcabcefg", .expected = false }, 92 + { .pat = "*ab*cd*", .str = "abcabcabcabcefg", .expected = false }, 93 + }; 94 + 95 + static void glob_case_to_desc(const struct glob_test_case *t, char *desc) 96 + { 97 + snprintf(desc, KUNIT_PARAM_DESC_SIZE, "pat:\"%s\" str:\"%s\"", t->pat, t->str); 98 + } 99 + 100 + KUNIT_ARRAY_PARAM(glob, glob_test_cases, glob_case_to_desc); 101 + 102 + static void glob_test_match(struct kunit *test) 103 + { 104 + const struct glob_test_case *params = test->param_value; 105 + 106 + KUNIT_EXPECT_EQ_MSG(test, 107 + glob_match(params->pat, params->str), 108 + params->expected, 109 + "Pattern: \"%s\", String: \"%s\", Expected: %d", 110 + params->pat, params->str, params->expected); 111 + } 112 + 113 + static struct kunit_case glob_kunit_test_cases[] = { 114 + KUNIT_CASE_PARAM(glob_test_match, glob_gen_params), 115 + {} 116 + }; 117 + 118 + static struct kunit_suite glob_test_suite = { 119 + .name = "glob", 120 + .test_cases = glob_kunit_test_cases, 121 + }; 122 + 123 + kunit_test_suite(glob_test_suite); 124 + MODULE_DESCRIPTION("Test cases for glob functions"); 125 + MODULE_LICENSE("Dual MIT/GPL");