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