xref: /openbmc/linux/lib/globtest.c (revision ba95b045)
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 
test(char const * pat,char const * str,bool expected)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 
glob_init(void)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 */
glob_fini(void)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");
168