Merge tag 'ti-v2020.07-rc3' of https://gitlab.denx.de/u-boot/custodians/u-boot-ti
[platform/kernel/u-boot.git] / test / bloblist.c
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         TEST_SIZE_LARGE         = 0xe0,
28
29         TEST_ADDR               = CONFIG_BLOBLIST_ADDR,
30         TEST_BLOBLIST_SIZE      = 0x100,
31 };
32
33 static struct bloblist_hdr *clear_bloblist(void)
34 {
35         struct bloblist_hdr *hdr;
36
37         /*
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          */
42         hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
43         memset(hdr, '\xff', TEST_BLOBLIST_SIZE);
44         memset(hdr, '\0', sizeof(*hdr));
45
46         return hdr;
47 }
48
49 static 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
62 static 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 }
85 BLOBLIST_TEST(bloblist_test_init, 0);
86
87 static 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
105         /* Check the data is zeroed */
106         ut_assertok(check_zero(data, TEST_SIZE));
107
108         /* 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));
112         ut_assertok(check_zero(data, TEST_SIZE));
113
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 }
121 BLOBLIST_TEST(bloblist_test_blob, 0);
122
123 /* Check bloblist_ensure_size_ret() */
124 static 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);
137         ut_assertok(check_zero(data, TEST_SIZE));
138
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 }
155 BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
156
157 static 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 }
171 BLOBLIST_TEST(bloblist_test_bad_blob, 0);
172
173 static 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
235 BLOBLIST_TEST(bloblist_test_checksum, 0);
236
237 int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
238                    char *const argv[])
239 {
240         struct unit_test *tests = ll_entry_start(struct unit_test,
241                                                  bloblist_test);
242         const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
243
244         return cmd_ut_category("bloblist", "bloblist_test_",
245                                tests, n_ents, argc, argv);
246 }