Blame view

lib/kunit/kunit-test.c 11.3 KB
e4eb117f6   Brendan Higgins   kunit: test: add ...
1
2
3
4
5
6
7
8
  // SPDX-License-Identifier: GPL-2.0
  /*
   * KUnit test for core test infrastructure.
   *
   * Copyright (C) 2019, Google LLC.
   * Author: Brendan Higgins <brendanhiggins@google.com>
   */
  #include <kunit/test.h>
9bbb11c6b   Alan Maguire   kunit: hide unexp...
9
  #include "try-catch-impl.h"
e4eb117f6   Brendan Higgins   kunit: test: add ...
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  struct kunit_try_catch_test_context {
  	struct kunit_try_catch *try_catch;
  	bool function_called;
  };
  
  static void kunit_test_successful_try(void *data)
  {
  	struct kunit *test = data;
  	struct kunit_try_catch_test_context *ctx = test->priv;
  
  	ctx->function_called = true;
  }
  
  static void kunit_test_no_catch(void *data)
  {
  	struct kunit *test = data;
  
  	KUNIT_FAIL(test, "Catch should not be called
  ");
  }
  
  static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
  {
  	struct kunit_try_catch_test_context *ctx = test->priv;
  	struct kunit_try_catch *try_catch = ctx->try_catch;
  
  	kunit_try_catch_init(try_catch,
  			     test,
  			     kunit_test_successful_try,
  			     kunit_test_no_catch);
  	kunit_try_catch_run(try_catch, test);
  
  	KUNIT_EXPECT_TRUE(test, ctx->function_called);
  }
  
  static void kunit_test_unsuccessful_try(void *data)
  {
  	struct kunit *test = data;
  	struct kunit_try_catch_test_context *ctx = test->priv;
  	struct kunit_try_catch *try_catch = ctx->try_catch;
  
  	kunit_try_catch_throw(try_catch);
  	KUNIT_FAIL(test, "This line should never be reached
  ");
  }
  
  static void kunit_test_catch(void *data)
  {
  	struct kunit *test = data;
  	struct kunit_try_catch_test_context *ctx = test->priv;
  
  	ctx->function_called = true;
  }
  
  static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
  {
  	struct kunit_try_catch_test_context *ctx = test->priv;
  	struct kunit_try_catch *try_catch = ctx->try_catch;
  
  	kunit_try_catch_init(try_catch,
  			     test,
  			     kunit_test_unsuccessful_try,
  			     kunit_test_catch);
  	kunit_try_catch_run(try_catch, test);
  
  	KUNIT_EXPECT_TRUE(test, ctx->function_called);
  }
  
  static int kunit_try_catch_test_init(struct kunit *test)
  {
  	struct kunit_try_catch_test_context *ctx;
  
  	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
e4aea8f85   Brendan Higgins   kunit: test: add ...
83
  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
e4eb117f6   Brendan Higgins   kunit: test: add ...
84
85
86
87
88
  	test->priv = ctx;
  
  	ctx->try_catch = kunit_kmalloc(test,
  				       sizeof(*ctx->try_catch),
  				       GFP_KERNEL);
e4aea8f85   Brendan Higgins   kunit: test: add ...
89
  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch);
e4eb117f6   Brendan Higgins   kunit: test: add ...
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  
  	return 0;
  }
  
  static struct kunit_case kunit_try_catch_test_cases[] = {
  	KUNIT_CASE(kunit_test_try_catch_successful_try_no_catch),
  	KUNIT_CASE(kunit_test_try_catch_unsuccessful_try_does_catch),
  	{}
  };
  
  static struct kunit_suite kunit_try_catch_test_suite = {
  	.name = "kunit-try-catch-test",
  	.init = kunit_try_catch_test_init,
  	.test_cases = kunit_try_catch_test_cases,
  };
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  
  /*
   * Context for testing test managed resources
   * is_resource_initialized is used to test arbitrary resources
   */
  struct kunit_test_resource_context {
  	struct kunit test;
  	bool is_resource_initialized;
  	int allocate_order[2];
  	int free_order[2];
  };
  
  static int fake_resource_init(struct kunit_resource *res, void *context)
  {
  	struct kunit_test_resource_context *ctx = context;
d4cdd146d   Alan Maguire   kunit: generalize...
120
  	res->data = &ctx->is_resource_initialized;
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
121
122
123
124
125
126
  	ctx->is_resource_initialized = true;
  	return 0;
  }
  
  static void fake_resource_free(struct kunit_resource *res)
  {
d4cdd146d   Alan Maguire   kunit: generalize...
127
  	bool *is_resource_initialized = res->data;
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
128
129
130
131
132
133
134
  
  	*is_resource_initialized = false;
  }
  
  static void kunit_resource_test_init_resources(struct kunit *test)
  {
  	struct kunit_test_resource_context *ctx = test->priv;
e2219db28   Alan Maguire   kunit: add debugf...
135
  	kunit_init_test(&ctx->test, "testing_test_init_test", NULL);
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  
  	KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
  }
  
  static void kunit_resource_test_alloc_resource(struct kunit *test)
  {
  	struct kunit_test_resource_context *ctx = test->priv;
  	struct kunit_resource *res;
  	kunit_resource_free_t free = fake_resource_free;
  
  	res = kunit_alloc_and_get_resource(&ctx->test,
  					   fake_resource_init,
  					   fake_resource_free,
  					   GFP_KERNEL,
  					   ctx);
  
  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res);
  	KUNIT_EXPECT_PTR_EQ(test,
  			    &ctx->is_resource_initialized,
d4cdd146d   Alan Maguire   kunit: generalize...
155
  			    (bool *)res->data);
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
156
157
  	KUNIT_EXPECT_TRUE(test, list_is_last(&res->node, &ctx->test.resources));
  	KUNIT_EXPECT_PTR_EQ(test, free, res->free);
d4cdd146d   Alan Maguire   kunit: generalize...
158
159
  
  	kunit_put_resource(res);
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
160
  }
d4cdd146d   Alan Maguire   kunit: generalize...
161
162
163
164
165
166
167
168
  /*
   * Note: tests below use kunit_alloc_and_get_resource(), so as a consequence
   * they have a reference to the associated resource that they must release
   * via kunit_put_resource().  In normal operation, users will only
   * have to do this for cases where they use kunit_find_resource(), and the
   * kunit_alloc_resource() function will be used (which does not take a
   * resource reference).
   */
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
169
170
171
172
173
174
175
176
177
  static void kunit_resource_test_destroy_resource(struct kunit *test)
  {
  	struct kunit_test_resource_context *ctx = test->priv;
  	struct kunit_resource *res = kunit_alloc_and_get_resource(
  			&ctx->test,
  			fake_resource_init,
  			fake_resource_free,
  			GFP_KERNEL,
  			ctx);
d4cdd146d   Alan Maguire   kunit: generalize...
178
  	kunit_put_resource(res);
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
179
  	KUNIT_ASSERT_FALSE(test,
d4cdd146d   Alan Maguire   kunit: generalize...
180
  			   kunit_destroy_resource(&ctx->test,
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
181
  						  kunit_resource_instance_match,
d4cdd146d   Alan Maguire   kunit: generalize...
182
  						  res->data));
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  
  	KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
  	KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
  }
  
  static void kunit_resource_test_cleanup_resources(struct kunit *test)
  {
  	int i;
  	struct kunit_test_resource_context *ctx = test->priv;
  	struct kunit_resource *resources[5];
  
  	for (i = 0; i < ARRAY_SIZE(resources); i++) {
  		resources[i] = kunit_alloc_and_get_resource(&ctx->test,
  							    fake_resource_init,
  							    fake_resource_free,
  							    GFP_KERNEL,
  							    ctx);
d4cdd146d   Alan Maguire   kunit: generalize...
200
  		kunit_put_resource(resources[i]);
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  	}
  
  	kunit_cleanup(&ctx->test);
  
  	KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
  }
  
  static void kunit_resource_test_mark_order(int order_array[],
  					   size_t order_size,
  					   int key)
  {
  	int i;
  
  	for (i = 0; i < order_size && order_array[i]; i++)
  		;
  
  	order_array[i] = key;
  }
  
  #define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key)		       \
  		kunit_resource_test_mark_order(ctx->order_field,	       \
  					       ARRAY_SIZE(ctx->order_field),   \
  					       key)
  
  static int fake_resource_2_init(struct kunit_resource *res, void *context)
  {
  	struct kunit_test_resource_context *ctx = context;
  
  	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2);
d4cdd146d   Alan Maguire   kunit: generalize...
230
  	res->data = ctx;
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
231
232
233
234
235
236
  
  	return 0;
  }
  
  static void fake_resource_2_free(struct kunit_resource *res)
  {
d4cdd146d   Alan Maguire   kunit: generalize...
237
  	struct kunit_test_resource_context *ctx = res->data;
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
238
239
240
241
242
243
244
  
  	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2);
  }
  
  static int fake_resource_1_init(struct kunit_resource *res, void *context)
  {
  	struct kunit_test_resource_context *ctx = context;
d4cdd146d   Alan Maguire   kunit: generalize...
245
  	struct kunit_resource *res2;
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
246

d4cdd146d   Alan Maguire   kunit: generalize...
247
248
249
250
251
  	res2 = kunit_alloc_and_get_resource(&ctx->test,
  					    fake_resource_2_init,
  					    fake_resource_2_free,
  					    GFP_KERNEL,
  					    ctx);
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
252
253
  
  	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1);
d4cdd146d   Alan Maguire   kunit: generalize...
254
255
256
  	res->data = ctx;
  
  	kunit_put_resource(res2);
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
257
258
259
260
261
262
  
  	return 0;
  }
  
  static void fake_resource_1_free(struct kunit_resource *res)
  {
d4cdd146d   Alan Maguire   kunit: generalize...
263
  	struct kunit_test_resource_context *ctx = res->data;
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
264
265
266
267
268
269
270
271
272
273
274
275
  
  	KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1);
  }
  
  /*
   * TODO(brendanhiggins@google.com): replace the arrays that keep track of the
   * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro
   * to assert allocation and freeing order when the feature becomes available.
   */
  static void kunit_resource_test_proper_free_ordering(struct kunit *test)
  {
  	struct kunit_test_resource_context *ctx = test->priv;
d4cdd146d   Alan Maguire   kunit: generalize...
276
  	struct kunit_resource *res;
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
277
278
  
  	/* fake_resource_1 allocates a fake_resource_2 in its init. */
d4cdd146d   Alan Maguire   kunit: generalize...
279
280
281
282
283
  	res = kunit_alloc_and_get_resource(&ctx->test,
  					   fake_resource_1_init,
  					   fake_resource_1_free,
  					   GFP_KERNEL,
  					   ctx);
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
284
285
286
287
288
289
290
291
  
  	/*
  	 * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER
  	 * before returning to fake_resource_1_init, it should be the first to
  	 * put its key in the allocate_order array.
  	 */
  	KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2);
  	KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1);
d4cdd146d   Alan Maguire   kunit: generalize...
292
  	kunit_put_resource(res);
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
293
294
295
296
297
298
299
300
301
302
  	kunit_cleanup(&ctx->test);
  
  	/*
  	 * Because fake_resource_2 finishes allocation before fake_resource_1,
  	 * fake_resource_1 should be freed first since it could depend on
  	 * fake_resource_2.
  	 */
  	KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1);
  	KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2);
  }
d4cdd146d   Alan Maguire   kunit: generalize...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  static void kunit_resource_test_static(struct kunit *test)
  {
  	struct kunit_test_resource_context ctx;
  	struct kunit_resource res;
  
  	KUNIT_EXPECT_EQ(test, kunit_add_resource(test, NULL, NULL, &res, &ctx),
  			0);
  
  	KUNIT_EXPECT_PTR_EQ(test, res.data, (void *)&ctx);
  
  	kunit_cleanup(test);
  
  	KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
  }
725aca958   Alan Maguire   kunit: add suppor...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
  static void kunit_resource_test_named(struct kunit *test)
  {
  	struct kunit_resource res1, res2, *found = NULL;
  	struct kunit_test_resource_context ctx;
  
  	KUNIT_EXPECT_EQ(test,
  			kunit_add_named_resource(test, NULL, NULL, &res1,
  						 "resource_1", &ctx),
  			0);
  	KUNIT_EXPECT_PTR_EQ(test, res1.data, (void *)&ctx);
  
  	KUNIT_EXPECT_EQ(test,
  			kunit_add_named_resource(test, NULL, NULL, &res1,
  						 "resource_1", &ctx),
  			-EEXIST);
  
  	KUNIT_EXPECT_EQ(test,
  			kunit_add_named_resource(test, NULL, NULL, &res2,
  						 "resource_2", &ctx),
  			0);
  
  	found = kunit_find_named_resource(test, "resource_1");
  
  	KUNIT_EXPECT_PTR_EQ(test, found, &res1);
  
  	if (found)
  		kunit_put_resource(&res1);
  
  	KUNIT_EXPECT_EQ(test, kunit_destroy_named_resource(test, "resource_2"),
  			0);
  
  	kunit_cleanup(test);
  
  	KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
  }
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
352
353
354
355
356
357
358
359
  static int kunit_resource_test_init(struct kunit *test)
  {
  	struct kunit_test_resource_context *ctx =
  			kzalloc(sizeof(*ctx), GFP_KERNEL);
  
  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
  
  	test->priv = ctx;
e2219db28   Alan Maguire   kunit: add debugf...
360
  	kunit_init_test(&ctx->test, "test_test_context", NULL);
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
  
  	return 0;
  }
  
  static void kunit_resource_test_exit(struct kunit *test)
  {
  	struct kunit_test_resource_context *ctx = test->priv;
  
  	kunit_cleanup(&ctx->test);
  	kfree(ctx);
  }
  
  static struct kunit_case kunit_resource_test_cases[] = {
  	KUNIT_CASE(kunit_resource_test_init_resources),
  	KUNIT_CASE(kunit_resource_test_alloc_resource),
  	KUNIT_CASE(kunit_resource_test_destroy_resource),
  	KUNIT_CASE(kunit_resource_test_cleanup_resources),
  	KUNIT_CASE(kunit_resource_test_proper_free_ordering),
d4cdd146d   Alan Maguire   kunit: generalize...
379
  	KUNIT_CASE(kunit_resource_test_static),
725aca958   Alan Maguire   kunit: add suppor...
380
  	KUNIT_CASE(kunit_resource_test_named),
73ba5aaf9   Avinash Kondareddy   kunit: test: add ...
381
382
383
384
385
386
387
388
389
  	{}
  };
  
  static struct kunit_suite kunit_resource_test_suite = {
  	.name = "kunit-resource-test",
  	.init = kunit_resource_test_init,
  	.exit = kunit_resource_test_exit,
  	.test_cases = kunit_resource_test_cases,
  };
eda8e324f   Alan Maguire   kunit: add log test
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
  
  static void kunit_log_test(struct kunit *test);
  
  static struct kunit_case kunit_log_test_cases[] = {
  	KUNIT_CASE(kunit_log_test),
  	{}
  };
  
  static struct kunit_suite kunit_log_test_suite = {
  	.name = "kunit-log-test",
  	.test_cases = kunit_log_test_cases,
  };
  
  static void kunit_log_test(struct kunit *test)
  {
  	struct kunit_suite *suite = &kunit_log_test_suite;
  
  	kunit_log(KERN_INFO, test, "put this in log.");
  	kunit_log(KERN_INFO, test, "this too.");
  	kunit_log(KERN_INFO, suite, "add to suite log.");
  	kunit_log(KERN_INFO, suite, "along with this.");
  
  #ifdef CONFIG_KUNIT_DEBUGFS
  	KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  				     strstr(test->log, "put this in log."));
  	KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  				     strstr(test->log, "this too."));
  	KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  				     strstr(suite->log, "add to suite log."));
  	KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  				     strstr(suite->log, "along with this."));
  #else
  	KUNIT_EXPECT_PTR_EQ(test, test->log, (char *)NULL);
  	KUNIT_EXPECT_PTR_EQ(test, suite->log, (char *)NULL);
  #endif
  }
  
  kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite,
  		  &kunit_log_test_suite);
c475c77d5   Alan Maguire   kunit: allow kuni...
429
430
  
  MODULE_LICENSE("GPL v2");