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
clear_bloblist(void)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
bloblist_test_init(struct unit_test_state * uts)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
bloblist_test_blob(struct unit_test_state * uts)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
bloblist_test_bad_blob(struct unit_test_state * uts)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
bloblist_test_checksum(struct unit_test_state * uts)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
do_ut_bloblist(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])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