test_bitmap.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /*
  2. * Test cases for printf facility.
  3. */
  4. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  5. #include <linux/bitmap.h>
  6. #include <linux/init.h>
  7. #include <linux/kernel.h>
  8. #include <linux/module.h>
  9. #include <linux/printk.h>
  10. #include <linux/slab.h>
  11. #include <linux/string.h>
  12. static unsigned total_tests __initdata;
  13. static unsigned failed_tests __initdata;
  14. static char pbl_buffer[PAGE_SIZE] __initdata;
  15. static bool __init
  16. __check_eq_uint(const char *srcfile, unsigned int line,
  17. const unsigned int exp_uint, unsigned int x)
  18. {
  19. if (exp_uint != x) {
  20. pr_err("[%s:%u] expected %u, got %u\n",
  21. srcfile, line, exp_uint, x);
  22. return false;
  23. }
  24. return true;
  25. }
  26. static bool __init
  27. __check_eq_bitmap(const char *srcfile, unsigned int line,
  28. const unsigned long *exp_bmap, const unsigned long *bmap,
  29. unsigned int nbits)
  30. {
  31. if (!bitmap_equal(exp_bmap, bmap, nbits)) {
  32. pr_warn("[%s:%u] bitmaps contents differ: expected \"%*pbl\", got \"%*pbl\"\n",
  33. srcfile, line,
  34. nbits, exp_bmap, nbits, bmap);
  35. return false;
  36. }
  37. return true;
  38. }
  39. static bool __init
  40. __check_eq_pbl(const char *srcfile, unsigned int line,
  41. const char *expected_pbl,
  42. const unsigned long *bitmap, unsigned int nbits)
  43. {
  44. snprintf(pbl_buffer, sizeof(pbl_buffer), "%*pbl", nbits, bitmap);
  45. if (strcmp(expected_pbl, pbl_buffer)) {
  46. pr_warn("[%s:%u] expected \"%s\", got \"%s\"\n",
  47. srcfile, line,
  48. expected_pbl, pbl_buffer);
  49. return false;
  50. }
  51. return true;
  52. }
  53. static bool __init
  54. __check_eq_u32_array(const char *srcfile, unsigned int line,
  55. const u32 *exp_arr, unsigned int exp_len,
  56. const u32 *arr, unsigned int len) __used;
  57. static bool __init
  58. __check_eq_u32_array(const char *srcfile, unsigned int line,
  59. const u32 *exp_arr, unsigned int exp_len,
  60. const u32 *arr, unsigned int len)
  61. {
  62. if (exp_len != len) {
  63. pr_warn("[%s:%u] array length differ: expected %u, got %u\n",
  64. srcfile, line,
  65. exp_len, len);
  66. return false;
  67. }
  68. if (memcmp(exp_arr, arr, len*sizeof(*arr))) {
  69. pr_warn("[%s:%u] array contents differ\n", srcfile, line);
  70. print_hex_dump(KERN_WARNING, " exp: ", DUMP_PREFIX_OFFSET,
  71. 32, 4, exp_arr, exp_len*sizeof(*exp_arr), false);
  72. print_hex_dump(KERN_WARNING, " got: ", DUMP_PREFIX_OFFSET,
  73. 32, 4, arr, len*sizeof(*arr), false);
  74. return false;
  75. }
  76. return true;
  77. }
  78. #define __expect_eq(suffix, ...) \
  79. ({ \
  80. int result = 0; \
  81. total_tests++; \
  82. if (!__check_eq_ ## suffix(__FILE__, __LINE__, \
  83. ##__VA_ARGS__)) { \
  84. failed_tests++; \
  85. result = 1; \
  86. } \
  87. result; \
  88. })
  89. #define expect_eq_uint(...) __expect_eq(uint, ##__VA_ARGS__)
  90. #define expect_eq_bitmap(...) __expect_eq(bitmap, ##__VA_ARGS__)
  91. #define expect_eq_pbl(...) __expect_eq(pbl, ##__VA_ARGS__)
  92. #define expect_eq_u32_array(...) __expect_eq(u32_array, ##__VA_ARGS__)
  93. static void __init test_zero_clear(void)
  94. {
  95. DECLARE_BITMAP(bmap, 1024);
  96. /* Known way to set all bits */
  97. memset(bmap, 0xff, 128);
  98. expect_eq_pbl("0-22", bmap, 23);
  99. expect_eq_pbl("0-1023", bmap, 1024);
  100. /* single-word bitmaps */
  101. bitmap_clear(bmap, 0, 9);
  102. expect_eq_pbl("9-1023", bmap, 1024);
  103. bitmap_zero(bmap, 35);
  104. expect_eq_pbl("64-1023", bmap, 1024);
  105. /* cross boundaries operations */
  106. bitmap_clear(bmap, 79, 19);
  107. expect_eq_pbl("64-78,98-1023", bmap, 1024);
  108. bitmap_zero(bmap, 115);
  109. expect_eq_pbl("128-1023", bmap, 1024);
  110. /* Zeroing entire area */
  111. bitmap_zero(bmap, 1024);
  112. expect_eq_pbl("", bmap, 1024);
  113. }
  114. static void __init test_fill_set(void)
  115. {
  116. DECLARE_BITMAP(bmap, 1024);
  117. /* Known way to clear all bits */
  118. memset(bmap, 0x00, 128);
  119. expect_eq_pbl("", bmap, 23);
  120. expect_eq_pbl("", bmap, 1024);
  121. /* single-word bitmaps */
  122. bitmap_set(bmap, 0, 9);
  123. expect_eq_pbl("0-8", bmap, 1024);
  124. bitmap_fill(bmap, 35);
  125. expect_eq_pbl("0-63", bmap, 1024);
  126. /* cross boundaries operations */
  127. bitmap_set(bmap, 79, 19);
  128. expect_eq_pbl("0-63,79-97", bmap, 1024);
  129. bitmap_fill(bmap, 115);
  130. expect_eq_pbl("0-127", bmap, 1024);
  131. /* Zeroing entire area */
  132. bitmap_fill(bmap, 1024);
  133. expect_eq_pbl("0-1023", bmap, 1024);
  134. }
  135. static void __init test_copy(void)
  136. {
  137. DECLARE_BITMAP(bmap1, 1024);
  138. DECLARE_BITMAP(bmap2, 1024);
  139. bitmap_zero(bmap1, 1024);
  140. bitmap_zero(bmap2, 1024);
  141. /* single-word bitmaps */
  142. bitmap_set(bmap1, 0, 19);
  143. bitmap_copy(bmap2, bmap1, 23);
  144. expect_eq_pbl("0-18", bmap2, 1024);
  145. bitmap_set(bmap2, 0, 23);
  146. bitmap_copy(bmap2, bmap1, 23);
  147. expect_eq_pbl("0-18", bmap2, 1024);
  148. /* multi-word bitmaps */
  149. bitmap_set(bmap1, 0, 109);
  150. bitmap_copy(bmap2, bmap1, 1024);
  151. expect_eq_pbl("0-108", bmap2, 1024);
  152. bitmap_fill(bmap2, 1024);
  153. bitmap_copy(bmap2, bmap1, 1024);
  154. expect_eq_pbl("0-108", bmap2, 1024);
  155. /* the following tests assume a 32- or 64-bit arch (even 128b
  156. * if we care)
  157. */
  158. bitmap_fill(bmap2, 1024);
  159. bitmap_copy(bmap2, bmap1, 109); /* ... but 0-padded til word length */
  160. expect_eq_pbl("0-108,128-1023", bmap2, 1024);
  161. bitmap_fill(bmap2, 1024);
  162. bitmap_copy(bmap2, bmap1, 97); /* ... but aligned on word length */
  163. expect_eq_pbl("0-108,128-1023", bmap2, 1024);
  164. }
  165. #define PARSE_TIME 0x1
  166. struct test_bitmap_parselist{
  167. const int errno;
  168. const char *in;
  169. const unsigned long *expected;
  170. const int nbits;
  171. const int flags;
  172. };
  173. static const unsigned long exp[] __initconst = {
  174. BITMAP_FROM_U64(1),
  175. BITMAP_FROM_U64(2),
  176. BITMAP_FROM_U64(0x0000ffff),
  177. BITMAP_FROM_U64(0xffff0000),
  178. BITMAP_FROM_U64(0x55555555),
  179. BITMAP_FROM_U64(0xaaaaaaaa),
  180. BITMAP_FROM_U64(0x11111111),
  181. BITMAP_FROM_U64(0x22222222),
  182. BITMAP_FROM_U64(0xffffffff),
  183. BITMAP_FROM_U64(0xfffffffe),
  184. BITMAP_FROM_U64(0x3333333311111111ULL),
  185. BITMAP_FROM_U64(0xffffffff77777777ULL)
  186. };
  187. static const unsigned long exp2[] __initconst = {
  188. BITMAP_FROM_U64(0x3333333311111111ULL),
  189. BITMAP_FROM_U64(0xffffffff77777777ULL)
  190. };
  191. static const struct test_bitmap_parselist parselist_tests[] __initconst = {
  192. #define step (sizeof(u64) / sizeof(unsigned long))
  193. {0, "0", &exp[0], 8, 0},
  194. {0, "1", &exp[1 * step], 8, 0},
  195. {0, "0-15", &exp[2 * step], 32, 0},
  196. {0, "16-31", &exp[3 * step], 32, 0},
  197. {0, "0-31:1/2", &exp[4 * step], 32, 0},
  198. {0, "1-31:1/2", &exp[5 * step], 32, 0},
  199. {0, "0-31:1/4", &exp[6 * step], 32, 0},
  200. {0, "1-31:1/4", &exp[7 * step], 32, 0},
  201. {0, "0-31:4/4", &exp[8 * step], 32, 0},
  202. {0, "1-31:4/4", &exp[9 * step], 32, 0},
  203. {0, "0-31:1/4,32-63:2/4", &exp[10 * step], 64, 0},
  204. {0, "0-31:3/4,32-63:4/4", &exp[11 * step], 64, 0},
  205. {0, "0-31:1/4,32-63:2/4,64-95:3/4,96-127:4/4", exp2, 128, 0},
  206. {0, "0-2047:128/256", NULL, 2048, PARSE_TIME},
  207. {-EINVAL, "-1", NULL, 8, 0},
  208. {-EINVAL, "-0", NULL, 8, 0},
  209. {-EINVAL, "10-1", NULL, 8, 0},
  210. {-EINVAL, "0-31:", NULL, 8, 0},
  211. {-EINVAL, "0-31:0", NULL, 8, 0},
  212. {-EINVAL, "0-31:0/0", NULL, 8, 0},
  213. {-EINVAL, "0-31:1/0", NULL, 8, 0},
  214. {-EINVAL, "0-31:10/1", NULL, 8, 0},
  215. };
  216. static void __init test_bitmap_parselist(void)
  217. {
  218. int i;
  219. int err;
  220. cycles_t cycles;
  221. DECLARE_BITMAP(bmap, 2048);
  222. for (i = 0; i < ARRAY_SIZE(parselist_tests); i++) {
  223. #define ptest parselist_tests[i]
  224. cycles = get_cycles();
  225. err = bitmap_parselist(ptest.in, bmap, ptest.nbits);
  226. cycles = get_cycles() - cycles;
  227. if (err != ptest.errno) {
  228. pr_err("test %d: input is %s, errno is %d, expected %d\n",
  229. i, ptest.in, err, ptest.errno);
  230. continue;
  231. }
  232. if (!err && ptest.expected
  233. && !__bitmap_equal(bmap, ptest.expected, ptest.nbits)) {
  234. pr_err("test %d: input is %s, result is 0x%lx, expected 0x%lx\n",
  235. i, ptest.in, bmap[0], *ptest.expected);
  236. continue;
  237. }
  238. if (ptest.flags & PARSE_TIME)
  239. pr_err("test %d: input is '%s' OK, Time: %llu\n",
  240. i, ptest.in,
  241. (unsigned long long)cycles);
  242. }
  243. }
  244. #define EXP_BYTES (sizeof(exp) * 8)
  245. static void __init test_bitmap_arr32(void)
  246. {
  247. unsigned int nbits, next_bit;
  248. u32 arr[sizeof(exp) / 4];
  249. DECLARE_BITMAP(bmap2, EXP_BYTES);
  250. memset(arr, 0xa5, sizeof(arr));
  251. for (nbits = 0; nbits < EXP_BYTES; ++nbits) {
  252. bitmap_to_arr32(arr, exp, nbits);
  253. bitmap_from_arr32(bmap2, arr, nbits);
  254. expect_eq_bitmap(bmap2, exp, nbits);
  255. next_bit = find_next_bit(bmap2,
  256. round_up(nbits, BITS_PER_LONG), nbits);
  257. if (next_bit < round_up(nbits, BITS_PER_LONG))
  258. pr_err("bitmap_copy_arr32(nbits == %d:"
  259. " tail is not safely cleared: %d\n",
  260. nbits, next_bit);
  261. if (nbits < EXP_BYTES - 32)
  262. expect_eq_uint(arr[DIV_ROUND_UP(nbits, 32)],
  263. 0xa5a5a5a5);
  264. }
  265. }
  266. static void noinline __init test_mem_optimisations(void)
  267. {
  268. DECLARE_BITMAP(bmap1, 1024);
  269. DECLARE_BITMAP(bmap2, 1024);
  270. unsigned int start, nbits;
  271. for (start = 0; start < 1024; start += 8) {
  272. memset(bmap1, 0x5a, sizeof(bmap1));
  273. memset(bmap2, 0x5a, sizeof(bmap2));
  274. for (nbits = 0; nbits < 1024 - start; nbits += 8) {
  275. bitmap_set(bmap1, start, nbits);
  276. __bitmap_set(bmap2, start, nbits);
  277. if (!bitmap_equal(bmap1, bmap2, 1024))
  278. printk("set not equal %d %d\n", start, nbits);
  279. if (!__bitmap_equal(bmap1, bmap2, 1024))
  280. printk("set not __equal %d %d\n", start, nbits);
  281. bitmap_clear(bmap1, start, nbits);
  282. __bitmap_clear(bmap2, start, nbits);
  283. if (!bitmap_equal(bmap1, bmap2, 1024))
  284. printk("clear not equal %d %d\n", start, nbits);
  285. if (!__bitmap_equal(bmap1, bmap2, 1024))
  286. printk("clear not __equal %d %d\n", start,
  287. nbits);
  288. }
  289. }
  290. }
  291. static int __init test_bitmap_init(void)
  292. {
  293. test_zero_clear();
  294. test_fill_set();
  295. test_copy();
  296. test_bitmap_arr32();
  297. test_bitmap_parselist();
  298. test_mem_optimisations();
  299. if (failed_tests == 0)
  300. pr_info("all %u tests passed\n", total_tests);
  301. else
  302. pr_warn("failed %u out of %u tests\n",
  303. failed_tests, total_tests);
  304. return failed_tests ? -EINVAL : 0;
  305. }
  306. static void __exit test_bitmap_cleanup(void)
  307. {
  308. }
  309. module_init(test_bitmap_init);
  310. module_exit(test_bitmap_cleanup);
  311. MODULE_AUTHOR("david decotigny <david.decotigny@googlers.com>");
  312. MODULE_LICENSE("GPL");