blob: bdcca0291c7127a8c2e68542eca7d9960eaf74e4 [file] [log] [blame]
Simon Glass78b0ef52018-11-15 18:43:53 -07001// 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
14DECLARE_GLOBAL_DATA_PTR;
15
16/* Declare a new compression test */
17#define BLOBLIST_TEST(_name, _flags) \
18 UNIT_TEST(_name, _flags, bloblist_test)
19
20enum {
21 TEST_TAG = 1,
22 TEST_TAG2 = 2,
23 TEST_TAG_MISSING = 3,
24
25 TEST_SIZE = 10,
26 TEST_SIZE2 = 20,
Simon Glass1e0304e2020-01-27 08:49:50 -070027 TEST_SIZE_LARGE = 0xe0,
Simon Glass78b0ef52018-11-15 18:43:53 -070028
29 TEST_ADDR = CONFIG_BLOBLIST_ADDR,
30 TEST_BLOBLIST_SIZE = 0x100,
31};
32
33static struct bloblist_hdr *clear_bloblist(void)
34{
35 struct bloblist_hdr *hdr;
36
Simon Glass3e85ea02020-01-27 08:49:52 -070037 /*
38 * Clear out any existing bloblist so we have a clean slate. Zero the
39 * header so that existing records are removed, but set everything else
40 * to 0xff for testing purposes.
41 */
Simon Glass78b0ef52018-11-15 18:43:53 -070042 hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
Simon Glass3e85ea02020-01-27 08:49:52 -070043 memset(hdr, '\xff', TEST_BLOBLIST_SIZE);
44 memset(hdr, '\0', sizeof(*hdr));
Simon Glass78b0ef52018-11-15 18:43:53 -070045
46 return hdr;
47}
48
Simon Glass3e85ea02020-01-27 08:49:52 -070049static int check_zero(void *data, int size)
50{
51 u8 *ptr;
52 int i;
53
54 for (ptr = data, i = 0; i < size; i++, ptr++) {
55 if (*ptr)
56 return -EINVAL;
57 }
58
59 return 0;
60}
61
Simon Glass78b0ef52018-11-15 18:43:53 -070062static int bloblist_test_init(struct unit_test_state *uts)
63{
64 struct bloblist_hdr *hdr;
65
66 hdr = clear_bloblist();
67 ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
68 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
69 hdr->version++;
70 ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
71 TEST_BLOBLIST_SIZE));
72
73 ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
74 ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
75 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
76
77 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
78 ut_assertok(bloblist_finish());
79 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
80 hdr->flags++;
81 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
82
83 return 1;
84}
85BLOBLIST_TEST(bloblist_test_init, 0);
86
87static int bloblist_test_blob(struct unit_test_state *uts)
88{
89 struct bloblist_hdr *hdr;
90 struct bloblist_rec *rec, *rec2;
91 char *data;
92
93 /* At the start there should be no records */
94 hdr = clear_bloblist();
95 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
96 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
97
98 /* Add a record and check that we can find it */
99 data = bloblist_add(TEST_TAG, TEST_SIZE);
100 rec = (void *)(hdr + 1);
101 ut_asserteq_ptr(rec + 1, data);
102 data = bloblist_find(TEST_TAG, TEST_SIZE);
103 ut_asserteq_ptr(rec + 1, data);
104
Simon Glass3e85ea02020-01-27 08:49:52 -0700105 /* Check the data is zeroed */
106 ut_assertok(check_zero(data, TEST_SIZE));
107
Simon Glass78b0ef52018-11-15 18:43:53 -0700108 /* Check the 'ensure' method */
109 ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
110 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
111 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
Simon Glass3e85ea02020-01-27 08:49:52 -0700112 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700113
114 /* Check for a non-existent record */
115 ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
116 ut_asserteq_ptr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
117 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
118
119 return 0;
120}
121BLOBLIST_TEST(bloblist_test_blob, 0);
122
Simon Glass1e0304e2020-01-27 08:49:50 -0700123/* Check bloblist_ensure_size_ret() */
124static int bloblist_test_blob_ensure(struct unit_test_state *uts)
125{
126 void *data, *data2;
127 int size;
128
129 /* At the start there should be no records */
130 clear_bloblist();
131 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
132
133 /* Test with an empty bloblist */
134 size = TEST_SIZE;
135 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
136 ut_asserteq(TEST_SIZE, size);
Simon Glass3e85ea02020-01-27 08:49:52 -0700137 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass1e0304e2020-01-27 08:49:50 -0700138
139 /* Check that we get the same thing again */
140 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
141 ut_asserteq(TEST_SIZE, size);
142 ut_asserteq_ptr(data, data2);
143
144 /* Check that the size remains the same */
145 size = TEST_SIZE2;
146 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
147 ut_asserteq(TEST_SIZE, size);
148
149 /* Check running out of space */
150 size = TEST_SIZE_LARGE;
151 ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
152
153 return 0;
154}
155BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
156
Simon Glass78b0ef52018-11-15 18:43:53 -0700157static int bloblist_test_bad_blob(struct unit_test_state *uts)
158{
159 struct bloblist_hdr *hdr;
160 void *data;
161
162 hdr = clear_bloblist();
163 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
164 data = hdr + 1;
165 data += sizeof(struct bloblist_rec);
166 ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
167 ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
168
169 return 0;
170}
171BLOBLIST_TEST(bloblist_test_bad_blob, 0);
172
173static int bloblist_test_checksum(struct unit_test_state *uts)
174{
175 struct bloblist_hdr *hdr;
176 char *data, *data2;
177
178 hdr = clear_bloblist();
179 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
180 ut_assertok(bloblist_finish());
181 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
182
183 /*
184 * Now change things amd make sure that the checksum notices. We cannot
185 * change the size or alloced fields, since that will crash the code.
186 * It has to rely on these being correct.
187 */
188 hdr->flags--;
189 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
190 hdr->flags++;
191
192 hdr->size--;
193 ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
194 hdr->size++;
195
196 hdr->spare++;
197 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
198 hdr->spare--;
199
200 hdr->chksum++;
201 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
202 hdr->chksum--;
203
204 /* Make sure the checksum changes when we add blobs */
205 data = bloblist_add(TEST_TAG, TEST_SIZE);
206 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
207
208 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
209 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
210 ut_assertok(bloblist_finish());
211
212 /* It should also change if we change the data */
213 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
214 *data += 1;
215 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
216 *data -= 1;
217
218 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
219 *data2 += 1;
220 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
221 *data2 -= 1;
222
223 /*
224 * Changing data outside the range of valid data should not affect
225 * the checksum.
226 */
227 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
228 data[TEST_SIZE]++;
229 data2[TEST_SIZE2]++;
230 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
231
232 return 0;
233}
234
235BLOBLIST_TEST(bloblist_test_checksum, 0);
236
237int do_ut_bloblist(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
238{
239 struct unit_test *tests = ll_entry_start(struct unit_test,
240 bloblist_test);
241 const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
242
Philippe Reynes1f99f842019-12-17 19:07:04 +0100243 return cmd_ut_category("bloblist", "bloblist_test_",
244 tests, n_ents, argc, argv);
Simon Glass78b0ef52018-11-15 18:43:53 -0700245}