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