1*bf457942SKir Chou // SPDX-License-Identifier: MIT OR GPL-2.0 2*bf457942SKir Chou /* 3*bf457942SKir Chou * Test cases for glob functions. 4*bf457942SKir Chou */ 5*bf457942SKir Chou 6*bf457942SKir Chou #include <kunit/test.h> 7*bf457942SKir Chou #include <linux/glob.h> 8*bf457942SKir Chou #include <linux/module.h> 9*bf457942SKir Chou 10*bf457942SKir Chou /** 11*bf457942SKir Chou * struct glob_test_case - Test case for glob matching. 12*bf457942SKir Chou * @pat: Pattern to match. 13*bf457942SKir Chou * @str: String to match against. 14*bf457942SKir Chou * @expected: Expected glob_match result, true if matched. 15*bf457942SKir Chou */ 16*bf457942SKir Chou struct glob_test_case { 17*bf457942SKir Chou const char *pat; 18*bf457942SKir Chou const char *str; 19*bf457942SKir Chou bool expected; 20*bf457942SKir Chou }; 21*bf457942SKir Chou 22*bf457942SKir Chou static const struct glob_test_case glob_test_cases[] = { 23*bf457942SKir Chou /* Some basic tests */ 24*bf457942SKir Chou { .pat = "a", .str = "a", .expected = true }, 25*bf457942SKir Chou { .pat = "a", .str = "b", .expected = false }, 26*bf457942SKir Chou { .pat = "a", .str = "aa", .expected = false }, 27*bf457942SKir Chou { .pat = "a", .str = "", .expected = false }, 28*bf457942SKir Chou { .pat = "", .str = "", .expected = true }, 29*bf457942SKir Chou { .pat = "", .str = "a", .expected = false }, 30*bf457942SKir Chou /* Simple character class tests */ 31*bf457942SKir Chou { .pat = "[a]", .str = "a", .expected = true }, 32*bf457942SKir Chou { .pat = "[a]", .str = "b", .expected = false }, 33*bf457942SKir Chou { .pat = "[!a]", .str = "a", .expected = false }, 34*bf457942SKir Chou { .pat = "[!a]", .str = "b", .expected = true }, 35*bf457942SKir Chou { .pat = "[ab]", .str = "a", .expected = true }, 36*bf457942SKir Chou { .pat = "[ab]", .str = "b", .expected = true }, 37*bf457942SKir Chou { .pat = "[ab]", .str = "c", .expected = false }, 38*bf457942SKir Chou { .pat = "[!ab]", .str = "c", .expected = true }, 39*bf457942SKir Chou { .pat = "[a-c]", .str = "b", .expected = true }, 40*bf457942SKir Chou { .pat = "[a-c]", .str = "d", .expected = false }, 41*bf457942SKir Chou /* Corner cases in character class parsing */ 42*bf457942SKir Chou { .pat = "[a-c-e-g]", .str = "-", .expected = true }, 43*bf457942SKir Chou { .pat = "[a-c-e-g]", .str = "d", .expected = false }, 44*bf457942SKir Chou { .pat = "[a-c-e-g]", .str = "f", .expected = true }, 45*bf457942SKir Chou { .pat = "[]a-ceg-ik[]", .str = "a", .expected = true }, 46*bf457942SKir Chou { .pat = "[]a-ceg-ik[]", .str = "]", .expected = true }, 47*bf457942SKir Chou { .pat = "[]a-ceg-ik[]", .str = "[", .expected = true }, 48*bf457942SKir Chou { .pat = "[]a-ceg-ik[]", .str = "h", .expected = true }, 49*bf457942SKir Chou { .pat = "[]a-ceg-ik[]", .str = "f", .expected = false }, 50*bf457942SKir Chou { .pat = "[!]a-ceg-ik[]", .str = "h", .expected = false }, 51*bf457942SKir Chou { .pat = "[!]a-ceg-ik[]", .str = "]", .expected = false }, 52*bf457942SKir Chou { .pat = "[!]a-ceg-ik[]", .str = "f", .expected = true }, 53*bf457942SKir Chou /* Simple wild cards */ 54*bf457942SKir Chou { .pat = "?", .str = "a", .expected = true }, 55*bf457942SKir Chou { .pat = "?", .str = "aa", .expected = false }, 56*bf457942SKir Chou { .pat = "??", .str = "a", .expected = false }, 57*bf457942SKir Chou { .pat = "?x?", .str = "axb", .expected = true }, 58*bf457942SKir Chou { .pat = "?x?", .str = "abx", .expected = false }, 59*bf457942SKir Chou { .pat = "?x?", .str = "xab", .expected = false }, 60*bf457942SKir Chou /* Asterisk wild cards (backtracking) */ 61*bf457942SKir Chou { .pat = "*??", .str = "a", .expected = false }, 62*bf457942SKir Chou { .pat = "*??", .str = "ab", .expected = true }, 63*bf457942SKir Chou { .pat = "*??", .str = "abc", .expected = true }, 64*bf457942SKir Chou { .pat = "*??", .str = "abcd", .expected = true }, 65*bf457942SKir Chou { .pat = "??*", .str = "a", .expected = false }, 66*bf457942SKir Chou { .pat = "??*", .str = "ab", .expected = true }, 67*bf457942SKir Chou { .pat = "??*", .str = "abc", .expected = true }, 68*bf457942SKir Chou { .pat = "??*", .str = "abcd", .expected = true }, 69*bf457942SKir Chou { .pat = "?*?", .str = "a", .expected = false }, 70*bf457942SKir Chou { .pat = "?*?", .str = "ab", .expected = true }, 71*bf457942SKir Chou { .pat = "?*?", .str = "abc", .expected = true }, 72*bf457942SKir Chou { .pat = "?*?", .str = "abcd", .expected = true }, 73*bf457942SKir Chou { .pat = "*b", .str = "b", .expected = true }, 74*bf457942SKir Chou { .pat = "*b", .str = "ab", .expected = true }, 75*bf457942SKir Chou { .pat = "*b", .str = "ba", .expected = false }, 76*bf457942SKir Chou { .pat = "*b", .str = "bb", .expected = true }, 77*bf457942SKir Chou { .pat = "*b", .str = "abb", .expected = true }, 78*bf457942SKir Chou { .pat = "*b", .str = "bab", .expected = true }, 79*bf457942SKir Chou { .pat = "*bc", .str = "abbc", .expected = true }, 80*bf457942SKir Chou { .pat = "*bc", .str = "bc", .expected = true }, 81*bf457942SKir Chou { .pat = "*bc", .str = "bbc", .expected = true }, 82*bf457942SKir Chou { .pat = "*bc", .str = "bcbc", .expected = true }, 83*bf457942SKir Chou /* Multiple asterisks (complex backtracking) */ 84*bf457942SKir Chou { .pat = "*ac*", .str = "abacadaeafag", .expected = true }, 85*bf457942SKir Chou { .pat = "*ac*ae*ag*", .str = "abacadaeafag", .expected = true }, 86*bf457942SKir Chou { .pat = "*a*b*[bc]*[ef]*g*", .str = "abacadaeafag", .expected = true }, 87*bf457942SKir Chou { .pat = "*a*b*[ef]*[cd]*g*", .str = "abacadaeafag", .expected = false }, 88*bf457942SKir Chou { .pat = "*abcd*", .str = "abcabcabcabcdefg", .expected = true }, 89*bf457942SKir Chou { .pat = "*ab*cd*", .str = "abcabcabcabcdefg", .expected = true }, 90*bf457942SKir Chou { .pat = "*abcd*abcdef*", .str = "abcabcdabcdeabcdefg", .expected = true }, 91*bf457942SKir Chou { .pat = "*abcd*", .str = "abcabcabcabcefg", .expected = false }, 92*bf457942SKir Chou { .pat = "*ab*cd*", .str = "abcabcabcabcefg", .expected = false }, 93*bf457942SKir Chou }; 94*bf457942SKir Chou 95*bf457942SKir Chou static void glob_case_to_desc(const struct glob_test_case *t, char *desc) 96*bf457942SKir Chou { 97*bf457942SKir Chou snprintf(desc, KUNIT_PARAM_DESC_SIZE, "pat:\"%s\" str:\"%s\"", t->pat, t->str); 98*bf457942SKir Chou } 99*bf457942SKir Chou 100*bf457942SKir Chou KUNIT_ARRAY_PARAM(glob, glob_test_cases, glob_case_to_desc); 101*bf457942SKir Chou 102*bf457942SKir Chou static void glob_test_match(struct kunit *test) 103*bf457942SKir Chou { 104*bf457942SKir Chou const struct glob_test_case *params = test->param_value; 105*bf457942SKir Chou 106*bf457942SKir Chou KUNIT_EXPECT_EQ_MSG(test, 107*bf457942SKir Chou glob_match(params->pat, params->str), 108*bf457942SKir Chou params->expected, 109*bf457942SKir Chou "Pattern: \"%s\", String: \"%s\", Expected: %d", 110*bf457942SKir Chou params->pat, params->str, params->expected); 111*bf457942SKir Chou } 112*bf457942SKir Chou 113*bf457942SKir Chou static struct kunit_case glob_kunit_test_cases[] = { 114*bf457942SKir Chou KUNIT_CASE_PARAM(glob_test_match, glob_gen_params), 115*bf457942SKir Chou {} 116*bf457942SKir Chou }; 117*bf457942SKir Chou 118*bf457942SKir Chou static struct kunit_suite glob_test_suite = { 119*bf457942SKir Chou .name = "glob", 120*bf457942SKir Chou .test_cases = glob_kunit_test_cases, 121*bf457942SKir Chou }; 122*bf457942SKir Chou 123*bf457942SKir Chou kunit_test_suite(glob_test_suite); 124*bf457942SKir Chou MODULE_DESCRIPTION("Test cases for glob functions"); 125*bf457942SKir Chou MODULE_LICENSE("Dual MIT/GPL"); 126