xref: /openbmc/linux/lib/kunit/executor_test.c (revision 1c9fd080)
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 #include <kunit/attributes.h>
11 
12 static void kfree_at_end(struct kunit *test, const void *to_free);
13 static struct kunit_suite *alloc_fake_suite(struct kunit *test,
14 					    const char *suite_name,
15 					    struct kunit_case *test_cases);
16 
17 static void dummy_test(struct kunit *test) {}
18 
19 static struct kunit_case dummy_test_cases[] = {
20 	/* .run_case is not important, just needs to be non-NULL */
21 	{ .name = "test1", .run_case = dummy_test },
22 	{ .name = "test2", .run_case = dummy_test },
23 	{},
24 };
25 
26 static void parse_filter_test(struct kunit *test)
27 {
28 	struct kunit_glob_filter filter = {NULL, NULL};
29 
30 	kunit_parse_glob_filter(&filter, "suite");
31 	KUNIT_EXPECT_STREQ(test, filter.suite_glob, "suite");
32 	KUNIT_EXPECT_FALSE(test, filter.test_glob);
33 	kfree(filter.suite_glob);
34 	kfree(filter.test_glob);
35 
36 	kunit_parse_glob_filter(&filter, "suite.test");
37 	KUNIT_EXPECT_STREQ(test, filter.suite_glob, "suite");
38 	KUNIT_EXPECT_STREQ(test, filter.test_glob, "test");
39 	kfree(filter.suite_glob);
40 	kfree(filter.test_glob);
41 }
42 
43 static void filter_suites_test(struct kunit *test)
44 {
45 	struct kunit_suite *subsuite[3] = {NULL, NULL};
46 	struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]};
47 	struct suite_set got;
48 	int err = 0;
49 
50 	subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases);
51 	subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases);
52 
53 	/* Want: suite1, suite2, NULL -> suite2, NULL */
54 	got = kunit_filter_suites(&suite_set, "suite2", NULL, NULL, &err);
55 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
56 	KUNIT_ASSERT_EQ(test, err, 0);
57 	kfree_at_end(test, got.start);
58 
59 	/* Validate we just have suite2 */
60 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]);
61 	KUNIT_EXPECT_STREQ(test, (const char *)got.start[0]->name, "suite2");
62 
63 	/* Contains one element (end is 1 past end) */
64 	KUNIT_ASSERT_EQ(test, got.end - got.start, 1);
65 }
66 
67 static void filter_suites_test_glob_test(struct kunit *test)
68 {
69 	struct kunit_suite *subsuite[3] = {NULL, NULL};
70 	struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]};
71 	struct suite_set got;
72 	int err = 0;
73 
74 	subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases);
75 	subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases);
76 
77 	/* Want: suite1, suite2, NULL -> suite2 (just test1), NULL */
78 	got = kunit_filter_suites(&suite_set, "suite2.test2", NULL, NULL, &err);
79 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
80 	KUNIT_ASSERT_EQ(test, err, 0);
81 	kfree_at_end(test, got.start);
82 
83 	/* Validate we just have suite2 */
84 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]);
85 	KUNIT_EXPECT_STREQ(test, (const char *)got.start[0]->name, "suite2");
86 	KUNIT_ASSERT_EQ(test, got.end - got.start, 1);
87 
88 	/* Now validate we just have test2 */
89 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]->test_cases);
90 	KUNIT_EXPECT_STREQ(test, (const char *)got.start[0]->test_cases[0].name, "test2");
91 	KUNIT_EXPECT_FALSE(test, got.start[0]->test_cases[1].name);
92 }
93 
94 static void filter_suites_to_empty_test(struct kunit *test)
95 {
96 	struct kunit_suite *subsuite[3] = {NULL, NULL};
97 	struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]};
98 	struct suite_set got;
99 	int err = 0;
100 
101 	subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases);
102 	subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases);
103 
104 	got = kunit_filter_suites(&suite_set, "not_found", NULL, NULL, &err);
105 	KUNIT_ASSERT_EQ(test, err, 0);
106 	kfree_at_end(test, got.start); /* just in case */
107 
108 	KUNIT_EXPECT_PTR_EQ_MSG(test, got.start, got.end,
109 				"should be empty to indicate no match");
110 }
111 
112 static void parse_filter_attr_test(struct kunit *test)
113 {
114 	int j, filter_count;
115 	struct kunit_attr_filter *parsed_filters;
116 	char *filters = "speed>slow, module!=example";
117 	int err = 0;
118 
119 	filter_count = kunit_get_filter_count(filters);
120 	KUNIT_EXPECT_EQ(test, filter_count, 2);
121 
122 	parsed_filters = kunit_kcalloc(test, filter_count, sizeof(*parsed_filters),
123 			GFP_KERNEL);
124 	for (j = 0; j < filter_count; j++) {
125 		parsed_filters[j] = kunit_next_attr_filter(&filters, &err);
126 		KUNIT_ASSERT_EQ_MSG(test, err, 0, "failed to parse filter '%s'", filters[j]);
127 	}
128 
129 	KUNIT_EXPECT_STREQ(test, kunit_attr_filter_name(parsed_filters[0]), "speed");
130 	KUNIT_EXPECT_STREQ(test, parsed_filters[0].input, ">slow");
131 
132 	KUNIT_EXPECT_STREQ(test, kunit_attr_filter_name(parsed_filters[1]), "module");
133 	KUNIT_EXPECT_STREQ(test, parsed_filters[1].input, "!=example");
134 }
135 
136 static struct kunit_case dummy_attr_test_cases[] = {
137 	/* .run_case is not important, just needs to be non-NULL */
138 	{ .name = "slow", .run_case = dummy_test, .module_name = "dummy",
139 	  .attr.speed = KUNIT_SPEED_SLOW },
140 	{ .name = "normal", .run_case = dummy_test, .module_name = "dummy" },
141 	{},
142 };
143 
144 static void filter_attr_test(struct kunit *test)
145 {
146 	struct kunit_suite *subsuite[3] = {NULL, NULL};
147 	struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]};
148 	struct suite_set got;
149 	int err = 0;
150 
151 	subsuite[0] = alloc_fake_suite(test, "normal_suite", dummy_attr_test_cases);
152 	subsuite[1] = alloc_fake_suite(test, "slow_suite", dummy_attr_test_cases);
153 	subsuite[1]->attr.speed = KUNIT_SPEED_SLOW; // Set suite attribute
154 
155 	/*
156 	 * Want: normal_suite(slow, normal), slow_suite(slow, normal),
157 	 *		NULL -> normal_suite(normal), NULL
158 	 *
159 	 * The normal test in slow_suite is filtered out because the speed
160 	 * attribute is unset and thus, the filtering is based on the parent attribute
161 	 * of slow.
162 	 */
163 	got = kunit_filter_suites(&suite_set, NULL, "speed>slow", NULL, &err);
164 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
165 	KUNIT_ASSERT_EQ(test, err, 0);
166 	kfree_at_end(test, got.start);
167 
168 	/* Validate we just have normal_suite */
169 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]);
170 	KUNIT_EXPECT_STREQ(test, got.start[0]->name, "normal_suite");
171 	KUNIT_ASSERT_EQ(test, got.end - got.start, 1);
172 
173 	/* Now validate we just have normal test case */
174 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]->test_cases);
175 	KUNIT_EXPECT_STREQ(test, got.start[0]->test_cases[0].name, "normal");
176 	KUNIT_EXPECT_FALSE(test, got.start[0]->test_cases[1].name);
177 }
178 
179 static void filter_attr_empty_test(struct kunit *test)
180 {
181 	struct kunit_suite *subsuite[3] = {NULL, NULL};
182 	struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]};
183 	struct suite_set got;
184 	int err = 0;
185 
186 	subsuite[0] = alloc_fake_suite(test, "suite1", dummy_attr_test_cases);
187 	subsuite[1] = alloc_fake_suite(test, "suite2", dummy_attr_test_cases);
188 
189 	got = kunit_filter_suites(&suite_set, NULL, "module!=dummy", NULL, &err);
190 	KUNIT_ASSERT_EQ(test, err, 0);
191 	kfree_at_end(test, got.start); /* just in case */
192 
193 	KUNIT_EXPECT_PTR_EQ_MSG(test, got.start, got.end,
194 				"should be empty to indicate no match");
195 }
196 
197 static void filter_attr_skip_test(struct kunit *test)
198 {
199 	struct kunit_suite *subsuite[2] = {NULL};
200 	struct suite_set suite_set = {.start = subsuite, .end = &subsuite[1]};
201 	struct suite_set got;
202 	int err = 0;
203 
204 	subsuite[0] = alloc_fake_suite(test, "suite", dummy_attr_test_cases);
205 
206 	/* Want: suite(slow, normal), NULL -> suite(slow with SKIP, normal), NULL */
207 	got = kunit_filter_suites(&suite_set, NULL, "speed>slow", "skip", &err);
208 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
209 	KUNIT_ASSERT_EQ(test, err, 0);
210 	kfree_at_end(test, got.start);
211 
212 	/* Validate we have both the slow and normal test */
213 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]->test_cases);
214 	KUNIT_ASSERT_EQ(test, kunit_suite_num_test_cases(got.start[0]), 2);
215 	KUNIT_EXPECT_STREQ(test, got.start[0]->test_cases[0].name, "slow");
216 	KUNIT_EXPECT_STREQ(test, got.start[0]->test_cases[1].name, "normal");
217 
218 	/* Now ensure slow is skipped and normal is not */
219 	KUNIT_EXPECT_EQ(test, got.start[0]->test_cases[0].status, KUNIT_SKIPPED);
220 	KUNIT_EXPECT_FALSE(test, got.start[0]->test_cases[1].status);
221 }
222 
223 static struct kunit_case executor_test_cases[] = {
224 	KUNIT_CASE(parse_filter_test),
225 	KUNIT_CASE(filter_suites_test),
226 	KUNIT_CASE(filter_suites_test_glob_test),
227 	KUNIT_CASE(filter_suites_to_empty_test),
228 	KUNIT_CASE(parse_filter_attr_test),
229 	KUNIT_CASE(filter_attr_test),
230 	KUNIT_CASE(filter_attr_empty_test),
231 	KUNIT_CASE(filter_attr_skip_test),
232 	{}
233 };
234 
235 static struct kunit_suite executor_test_suite = {
236 	.name = "kunit_executor_test",
237 	.test_cases = executor_test_cases,
238 };
239 
240 kunit_test_suites(&executor_test_suite);
241 
242 /* Test helpers */
243 
244 /* Use the resource API to register a call to kfree(to_free).
245  * Since we never actually use the resource, it's safe to use on const data.
246  */
247 static void kfree_at_end(struct kunit *test, const void *to_free)
248 {
249 	/* kfree() handles NULL already, but avoid allocating a no-op cleanup. */
250 	if (IS_ERR_OR_NULL(to_free))
251 		return;
252 
253 	kunit_add_action(test,
254 			(kunit_action_t *)kfree,
255 			(void *)to_free);
256 }
257 
258 static struct kunit_suite *alloc_fake_suite(struct kunit *test,
259 					    const char *suite_name,
260 					    struct kunit_case *test_cases)
261 {
262 	struct kunit_suite *suite;
263 
264 	/* We normally never expect to allocate suites, hence the non-const cast. */
265 	suite = kunit_kzalloc(test, sizeof(*suite), GFP_KERNEL);
266 	strncpy((char *)suite->name, suite_name, sizeof(suite->name) - 1);
267 	suite->test_cases = test_cases;
268 
269 	return suite;
270 }
271