xref: /linux/lib/globtest.c (revision ba95b045)
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