misc_minor_kunit.c 16 KB

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