aboutsummaryrefslogtreecommitdiffstats
path: root/lib/glob.c
diff options
context:
space:
mode:
authorGeorge Spelvin <linux@horizon.com>2014-08-06 19:09:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 21:01:25 -0400
commit5f9be8248d9802730185f98f4db41285dc00283c (patch)
tree03df2ac3a2557e1565943d36cda6fe1d1e28539a /lib/glob.c
parentb01250856b25f4417c51aa33afc451fbf7da1484 (diff)
lib/glob.c: add CONFIG_GLOB_SELFTEST
This was useful during development, and is retained for future regression testing. GCC appears to have no way to place string literals in a particular section; adding __initconst to a char pointer leaves the string itself in the default string section, where it will not be thrown away after module load. Thus all string constants are kept in explicitly declared and named arrays. Sorry this makes printk a bit harder to read. At least the tests are more compact. Signed-off-by: George Spelvin <linux@horizon.com> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Tejun Heo <tj@kernel.org> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/glob.c')
-rw-r--r--lib/glob.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/lib/glob.c b/lib/glob.c
index 0ba3ea86b546..500fc80d23e1 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -121,3 +121,167 @@ backtrack:
121 } 121 }
122} 122}
123EXPORT_SYMBOL(glob_match); 123EXPORT_SYMBOL(glob_match);
124
125
126#ifdef CONFIG_GLOB_SELFTEST
127
128#include <linux/printk.h>
129#include <linux/moduleparam.h>
130
131/* Boot with "glob.verbose=1" to show successful tests, too */
132static bool verbose = false;
133module_param(verbose, bool, 0);
134
135struct glob_test {
136 char const *pat, *str;
137 bool expected;
138};
139
140static bool __pure __init test(char const *pat, char const *str, bool expected)
141{
142 bool match = glob_match(pat, str);
143 bool success = match == expected;
144
145 /* Can't get string literals into a particular section, so... */
146 static char const msg_error[] __initconst =
147 KERN_ERR "glob: \"%s\" vs. \"%s\": %s *** ERROR ***\n";
148 static char const msg_ok[] __initconst =
149 KERN_DEBUG "glob: \"%s\" vs. \"%s\": %s OK\n";
150 static char const mismatch[] __initconst = "mismatch";
151 char const *message;
152
153 if (!success)
154 message = msg_error;
155 else if (verbose)
156 message = msg_ok;
157 else
158 return success;
159
160 printk(message, pat, str, mismatch + 3*match);
161 return success;
162}
163
164/*
165 * The tests are all jammed together in one array to make it simpler
166 * to place that array in the .init.rodata section. The obvious
167 * "array of structures containing char *" has no way to force the
168 * pointed-to strings to be in a particular section.
169 *
170 * Anyway, a test consists of:
171 * 1. Expected glob_match result: '1' or '0'.
172 * 2. Pattern to match: null-terminated string
173 * 3. String to match against: null-terminated string
174 *
175 * The list of tests is terminated with a final '\0' instead of
176 * a glob_match result character.
177 */
178static char const glob_tests[] __initconst =
179 /* Some basic tests */
180 "1" "a\0" "a\0"
181 "0" "a\0" "b\0"
182 "0" "a\0" "aa\0"
183 "0" "a\0" "\0"
184 "1" "\0" "\0"
185 "0" "\0" "a\0"
186 /* Simple character class tests */
187 "1" "[a]\0" "a\0"
188 "0" "[a]\0" "b\0"
189 "0" "[!a]\0" "a\0"
190 "1" "[!a]\0" "b\0"
191 "1" "[ab]\0" "a\0"
192 "1" "[ab]\0" "b\0"
193 "0" "[ab]\0" "c\0"
194 "1" "[!ab]\0" "c\0"
195 "1" "[a-c]\0" "b\0"
196 "0" "[a-c]\0" "d\0"
197 /* Corner cases in character class parsing */
198 "1" "[a-c-e-g]\0" "-\0"
199 "0" "[a-c-e-g]\0" "d\0"
200 "1" "[a-c-e-g]\0" "f\0"
201 "1" "[]a-ceg-ik[]\0" "a\0"
202 "1" "[]a-ceg-ik[]\0" "]\0"
203 "1" "[]a-ceg-ik[]\0" "[\0"
204 "1" "[]a-ceg-ik[]\0" "h\0"
205 "0" "[]a-ceg-ik[]\0" "f\0"
206 "0" "[!]a-ceg-ik[]\0" "h\0"
207 "0" "[!]a-ceg-ik[]\0" "]\0"
208 "1" "[!]a-ceg-ik[]\0" "f\0"
209 /* Simple wild cards */
210 "1" "?\0" "a\0"
211 "0" "?\0" "aa\0"
212 "0" "??\0" "a\0"
213 "1" "?x?\0" "axb\0"
214 "0" "?x?\0" "abx\0"
215 "0" "?x?\0" "xab\0"
216 /* Asterisk wild cards (backtracking) */
217 "0" "*??\0" "a\0"
218 "1" "*??\0" "ab\0"
219 "1" "*??\0" "abc\0"
220 "1" "*??\0" "abcd\0"
221 "0" "??*\0" "a\0"
222 "1" "??*\0" "ab\0"
223 "1" "??*\0" "abc\0"
224 "1" "??*\0" "abcd\0"
225 "0" "?*?\0" "a\0"
226 "1" "?*?\0" "ab\0"
227 "1" "?*?\0" "abc\0"
228 "1" "?*?\0" "abcd\0"
229 "1" "*b\0" "b\0"
230 "1" "*b\0" "ab\0"
231 "0" "*b\0" "ba\0"
232 "1" "*b\0" "bb\0"
233 "1" "*b\0" "abb\0"
234 "1" "*b\0" "bab\0"
235 "1" "*bc\0" "abbc\0"
236 "1" "*bc\0" "bc\0"
237 "1" "*bc\0" "bbc\0"
238 "1" "*bc\0" "bcbc\0"
239 /* Multiple asterisks (complex backtracking) */
240 "1" "*ac*\0" "abacadaeafag\0"
241 "1" "*ac*ae*ag*\0" "abacadaeafag\0"
242 "1" "*a*b*[bc]*[ef]*g*\0" "abacadaeafag\0"
243 "0" "*a*b*[ef]*[cd]*g*\0" "abacadaeafag\0"
244 "1" "*abcd*\0" "abcabcabcabcdefg\0"
245 "1" "*ab*cd*\0" "abcabcabcabcdefg\0"
246 "1" "*abcd*abcdef*\0" "abcabcdabcdeabcdefg\0"
247 "0" "*abcd*\0" "abcabcabcabcefg\0"
248 "0" "*ab*cd*\0" "abcabcabcabcefg\0";
249
250static int __init glob_init(void)
251{
252 unsigned successes = 0;
253 unsigned n = 0;
254 char const *p = glob_tests;
255 static char const message[] __initconst =
256 KERN_INFO "glob: %u self-tests passed, %u failed\n";
257
258 /*
259 * Tests are jammed together in a string. The first byte is '1'
260 * or '0' to indicate the expected outcome, or '\0' to indicate the
261 * end of the tests. Then come two null-terminated strings: the
262 * pattern and the string to match it against.
263 */
264 while (*p) {
265 bool expected = *p++ & 1;
266 char const *pat = p;
267
268 p += strlen(p) + 1;
269 successes += test(pat, p, expected);
270 p += strlen(p) + 1;
271 n++;
272 }
273
274 n -= successes;
275 printk(message, successes, n);
276
277 /* What's the errno for "kernel bug detected"? Guess... */
278 return n ? -ECANCELED : 0;
279}
280
281/* We need a dummy exit function to allow unload */
282static void __exit glob_fini(void) { }
283
284module_init(glob_init);
285module_exit(glob_fini);
286
287#endif /* CONFIG_GLOB_SELFTEST */