1*ba95b045SGeert Uytterhoeven /*
2*ba95b045SGeert Uytterhoeven * Extracted fronm glob.c
3*ba95b045SGeert Uytterhoeven */
4*ba95b045SGeert Uytterhoeven
5*ba95b045SGeert Uytterhoeven #include <linux/module.h>
6*ba95b045SGeert Uytterhoeven #include <linux/moduleparam.h>
7*ba95b045SGeert Uytterhoeven #include <linux/glob.h>
8*ba95b045SGeert Uytterhoeven #include <linux/printk.h>
9*ba95b045SGeert Uytterhoeven
10*ba95b045SGeert Uytterhoeven /* Boot with "glob.verbose=1" to show successful tests, too */
11*ba95b045SGeert Uytterhoeven static bool verbose = false;
12*ba95b045SGeert Uytterhoeven module_param(verbose, bool, 0);
13*ba95b045SGeert Uytterhoeven
14*ba95b045SGeert Uytterhoeven struct glob_test {
15*ba95b045SGeert Uytterhoeven char const *pat, *str;
16*ba95b045SGeert Uytterhoeven bool expected;
17*ba95b045SGeert Uytterhoeven };
18*ba95b045SGeert Uytterhoeven
test(char const * pat,char const * str,bool expected)19*ba95b045SGeert Uytterhoeven static bool __pure __init test(char const *pat, char const *str, bool expected)
20*ba95b045SGeert Uytterhoeven {
21*ba95b045SGeert Uytterhoeven bool match = glob_match(pat, str);
22*ba95b045SGeert Uytterhoeven bool success = match == expected;
23*ba95b045SGeert Uytterhoeven
24*ba95b045SGeert Uytterhoeven /* Can't get string literals into a particular section, so... */
25*ba95b045SGeert Uytterhoeven static char const msg_error[] __initconst =
26*ba95b045SGeert Uytterhoeven KERN_ERR "glob: \"%s\" vs. \"%s\": %s *** ERROR ***\n";
27*ba95b045SGeert Uytterhoeven static char const msg_ok[] __initconst =
28*ba95b045SGeert Uytterhoeven KERN_DEBUG "glob: \"%s\" vs. \"%s\": %s OK\n";
29*ba95b045SGeert Uytterhoeven static char const mismatch[] __initconst = "mismatch";
30*ba95b045SGeert Uytterhoeven char const *message;
31*ba95b045SGeert Uytterhoeven
32*ba95b045SGeert Uytterhoeven if (!success)
33*ba95b045SGeert Uytterhoeven message = msg_error;
34*ba95b045SGeert Uytterhoeven else if (verbose)
35*ba95b045SGeert Uytterhoeven message = msg_ok;
36*ba95b045SGeert Uytterhoeven else
37*ba95b045SGeert Uytterhoeven return success;
38*ba95b045SGeert Uytterhoeven
39*ba95b045SGeert Uytterhoeven printk(message, pat, str, mismatch + 3*match);
40*ba95b045SGeert Uytterhoeven return success;
41*ba95b045SGeert Uytterhoeven }
42*ba95b045SGeert Uytterhoeven
43*ba95b045SGeert Uytterhoeven /*
44*ba95b045SGeert Uytterhoeven * The tests are all jammed together in one array to make it simpler
45*ba95b045SGeert Uytterhoeven * to place that array in the .init.rodata section. The obvious
46*ba95b045SGeert Uytterhoeven * "array of structures containing char *" has no way to force the
47*ba95b045SGeert Uytterhoeven * pointed-to strings to be in a particular section.
48*ba95b045SGeert Uytterhoeven *
49*ba95b045SGeert Uytterhoeven * Anyway, a test consists of:
50*ba95b045SGeert Uytterhoeven * 1. Expected glob_match result: '1' or '0'.
51*ba95b045SGeert Uytterhoeven * 2. Pattern to match: null-terminated string
52*ba95b045SGeert Uytterhoeven * 3. String to match against: null-terminated string
53*ba95b045SGeert Uytterhoeven *
54*ba95b045SGeert Uytterhoeven * The list of tests is terminated with a final '\0' instead of
55*ba95b045SGeert Uytterhoeven * a glob_match result character.
56*ba95b045SGeert Uytterhoeven */
57*ba95b045SGeert Uytterhoeven static char const glob_tests[] __initconst =
58*ba95b045SGeert Uytterhoeven /* Some basic tests */
59*ba95b045SGeert Uytterhoeven "1" "a\0" "a\0"
60*ba95b045SGeert Uytterhoeven "0" "a\0" "b\0"
61*ba95b045SGeert Uytterhoeven "0" "a\0" "aa\0"
62*ba95b045SGeert Uytterhoeven "0" "a\0" "\0"
63*ba95b045SGeert Uytterhoeven "1" "\0" "\0"
64*ba95b045SGeert Uytterhoeven "0" "\0" "a\0"
65*ba95b045SGeert Uytterhoeven /* Simple character class tests */
66*ba95b045SGeert Uytterhoeven "1" "[a]\0" "a\0"
67*ba95b045SGeert Uytterhoeven "0" "[a]\0" "b\0"
68*ba95b045SGeert Uytterhoeven "0" "[!a]\0" "a\0"
69*ba95b045SGeert Uytterhoeven "1" "[!a]\0" "b\0"
70*ba95b045SGeert Uytterhoeven "1" "[ab]\0" "a\0"
71*ba95b045SGeert Uytterhoeven "1" "[ab]\0" "b\0"
72*ba95b045SGeert Uytterhoeven "0" "[ab]\0" "c\0"
73*ba95b045SGeert Uytterhoeven "1" "[!ab]\0" "c\0"
74*ba95b045SGeert Uytterhoeven "1" "[a-c]\0" "b\0"
75*ba95b045SGeert Uytterhoeven "0" "[a-c]\0" "d\0"
76*ba95b045SGeert Uytterhoeven /* Corner cases in character class parsing */
77*ba95b045SGeert Uytterhoeven "1" "[a-c-e-g]\0" "-\0"
78*ba95b045SGeert Uytterhoeven "0" "[a-c-e-g]\0" "d\0"
79*ba95b045SGeert Uytterhoeven "1" "[a-c-e-g]\0" "f\0"
80*ba95b045SGeert Uytterhoeven "1" "[]a-ceg-ik[]\0" "a\0"
81*ba95b045SGeert Uytterhoeven "1" "[]a-ceg-ik[]\0" "]\0"
82*ba95b045SGeert Uytterhoeven "1" "[]a-ceg-ik[]\0" "[\0"
83*ba95b045SGeert Uytterhoeven "1" "[]a-ceg-ik[]\0" "h\0"
84*ba95b045SGeert Uytterhoeven "0" "[]a-ceg-ik[]\0" "f\0"
85*ba95b045SGeert Uytterhoeven "0" "[!]a-ceg-ik[]\0" "h\0"
86*ba95b045SGeert Uytterhoeven "0" "[!]a-ceg-ik[]\0" "]\0"
87*ba95b045SGeert Uytterhoeven "1" "[!]a-ceg-ik[]\0" "f\0"
88*ba95b045SGeert Uytterhoeven /* Simple wild cards */
89*ba95b045SGeert Uytterhoeven "1" "?\0" "a\0"
90*ba95b045SGeert Uytterhoeven "0" "?\0" "aa\0"
91*ba95b045SGeert Uytterhoeven "0" "??\0" "a\0"
92*ba95b045SGeert Uytterhoeven "1" "?x?\0" "axb\0"
93*ba95b045SGeert Uytterhoeven "0" "?x?\0" "abx\0"
94*ba95b045SGeert Uytterhoeven "0" "?x?\0" "xab\0"
95*ba95b045SGeert Uytterhoeven /* Asterisk wild cards (backtracking) */
96*ba95b045SGeert Uytterhoeven "0" "*??\0" "a\0"
97*ba95b045SGeert Uytterhoeven "1" "*??\0" "ab\0"
98*ba95b045SGeert Uytterhoeven "1" "*??\0" "abc\0"
99*ba95b045SGeert Uytterhoeven "1" "*??\0" "abcd\0"
100*ba95b045SGeert Uytterhoeven "0" "??*\0" "a\0"
101*ba95b045SGeert Uytterhoeven "1" "??*\0" "ab\0"
102*ba95b045SGeert Uytterhoeven "1" "??*\0" "abc\0"
103*ba95b045SGeert Uytterhoeven "1" "??*\0" "abcd\0"
104*ba95b045SGeert Uytterhoeven "0" "?*?\0" "a\0"
105*ba95b045SGeert Uytterhoeven "1" "?*?\0" "ab\0"
106*ba95b045SGeert Uytterhoeven "1" "?*?\0" "abc\0"
107*ba95b045SGeert Uytterhoeven "1" "?*?\0" "abcd\0"
108*ba95b045SGeert Uytterhoeven "1" "*b\0" "b\0"
109*ba95b045SGeert Uytterhoeven "1" "*b\0" "ab\0"
110*ba95b045SGeert Uytterhoeven "0" "*b\0" "ba\0"
111*ba95b045SGeert Uytterhoeven "1" "*b\0" "bb\0"
112*ba95b045SGeert Uytterhoeven "1" "*b\0" "abb\0"
113*ba95b045SGeert Uytterhoeven "1" "*b\0" "bab\0"
114*ba95b045SGeert Uytterhoeven "1" "*bc\0" "abbc\0"
115*ba95b045SGeert Uytterhoeven "1" "*bc\0" "bc\0"
116*ba95b045SGeert Uytterhoeven "1" "*bc\0" "bbc\0"
117*ba95b045SGeert Uytterhoeven "1" "*bc\0" "bcbc\0"
118*ba95b045SGeert Uytterhoeven /* Multiple asterisks (complex backtracking) */
119*ba95b045SGeert Uytterhoeven "1" "*ac*\0" "abacadaeafag\0"
120*ba95b045SGeert Uytterhoeven "1" "*ac*ae*ag*\0" "abacadaeafag\0"
121*ba95b045SGeert Uytterhoeven "1" "*a*b*[bc]*[ef]*g*\0" "abacadaeafag\0"
122*ba95b045SGeert Uytterhoeven "0" "*a*b*[ef]*[cd]*g*\0" "abacadaeafag\0"
123*ba95b045SGeert Uytterhoeven "1" "*abcd*\0" "abcabcabcabcdefg\0"
124*ba95b045SGeert Uytterhoeven "1" "*ab*cd*\0" "abcabcabcabcdefg\0"
125*ba95b045SGeert Uytterhoeven "1" "*abcd*abcdef*\0" "abcabcdabcdeabcdefg\0"
126*ba95b045SGeert Uytterhoeven "0" "*abcd*\0" "abcabcabcabcefg\0"
127*ba95b045SGeert Uytterhoeven "0" "*ab*cd*\0" "abcabcabcabcefg\0";
128*ba95b045SGeert Uytterhoeven
glob_init(void)129*ba95b045SGeert Uytterhoeven static int __init glob_init(void)
130*ba95b045SGeert Uytterhoeven {
131*ba95b045SGeert Uytterhoeven unsigned successes = 0;
132*ba95b045SGeert Uytterhoeven unsigned n = 0;
133*ba95b045SGeert Uytterhoeven char const *p = glob_tests;
134*ba95b045SGeert Uytterhoeven static char const message[] __initconst =
135*ba95b045SGeert Uytterhoeven KERN_INFO "glob: %u self-tests passed, %u failed\n";
136*ba95b045SGeert Uytterhoeven
137*ba95b045SGeert Uytterhoeven /*
138*ba95b045SGeert Uytterhoeven * Tests are jammed together in a string. The first byte is '1'
139*ba95b045SGeert Uytterhoeven * or '0' to indicate the expected outcome, or '\0' to indicate the
140*ba95b045SGeert Uytterhoeven * end of the tests. Then come two null-terminated strings: the
141*ba95b045SGeert Uytterhoeven * pattern and the string to match it against.
142*ba95b045SGeert Uytterhoeven */
143*ba95b045SGeert Uytterhoeven while (*p) {
144*ba95b045SGeert Uytterhoeven bool expected = *p++ & 1;
145*ba95b045SGeert Uytterhoeven char const *pat = p;
146*ba95b045SGeert Uytterhoeven
147*ba95b045SGeert Uytterhoeven p += strlen(p) + 1;
148*ba95b045SGeert Uytterhoeven successes += test(pat, p, expected);
149*ba95b045SGeert Uytterhoeven p += strlen(p) + 1;
150*ba95b045SGeert Uytterhoeven n++;
151*ba95b045SGeert Uytterhoeven }
152*ba95b045SGeert Uytterhoeven
153*ba95b045SGeert Uytterhoeven n -= successes;
154*ba95b045SGeert Uytterhoeven printk(message, successes, n);
155*ba95b045SGeert Uytterhoeven
156*ba95b045SGeert Uytterhoeven /* What's the errno for "kernel bug detected"? Guess... */
157*ba95b045SGeert Uytterhoeven return n ? -ECANCELED : 0;
158*ba95b045SGeert Uytterhoeven }
159*ba95b045SGeert Uytterhoeven
160*ba95b045SGeert Uytterhoeven /* We need a dummy exit function to allow unload */
glob_fini(void)161*ba95b045SGeert Uytterhoeven static void __exit glob_fini(void) { }
162*ba95b045SGeert Uytterhoeven
163*ba95b045SGeert Uytterhoeven module_init(glob_init);
164*ba95b045SGeert Uytterhoeven module_exit(glob_fini);
165*ba95b045SGeert Uytterhoeven
166*ba95b045SGeert Uytterhoeven MODULE_DESCRIPTION("glob(7) matching tests");
167*ba95b045SGeert Uytterhoeven MODULE_LICENSE("Dual MIT/GPL");
168