1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * KUnit test for core test infrastructure. |
4 | * |
5 | * Copyright (C) 2019, Google LLC. |
6 | * Author: Brendan Higgins <brendanhiggins@google.com> |
7 | */ |
8 | #include "linux/gfp_types.h" |
9 | #include <kunit/test.h> |
10 | #include <kunit/test-bug.h> |
11 | |
12 | #include <linux/device.h> |
13 | #include <kunit/device.h> |
14 | |
15 | #include "string-stream.h" |
16 | #include "try-catch-impl.h" |
17 | |
18 | struct kunit_try_catch_test_context { |
19 | struct kunit_try_catch *try_catch; |
20 | bool function_called; |
21 | }; |
22 | |
23 | static void kunit_test_successful_try(void *data) |
24 | { |
25 | struct kunit *test = data; |
26 | struct kunit_try_catch_test_context *ctx = test->priv; |
27 | |
28 | ctx->function_called = true; |
29 | } |
30 | |
31 | static void kunit_test_no_catch(void *data) |
32 | { |
33 | struct kunit *test = data; |
34 | |
35 | KUNIT_FAIL(test, "Catch should not be called\n" ); |
36 | } |
37 | |
38 | static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test) |
39 | { |
40 | struct kunit_try_catch_test_context *ctx = test->priv; |
41 | struct kunit_try_catch *try_catch = ctx->try_catch; |
42 | |
43 | kunit_try_catch_init(try_catch, |
44 | test, |
45 | try: kunit_test_successful_try, |
46 | catch: kunit_test_no_catch); |
47 | kunit_try_catch_run(try_catch, context: test); |
48 | |
49 | KUNIT_EXPECT_TRUE(test, ctx->function_called); |
50 | } |
51 | |
52 | static void kunit_test_unsuccessful_try(void *data) |
53 | { |
54 | struct kunit *test = data; |
55 | struct kunit_try_catch_test_context *ctx = test->priv; |
56 | struct kunit_try_catch *try_catch = ctx->try_catch; |
57 | |
58 | kunit_try_catch_throw(try_catch); |
59 | KUNIT_FAIL(test, "This line should never be reached\n" ); |
60 | } |
61 | |
62 | static void kunit_test_catch(void *data) |
63 | { |
64 | struct kunit *test = data; |
65 | struct kunit_try_catch_test_context *ctx = test->priv; |
66 | |
67 | ctx->function_called = true; |
68 | } |
69 | |
70 | static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test) |
71 | { |
72 | struct kunit_try_catch_test_context *ctx = test->priv; |
73 | struct kunit_try_catch *try_catch = ctx->try_catch; |
74 | |
75 | kunit_try_catch_init(try_catch, |
76 | test, |
77 | try: kunit_test_unsuccessful_try, |
78 | catch: kunit_test_catch); |
79 | kunit_try_catch_run(try_catch, context: test); |
80 | |
81 | KUNIT_EXPECT_TRUE(test, ctx->function_called); |
82 | } |
83 | |
84 | static int kunit_try_catch_test_init(struct kunit *test) |
85 | { |
86 | struct kunit_try_catch_test_context *ctx; |
87 | |
88 | ctx = kunit_kzalloc(test, size: sizeof(*ctx), GFP_KERNEL); |
89 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
90 | test->priv = ctx; |
91 | |
92 | ctx->try_catch = kunit_kmalloc(test, |
93 | size: sizeof(*ctx->try_catch), |
94 | GFP_KERNEL); |
95 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch); |
96 | |
97 | return 0; |
98 | } |
99 | |
100 | static struct kunit_case kunit_try_catch_test_cases[] = { |
101 | KUNIT_CASE(kunit_test_try_catch_successful_try_no_catch), |
102 | KUNIT_CASE(kunit_test_try_catch_unsuccessful_try_does_catch), |
103 | {} |
104 | }; |
105 | |
106 | static struct kunit_suite kunit_try_catch_test_suite = { |
107 | .name = "kunit-try-catch-test" , |
108 | .init = kunit_try_catch_test_init, |
109 | .test_cases = kunit_try_catch_test_cases, |
110 | }; |
111 | |
112 | /* |
113 | * Context for testing test managed resources |
114 | * is_resource_initialized is used to test arbitrary resources |
115 | */ |
116 | struct kunit_test_resource_context { |
117 | struct kunit test; |
118 | bool is_resource_initialized; |
119 | int allocate_order[2]; |
120 | int free_order[4]; |
121 | }; |
122 | |
123 | static int fake_resource_init(struct kunit_resource *res, void *context) |
124 | { |
125 | struct kunit_test_resource_context *ctx = context; |
126 | |
127 | res->data = &ctx->is_resource_initialized; |
128 | ctx->is_resource_initialized = true; |
129 | return 0; |
130 | } |
131 | |
132 | static void fake_resource_free(struct kunit_resource *res) |
133 | { |
134 | bool *is_resource_initialized = res->data; |
135 | |
136 | *is_resource_initialized = false; |
137 | } |
138 | |
139 | static void kunit_resource_test_init_resources(struct kunit *test) |
140 | { |
141 | struct kunit_test_resource_context *ctx = test->priv; |
142 | |
143 | kunit_init_test(test: &ctx->test, name: "testing_test_init_test" , NULL); |
144 | |
145 | KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); |
146 | } |
147 | |
148 | static void kunit_resource_test_alloc_resource(struct kunit *test) |
149 | { |
150 | struct kunit_test_resource_context *ctx = test->priv; |
151 | struct kunit_resource *res; |
152 | kunit_resource_free_t free = fake_resource_free; |
153 | |
154 | res = kunit_alloc_and_get_resource(test: &ctx->test, |
155 | init: fake_resource_init, |
156 | free: fake_resource_free, |
157 | GFP_KERNEL, |
158 | context: ctx); |
159 | |
160 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res); |
161 | KUNIT_EXPECT_PTR_EQ(test, |
162 | &ctx->is_resource_initialized, |
163 | (bool *)res->data); |
164 | KUNIT_EXPECT_TRUE(test, list_is_last(&res->node, &ctx->test.resources)); |
165 | KUNIT_EXPECT_PTR_EQ(test, free, res->free); |
166 | |
167 | kunit_put_resource(res); |
168 | } |
169 | |
170 | static inline bool kunit_resource_instance_match(struct kunit *test, |
171 | struct kunit_resource *res, |
172 | void *match_data) |
173 | { |
174 | return res->data == match_data; |
175 | } |
176 | |
177 | /* |
178 | * Note: tests below use kunit_alloc_and_get_resource(), so as a consequence |
179 | * they have a reference to the associated resource that they must release |
180 | * via kunit_put_resource(). In normal operation, users will only |
181 | * have to do this for cases where they use kunit_find_resource(), and the |
182 | * kunit_alloc_resource() function will be used (which does not take a |
183 | * resource reference). |
184 | */ |
185 | static void kunit_resource_test_destroy_resource(struct kunit *test) |
186 | { |
187 | struct kunit_test_resource_context *ctx = test->priv; |
188 | struct kunit_resource *res = kunit_alloc_and_get_resource( |
189 | test: &ctx->test, |
190 | init: fake_resource_init, |
191 | free: fake_resource_free, |
192 | GFP_KERNEL, |
193 | context: ctx); |
194 | |
195 | kunit_put_resource(res); |
196 | |
197 | KUNIT_ASSERT_FALSE(test, |
198 | kunit_destroy_resource(&ctx->test, |
199 | kunit_resource_instance_match, |
200 | res->data)); |
201 | |
202 | KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized); |
203 | KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); |
204 | } |
205 | |
206 | static void kunit_resource_test_remove_resource(struct kunit *test) |
207 | { |
208 | struct kunit_test_resource_context *ctx = test->priv; |
209 | struct kunit_resource *res = kunit_alloc_and_get_resource( |
210 | test: &ctx->test, |
211 | init: fake_resource_init, |
212 | free: fake_resource_free, |
213 | GFP_KERNEL, |
214 | context: ctx); |
215 | |
216 | /* The resource is in the list */ |
217 | KUNIT_EXPECT_FALSE(test, list_empty(&ctx->test.resources)); |
218 | |
219 | /* Remove the resource. The pointer is still valid, but it can't be |
220 | * found. |
221 | */ |
222 | kunit_remove_resource(test, res); |
223 | KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); |
224 | /* We haven't been freed yet. */ |
225 | KUNIT_EXPECT_TRUE(test, ctx->is_resource_initialized); |
226 | |
227 | /* Removing the resource multiple times is valid. */ |
228 | kunit_remove_resource(test, res); |
229 | KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); |
230 | /* Despite having been removed twice (from only one reference), the |
231 | * resource still has not been freed. |
232 | */ |
233 | KUNIT_EXPECT_TRUE(test, ctx->is_resource_initialized); |
234 | |
235 | /* Free the resource. */ |
236 | kunit_put_resource(res); |
237 | KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized); |
238 | } |
239 | |
240 | static void kunit_resource_test_cleanup_resources(struct kunit *test) |
241 | { |
242 | int i; |
243 | struct kunit_test_resource_context *ctx = test->priv; |
244 | struct kunit_resource *resources[5]; |
245 | |
246 | for (i = 0; i < ARRAY_SIZE(resources); i++) { |
247 | resources[i] = kunit_alloc_and_get_resource(test: &ctx->test, |
248 | init: fake_resource_init, |
249 | free: fake_resource_free, |
250 | GFP_KERNEL, |
251 | context: ctx); |
252 | kunit_put_resource(res: resources[i]); |
253 | } |
254 | |
255 | kunit_cleanup(test: &ctx->test); |
256 | |
257 | KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); |
258 | } |
259 | |
260 | static void kunit_resource_test_mark_order(int order_array[], |
261 | size_t order_size, |
262 | int key) |
263 | { |
264 | int i; |
265 | |
266 | for (i = 0; i < order_size && order_array[i]; i++) |
267 | ; |
268 | |
269 | order_array[i] = key; |
270 | } |
271 | |
272 | #define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key) \ |
273 | kunit_resource_test_mark_order(ctx->order_field, \ |
274 | ARRAY_SIZE(ctx->order_field), \ |
275 | key) |
276 | |
277 | static int fake_resource_2_init(struct kunit_resource *res, void *context) |
278 | { |
279 | struct kunit_test_resource_context *ctx = context; |
280 | |
281 | KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2); |
282 | |
283 | res->data = ctx; |
284 | |
285 | return 0; |
286 | } |
287 | |
288 | static void fake_resource_2_free(struct kunit_resource *res) |
289 | { |
290 | struct kunit_test_resource_context *ctx = res->data; |
291 | |
292 | KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2); |
293 | } |
294 | |
295 | static int fake_resource_1_init(struct kunit_resource *res, void *context) |
296 | { |
297 | struct kunit_test_resource_context *ctx = context; |
298 | struct kunit_resource *res2; |
299 | |
300 | res2 = kunit_alloc_and_get_resource(test: &ctx->test, |
301 | init: fake_resource_2_init, |
302 | free: fake_resource_2_free, |
303 | GFP_KERNEL, |
304 | context: ctx); |
305 | |
306 | KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1); |
307 | |
308 | res->data = ctx; |
309 | |
310 | kunit_put_resource(res: res2); |
311 | |
312 | return 0; |
313 | } |
314 | |
315 | static void fake_resource_1_free(struct kunit_resource *res) |
316 | { |
317 | struct kunit_test_resource_context *ctx = res->data; |
318 | |
319 | KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1); |
320 | } |
321 | |
322 | /* |
323 | * TODO(brendanhiggins@google.com): replace the arrays that keep track of the |
324 | * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro |
325 | * to assert allocation and freeing order when the feature becomes available. |
326 | */ |
327 | static void kunit_resource_test_proper_free_ordering(struct kunit *test) |
328 | { |
329 | struct kunit_test_resource_context *ctx = test->priv; |
330 | struct kunit_resource *res; |
331 | |
332 | /* fake_resource_1 allocates a fake_resource_2 in its init. */ |
333 | res = kunit_alloc_and_get_resource(test: &ctx->test, |
334 | init: fake_resource_1_init, |
335 | free: fake_resource_1_free, |
336 | GFP_KERNEL, |
337 | context: ctx); |
338 | |
339 | /* |
340 | * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER |
341 | * before returning to fake_resource_1_init, it should be the first to |
342 | * put its key in the allocate_order array. |
343 | */ |
344 | KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2); |
345 | KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1); |
346 | |
347 | kunit_put_resource(res); |
348 | |
349 | kunit_cleanup(test: &ctx->test); |
350 | |
351 | /* |
352 | * Because fake_resource_2 finishes allocation before fake_resource_1, |
353 | * fake_resource_1 should be freed first since it could depend on |
354 | * fake_resource_2. |
355 | */ |
356 | KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1); |
357 | KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2); |
358 | } |
359 | |
360 | static void kunit_resource_test_static(struct kunit *test) |
361 | { |
362 | struct kunit_test_resource_context ctx; |
363 | struct kunit_resource res; |
364 | |
365 | KUNIT_EXPECT_EQ(test, kunit_add_resource(test, NULL, NULL, &res, &ctx), |
366 | 0); |
367 | |
368 | KUNIT_EXPECT_PTR_EQ(test, res.data, (void *)&ctx); |
369 | |
370 | kunit_cleanup(test); |
371 | |
372 | KUNIT_EXPECT_TRUE(test, list_empty(&test->resources)); |
373 | } |
374 | |
375 | static void kunit_resource_test_named(struct kunit *test) |
376 | { |
377 | struct kunit_resource res1, res2, *found = NULL; |
378 | struct kunit_test_resource_context ctx; |
379 | |
380 | KUNIT_EXPECT_EQ(test, |
381 | kunit_add_named_resource(test, NULL, NULL, &res1, |
382 | "resource_1" , &ctx), |
383 | 0); |
384 | KUNIT_EXPECT_PTR_EQ(test, res1.data, (void *)&ctx); |
385 | |
386 | KUNIT_EXPECT_EQ(test, |
387 | kunit_add_named_resource(test, NULL, NULL, &res1, |
388 | "resource_1" , &ctx), |
389 | -EEXIST); |
390 | |
391 | KUNIT_EXPECT_EQ(test, |
392 | kunit_add_named_resource(test, NULL, NULL, &res2, |
393 | "resource_2" , &ctx), |
394 | 0); |
395 | |
396 | found = kunit_find_named_resource(test, name: "resource_1" ); |
397 | |
398 | KUNIT_EXPECT_PTR_EQ(test, found, &res1); |
399 | |
400 | if (found) |
401 | kunit_put_resource(res: &res1); |
402 | |
403 | KUNIT_EXPECT_EQ(test, kunit_destroy_named_resource(test, "resource_2" ), |
404 | 0); |
405 | |
406 | kunit_cleanup(test); |
407 | |
408 | KUNIT_EXPECT_TRUE(test, list_empty(&test->resources)); |
409 | } |
410 | |
411 | static void increment_int(void *ctx) |
412 | { |
413 | int *i = (int *)ctx; |
414 | (*i)++; |
415 | } |
416 | |
417 | static void kunit_resource_test_action(struct kunit *test) |
418 | { |
419 | int num_actions = 0; |
420 | |
421 | kunit_add_action(test, action: increment_int, ctx: &num_actions); |
422 | KUNIT_EXPECT_EQ(test, num_actions, 0); |
423 | kunit_cleanup(test); |
424 | KUNIT_EXPECT_EQ(test, num_actions, 1); |
425 | |
426 | /* Once we've cleaned up, the action queue is empty. */ |
427 | kunit_cleanup(test); |
428 | KUNIT_EXPECT_EQ(test, num_actions, 1); |
429 | |
430 | /* Check the same function can be deferred multiple times. */ |
431 | kunit_add_action(test, action: increment_int, ctx: &num_actions); |
432 | kunit_add_action(test, action: increment_int, ctx: &num_actions); |
433 | kunit_cleanup(test); |
434 | KUNIT_EXPECT_EQ(test, num_actions, 3); |
435 | } |
436 | static void kunit_resource_test_remove_action(struct kunit *test) |
437 | { |
438 | int num_actions = 0; |
439 | |
440 | kunit_add_action(test, action: increment_int, ctx: &num_actions); |
441 | KUNIT_EXPECT_EQ(test, num_actions, 0); |
442 | |
443 | kunit_remove_action(test, action: increment_int, ctx: &num_actions); |
444 | kunit_cleanup(test); |
445 | KUNIT_EXPECT_EQ(test, num_actions, 0); |
446 | } |
447 | static void kunit_resource_test_release_action(struct kunit *test) |
448 | { |
449 | int num_actions = 0; |
450 | |
451 | kunit_add_action(test, action: increment_int, ctx: &num_actions); |
452 | KUNIT_EXPECT_EQ(test, num_actions, 0); |
453 | /* Runs immediately on trigger. */ |
454 | kunit_release_action(test, action: increment_int, ctx: &num_actions); |
455 | KUNIT_EXPECT_EQ(test, num_actions, 1); |
456 | |
457 | /* Doesn't run again on test exit. */ |
458 | kunit_cleanup(test); |
459 | KUNIT_EXPECT_EQ(test, num_actions, 1); |
460 | } |
461 | static void action_order_1(void *ctx) |
462 | { |
463 | struct kunit_test_resource_context *res_ctx = (struct kunit_test_resource_context *)ctx; |
464 | |
465 | KUNIT_RESOURCE_TEST_MARK_ORDER(res_ctx, free_order, 1); |
466 | kunit_log(KERN_INFO, current->kunit_test, "action_order_1" ); |
467 | } |
468 | static void action_order_2(void *ctx) |
469 | { |
470 | struct kunit_test_resource_context *res_ctx = (struct kunit_test_resource_context *)ctx; |
471 | |
472 | KUNIT_RESOURCE_TEST_MARK_ORDER(res_ctx, free_order, 2); |
473 | kunit_log(KERN_INFO, current->kunit_test, "action_order_2" ); |
474 | } |
475 | static void kunit_resource_test_action_ordering(struct kunit *test) |
476 | { |
477 | struct kunit_test_resource_context *ctx = test->priv; |
478 | |
479 | kunit_add_action(test, action: action_order_1, ctx); |
480 | kunit_add_action(test, action: action_order_2, ctx); |
481 | kunit_add_action(test, action: action_order_1, ctx); |
482 | kunit_add_action(test, action: action_order_2, ctx); |
483 | kunit_remove_action(test, action: action_order_1, ctx); |
484 | kunit_release_action(test, action: action_order_2, ctx); |
485 | kunit_cleanup(test); |
486 | |
487 | /* [2 is triggered] [2], [(1 is cancelled)] [1] */ |
488 | KUNIT_EXPECT_EQ(test, ctx->free_order[0], 2); |
489 | KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2); |
490 | KUNIT_EXPECT_EQ(test, ctx->free_order[2], 1); |
491 | } |
492 | |
493 | static int kunit_resource_test_init(struct kunit *test) |
494 | { |
495 | struct kunit_test_resource_context *ctx = |
496 | kzalloc(size: sizeof(*ctx), GFP_KERNEL); |
497 | |
498 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
499 | |
500 | test->priv = ctx; |
501 | |
502 | kunit_init_test(test: &ctx->test, name: "test_test_context" , NULL); |
503 | |
504 | return 0; |
505 | } |
506 | |
507 | static void kunit_resource_test_exit(struct kunit *test) |
508 | { |
509 | struct kunit_test_resource_context *ctx = test->priv; |
510 | |
511 | kunit_cleanup(test: &ctx->test); |
512 | kfree(objp: ctx); |
513 | } |
514 | |
515 | static struct kunit_case kunit_resource_test_cases[] = { |
516 | KUNIT_CASE(kunit_resource_test_init_resources), |
517 | KUNIT_CASE(kunit_resource_test_alloc_resource), |
518 | KUNIT_CASE(kunit_resource_test_destroy_resource), |
519 | KUNIT_CASE(kunit_resource_test_remove_resource), |
520 | KUNIT_CASE(kunit_resource_test_cleanup_resources), |
521 | KUNIT_CASE(kunit_resource_test_proper_free_ordering), |
522 | KUNIT_CASE(kunit_resource_test_static), |
523 | KUNIT_CASE(kunit_resource_test_named), |
524 | KUNIT_CASE(kunit_resource_test_action), |
525 | KUNIT_CASE(kunit_resource_test_remove_action), |
526 | KUNIT_CASE(kunit_resource_test_release_action), |
527 | KUNIT_CASE(kunit_resource_test_action_ordering), |
528 | {} |
529 | }; |
530 | |
531 | static struct kunit_suite kunit_resource_test_suite = { |
532 | .name = "kunit-resource-test" , |
533 | .init = kunit_resource_test_init, |
534 | .exit = kunit_resource_test_exit, |
535 | .test_cases = kunit_resource_test_cases, |
536 | }; |
537 | |
538 | /* |
539 | * Log tests call string_stream functions, which aren't exported. So only |
540 | * build this code if this test is built-in. |
541 | */ |
542 | #if IS_BUILTIN(CONFIG_KUNIT_TEST) |
543 | |
544 | /* This avoids a cast warning if kfree() is passed direct to kunit_add_action(). */ |
545 | KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *); |
546 | |
547 | static void kunit_log_test(struct kunit *test) |
548 | { |
549 | struct kunit_suite suite; |
550 | #ifdef CONFIG_KUNIT_DEBUGFS |
551 | char *full_log; |
552 | #endif |
553 | suite.log = kunit_alloc_string_stream(test, GFP_KERNEL); |
554 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, suite.log); |
555 | string_stream_set_append_newlines(stream: suite.log, append_newlines: true); |
556 | |
557 | kunit_log(KERN_INFO, test, "put this in log." ); |
558 | kunit_log(KERN_INFO, test, "this too." ); |
559 | kunit_log(KERN_INFO, &suite, "add to suite log." ); |
560 | kunit_log(KERN_INFO, &suite, "along with this." ); |
561 | |
562 | #ifdef CONFIG_KUNIT_DEBUGFS |
563 | KUNIT_EXPECT_TRUE(test, test->log->append_newlines); |
564 | |
565 | full_log = string_stream_get_string(stream: test->log); |
566 | kunit_add_action(test, action: kfree_wrapper, ctx: full_log); |
567 | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, |
568 | strstr(full_log, "put this in log." )); |
569 | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, |
570 | strstr(full_log, "this too." )); |
571 | |
572 | full_log = string_stream_get_string(stream: suite.log); |
573 | kunit_add_action(test, action: kfree_wrapper, ctx: full_log); |
574 | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, |
575 | strstr(full_log, "add to suite log." )); |
576 | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, |
577 | strstr(full_log, "along with this." )); |
578 | #else |
579 | KUNIT_EXPECT_NULL(test, test->log); |
580 | #endif |
581 | } |
582 | |
583 | static void kunit_log_newline_test(struct kunit *test) |
584 | { |
585 | char *full_log; |
586 | |
587 | kunit_info(test, "Add newline\n" ); |
588 | if (test->log) { |
589 | full_log = string_stream_get_string(stream: test->log); |
590 | kunit_add_action(test, action: kfree_wrapper, ctx: full_log); |
591 | KUNIT_ASSERT_NOT_NULL_MSG(test, strstr(full_log, "Add newline\n" ), |
592 | "Missing log line, full log:\n%s" , full_log); |
593 | KUNIT_EXPECT_NULL(test, strstr(full_log, "Add newline\n\n" )); |
594 | } else { |
595 | kunit_skip(test, "only useful when debugfs is enabled" ); |
596 | } |
597 | } |
598 | #else |
599 | static void kunit_log_test(struct kunit *test) |
600 | { |
601 | kunit_skip(test, "Log tests only run when built-in" ); |
602 | } |
603 | |
604 | static void kunit_log_newline_test(struct kunit *test) |
605 | { |
606 | kunit_skip(test, "Log tests only run when built-in" ); |
607 | } |
608 | #endif /* IS_BUILTIN(CONFIG_KUNIT_TEST) */ |
609 | |
610 | static struct kunit_case kunit_log_test_cases[] = { |
611 | KUNIT_CASE(kunit_log_test), |
612 | KUNIT_CASE(kunit_log_newline_test), |
613 | {} |
614 | }; |
615 | |
616 | static struct kunit_suite kunit_log_test_suite = { |
617 | .name = "kunit-log-test" , |
618 | .test_cases = kunit_log_test_cases, |
619 | }; |
620 | |
621 | static void kunit_status_set_failure_test(struct kunit *test) |
622 | { |
623 | struct kunit fake; |
624 | |
625 | kunit_init_test(test: &fake, name: "fake test" , NULL); |
626 | |
627 | KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_SUCCESS); |
628 | kunit_set_failure(test: &fake); |
629 | KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_FAILURE); |
630 | } |
631 | |
632 | static void kunit_status_mark_skipped_test(struct kunit *test) |
633 | { |
634 | struct kunit fake; |
635 | |
636 | kunit_init_test(test: &fake, name: "fake test" , NULL); |
637 | |
638 | /* Before: Should be SUCCESS with no comment. */ |
639 | KUNIT_EXPECT_EQ(test, fake.status, KUNIT_SUCCESS); |
640 | KUNIT_EXPECT_STREQ(test, fake.status_comment, "" ); |
641 | |
642 | /* Mark the test as skipped. */ |
643 | kunit_mark_skipped(&fake, "Accepts format string: %s" , "YES" ); |
644 | |
645 | /* After: Should be SKIPPED with our comment. */ |
646 | KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_SKIPPED); |
647 | KUNIT_EXPECT_STREQ(test, fake.status_comment, "Accepts format string: YES" ); |
648 | } |
649 | |
650 | static struct kunit_case kunit_status_test_cases[] = { |
651 | KUNIT_CASE(kunit_status_set_failure_test), |
652 | KUNIT_CASE(kunit_status_mark_skipped_test), |
653 | {} |
654 | }; |
655 | |
656 | static struct kunit_suite kunit_status_test_suite = { |
657 | .name = "kunit_status" , |
658 | .test_cases = kunit_status_test_cases, |
659 | }; |
660 | |
661 | static void kunit_current_test(struct kunit *test) |
662 | { |
663 | /* Check results of both current->kunit_test and |
664 | * kunit_get_current_test() are equivalent to current test. |
665 | */ |
666 | KUNIT_EXPECT_PTR_EQ(test, test, current->kunit_test); |
667 | KUNIT_EXPECT_PTR_EQ(test, test, kunit_get_current_test()); |
668 | } |
669 | |
670 | static void kunit_current_fail_test(struct kunit *test) |
671 | { |
672 | struct kunit fake; |
673 | |
674 | kunit_init_test(test: &fake, name: "fake test" , NULL); |
675 | KUNIT_EXPECT_EQ(test, fake.status, KUNIT_SUCCESS); |
676 | |
677 | /* Set current->kunit_test to fake test. */ |
678 | current->kunit_test = &fake; |
679 | |
680 | kunit_fail_current_test("This should make `fake` test fail." ); |
681 | KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_FAILURE); |
682 | kunit_cleanup(test: &fake); |
683 | |
684 | /* Reset current->kunit_test to current test. */ |
685 | current->kunit_test = test; |
686 | } |
687 | |
688 | static struct kunit_case kunit_current_test_cases[] = { |
689 | KUNIT_CASE(kunit_current_test), |
690 | KUNIT_CASE(kunit_current_fail_test), |
691 | {} |
692 | }; |
693 | |
694 | static void test_dev_action(void *priv) |
695 | { |
696 | *(void **)priv = (void *)1; |
697 | } |
698 | |
699 | static void kunit_device_test(struct kunit *test) |
700 | { |
701 | struct device *test_device; |
702 | long action_was_run = 0; |
703 | |
704 | test_device = kunit_device_register(test, name: "my_device" ); |
705 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, test_device); |
706 | |
707 | // Add an action to verify cleanup. |
708 | devm_add_action(test_device, test_dev_action, &action_was_run); |
709 | |
710 | KUNIT_EXPECT_EQ(test, action_was_run, 0); |
711 | |
712 | kunit_device_unregister(test, dev: test_device); |
713 | |
714 | KUNIT_EXPECT_EQ(test, action_was_run, 1); |
715 | } |
716 | |
717 | static void kunit_device_cleanup_test(struct kunit *test) |
718 | { |
719 | struct device *test_device; |
720 | long action_was_run = 0; |
721 | |
722 | test_device = kunit_device_register(test, name: "my_device" ); |
723 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, test_device); |
724 | |
725 | /* Add an action to verify cleanup. */ |
726 | devm_add_action(test_device, test_dev_action, &action_was_run); |
727 | |
728 | KUNIT_EXPECT_EQ(test, action_was_run, 0); |
729 | |
730 | /* Force KUnit to run cleanup early. */ |
731 | kunit_cleanup(test); |
732 | |
733 | KUNIT_EXPECT_EQ(test, action_was_run, 1); |
734 | } |
735 | |
736 | struct driver_test_state { |
737 | bool driver_device_probed; |
738 | bool driver_device_removed; |
739 | long action_was_run; |
740 | }; |
741 | |
742 | static int driver_probe_hook(struct device *dev) |
743 | { |
744 | struct kunit *test = kunit_get_current_test(); |
745 | struct driver_test_state *state = (struct driver_test_state *)test->priv; |
746 | |
747 | state->driver_device_probed = true; |
748 | return 0; |
749 | } |
750 | |
751 | static int driver_remove_hook(struct device *dev) |
752 | { |
753 | struct kunit *test = kunit_get_current_test(); |
754 | struct driver_test_state *state = (struct driver_test_state *)test->priv; |
755 | |
756 | state->driver_device_removed = true; |
757 | return 0; |
758 | } |
759 | |
760 | static void kunit_device_driver_test(struct kunit *test) |
761 | { |
762 | struct device_driver *test_driver; |
763 | struct device *test_device; |
764 | struct driver_test_state *test_state = kunit_kzalloc(test, size: sizeof(*test_state), GFP_KERNEL); |
765 | |
766 | test->priv = test_state; |
767 | test_driver = kunit_driver_create(test, name: "my_driver" ); |
768 | |
769 | // This can fail with an error pointer. |
770 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, test_driver); |
771 | |
772 | test_driver->probe = driver_probe_hook; |
773 | test_driver->remove = driver_remove_hook; |
774 | |
775 | test_device = kunit_device_register_with_driver(test, name: "my_device" , drv: test_driver); |
776 | |
777 | // This can fail with an error pointer. |
778 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, test_device); |
779 | |
780 | // Make sure the probe function was called. |
781 | KUNIT_ASSERT_TRUE(test, test_state->driver_device_probed); |
782 | |
783 | // Add an action to verify cleanup. |
784 | devm_add_action(test_device, test_dev_action, &test_state->action_was_run); |
785 | |
786 | KUNIT_EXPECT_EQ(test, test_state->action_was_run, 0); |
787 | |
788 | kunit_device_unregister(test, dev: test_device); |
789 | test_device = NULL; |
790 | |
791 | // Make sure the remove hook was called. |
792 | KUNIT_ASSERT_TRUE(test, test_state->driver_device_removed); |
793 | |
794 | // We're going to test this again. |
795 | test_state->driver_device_probed = false; |
796 | |
797 | // The driver should not automatically be destroyed by |
798 | // kunit_device_unregister, so we can re-use it. |
799 | test_device = kunit_device_register_with_driver(test, name: "my_device" , drv: test_driver); |
800 | |
801 | // This can fail with an error pointer. |
802 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, test_device); |
803 | |
804 | // Probe was called again. |
805 | KUNIT_ASSERT_TRUE(test, test_state->driver_device_probed); |
806 | |
807 | // Everything is automatically freed here. |
808 | } |
809 | |
810 | static struct kunit_case kunit_device_test_cases[] = { |
811 | KUNIT_CASE(kunit_device_test), |
812 | KUNIT_CASE(kunit_device_cleanup_test), |
813 | KUNIT_CASE(kunit_device_driver_test), |
814 | {} |
815 | }; |
816 | |
817 | static struct kunit_suite kunit_device_test_suite = { |
818 | .name = "kunit_device" , |
819 | .test_cases = kunit_device_test_cases, |
820 | }; |
821 | |
822 | static struct kunit_suite kunit_current_test_suite = { |
823 | .name = "kunit_current" , |
824 | .test_cases = kunit_current_test_cases, |
825 | }; |
826 | |
827 | kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite, |
828 | &kunit_log_test_suite, &kunit_status_test_suite, |
829 | &kunit_current_test_suite, &kunit_device_test_suite); |
830 | |
831 | MODULE_LICENSE("GPL v2" ); |
832 | |