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