]>
Commit | Line | Data |
---|---|---|
7546861a AS |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Test cases for API provided by cmdline.c | |
4 | */ | |
5 | ||
6 | #include <kunit/test.h> | |
7 | #include <linux/kernel.h> | |
8 | #include <linux/random.h> | |
9 | #include <linux/string.h> | |
10 | ||
11 | static const char *cmdline_test_strings[] = { | |
12 | "\"\"", "" , "=" , "\"-", "," , "-," , ",-" , "-" , | |
13 | "+," , "--", ",,", "''" , "\"\",", "\",\"", "-\"\"", "\"", | |
14 | }; | |
15 | ||
16 | static const int cmdline_test_values[] = { | |
17 | 1, 1, 1, 1, 2, 3, 2, 3, | |
18 | 1, 3, 2, 1, 1, 1, 3, 1, | |
19 | }; | |
20 | ||
d3c7cfc6 AS |
21 | static_assert(ARRAY_SIZE(cmdline_test_strings) == ARRAY_SIZE(cmdline_test_values)); |
22 | ||
23 | static const char *cmdline_test_range_strings[] = { | |
24 | "-7" , "--7" , "-1-2" , "7--9", | |
25 | "7-" , "-7--9", "7-9," , "9-7" , | |
26 | "5-a", "a-5" , "5-8" , ",8-5", | |
27 | "+,1", "-,4" , "-3,0-1,6", "4,-" , | |
28 | " +2", " -9" , "0-1,-3,6", "- 9" , | |
29 | }; | |
30 | ||
31 | static const int cmdline_test_range_values[][16] = { | |
32 | { 1, -7, }, { 0, -0, }, { 4, -1, 0, +1, 2, }, { 0, 7, }, | |
33 | { 0, +7, }, { 0, -7, }, { 3, +7, 8, +9, 0, }, { 0, 9, }, | |
34 | { 0, +5, }, { 0, -0, }, { 4, +5, 6, +7, 8, }, { 0, 0, }, | |
35 | { 0, +0, }, { 0, -0, }, { 4, -3, 0, +1, 6, }, { 1, 4, }, | |
36 | { 0, +0, }, { 0, -0, }, { 4, +0, 1, -3, 6, }, { 0, 0, }, | |
37 | }; | |
38 | ||
39 | static_assert(ARRAY_SIZE(cmdline_test_range_strings) == ARRAY_SIZE(cmdline_test_range_values)); | |
40 | ||
7546861a AS |
41 | static void cmdline_do_one_test(struct kunit *test, const char *in, int rc, int offset) |
42 | { | |
43 | const char *fmt = "Pattern: %s"; | |
44 | const char *out = in; | |
45 | int dummy; | |
46 | int ret; | |
47 | ||
48 | ret = get_option((char **)&out, &dummy); | |
49 | ||
50 | KUNIT_EXPECT_EQ_MSG(test, ret, rc, fmt, in); | |
51 | KUNIT_EXPECT_PTR_EQ_MSG(test, out, in + offset, fmt, in); | |
52 | } | |
53 | ||
54 | static void cmdline_test_noint(struct kunit *test) | |
55 | { | |
56 | unsigned int i = 0; | |
57 | ||
58 | do { | |
59 | const char *str = cmdline_test_strings[i]; | |
60 | int rc = 0; | |
61 | int offset; | |
62 | ||
63 | /* Only first and leading '-' will advance the pointer */ | |
64 | offset = !!(*str == '-'); | |
65 | cmdline_do_one_test(test, str, rc, offset); | |
66 | } while (++i < ARRAY_SIZE(cmdline_test_strings)); | |
67 | } | |
68 | ||
69 | static void cmdline_test_lead_int(struct kunit *test) | |
70 | { | |
71 | unsigned int i = 0; | |
72 | char in[32]; | |
73 | ||
74 | do { | |
75 | const char *str = cmdline_test_strings[i]; | |
76 | int rc = cmdline_test_values[i]; | |
77 | int offset; | |
78 | ||
79 | sprintf(in, "%u%s", get_random_int() % 256, str); | |
80 | /* Only first '-' after the number will advance the pointer */ | |
81 | offset = strlen(in) - strlen(str) + !!(rc == 2); | |
82 | cmdline_do_one_test(test, in, rc, offset); | |
83 | } while (++i < ARRAY_SIZE(cmdline_test_strings)); | |
84 | } | |
85 | ||
86 | static void cmdline_test_tail_int(struct kunit *test) | |
87 | { | |
88 | unsigned int i = 0; | |
89 | char in[32]; | |
90 | ||
91 | do { | |
92 | const char *str = cmdline_test_strings[i]; | |
93 | /* When "" or "-" the result will be valid integer */ | |
94 | int rc = strcmp(str, "") ? (strcmp(str, "-") ? 0 : 1) : 1; | |
95 | int offset; | |
96 | ||
97 | sprintf(in, "%s%u", str, get_random_int() % 256); | |
98 | /* | |
99 | * Only first and leading '-' not followed by integer | |
100 | * will advance the pointer. | |
101 | */ | |
102 | offset = rc ? strlen(in) : !!(*str == '-'); | |
103 | cmdline_do_one_test(test, in, rc, offset); | |
104 | } while (++i < ARRAY_SIZE(cmdline_test_strings)); | |
105 | } | |
106 | ||
d3c7cfc6 AS |
107 | static void cmdline_do_one_range_test(struct kunit *test, const char *in, |
108 | unsigned int n, const int *e) | |
109 | { | |
110 | unsigned int i; | |
111 | int r[16]; | |
0ea09083 | 112 | int *p; |
d3c7cfc6 AS |
113 | |
114 | memset(r, 0, sizeof(r)); | |
115 | get_options(in, ARRAY_SIZE(r), r); | |
0ea09083 | 116 | KUNIT_EXPECT_EQ_MSG(test, r[0], e[0], "in test %u (parsed) expected %d numbers, got %d", |
d3c7cfc6 AS |
117 | n, e[0], r[0]); |
118 | for (i = 1; i < ARRAY_SIZE(r); i++) | |
119 | KUNIT_EXPECT_EQ_MSG(test, r[i], e[i], "in test %u at %u", n, i); | |
0ea09083 AS |
120 | |
121 | memset(r, 0, sizeof(r)); | |
122 | get_options(in, 0, r); | |
123 | KUNIT_EXPECT_EQ_MSG(test, r[0], e[0], "in test %u (validated) expected %d numbers, got %d", | |
124 | n, e[0], r[0]); | |
125 | ||
126 | p = memchr_inv(&r[1], 0, sizeof(r) - sizeof(r[0])); | |
255ede3b | 127 | KUNIT_EXPECT_PTR_EQ_MSG(test, p, NULL, "in test %u at %u out of bound", n, p - r); |
d3c7cfc6 AS |
128 | } |
129 | ||
130 | static void cmdline_test_range(struct kunit *test) | |
131 | { | |
132 | unsigned int i = 0; | |
133 | ||
134 | do { | |
135 | const char *str = cmdline_test_range_strings[i]; | |
136 | const int *e = cmdline_test_range_values[i]; | |
137 | ||
138 | cmdline_do_one_range_test(test, str, i, e); | |
139 | } while (++i < ARRAY_SIZE(cmdline_test_range_strings)); | |
140 | } | |
141 | ||
7546861a AS |
142 | static struct kunit_case cmdline_test_cases[] = { |
143 | KUNIT_CASE(cmdline_test_noint), | |
144 | KUNIT_CASE(cmdline_test_lead_int), | |
145 | KUNIT_CASE(cmdline_test_tail_int), | |
d3c7cfc6 | 146 | KUNIT_CASE(cmdline_test_range), |
7546861a AS |
147 | {} |
148 | }; | |
149 | ||
150 | static struct kunit_suite cmdline_test_suite = { | |
151 | .name = "cmdline", | |
152 | .test_cases = cmdline_test_cases, | |
153 | }; | |
154 | kunit_test_suite(cmdline_test_suite); | |
155 | ||
156 | MODULE_LICENSE("GPL"); |