bloblist: Add a new function to add or check size
[oweals/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         /* Clear out any existing bloblist so we have a clean slate */
38         hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
39         memset(hdr, '\0', TEST_BLOBLIST_SIZE);
40
41         return hdr;
42 }
43
44 static int bloblist_test_init(struct unit_test_state *uts)
45 {
46         struct bloblist_hdr *hdr;
47
48         hdr = clear_bloblist();
49         ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
50         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
51         hdr->version++;
52         ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
53                                                      TEST_BLOBLIST_SIZE));
54
55         ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
56         ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
57         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
58
59         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
60         ut_assertok(bloblist_finish());
61         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
62         hdr->flags++;
63         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
64
65         return 1;
66 }
67 BLOBLIST_TEST(bloblist_test_init, 0);
68
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
75         /* At the start there should be no records */
76         hdr = clear_bloblist();
77         ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
78         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
79
80         /* Add a record and check that we can find it */
81         data = bloblist_add(TEST_TAG, TEST_SIZE);
82         rec = (void *)(hdr + 1);
83         ut_asserteq_ptr(rec + 1, data);
84         data = bloblist_find(TEST_TAG, TEST_SIZE);
85         ut_asserteq_ptr(rec + 1, data);
86
87         /* Check the 'ensure' method */
88         ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
89         ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
90         rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
91
92         /* Check for a non-existent record */
93         ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
94         ut_asserteq_ptr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
95         ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
96
97         return 0;
98 }
99 BLOBLIST_TEST(bloblist_test_blob, 0);
100
101 /* Check bloblist_ensure_size_ret() */
102 static int bloblist_test_blob_ensure(struct unit_test_state *uts)
103 {
104         void *data, *data2;
105         int size;
106
107         /* At the start there should be no records */
108         clear_bloblist();
109         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
110
111         /* Test with an empty bloblist */
112         size = TEST_SIZE;
113         ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
114         ut_asserteq(TEST_SIZE, size);
115
116         /* Check that we get the same thing again */
117         ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
118         ut_asserteq(TEST_SIZE, size);
119         ut_asserteq_ptr(data, data2);
120
121         /* Check that the size remains the same */
122         size = TEST_SIZE2;
123         ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
124         ut_asserteq(TEST_SIZE, size);
125
126         /* Check running out of space */
127         size = TEST_SIZE_LARGE;
128         ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
129
130         return 0;
131 }
132 BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
133
134 static int bloblist_test_bad_blob(struct unit_test_state *uts)
135 {
136         struct bloblist_hdr *hdr;
137         void *data;
138
139         hdr = clear_bloblist();
140         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
141         data = hdr + 1;
142         data += sizeof(struct bloblist_rec);
143         ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
144         ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
145
146         return 0;
147 }
148 BLOBLIST_TEST(bloblist_test_bad_blob, 0);
149
150 static int bloblist_test_checksum(struct unit_test_state *uts)
151 {
152         struct bloblist_hdr *hdr;
153         char *data, *data2;
154
155         hdr = clear_bloblist();
156         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
157         ut_assertok(bloblist_finish());
158         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
159
160         /*
161          * Now change things amd make sure that the checksum notices. We cannot
162          * change the size or alloced fields, since that will crash the code.
163          * It has to rely on these being correct.
164          */
165         hdr->flags--;
166         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
167         hdr->flags++;
168
169         hdr->size--;
170         ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
171         hdr->size++;
172
173         hdr->spare++;
174         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
175         hdr->spare--;
176
177         hdr->chksum++;
178         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
179         hdr->chksum--;
180
181         /* Make sure the checksum changes when we add blobs */
182         data = bloblist_add(TEST_TAG, TEST_SIZE);
183         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
184
185         data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
186         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
187         ut_assertok(bloblist_finish());
188
189         /* It should also change if we change the data */
190         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
191         *data += 1;
192         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
193         *data -= 1;
194
195         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
196         *data2 += 1;
197         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
198         *data2 -= 1;
199
200         /*
201          * Changing data outside the range of valid data should not affect
202          * the checksum.
203          */
204         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
205         data[TEST_SIZE]++;
206         data2[TEST_SIZE2]++;
207         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
208
209         return 0;
210 }
211
212 BLOBLIST_TEST(bloblist_test_checksum, 0);
213
214 int do_ut_bloblist(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
215 {
216         struct unit_test *tests = ll_entry_start(struct unit_test,
217                                                  bloblist_test);
218         const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
219
220         return cmd_ut_category("bloblist", "bloblist_test_",
221                                tests, n_ents, argc, argv);
222 }