util_macros_kunit.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Test cases for bitfield helpers.
  4. */
  5. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  6. #include <kunit/test.h>
  7. #include <linux/util_macros.h>
  8. #define FIND_CLOSEST_RANGE_CHECK(from, to, array, exp_idx) \
  9. { \
  10. int i; \
  11. for (i = from; i <= to; i++) { \
  12. int found = find_closest(i, array, ARRAY_SIZE(array)); \
  13. KUNIT_ASSERT_EQ(ctx, exp_idx, found); \
  14. } \
  15. }
  16. static void test_find_closest(struct kunit *ctx)
  17. {
  18. /* This will test a few arrays that are found in drivers */
  19. static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 };
  20. static const unsigned int ad7616_oversampling_avail[] = {
  21. 1, 2, 4, 8, 16, 32, 64, 128,
  22. };
  23. static u32 wd_timeout_table[] = { 2, 4, 6, 8, 16, 32, 48, 64 };
  24. static int array_prog1a[] = { 1, 2, 3, 4, 5 };
  25. static u32 array_prog1b[] = { 2, 3, 4, 5, 6 };
  26. static int array_prog1mix[] = { -2, -1, 0, 1, 2 };
  27. static int array_prog2a[] = { 1, 3, 5, 7 };
  28. static u32 array_prog2b[] = { 2, 4, 6, 8 };
  29. static int array_prog3a[] = { 1, 4, 7, 10 };
  30. static u32 array_prog3b[] = { 2, 5, 8, 11 };
  31. static int array_prog4a[] = { 1, 5, 9, 13 };
  32. static u32 array_prog4b[] = { 2, 6, 10, 14 };
  33. FIND_CLOSEST_RANGE_CHECK(-3, 2, ina226_avg_tab, 0);
  34. FIND_CLOSEST_RANGE_CHECK(3, 10, ina226_avg_tab, 1);
  35. FIND_CLOSEST_RANGE_CHECK(11, 40, ina226_avg_tab, 2);
  36. FIND_CLOSEST_RANGE_CHECK(41, 96, ina226_avg_tab, 3);
  37. FIND_CLOSEST_RANGE_CHECK(97, 192, ina226_avg_tab, 4);
  38. FIND_CLOSEST_RANGE_CHECK(193, 384, ina226_avg_tab, 5);
  39. FIND_CLOSEST_RANGE_CHECK(385, 768, ina226_avg_tab, 6);
  40. FIND_CLOSEST_RANGE_CHECK(769, 2048, ina226_avg_tab, 7);
  41. /* The array that found the bug that caused this kunit to exist */
  42. FIND_CLOSEST_RANGE_CHECK(-3, 1, ad7616_oversampling_avail, 0);
  43. FIND_CLOSEST_RANGE_CHECK(2, 3, ad7616_oversampling_avail, 1);
  44. FIND_CLOSEST_RANGE_CHECK(4, 6, ad7616_oversampling_avail, 2);
  45. FIND_CLOSEST_RANGE_CHECK(7, 12, ad7616_oversampling_avail, 3);
  46. FIND_CLOSEST_RANGE_CHECK(13, 24, ad7616_oversampling_avail, 4);
  47. FIND_CLOSEST_RANGE_CHECK(25, 48, ad7616_oversampling_avail, 5);
  48. FIND_CLOSEST_RANGE_CHECK(49, 96, ad7616_oversampling_avail, 6);
  49. FIND_CLOSEST_RANGE_CHECK(97, 256, ad7616_oversampling_avail, 7);
  50. FIND_CLOSEST_RANGE_CHECK(-3, 3, wd_timeout_table, 0);
  51. FIND_CLOSEST_RANGE_CHECK(4, 5, wd_timeout_table, 1);
  52. FIND_CLOSEST_RANGE_CHECK(6, 7, wd_timeout_table, 2);
  53. FIND_CLOSEST_RANGE_CHECK(8, 12, wd_timeout_table, 3);
  54. FIND_CLOSEST_RANGE_CHECK(13, 24, wd_timeout_table, 4);
  55. FIND_CLOSEST_RANGE_CHECK(25, 40, wd_timeout_table, 5);
  56. FIND_CLOSEST_RANGE_CHECK(41, 56, wd_timeout_table, 6);
  57. FIND_CLOSEST_RANGE_CHECK(57, 128, wd_timeout_table, 7);
  58. /* One could argue that find_closest() should not be used for monotonic
  59. * arrays (like 1,2,3,4,5), but even so, it should work as long as the
  60. * array is sorted ascending. */
  61. FIND_CLOSEST_RANGE_CHECK(-3, 1, array_prog1a, 0);
  62. FIND_CLOSEST_RANGE_CHECK(2, 2, array_prog1a, 1);
  63. FIND_CLOSEST_RANGE_CHECK(3, 3, array_prog1a, 2);
  64. FIND_CLOSEST_RANGE_CHECK(4, 4, array_prog1a, 3);
  65. FIND_CLOSEST_RANGE_CHECK(5, 8, array_prog1a, 4);
  66. FIND_CLOSEST_RANGE_CHECK(-3, 2, array_prog1b, 0);
  67. FIND_CLOSEST_RANGE_CHECK(3, 3, array_prog1b, 1);
  68. FIND_CLOSEST_RANGE_CHECK(4, 4, array_prog1b, 2);
  69. FIND_CLOSEST_RANGE_CHECK(5, 5, array_prog1b, 3);
  70. FIND_CLOSEST_RANGE_CHECK(6, 8, array_prog1b, 4);
  71. FIND_CLOSEST_RANGE_CHECK(-4, -2, array_prog1mix, 0);
  72. FIND_CLOSEST_RANGE_CHECK(-1, -1, array_prog1mix, 1);
  73. FIND_CLOSEST_RANGE_CHECK(0, 0, array_prog1mix, 2);
  74. FIND_CLOSEST_RANGE_CHECK(1, 1, array_prog1mix, 3);
  75. FIND_CLOSEST_RANGE_CHECK(2, 5, array_prog1mix, 4);
  76. FIND_CLOSEST_RANGE_CHECK(-3, 2, array_prog2a, 0);
  77. FIND_CLOSEST_RANGE_CHECK(3, 4, array_prog2a, 1);
  78. FIND_CLOSEST_RANGE_CHECK(5, 6, array_prog2a, 2);
  79. FIND_CLOSEST_RANGE_CHECK(7, 10, array_prog2a, 3);
  80. FIND_CLOSEST_RANGE_CHECK(-3, 3, array_prog2b, 0);
  81. FIND_CLOSEST_RANGE_CHECK(4, 5, array_prog2b, 1);
  82. FIND_CLOSEST_RANGE_CHECK(6, 7, array_prog2b, 2);
  83. FIND_CLOSEST_RANGE_CHECK(8, 10, array_prog2b, 3);
  84. FIND_CLOSEST_RANGE_CHECK(-3, 2, array_prog3a, 0);
  85. FIND_CLOSEST_RANGE_CHECK(3, 5, array_prog3a, 1);
  86. FIND_CLOSEST_RANGE_CHECK(6, 8, array_prog3a, 2);
  87. FIND_CLOSEST_RANGE_CHECK(9, 20, array_prog3a, 3);
  88. FIND_CLOSEST_RANGE_CHECK(-3, 3, array_prog3b, 0);
  89. FIND_CLOSEST_RANGE_CHECK(4, 6, array_prog3b, 1);
  90. FIND_CLOSEST_RANGE_CHECK(7, 9, array_prog3b, 2);
  91. FIND_CLOSEST_RANGE_CHECK(10, 20, array_prog3b, 3);
  92. FIND_CLOSEST_RANGE_CHECK(-3, 3, array_prog4a, 0);
  93. FIND_CLOSEST_RANGE_CHECK(4, 7, array_prog4a, 1);
  94. FIND_CLOSEST_RANGE_CHECK(8, 11, array_prog4a, 2);
  95. FIND_CLOSEST_RANGE_CHECK(12, 20, array_prog4a, 3);
  96. FIND_CLOSEST_RANGE_CHECK(-3, 4, array_prog4b, 0);
  97. FIND_CLOSEST_RANGE_CHECK(5, 8, array_prog4b, 1);
  98. FIND_CLOSEST_RANGE_CHECK(9, 12, array_prog4b, 2);
  99. FIND_CLOSEST_RANGE_CHECK(13, 20, array_prog4b, 3);
  100. }
  101. #define FIND_CLOSEST_DESC_RANGE_CHECK(from, to, array, exp_idx) \
  102. { \
  103. int i; \
  104. for (i = from; i <= to; i++) { \
  105. int found = find_closest_descending(i, array, \
  106. ARRAY_SIZE(array)); \
  107. KUNIT_ASSERT_EQ(ctx, exp_idx, found); \
  108. } \
  109. }
  110. static void test_find_closest_descending(struct kunit *ctx)
  111. {
  112. /* Same arrays as 'test_find_closest' but reversed */
  113. static const int ina226_avg_tab[] = { 1024, 512, 256, 128, 64, 16, 4, 1 };
  114. static const unsigned int ad7616_oversampling_avail[] = {
  115. 128, 64, 32, 16, 8, 4, 2, 1
  116. };
  117. static u32 wd_timeout_table[] = { 64, 48, 32, 16, 8, 6, 4, 2 };
  118. static int array_prog1a[] = { 5, 4, 3, 2, 1 };
  119. static u32 array_prog1b[] = { 6, 5, 4, 3, 2 };
  120. static int array_prog1mix[] = { 2, 1, 0, -1, -2 };
  121. static int array_prog2a[] = { 7, 5, 3, 1 };
  122. static u32 array_prog2b[] = { 8, 6, 4, 2 };
  123. static int array_prog3a[] = { 10, 7, 4, 1 };
  124. static u32 array_prog3b[] = { 11, 8, 5, 2 };
  125. static int array_prog4a[] = { 13, 9, 5, 1 };
  126. static u32 array_prog4b[] = { 14, 10, 6, 2 };
  127. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 2, ina226_avg_tab, 7);
  128. FIND_CLOSEST_DESC_RANGE_CHECK(3, 10, ina226_avg_tab, 6);
  129. FIND_CLOSEST_DESC_RANGE_CHECK(11, 40, ina226_avg_tab, 5);
  130. FIND_CLOSEST_DESC_RANGE_CHECK(41, 96, ina226_avg_tab, 4);
  131. FIND_CLOSEST_DESC_RANGE_CHECK(97, 192, ina226_avg_tab, 3);
  132. FIND_CLOSEST_DESC_RANGE_CHECK(193, 384, ina226_avg_tab, 2);
  133. FIND_CLOSEST_DESC_RANGE_CHECK(385, 768, ina226_avg_tab, 1);
  134. FIND_CLOSEST_DESC_RANGE_CHECK(769, 2048, ina226_avg_tab, 0);
  135. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 1, ad7616_oversampling_avail, 7);
  136. FIND_CLOSEST_DESC_RANGE_CHECK(2, 3, ad7616_oversampling_avail, 6);
  137. FIND_CLOSEST_DESC_RANGE_CHECK(4, 6, ad7616_oversampling_avail, 5);
  138. FIND_CLOSEST_DESC_RANGE_CHECK(7, 12, ad7616_oversampling_avail, 4);
  139. FIND_CLOSEST_DESC_RANGE_CHECK(13, 24, ad7616_oversampling_avail, 3);
  140. FIND_CLOSEST_DESC_RANGE_CHECK(25, 48, ad7616_oversampling_avail, 2);
  141. FIND_CLOSEST_DESC_RANGE_CHECK(49, 96, ad7616_oversampling_avail, 1);
  142. FIND_CLOSEST_DESC_RANGE_CHECK(97, 256, ad7616_oversampling_avail, 0);
  143. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 3, wd_timeout_table, 7);
  144. FIND_CLOSEST_DESC_RANGE_CHECK(4, 5, wd_timeout_table, 6);
  145. FIND_CLOSEST_DESC_RANGE_CHECK(6, 7, wd_timeout_table, 5);
  146. FIND_CLOSEST_DESC_RANGE_CHECK(8, 12, wd_timeout_table, 4);
  147. FIND_CLOSEST_DESC_RANGE_CHECK(13, 24, wd_timeout_table, 3);
  148. FIND_CLOSEST_DESC_RANGE_CHECK(25, 40, wd_timeout_table, 2);
  149. FIND_CLOSEST_DESC_RANGE_CHECK(41, 56, wd_timeout_table, 1);
  150. FIND_CLOSEST_DESC_RANGE_CHECK(57, 128, wd_timeout_table, 0);
  151. /* One could argue that find_closest_descending() should not be used
  152. * for monotonic arrays (like 5,4,3,2,1), but even so, it should still
  153. * it should work as long as the array is sorted descending. */
  154. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 1, array_prog1a, 4);
  155. FIND_CLOSEST_DESC_RANGE_CHECK(2, 2, array_prog1a, 3);
  156. FIND_CLOSEST_DESC_RANGE_CHECK(3, 3, array_prog1a, 2);
  157. FIND_CLOSEST_DESC_RANGE_CHECK(4, 4, array_prog1a, 1);
  158. FIND_CLOSEST_DESC_RANGE_CHECK(5, 8, array_prog1a, 0);
  159. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 2, array_prog1b, 4);
  160. FIND_CLOSEST_DESC_RANGE_CHECK(3, 3, array_prog1b, 3);
  161. FIND_CLOSEST_DESC_RANGE_CHECK(4, 4, array_prog1b, 2);
  162. FIND_CLOSEST_DESC_RANGE_CHECK(5, 5, array_prog1b, 1);
  163. FIND_CLOSEST_DESC_RANGE_CHECK(6, 8, array_prog1b, 0);
  164. FIND_CLOSEST_DESC_RANGE_CHECK(-4, -2, array_prog1mix, 4);
  165. FIND_CLOSEST_DESC_RANGE_CHECK(-1, -1, array_prog1mix, 3);
  166. FIND_CLOSEST_DESC_RANGE_CHECK(0, 0, array_prog1mix, 2);
  167. FIND_CLOSEST_DESC_RANGE_CHECK(1, 1, array_prog1mix, 1);
  168. FIND_CLOSEST_DESC_RANGE_CHECK(2, 5, array_prog1mix, 0);
  169. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 2, array_prog2a, 3);
  170. FIND_CLOSEST_DESC_RANGE_CHECK(3, 4, array_prog2a, 2);
  171. FIND_CLOSEST_DESC_RANGE_CHECK(5, 6, array_prog2a, 1);
  172. FIND_CLOSEST_DESC_RANGE_CHECK(7, 10, array_prog2a, 0);
  173. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 3, array_prog2b, 3);
  174. FIND_CLOSEST_DESC_RANGE_CHECK(4, 5, array_prog2b, 2);
  175. FIND_CLOSEST_DESC_RANGE_CHECK(6, 7, array_prog2b, 1);
  176. FIND_CLOSEST_DESC_RANGE_CHECK(8, 10, array_prog2b, 0);
  177. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 2, array_prog3a, 3);
  178. FIND_CLOSEST_DESC_RANGE_CHECK(3, 5, array_prog3a, 2);
  179. FIND_CLOSEST_DESC_RANGE_CHECK(6, 8, array_prog3a, 1);
  180. FIND_CLOSEST_DESC_RANGE_CHECK(9, 20, array_prog3a, 0);
  181. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 3, array_prog3b, 3);
  182. FIND_CLOSEST_DESC_RANGE_CHECK(4, 6, array_prog3b, 2);
  183. FIND_CLOSEST_DESC_RANGE_CHECK(7, 9, array_prog3b, 1);
  184. FIND_CLOSEST_DESC_RANGE_CHECK(10, 20, array_prog3b, 0);
  185. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 3, array_prog4a, 3);
  186. FIND_CLOSEST_DESC_RANGE_CHECK(4, 7, array_prog4a, 2);
  187. FIND_CLOSEST_DESC_RANGE_CHECK(8, 11, array_prog4a, 1);
  188. FIND_CLOSEST_DESC_RANGE_CHECK(12, 20, array_prog4a, 0);
  189. FIND_CLOSEST_DESC_RANGE_CHECK(-3, 4, array_prog4b, 3);
  190. FIND_CLOSEST_DESC_RANGE_CHECK(5, 8, array_prog4b, 2);
  191. FIND_CLOSEST_DESC_RANGE_CHECK(9, 12, array_prog4b, 1);
  192. FIND_CLOSEST_DESC_RANGE_CHECK(13, 20, array_prog4b, 0);
  193. }
  194. static struct kunit_case __refdata util_macros_test_cases[] = {
  195. KUNIT_CASE(test_find_closest),
  196. KUNIT_CASE(test_find_closest_descending),
  197. {}
  198. };
  199. static struct kunit_suite util_macros_test_suite = {
  200. .name = "util_macros.h",
  201. .test_cases = util_macros_test_cases,
  202. };
  203. kunit_test_suites(&util_macros_test_suite);
  204. MODULE_AUTHOR("Alexandru Ardelean <aardelean@baylibre.com>");
  205. MODULE_DESCRIPTION("Test cases for util_macros.h helpers");
  206. MODULE_LICENSE("GPL");