Commit | Line | Data |
---|---|---|
1d71307a DL |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * KUnit test for the KUnit executor. | |
4 | * | |
5 | * Copyright (C) 2021, Google LLC. | |
6 | * Author: Daniel Latypov <dlatypov@google.com> | |
7 | */ | |
8 | ||
9 | #include <kunit/test.h> | |
10 | ||
11 | static void kfree_at_end(struct kunit *test, const void *to_free); | |
a127b154 DL |
12 | static void free_subsuite_at_end(struct kunit *test, |
13 | struct kunit_suite *const *to_free); | |
1d71307a | 14 | static struct kunit_suite *alloc_fake_suite(struct kunit *test, |
a127b154 DL |
15 | const char *suite_name, |
16 | struct kunit_case *test_cases); | |
17 | ||
18 | static void dummy_test(struct kunit *test) {} | |
19 | ||
20 | static struct kunit_case dummy_test_cases[] = { | |
21 | /* .run_case is not important, just needs to be non-NULL */ | |
22 | { .name = "test1", .run_case = dummy_test }, | |
23 | { .name = "test2", .run_case = dummy_test }, | |
24 | {}, | |
25 | }; | |
26 | ||
27 | static void parse_filter_test(struct kunit *test) | |
28 | { | |
29 | struct kunit_test_filter filter = {NULL, NULL}; | |
30 | ||
31 | kunit_parse_filter_glob(&filter, "suite"); | |
32 | KUNIT_EXPECT_STREQ(test, filter.suite_glob, "suite"); | |
33 | KUNIT_EXPECT_FALSE(test, filter.test_glob); | |
34 | kfree(filter.suite_glob); | |
35 | kfree(filter.test_glob); | |
36 | ||
37 | kunit_parse_filter_glob(&filter, "suite.test"); | |
38 | KUNIT_EXPECT_STREQ(test, filter.suite_glob, "suite"); | |
39 | KUNIT_EXPECT_STREQ(test, filter.test_glob, "test"); | |
40 | kfree(filter.suite_glob); | |
41 | kfree(filter.test_glob); | |
42 | } | |
1d71307a DL |
43 | |
44 | static void filter_subsuite_test(struct kunit *test) | |
45 | { | |
46 | struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; | |
47 | struct kunit_suite * const *filtered; | |
a127b154 DL |
48 | struct kunit_test_filter filter = { |
49 | .suite_glob = "suite2", | |
50 | .test_glob = NULL, | |
51 | }; | |
1d71307a | 52 | |
a127b154 DL |
53 | subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); |
54 | subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases); | |
1d71307a DL |
55 | |
56 | /* Want: suite1, suite2, NULL -> suite2, NULL */ | |
a127b154 | 57 | filtered = kunit_filter_subsuite(subsuite, &filter); |
1d71307a | 58 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered); |
a127b154 | 59 | free_subsuite_at_end(test, filtered); |
1d71307a | 60 | |
a127b154 | 61 | /* Validate we just have suite2 */ |
1d71307a DL |
62 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]); |
63 | KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->name, "suite2"); | |
a127b154 DL |
64 | KUNIT_EXPECT_FALSE(test, filtered[1]); |
65 | } | |
66 | ||
67 | static void filter_subsuite_test_glob_test(struct kunit *test) | |
68 | { | |
69 | struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; | |
70 | struct kunit_suite * const *filtered; | |
71 | struct kunit_test_filter filter = { | |
72 | .suite_glob = "suite2", | |
73 | .test_glob = "test2", | |
74 | }; | |
75 | ||
76 | subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); | |
77 | subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases); | |
1d71307a | 78 | |
a127b154 DL |
79 | /* Want: suite1, suite2, NULL -> suite2 (just test1), NULL */ |
80 | filtered = kunit_filter_subsuite(subsuite, &filter); | |
81 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered); | |
82 | free_subsuite_at_end(test, filtered); | |
83 | ||
84 | /* Validate we just have suite2 */ | |
85 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]); | |
86 | KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->name, "suite2"); | |
1d71307a | 87 | KUNIT_EXPECT_FALSE(test, filtered[1]); |
a127b154 DL |
88 | |
89 | /* Now validate we just have test2 */ | |
90 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]->test_cases); | |
91 | KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->test_cases[0].name, "test2"); | |
92 | KUNIT_EXPECT_FALSE(test, filtered[0]->test_cases[1].name); | |
1d71307a DL |
93 | } |
94 | ||
95 | static void filter_subsuite_to_empty_test(struct kunit *test) | |
96 | { | |
97 | struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; | |
98 | struct kunit_suite * const *filtered; | |
a127b154 DL |
99 | struct kunit_test_filter filter = { |
100 | .suite_glob = "not_found", | |
101 | .test_glob = NULL, | |
102 | }; | |
1d71307a | 103 | |
a127b154 DL |
104 | subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); |
105 | subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases); | |
1d71307a | 106 | |
a127b154 DL |
107 | filtered = kunit_filter_subsuite(subsuite, &filter); |
108 | free_subsuite_at_end(test, filtered); /* just in case */ | |
1d71307a DL |
109 | |
110 | KUNIT_EXPECT_FALSE_MSG(test, filtered, | |
111 | "should be NULL to indicate no match"); | |
112 | } | |
113 | ||
114 | static void kfree_subsuites_at_end(struct kunit *test, struct suite_set *suite_set) | |
115 | { | |
116 | struct kunit_suite * const * const *suites; | |
117 | ||
118 | kfree_at_end(test, suite_set->start); | |
119 | for (suites = suite_set->start; suites < suite_set->end; suites++) | |
a127b154 | 120 | free_subsuite_at_end(test, *suites); |
1d71307a DL |
121 | } |
122 | ||
123 | static void filter_suites_test(struct kunit *test) | |
124 | { | |
125 | /* Suites per-file are stored as a NULL terminated array */ | |
126 | struct kunit_suite *subsuites[2][2] = { | |
127 | {NULL, NULL}, | |
128 | {NULL, NULL}, | |
129 | }; | |
130 | /* Match the memory layout of suite_set */ | |
131 | struct kunit_suite * const * const suites[2] = { | |
132 | subsuites[0], subsuites[1], | |
133 | }; | |
134 | ||
135 | const struct suite_set suite_set = { | |
136 | .start = suites, | |
137 | .end = suites + 2, | |
138 | }; | |
139 | struct suite_set filtered = {.start = NULL, .end = NULL}; | |
140 | ||
141 | /* Emulate two files, each having one suite */ | |
a127b154 DL |
142 | subsuites[0][0] = alloc_fake_suite(test, "suite0", dummy_test_cases); |
143 | subsuites[1][0] = alloc_fake_suite(test, "suite1", dummy_test_cases); | |
1d71307a DL |
144 | |
145 | /* Filter out suite1 */ | |
146 | filtered = kunit_filter_suites(&suite_set, "suite0"); | |
147 | kfree_subsuites_at_end(test, &filtered); /* let us use ASSERTs without leaking */ | |
148 | KUNIT_ASSERT_EQ(test, filtered.end - filtered.start, (ptrdiff_t)1); | |
149 | ||
150 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start); | |
151 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start[0]); | |
cd94fbc2 | 152 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start[0][0]); |
1d71307a DL |
153 | KUNIT_EXPECT_STREQ(test, (const char *)filtered.start[0][0]->name, "suite0"); |
154 | } | |
155 | ||
156 | static struct kunit_case executor_test_cases[] = { | |
a127b154 | 157 | KUNIT_CASE(parse_filter_test), |
1d71307a | 158 | KUNIT_CASE(filter_subsuite_test), |
a127b154 | 159 | KUNIT_CASE(filter_subsuite_test_glob_test), |
1d71307a DL |
160 | KUNIT_CASE(filter_subsuite_to_empty_test), |
161 | KUNIT_CASE(filter_suites_test), | |
162 | {} | |
163 | }; | |
164 | ||
165 | static struct kunit_suite executor_test_suite = { | |
166 | .name = "kunit_executor_test", | |
167 | .test_cases = executor_test_cases, | |
168 | }; | |
169 | ||
170 | kunit_test_suites(&executor_test_suite); | |
171 | ||
172 | /* Test helpers */ | |
173 | ||
174 | static void kfree_res_free(struct kunit_resource *res) | |
175 | { | |
176 | kfree(res->data); | |
177 | } | |
178 | ||
179 | /* Use the resource API to register a call to kfree(to_free). | |
180 | * Since we never actually use the resource, it's safe to use on const data. | |
181 | */ | |
182 | static void kfree_at_end(struct kunit *test, const void *to_free) | |
183 | { | |
184 | /* kfree() handles NULL already, but avoid allocating a no-op cleanup. */ | |
185 | if (IS_ERR_OR_NULL(to_free)) | |
186 | return; | |
f62314b1 XY |
187 | kunit_alloc_resource(test, NULL, kfree_res_free, GFP_KERNEL, |
188 | (void *)to_free); | |
1d71307a DL |
189 | } |
190 | ||
a127b154 DL |
191 | static void free_subsuite_res_free(struct kunit_resource *res) |
192 | { | |
193 | kunit_free_subsuite(res->data); | |
194 | } | |
195 | ||
196 | static void free_subsuite_at_end(struct kunit *test, | |
197 | struct kunit_suite *const *to_free) | |
198 | { | |
199 | if (IS_ERR_OR_NULL(to_free)) | |
200 | return; | |
201 | kunit_alloc_resource(test, NULL, free_subsuite_res_free, | |
202 | GFP_KERNEL, (void *)to_free); | |
203 | } | |
204 | ||
1d71307a | 205 | static struct kunit_suite *alloc_fake_suite(struct kunit *test, |
a127b154 DL |
206 | const char *suite_name, |
207 | struct kunit_case *test_cases) | |
1d71307a DL |
208 | { |
209 | struct kunit_suite *suite; | |
210 | ||
211 | /* We normally never expect to allocate suites, hence the non-const cast. */ | |
212 | suite = kunit_kzalloc(test, sizeof(*suite), GFP_KERNEL); | |
213 | strncpy((char *)suite->name, suite_name, sizeof(suite->name) - 1); | |
a127b154 | 214 | suite->test_cases = test_cases; |
1d71307a DL |
215 | |
216 | return suite; | |
217 | } |