xref: /OK3568_Linux_fs/kernel/lib/globtest.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Extracted fronm glob.c
3*4882a593Smuzhiyun  */
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #include <linux/module.h>
6*4882a593Smuzhiyun #include <linux/moduleparam.h>
7*4882a593Smuzhiyun #include <linux/glob.h>
8*4882a593Smuzhiyun #include <linux/printk.h>
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun /* Boot with "glob.verbose=1" to show successful tests, too */
11*4882a593Smuzhiyun static bool verbose = false;
12*4882a593Smuzhiyun module_param(verbose, bool, 0);
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun struct glob_test {
15*4882a593Smuzhiyun 	char const *pat, *str;
16*4882a593Smuzhiyun 	bool expected;
17*4882a593Smuzhiyun };
18*4882a593Smuzhiyun 
test(char const * pat,char const * str,bool expected)19*4882a593Smuzhiyun static bool __pure __init test(char const *pat, char const *str, bool expected)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun 	bool match = glob_match(pat, str);
22*4882a593Smuzhiyun 	bool success = match == expected;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 	/* Can't get string literals into a particular section, so... */
25*4882a593Smuzhiyun 	static char const msg_error[] __initconst =
26*4882a593Smuzhiyun 		KERN_ERR "glob: \"%s\" vs. \"%s\": %s *** ERROR ***\n";
27*4882a593Smuzhiyun 	static char const msg_ok[] __initconst =
28*4882a593Smuzhiyun 		KERN_DEBUG "glob: \"%s\" vs. \"%s\": %s OK\n";
29*4882a593Smuzhiyun 	static char const mismatch[] __initconst = "mismatch";
30*4882a593Smuzhiyun 	char const *message;
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun 	if (!success)
33*4882a593Smuzhiyun 		message = msg_error;
34*4882a593Smuzhiyun 	else if (verbose)
35*4882a593Smuzhiyun 		message = msg_ok;
36*4882a593Smuzhiyun 	else
37*4882a593Smuzhiyun 		return success;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	printk(message, pat, str, mismatch + 3*match);
40*4882a593Smuzhiyun 	return success;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun /*
44*4882a593Smuzhiyun  * The tests are all jammed together in one array to make it simpler
45*4882a593Smuzhiyun  * to place that array in the .init.rodata section.  The obvious
46*4882a593Smuzhiyun  * "array of structures containing char *" has no way to force the
47*4882a593Smuzhiyun  * pointed-to strings to be in a particular section.
48*4882a593Smuzhiyun  *
49*4882a593Smuzhiyun  * Anyway, a test consists of:
50*4882a593Smuzhiyun  * 1. Expected glob_match result: '1' or '0'.
51*4882a593Smuzhiyun  * 2. Pattern to match: null-terminated string
52*4882a593Smuzhiyun  * 3. String to match against: null-terminated string
53*4882a593Smuzhiyun  *
54*4882a593Smuzhiyun  * The list of tests is terminated with a final '\0' instead of
55*4882a593Smuzhiyun  * a glob_match result character.
56*4882a593Smuzhiyun  */
57*4882a593Smuzhiyun static char const glob_tests[] __initconst =
58*4882a593Smuzhiyun 	/* Some basic tests */
59*4882a593Smuzhiyun 	"1" "a\0" "a\0"
60*4882a593Smuzhiyun 	"0" "a\0" "b\0"
61*4882a593Smuzhiyun 	"0" "a\0" "aa\0"
62*4882a593Smuzhiyun 	"0" "a\0" "\0"
63*4882a593Smuzhiyun 	"1" "\0" "\0"
64*4882a593Smuzhiyun 	"0" "\0" "a\0"
65*4882a593Smuzhiyun 	/* Simple character class tests */
66*4882a593Smuzhiyun 	"1" "[a]\0" "a\0"
67*4882a593Smuzhiyun 	"0" "[a]\0" "b\0"
68*4882a593Smuzhiyun 	"0" "[!a]\0" "a\0"
69*4882a593Smuzhiyun 	"1" "[!a]\0" "b\0"
70*4882a593Smuzhiyun 	"1" "[ab]\0" "a\0"
71*4882a593Smuzhiyun 	"1" "[ab]\0" "b\0"
72*4882a593Smuzhiyun 	"0" "[ab]\0" "c\0"
73*4882a593Smuzhiyun 	"1" "[!ab]\0" "c\0"
74*4882a593Smuzhiyun 	"1" "[a-c]\0" "b\0"
75*4882a593Smuzhiyun 	"0" "[a-c]\0" "d\0"
76*4882a593Smuzhiyun 	/* Corner cases in character class parsing */
77*4882a593Smuzhiyun 	"1" "[a-c-e-g]\0" "-\0"
78*4882a593Smuzhiyun 	"0" "[a-c-e-g]\0" "d\0"
79*4882a593Smuzhiyun 	"1" "[a-c-e-g]\0" "f\0"
80*4882a593Smuzhiyun 	"1" "[]a-ceg-ik[]\0" "a\0"
81*4882a593Smuzhiyun 	"1" "[]a-ceg-ik[]\0" "]\0"
82*4882a593Smuzhiyun 	"1" "[]a-ceg-ik[]\0" "[\0"
83*4882a593Smuzhiyun 	"1" "[]a-ceg-ik[]\0" "h\0"
84*4882a593Smuzhiyun 	"0" "[]a-ceg-ik[]\0" "f\0"
85*4882a593Smuzhiyun 	"0" "[!]a-ceg-ik[]\0" "h\0"
86*4882a593Smuzhiyun 	"0" "[!]a-ceg-ik[]\0" "]\0"
87*4882a593Smuzhiyun 	"1" "[!]a-ceg-ik[]\0" "f\0"
88*4882a593Smuzhiyun 	/* Simple wild cards */
89*4882a593Smuzhiyun 	"1" "?\0" "a\0"
90*4882a593Smuzhiyun 	"0" "?\0" "aa\0"
91*4882a593Smuzhiyun 	"0" "??\0" "a\0"
92*4882a593Smuzhiyun 	"1" "?x?\0" "axb\0"
93*4882a593Smuzhiyun 	"0" "?x?\0" "abx\0"
94*4882a593Smuzhiyun 	"0" "?x?\0" "xab\0"
95*4882a593Smuzhiyun 	/* Asterisk wild cards (backtracking) */
96*4882a593Smuzhiyun 	"0" "*??\0" "a\0"
97*4882a593Smuzhiyun 	"1" "*??\0" "ab\0"
98*4882a593Smuzhiyun 	"1" "*??\0" "abc\0"
99*4882a593Smuzhiyun 	"1" "*??\0" "abcd\0"
100*4882a593Smuzhiyun 	"0" "??*\0" "a\0"
101*4882a593Smuzhiyun 	"1" "??*\0" "ab\0"
102*4882a593Smuzhiyun 	"1" "??*\0" "abc\0"
103*4882a593Smuzhiyun 	"1" "??*\0" "abcd\0"
104*4882a593Smuzhiyun 	"0" "?*?\0" "a\0"
105*4882a593Smuzhiyun 	"1" "?*?\0" "ab\0"
106*4882a593Smuzhiyun 	"1" "?*?\0" "abc\0"
107*4882a593Smuzhiyun 	"1" "?*?\0" "abcd\0"
108*4882a593Smuzhiyun 	"1" "*b\0" "b\0"
109*4882a593Smuzhiyun 	"1" "*b\0" "ab\0"
110*4882a593Smuzhiyun 	"0" "*b\0" "ba\0"
111*4882a593Smuzhiyun 	"1" "*b\0" "bb\0"
112*4882a593Smuzhiyun 	"1" "*b\0" "abb\0"
113*4882a593Smuzhiyun 	"1" "*b\0" "bab\0"
114*4882a593Smuzhiyun 	"1" "*bc\0" "abbc\0"
115*4882a593Smuzhiyun 	"1" "*bc\0" "bc\0"
116*4882a593Smuzhiyun 	"1" "*bc\0" "bbc\0"
117*4882a593Smuzhiyun 	"1" "*bc\0" "bcbc\0"
118*4882a593Smuzhiyun 	/* Multiple asterisks (complex backtracking) */
119*4882a593Smuzhiyun 	"1" "*ac*\0" "abacadaeafag\0"
120*4882a593Smuzhiyun 	"1" "*ac*ae*ag*\0" "abacadaeafag\0"
121*4882a593Smuzhiyun 	"1" "*a*b*[bc]*[ef]*g*\0" "abacadaeafag\0"
122*4882a593Smuzhiyun 	"0" "*a*b*[ef]*[cd]*g*\0" "abacadaeafag\0"
123*4882a593Smuzhiyun 	"1" "*abcd*\0" "abcabcabcabcdefg\0"
124*4882a593Smuzhiyun 	"1" "*ab*cd*\0" "abcabcabcabcdefg\0"
125*4882a593Smuzhiyun 	"1" "*abcd*abcdef*\0" "abcabcdabcdeabcdefg\0"
126*4882a593Smuzhiyun 	"0" "*abcd*\0" "abcabcabcabcefg\0"
127*4882a593Smuzhiyun 	"0" "*ab*cd*\0" "abcabcabcabcefg\0";
128*4882a593Smuzhiyun 
glob_init(void)129*4882a593Smuzhiyun static int __init glob_init(void)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	unsigned successes = 0;
132*4882a593Smuzhiyun 	unsigned n = 0;
133*4882a593Smuzhiyun 	char const *p = glob_tests;
134*4882a593Smuzhiyun 	static char const message[] __initconst =
135*4882a593Smuzhiyun 		KERN_INFO "glob: %u self-tests passed, %u failed\n";
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	/*
138*4882a593Smuzhiyun 	 * Tests are jammed together in a string.  The first byte is '1'
139*4882a593Smuzhiyun 	 * or '0' to indicate the expected outcome, or '\0' to indicate the
140*4882a593Smuzhiyun 	 * end of the tests.  Then come two null-terminated strings: the
141*4882a593Smuzhiyun 	 * pattern and the string to match it against.
142*4882a593Smuzhiyun 	 */
143*4882a593Smuzhiyun 	while (*p) {
144*4882a593Smuzhiyun 		bool expected = *p++ & 1;
145*4882a593Smuzhiyun 		char const *pat = p;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 		p += strlen(p) + 1;
148*4882a593Smuzhiyun 		successes += test(pat, p, expected);
149*4882a593Smuzhiyun 		p += strlen(p) + 1;
150*4882a593Smuzhiyun 		n++;
151*4882a593Smuzhiyun 	}
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	n -= successes;
154*4882a593Smuzhiyun 	printk(message, successes, n);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	/* What's the errno for "kernel bug detected"?  Guess... */
157*4882a593Smuzhiyun 	return n ? -ECANCELED : 0;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun /* We need a dummy exit function to allow unload */
glob_fini(void)161*4882a593Smuzhiyun static void __exit glob_fini(void) { }
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun module_init(glob_init);
164*4882a593Smuzhiyun module_exit(glob_fini);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun MODULE_DESCRIPTION("glob(7) matching tests");
167*4882a593Smuzhiyun MODULE_LICENSE("Dual MIT/GPL");
168