bloblist.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2018, Google Inc. All rights reserved.
  4. */
  5. #include <common.h>
  6. #include <bloblist.h>
  7. #include <log.h>
  8. #include <mapmem.h>
  9. #include <test/suites.h>
  10. #include <test/test.h>
  11. #include <test/ut.h>
  12. DECLARE_GLOBAL_DATA_PTR;
  13. /* Declare a new compression test */
  14. #define BLOBLIST_TEST(_name, _flags) \
  15. UNIT_TEST(_name, _flags, bloblist_test)
  16. enum {
  17. TEST_TAG = 1,
  18. TEST_TAG2 = 2,
  19. TEST_TAG_MISSING = 3,
  20. TEST_SIZE = 10,
  21. TEST_SIZE2 = 20,
  22. TEST_SIZE_LARGE = 0xe0,
  23. TEST_ADDR = CONFIG_BLOBLIST_ADDR,
  24. TEST_BLOBLIST_SIZE = 0x100,
  25. };
  26. static struct bloblist_hdr *clear_bloblist(void)
  27. {
  28. struct bloblist_hdr *hdr;
  29. /*
  30. * Clear out any existing bloblist so we have a clean slate. Zero the
  31. * header so that existing records are removed, but set everything else
  32. * to 0xff for testing purposes.
  33. */
  34. hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
  35. memset(hdr, '\xff', TEST_BLOBLIST_SIZE);
  36. memset(hdr, '\0', sizeof(*hdr));
  37. return hdr;
  38. }
  39. static int check_zero(void *data, int size)
  40. {
  41. u8 *ptr;
  42. int i;
  43. for (ptr = data, i = 0; i < size; i++, ptr++) {
  44. if (*ptr)
  45. return -EINVAL;
  46. }
  47. return 0;
  48. }
  49. static int bloblist_test_init(struct unit_test_state *uts)
  50. {
  51. struct bloblist_hdr *hdr;
  52. hdr = clear_bloblist();
  53. ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  54. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  55. hdr->version++;
  56. ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
  57. TEST_BLOBLIST_SIZE));
  58. ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
  59. ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
  60. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  61. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  62. ut_assertok(bloblist_finish());
  63. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  64. hdr->flags++;
  65. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  66. return 1;
  67. }
  68. BLOBLIST_TEST(bloblist_test_init, 0);
  69. static int bloblist_test_blob(struct unit_test_state *uts)
  70. {
  71. struct bloblist_hdr *hdr;
  72. struct bloblist_rec *rec, *rec2;
  73. char *data;
  74. /* At the start there should be no records */
  75. hdr = clear_bloblist();
  76. ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
  77. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  78. /* Add a record and check that we can find it */
  79. data = bloblist_add(TEST_TAG, TEST_SIZE);
  80. rec = (void *)(hdr + 1);
  81. ut_asserteq_ptr(rec + 1, data);
  82. data = bloblist_find(TEST_TAG, TEST_SIZE);
  83. ut_asserteq_ptr(rec + 1, data);
  84. /* Check the data is zeroed */
  85. ut_assertok(check_zero(data, TEST_SIZE));
  86. /* Check the 'ensure' method */
  87. ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
  88. ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
  89. rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
  90. ut_assertok(check_zero(data, TEST_SIZE));
  91. /* Check for a non-existent record */
  92. ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
  93. ut_asserteq_ptr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
  94. ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
  95. return 0;
  96. }
  97. BLOBLIST_TEST(bloblist_test_blob, 0);
  98. /* Check bloblist_ensure_size_ret() */
  99. static int bloblist_test_blob_ensure(struct unit_test_state *uts)
  100. {
  101. void *data, *data2;
  102. int size;
  103. /* At the start there should be no records */
  104. clear_bloblist();
  105. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  106. /* Test with an empty bloblist */
  107. size = TEST_SIZE;
  108. ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
  109. ut_asserteq(TEST_SIZE, size);
  110. ut_assertok(check_zero(data, TEST_SIZE));
  111. /* Check that we get the same thing again */
  112. ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
  113. ut_asserteq(TEST_SIZE, size);
  114. ut_asserteq_ptr(data, data2);
  115. /* Check that the size remains the same */
  116. size = TEST_SIZE2;
  117. ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
  118. ut_asserteq(TEST_SIZE, size);
  119. /* Check running out of space */
  120. size = TEST_SIZE_LARGE;
  121. ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
  122. return 0;
  123. }
  124. BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
  125. static int bloblist_test_bad_blob(struct unit_test_state *uts)
  126. {
  127. struct bloblist_hdr *hdr;
  128. void *data;
  129. hdr = clear_bloblist();
  130. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  131. data = hdr + 1;
  132. data += sizeof(struct bloblist_rec);
  133. ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
  134. ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
  135. return 0;
  136. }
  137. BLOBLIST_TEST(bloblist_test_bad_blob, 0);
  138. static int bloblist_test_checksum(struct unit_test_state *uts)
  139. {
  140. struct bloblist_hdr *hdr;
  141. char *data, *data2;
  142. hdr = clear_bloblist();
  143. ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
  144. ut_assertok(bloblist_finish());
  145. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  146. /*
  147. * Now change things amd make sure that the checksum notices. We cannot
  148. * change the size or alloced fields, since that will crash the code.
  149. * It has to rely on these being correct.
  150. */
  151. hdr->flags--;
  152. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  153. hdr->flags++;
  154. hdr->size--;
  155. ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  156. hdr->size++;
  157. hdr->spare++;
  158. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  159. hdr->spare--;
  160. hdr->chksum++;
  161. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  162. hdr->chksum--;
  163. /* Make sure the checksum changes when we add blobs */
  164. data = bloblist_add(TEST_TAG, TEST_SIZE);
  165. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  166. data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
  167. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  168. ut_assertok(bloblist_finish());
  169. /* It should also change if we change the data */
  170. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  171. *data += 1;
  172. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  173. *data -= 1;
  174. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  175. *data2 += 1;
  176. ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  177. *data2 -= 1;
  178. /*
  179. * Changing data outside the range of valid data should not affect
  180. * the checksum.
  181. */
  182. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  183. data[TEST_SIZE]++;
  184. data2[TEST_SIZE2]++;
  185. ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
  186. return 0;
  187. }
  188. BLOBLIST_TEST(bloblist_test_checksum, 0);
  189. int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
  190. char *const argv[])
  191. {
  192. struct unit_test *tests = ll_entry_start(struct unit_test,
  193. bloblist_test);
  194. const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
  195. return cmd_ut_category("bloblist", "bloblist_test_",
  196. tests, n_ents, argc, argv);
  197. }