diff options
Diffstat (limited to 'lib/globtest.c')
-rw-r--r-- | lib/globtest.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/lib/globtest.c b/lib/globtest.c new file mode 100644 index 000000000000..d8e97d43b905 --- /dev/null +++ b/lib/globtest.c | |||
@@ -0,0 +1,167 @@ | |||
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"); | ||