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

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>

authored by

George Spelvin and committed by
Linus Torvalds
5f9be824 b0125085

+178
+14
lib/Kconfig
··· 415 415 are compiling an out-of tree driver which tells you that it 416 416 depends on this. 417 417 418 + config GLOB_SELFTEST 419 + bool "glob self-test on init" 420 + default n 421 + depends on GLOB 422 + help 423 + This option enables a simple self-test of the glob_match 424 + function on startup. It is primarily useful for people 425 + working on the code to ensure they haven't introduced any 426 + regressions. 427 + 428 + It only adds a little bit of code and slows kernel boot (or 429 + module load) by a small amount, so you're welcome to play with 430 + it, but you probably don't need it. 431 + 418 432 # 419 433 # Netlink attribute parsing support is select'ed if needed 420 434 #
+164
lib/glob.c
··· 121 121 } 122 122 } 123 123 EXPORT_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 */ 132 + static bool verbose = false; 133 + module_param(verbose, bool, 0); 134 + 135 + struct glob_test { 136 + char const *pat, *str; 137 + bool expected; 138 + }; 139 + 140 + static 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 + */ 178 + static 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 + 250 + static 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 */ 282 + static void __exit glob_fini(void) { } 283 + 284 + module_init(glob_init); 285 + module_exit(glob_fini); 286 + 287 + #endif /* CONFIG_GLOB_SELFTEST */