1 // SPDX-License-Identifier: GPL-2.0
2 #include <kunit/test.h>
3 #include <kunit/test-bug.h>
4 #include <linux/module.h>
5 #include <linux/miscdevice.h>
6 #include <linux/fs.h>
7 #include <linux/file.h>
8 #include <linux/init_syscalls.h>
9
10 /* static minor (LCD_MINOR) */
11 static struct miscdevice dev_static_minor = {
12 .minor = LCD_MINOR,
13 .name = "dev_static_minor",
14 };
15
16 /* misc dynamic minor */
17 static struct miscdevice dev_misc_dynamic_minor = {
18 .minor = MISC_DYNAMIC_MINOR,
19 .name = "dev_misc_dynamic_minor",
20 };
21
kunit_static_minor(struct kunit * test)22 static void kunit_static_minor(struct kunit *test)
23 {
24 int ret;
25
26 ret = misc_register(&dev_static_minor);
27 KUNIT_EXPECT_EQ(test, 0, ret);
28 KUNIT_EXPECT_EQ(test, LCD_MINOR, dev_static_minor.minor);
29 misc_deregister(&dev_static_minor);
30 }
31
kunit_misc_dynamic_minor(struct kunit * test)32 static void kunit_misc_dynamic_minor(struct kunit *test)
33 {
34 int ret;
35
36 ret = misc_register(&dev_misc_dynamic_minor);
37 KUNIT_EXPECT_EQ(test, 0, ret);
38 misc_deregister(&dev_misc_dynamic_minor);
39 }
40
41 struct miscdev_test_case {
42 const char *str;
43 int minor;
44 };
45
46 static struct miscdev_test_case miscdev_test_ranges[] = {
47 {
48 .str = "lower static range, top",
49 .minor = 15,
50 },
51 {
52 .str = "upper static range, bottom",
53 .minor = 130,
54 },
55 {
56 .str = "lower static range, bottom",
57 .minor = 0,
58 },
59 {
60 .str = "upper static range, top",
61 .minor = MISC_DYNAMIC_MINOR - 1,
62 },
63 };
64
65 KUNIT_ARRAY_PARAM_DESC(miscdev, miscdev_test_ranges, str);
66
miscdev_find_minors(struct kunit_suite * suite)67 static int miscdev_find_minors(struct kunit_suite *suite)
68 {
69 int ret;
70 struct miscdevice miscstat = {
71 .name = "miscstat",
72 };
73 int i;
74
75 for (i = 15; i >= 0; i--) {
76 miscstat.minor = i;
77 ret = misc_register(&miscstat);
78 if (ret == 0)
79 break;
80 }
81
82 if (ret == 0) {
83 kunit_info(suite, "found misc device minor %d available\n",
84 miscstat.minor);
85 miscdev_test_ranges[0].minor = miscstat.minor;
86 misc_deregister(&miscstat);
87 } else {
88 return ret;
89 }
90
91 for (i = 128; i < MISC_DYNAMIC_MINOR; i++) {
92 miscstat.minor = i;
93 ret = misc_register(&miscstat);
94 if (ret == 0)
95 break;
96 }
97
98 if (ret == 0) {
99 kunit_info(suite, "found misc device minor %d available\n",
100 miscstat.minor);
101 miscdev_test_ranges[1].minor = miscstat.minor;
102 misc_deregister(&miscstat);
103 } else {
104 return ret;
105 }
106
107 for (i = 0; i < miscdev_test_ranges[0].minor; i++) {
108 miscstat.minor = i;
109 ret = misc_register(&miscstat);
110 if (ret == 0)
111 break;
112 }
113
114 if (ret == 0) {
115 kunit_info(suite, "found misc device minor %d available\n",
116 miscstat.minor);
117 miscdev_test_ranges[2].minor = miscstat.minor;
118 misc_deregister(&miscstat);
119 } else {
120 return ret;
121 }
122
123 for (i = MISC_DYNAMIC_MINOR - 1; i > miscdev_test_ranges[1].minor; i--) {
124 miscstat.minor = i;
125 ret = misc_register(&miscstat);
126 if (ret == 0)
127 break;
128 }
129
130 if (ret == 0) {
131 kunit_info(suite, "found misc device minor %d available\n",
132 miscstat.minor);
133 miscdev_test_ranges[3].minor = miscstat.minor;
134 misc_deregister(&miscstat);
135 }
136
137 return ret;
138 }
139
is_valid_dynamic_minor(int minor)140 static bool is_valid_dynamic_minor(int minor)
141 {
142 if (minor < 0)
143 return false;
144 return minor > MISC_DYNAMIC_MINOR;
145 }
146
miscdev_test_open(struct inode * inode,struct file * file)147 static int miscdev_test_open(struct inode *inode, struct file *file)
148 {
149 return 0;
150 }
151
152 static const struct file_operations miscdev_test_fops = {
153 .open = miscdev_test_open,
154 };
155
miscdev_test_can_open(struct kunit * test,struct miscdevice * misc)156 static void __init miscdev_test_can_open(struct kunit *test, struct miscdevice *misc)
157 {
158 int ret;
159 struct file *filp;
160 char *devname;
161
162 devname = kasprintf(GFP_KERNEL, "/dev/%s", misc->name);
163 ret = init_mknod(devname, S_IFCHR | 0600,
164 new_encode_dev(MKDEV(MISC_MAJOR, misc->minor)));
165 if (ret != 0)
166 KUNIT_FAIL(test, "failed to create node\n");
167
168 filp = filp_open(devname, O_RDONLY, 0);
169 if (IS_ERR_OR_NULL(filp))
170 KUNIT_FAIL(test, "failed to open misc device: %ld\n", PTR_ERR(filp));
171 else
172 fput(filp);
173
174 init_unlink(devname);
175 kfree(devname);
176 }
177
miscdev_test_static_basic(struct kunit * test)178 static void __init miscdev_test_static_basic(struct kunit *test)
179 {
180 struct miscdevice misc_test = {
181 .name = "misc_test",
182 .fops = &miscdev_test_fops,
183 };
184 int ret;
185 const struct miscdev_test_case *params = test->param_value;
186
187 misc_test.minor = params->minor;
188
189 ret = misc_register(&misc_test);
190 KUNIT_EXPECT_EQ(test, ret, 0);
191 KUNIT_EXPECT_EQ(test, misc_test.minor, params->minor);
192
193 if (ret == 0) {
194 miscdev_test_can_open(test, &misc_test);
195 misc_deregister(&misc_test);
196 }
197 }
198
miscdev_test_dynamic_basic(struct kunit * test)199 static void __init miscdev_test_dynamic_basic(struct kunit *test)
200 {
201 struct miscdevice misc_test = {
202 .minor = MISC_DYNAMIC_MINOR,
203 .name = "misc_test",
204 .fops = &miscdev_test_fops,
205 };
206 int ret;
207
208 ret = misc_register(&misc_test);
209 KUNIT_EXPECT_EQ(test, ret, 0);
210 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(misc_test.minor));
211
212 if (ret == 0) {
213 miscdev_test_can_open(test, &misc_test);
214 misc_deregister(&misc_test);
215 }
216 }
217
miscdev_test_twice(struct kunit * test)218 static void miscdev_test_twice(struct kunit *test)
219 {
220 struct miscdevice misc_test = {
221 .name = "misc_test",
222 .fops = &miscdev_test_fops,
223 };
224 int ret;
225 const struct miscdev_test_case *params = test->param_value;
226
227 misc_test.minor = params->minor;
228
229 ret = misc_register(&misc_test);
230 KUNIT_EXPECT_EQ(test, ret, 0);
231 KUNIT_EXPECT_EQ(test, misc_test.minor, params->minor);
232 if (ret == 0)
233 misc_deregister(&misc_test);
234
235 ret = misc_register(&misc_test);
236 KUNIT_EXPECT_EQ(test, ret, 0);
237 KUNIT_EXPECT_EQ(test, misc_test.minor, params->minor);
238 if (ret == 0)
239 misc_deregister(&misc_test);
240 }
241
miscdev_test_duplicate_minor(struct kunit * test)242 static void miscdev_test_duplicate_minor(struct kunit *test)
243 {
244 struct miscdevice misc1 = {
245 .name = "misc1",
246 .fops = &miscdev_test_fops,
247 };
248 struct miscdevice misc2 = {
249 .name = "misc2",
250 .fops = &miscdev_test_fops,
251 };
252 int ret;
253 const struct miscdev_test_case *params = test->param_value;
254
255 misc1.minor = params->minor;
256 misc2.minor = params->minor;
257
258 ret = misc_register(&misc1);
259 KUNIT_EXPECT_EQ(test, ret, 0);
260 KUNIT_EXPECT_EQ(test, misc1.minor, params->minor);
261
262 ret = misc_register(&misc2);
263 KUNIT_EXPECT_EQ(test, ret, -EBUSY);
264 if (ret == 0)
265 misc_deregister(&misc2);
266
267 misc_deregister(&misc1);
268 }
269
miscdev_test_duplicate_name(struct kunit * test)270 static void miscdev_test_duplicate_name(struct kunit *test)
271 {
272 struct miscdevice misc1 = {
273 .minor = MISC_DYNAMIC_MINOR,
274 .name = "misc1",
275 .fops = &miscdev_test_fops,
276 };
277 struct miscdevice misc2 = {
278 .minor = MISC_DYNAMIC_MINOR,
279 .name = "misc1",
280 .fops = &miscdev_test_fops,
281 };
282 int ret;
283
284 ret = misc_register(&misc1);
285 KUNIT_EXPECT_EQ(test, ret, 0);
286 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(misc1.minor));
287
288 ret = misc_register(&misc2);
289 KUNIT_EXPECT_EQ(test, ret, -EEXIST);
290 if (ret == 0)
291 misc_deregister(&misc2);
292
293 misc_deregister(&misc1);
294 }
295
296 /*
297 * Test that after a duplicate name failure, the reserved minor number is
298 * freed to be allocated next.
299 */
miscdev_test_duplicate_name_leak(struct kunit * test)300 static void miscdev_test_duplicate_name_leak(struct kunit *test)
301 {
302 struct miscdevice misc1 = {
303 .minor = MISC_DYNAMIC_MINOR,
304 .name = "misc1",
305 .fops = &miscdev_test_fops,
306 };
307 struct miscdevice misc2 = {
308 .minor = MISC_DYNAMIC_MINOR,
309 .name = "misc1",
310 .fops = &miscdev_test_fops,
311 };
312 struct miscdevice misc3 = {
313 .minor = MISC_DYNAMIC_MINOR,
314 .name = "misc3",
315 .fops = &miscdev_test_fops,
316 };
317 int ret;
318 int dyn_minor;
319
320 ret = misc_register(&misc1);
321 KUNIT_EXPECT_EQ(test, ret, 0);
322 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(misc1.minor));
323
324 /*
325 * Find out what is the next minor number available.
326 */
327 ret = misc_register(&misc3);
328 KUNIT_EXPECT_EQ(test, ret, 0);
329 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(misc3.minor));
330 dyn_minor = misc3.minor;
331 misc_deregister(&misc3);
332 misc3.minor = MISC_DYNAMIC_MINOR;
333
334 ret = misc_register(&misc2);
335 KUNIT_EXPECT_EQ(test, ret, -EEXIST);
336 if (ret == 0)
337 misc_deregister(&misc2);
338
339 /*
340 * Now check that we can still get the same minor we found before.
341 */
342 ret = misc_register(&misc3);
343 KUNIT_EXPECT_EQ(test, ret, 0);
344 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(misc3.minor));
345 KUNIT_EXPECT_EQ(test, misc3.minor, dyn_minor);
346 misc_deregister(&misc3);
347
348 misc_deregister(&misc1);
349 }
350
351 /*
352 * Try to register a static minor with a duplicate name. That might not
353 * deallocate the minor, preventing it from being used again.
354 */
miscdev_test_duplicate_error(struct kunit * test)355 static void miscdev_test_duplicate_error(struct kunit *test)
356 {
357 struct miscdevice miscdyn = {
358 .minor = MISC_DYNAMIC_MINOR,
359 .name = "name1",
360 .fops = &miscdev_test_fops,
361 };
362 struct miscdevice miscstat = {
363 .name = "name1",
364 .fops = &miscdev_test_fops,
365 };
366 struct miscdevice miscnew = {
367 .name = "name2",
368 .fops = &miscdev_test_fops,
369 };
370 int ret;
371 const struct miscdev_test_case *params = test->param_value;
372
373 miscstat.minor = params->minor;
374 miscnew.minor = params->minor;
375
376 ret = misc_register(&miscdyn);
377 KUNIT_EXPECT_EQ(test, ret, 0);
378 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn.minor));
379
380 ret = misc_register(&miscstat);
381 KUNIT_EXPECT_EQ(test, ret, -EEXIST);
382 if (ret == 0)
383 misc_deregister(&miscstat);
384
385 ret = misc_register(&miscnew);
386 KUNIT_EXPECT_EQ(test, ret, 0);
387 KUNIT_EXPECT_EQ(test, miscnew.minor, params->minor);
388 if (ret == 0)
389 misc_deregister(&miscnew);
390
391 misc_deregister(&miscdyn);
392 }
393
miscdev_test_dynamic_only_range(struct kunit * test)394 static void __init miscdev_test_dynamic_only_range(struct kunit *test)
395 {
396 int ret;
397 struct miscdevice *miscdev;
398 const int dynamic_minors = 256;
399 int i;
400
401 miscdev = kunit_kmalloc_array(test, dynamic_minors,
402 sizeof(struct miscdevice),
403 GFP_KERNEL | __GFP_ZERO);
404
405 for (i = 0; i < dynamic_minors; i++) {
406 miscdev[i].minor = MISC_DYNAMIC_MINOR;
407 miscdev[i].name = kasprintf(GFP_KERNEL, "misc_test%d", i);
408 miscdev[i].fops = &miscdev_test_fops;
409 ret = misc_register(&miscdev[i]);
410 if (ret != 0)
411 break;
412 /*
413 * This is the bug we are looking for!
414 * We asked for a dynamic minor and got a minor in the static range space.
415 */
416 if (miscdev[i].minor >= 0 && miscdev[i].minor <= 15) {
417 KUNIT_FAIL(test, "misc_register allocated minor %d\n", miscdev[i].minor);
418 i++;
419 break;
420 }
421 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdev[i].minor));
422 }
423
424 for (i--; i >= 0; i--) {
425 miscdev_test_can_open(test, &miscdev[i]);
426 misc_deregister(&miscdev[i]);
427 kfree_const(miscdev[i].name);
428 }
429
430 KUNIT_EXPECT_EQ(test, ret, 0);
431 }
432
miscdev_test_collision(struct kunit * test)433 static void __init miscdev_test_collision(struct kunit *test)
434 {
435 int ret;
436 struct miscdevice *miscdev;
437 struct miscdevice miscstat = {
438 .name = "miscstat",
439 .fops = &miscdev_test_fops,
440 };
441 const int dynamic_minors = 256;
442 int i;
443
444 miscdev = kunit_kmalloc_array(test, dynamic_minors,
445 sizeof(struct miscdevice),
446 GFP_KERNEL | __GFP_ZERO);
447
448 miscstat.minor = miscdev_test_ranges[0].minor;
449 ret = misc_register(&miscstat);
450 KUNIT_ASSERT_EQ(test, ret, 0);
451 KUNIT_EXPECT_EQ(test, miscstat.minor, miscdev_test_ranges[0].minor);
452
453 for (i = 0; i < dynamic_minors; i++) {
454 miscdev[i].minor = MISC_DYNAMIC_MINOR;
455 miscdev[i].name = kasprintf(GFP_KERNEL, "misc_test%d", i);
456 miscdev[i].fops = &miscdev_test_fops;
457 ret = misc_register(&miscdev[i]);
458 if (ret != 0)
459 break;
460 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdev[i].minor));
461 }
462
463 for (i--; i >= 0; i--) {
464 miscdev_test_can_open(test, &miscdev[i]);
465 misc_deregister(&miscdev[i]);
466 kfree_const(miscdev[i].name);
467 }
468
469 misc_deregister(&miscstat);
470
471 KUNIT_EXPECT_EQ(test, ret, 0);
472 }
473
miscdev_test_collision_reverse(struct kunit * test)474 static void __init miscdev_test_collision_reverse(struct kunit *test)
475 {
476 int ret;
477 struct miscdevice *miscdev;
478 struct miscdevice miscstat = {
479 .name = "miscstat",
480 .fops = &miscdev_test_fops,
481 };
482 const int dynamic_minors = 256;
483 int i;
484
485 miscdev = kunit_kmalloc_array(test, dynamic_minors,
486 sizeof(struct miscdevice),
487 GFP_KERNEL | __GFP_ZERO);
488
489 for (i = 0; i < dynamic_minors; i++) {
490 miscdev[i].minor = MISC_DYNAMIC_MINOR;
491 miscdev[i].name = kasprintf(GFP_KERNEL, "misc_test%d", i);
492 miscdev[i].fops = &miscdev_test_fops;
493 ret = misc_register(&miscdev[i]);
494 if (ret != 0)
495 break;
496 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdev[i].minor));
497 }
498
499 KUNIT_EXPECT_EQ(test, ret, 0);
500
501 miscstat.minor = miscdev_test_ranges[0].minor;
502 ret = misc_register(&miscstat);
503 KUNIT_EXPECT_EQ(test, ret, 0);
504 KUNIT_EXPECT_EQ(test, miscstat.minor, miscdev_test_ranges[0].minor);
505 if (ret == 0)
506 misc_deregister(&miscstat);
507
508 for (i--; i >= 0; i--) {
509 miscdev_test_can_open(test, &miscdev[i]);
510 misc_deregister(&miscdev[i]);
511 kfree_const(miscdev[i].name);
512 }
513 }
514
miscdev_test_conflict(struct kunit * test)515 static void __init miscdev_test_conflict(struct kunit *test)
516 {
517 int ret;
518 struct miscdevice miscdyn = {
519 .name = "miscdyn",
520 .minor = MISC_DYNAMIC_MINOR,
521 .fops = &miscdev_test_fops,
522 };
523 struct miscdevice miscstat = {
524 .name = "miscstat",
525 .fops = &miscdev_test_fops,
526 };
527
528 ret = misc_register(&miscdyn);
529 KUNIT_ASSERT_EQ(test, ret, 0);
530 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn.minor));
531
532 /*
533 * Try to register a static minor with the same minor as the
534 * dynamic one.
535 */
536 miscstat.minor = miscdyn.minor;
537 ret = misc_register(&miscstat);
538 KUNIT_EXPECT_EQ(test, ret, -EINVAL);
539 if (ret == 0)
540 misc_deregister(&miscstat);
541
542 miscdev_test_can_open(test, &miscdyn);
543
544 misc_deregister(&miscdyn);
545 }
546
miscdev_test_conflict_reverse(struct kunit * test)547 static void __init miscdev_test_conflict_reverse(struct kunit *test)
548 {
549 int ret;
550 struct miscdevice miscdyn = {
551 .name = "miscdyn",
552 .minor = MISC_DYNAMIC_MINOR,
553 .fops = &miscdev_test_fops,
554 };
555 struct miscdevice miscstat = {
556 .name = "miscstat",
557 .fops = &miscdev_test_fops,
558 };
559
560 /*
561 * Find the first available dynamic minor to use it as a static
562 * minor later on.
563 */
564 ret = misc_register(&miscdyn);
565 KUNIT_ASSERT_EQ(test, ret, 0);
566 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn.minor));
567 miscstat.minor = miscdyn.minor;
568 misc_deregister(&miscdyn);
569
570 ret = misc_register(&miscstat);
571 KUNIT_EXPECT_EQ(test, ret, -EINVAL);
572 if (ret == 0)
573 misc_deregister(&miscstat);
574
575 /*
576 * Try to register a dynamic minor after registering a static minor
577 * within the dynamic range. It should work but get a different
578 * minor.
579 */
580 miscdyn.minor = MISC_DYNAMIC_MINOR;
581 ret = misc_register(&miscdyn);
582 KUNIT_EXPECT_EQ(test, ret, 0);
583 KUNIT_EXPECT_EQ(test, miscdyn.minor, miscstat.minor);
584 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn.minor));
585 if (ret == 0)
586 misc_deregister(&miscdyn);
587 }
588
589 /* Take minor(> MISC_DYNAMIC_MINOR) as invalid when register miscdevice */
miscdev_test_invalid_input(struct kunit * test)590 static void miscdev_test_invalid_input(struct kunit *test)
591 {
592 struct miscdevice misc_test = {
593 .minor = MISC_DYNAMIC_MINOR + 1,
594 .name = "misc_test",
595 .fops = &miscdev_test_fops,
596 };
597 int ret;
598
599 ret = misc_register(&misc_test);
600 KUNIT_EXPECT_EQ(test, ret, -EINVAL);
601 if (ret == 0)
602 misc_deregister(&misc_test);
603 }
604
605 /*
606 * Verify if @miscdyn_a can still be registered successfully without
607 * reinitialization even if its minor ever owned was requested by
608 * another miscdevice such as @miscdyn_b.
609 */
miscdev_test_dynamic_reentry(struct kunit * test)610 static void miscdev_test_dynamic_reentry(struct kunit *test)
611 {
612 struct miscdevice miscdyn_a = {
613 .name = "miscdyn_a",
614 .minor = MISC_DYNAMIC_MINOR,
615 .fops = &miscdev_test_fops,
616 };
617 struct miscdevice miscdyn_b = {
618 .name = "miscdyn_b",
619 .minor = MISC_DYNAMIC_MINOR,
620 .fops = &miscdev_test_fops,
621 };
622 int ret, minor_a;
623
624 ret = misc_register(&miscdyn_a);
625 KUNIT_ASSERT_EQ(test, ret, 0);
626 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn_a.minor));
627 minor_a = miscdyn_a.minor;
628 if (ret != 0)
629 return;
630 misc_deregister(&miscdyn_a);
631
632 ret = misc_register(&miscdyn_b);
633 KUNIT_ASSERT_EQ(test, ret, 0);
634 KUNIT_EXPECT_EQ(test, miscdyn_b.minor, minor_a);
635 if (ret != 0)
636 return;
637
638 ret = misc_register(&miscdyn_a);
639 KUNIT_ASSERT_EQ(test, ret, 0);
640 KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn_a.minor));
641 KUNIT_EXPECT_NE(test, miscdyn_a.minor, miscdyn_b.minor);
642 if (ret == 0)
643 misc_deregister(&miscdyn_a);
644
645 misc_deregister(&miscdyn_b);
646 }
647
648 static struct kunit_case test_cases[] = {
649 KUNIT_CASE(kunit_static_minor),
650 KUNIT_CASE(kunit_misc_dynamic_minor),
651 KUNIT_CASE(miscdev_test_invalid_input),
652 KUNIT_CASE_PARAM(miscdev_test_twice, miscdev_gen_params),
653 KUNIT_CASE_PARAM(miscdev_test_duplicate_minor, miscdev_gen_params),
654 KUNIT_CASE(miscdev_test_duplicate_name),
655 KUNIT_CASE(miscdev_test_duplicate_name_leak),
656 KUNIT_CASE_PARAM(miscdev_test_duplicate_error, miscdev_gen_params),
657 KUNIT_CASE(miscdev_test_dynamic_reentry),
658 {}
659 };
660
661 static struct kunit_suite test_suite = {
662 .name = "miscdev",
663 .suite_init = miscdev_find_minors,
664 .test_cases = test_cases,
665 };
666 kunit_test_suite(test_suite);
667
668 static struct kunit_case __refdata test_init_cases[] = {
669 KUNIT_CASE_PARAM(miscdev_test_static_basic, miscdev_gen_params),
670 KUNIT_CASE(miscdev_test_dynamic_basic),
671 KUNIT_CASE(miscdev_test_dynamic_only_range),
672 KUNIT_CASE(miscdev_test_collision),
673 KUNIT_CASE(miscdev_test_collision_reverse),
674 KUNIT_CASE(miscdev_test_conflict),
675 KUNIT_CASE(miscdev_test_conflict_reverse),
676 {}
677 };
678
679 static struct kunit_suite test_init_suite = {
680 .name = "miscdev_init",
681 .suite_init = miscdev_find_minors,
682 .test_cases = test_init_cases,
683 };
684 kunit_test_init_section_suite(test_init_suite);
685
686 MODULE_LICENSE("GPL");
687 MODULE_AUTHOR("Vimal Agrawal");
688 MODULE_AUTHOR("Thadeu Lima de Souza Cascardo <cascardo@igalia.com>");
689 MODULE_DESCRIPTION("Test module for misc character devices");
690