xref: /linux/lib/packing_test.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2024, Vladimir Oltean <olteanv@gmail.com>
3  * Copyright (c) 2024, Intel Corporation.
4  */
5 #include <kunit/test.h>
6 #include <linux/packing.h>
7 
8 struct packing_test_case {
9 	const char *desc;
10 	const u8 *pbuf;
11 	size_t pbuf_size;
12 	u64 uval;
13 	size_t start_bit;
14 	size_t end_bit;
15 	u8 quirks;
16 };
17 
18 #define NO_QUIRKS	0
19 
20 /**
21  * PBUF - Initialize .pbuf and .pbuf_size
22  * @array: elements of constant physical buffer
23  *
24  * Initializes the .pbuf and .pbuf_size fields of a struct packing_test_case
25  * with a constant array of the specified elements.
26  */
27 #define PBUF(array...)					\
28 	.pbuf = (const u8[]){ array },			\
29 	.pbuf_size = sizeof((const u8 []){ array })
30 
31 static const struct packing_test_case cases[] = {
32 	/* These tests pack and unpack a magic 64-bit value
33 	 * (0xcafedeadbeefcafe) at a fixed logical offset (32) within an
34 	 * otherwise zero array of 128 bits (16 bytes). They test all possible
35 	 * bit layouts of the 128 bit buffer.
36 	 */
37 	{
38 		.desc = "no quirks, 16 bytes",
39 		PBUF(0x00, 0x00, 0x00, 0x00, 0xca, 0xfe, 0xde, 0xad,
40 		     0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00),
41 		.uval = 0xcafedeadbeefcafe,
42 		.start_bit = 95,
43 		.end_bit = 32,
44 		.quirks = NO_QUIRKS,
45 	},
46 	{
47 		.desc = "lsw32 first, 16 bytes",
48 		PBUF(0x00, 0x00, 0x00, 0x00, 0xbe, 0xef, 0xca, 0xfe,
49 		     0xca, 0xfe, 0xde, 0xad, 0x00, 0x00, 0x00, 0x00),
50 		.uval = 0xcafedeadbeefcafe,
51 		.start_bit = 95,
52 		.end_bit = 32,
53 		.quirks = QUIRK_LSW32_IS_FIRST,
54 	},
55 	{
56 		.desc = "little endian words, 16 bytes",
57 		PBUF(0x00, 0x00, 0x00, 0x00, 0xad, 0xde, 0xfe, 0xca,
58 		     0xfe, 0xca, 0xef, 0xbe, 0x00, 0x00, 0x00, 0x00),
59 		.uval = 0xcafedeadbeefcafe,
60 		.start_bit = 95,
61 		.end_bit = 32,
62 		.quirks = QUIRK_LITTLE_ENDIAN,
63 	},
64 	{
65 		.desc = "lsw32 first + little endian words, 16 bytes",
66 		PBUF(0x00, 0x00, 0x00, 0x00, 0xfe, 0xca, 0xef, 0xbe,
67 		     0xad, 0xde, 0xfe, 0xca, 0x00, 0x00, 0x00, 0x00),
68 		.uval = 0xcafedeadbeefcafe,
69 		.start_bit = 95,
70 		.end_bit = 32,
71 		.quirks = QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
72 	},
73 	{
74 		.desc = "msb right, 16 bytes",
75 		PBUF(0x00, 0x00, 0x00, 0x00, 0x53, 0x7f, 0x7b, 0xb5,
76 		     0x7d, 0xf7, 0x53, 0x7f, 0x00, 0x00, 0x00, 0x00),
77 		.uval = 0xcafedeadbeefcafe,
78 		.start_bit = 95,
79 		.end_bit = 32,
80 		.quirks = QUIRK_MSB_ON_THE_RIGHT,
81 	},
82 	{
83 		.desc = "msb right + lsw32 first, 16 bytes",
84 		PBUF(0x00, 0x00, 0x00, 0x00, 0x7d, 0xf7, 0x53, 0x7f,
85 		     0x53, 0x7f, 0x7b, 0xb5, 0x00, 0x00, 0x00, 0x00),
86 		.uval = 0xcafedeadbeefcafe,
87 		.start_bit = 95,
88 		.end_bit = 32,
89 		.quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LSW32_IS_FIRST,
90 	},
91 	{
92 		.desc = "msb right + little endian words, 16 bytes",
93 		PBUF(0x00, 0x00, 0x00, 0x00, 0xb5, 0x7b, 0x7f, 0x53,
94 		     0x7f, 0x53, 0xf7, 0x7d, 0x00, 0x00, 0x00, 0x00),
95 		.uval = 0xcafedeadbeefcafe,
96 		.start_bit = 95,
97 		.end_bit = 32,
98 		.quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LITTLE_ENDIAN,
99 	},
100 	{
101 		.desc = "msb right + lsw32 first + little endian words, 16 bytes",
102 		PBUF(0x00, 0x00, 0x00, 0x00, 0x7f, 0x53, 0xf7, 0x7d,
103 		     0xb5, 0x7b, 0x7f, 0x53, 0x00, 0x00, 0x00, 0x00),
104 		.uval = 0xcafedeadbeefcafe,
105 		.start_bit = 95,
106 		.end_bit = 32,
107 		.quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
108 	},
109 	/* These tests pack and unpack a magic 64-bit value
110 	 * (0xcafedeadbeefcafe) at a fixed logical offset (32) within an
111 	 * otherwise zero array of varying size from 18 bytes to 24 bytes.
112 	 */
113 	{
114 		.desc = "no quirks, 18 bytes",
115 		PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xfe,
116 		     0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00,
117 		     0x00, 0x00),
118 		.uval = 0xcafedeadbeefcafe,
119 		.start_bit = 95,
120 		.end_bit = 32,
121 		.quirks = NO_QUIRKS,
122 	},
123 	{
124 		.desc = "no quirks, 19 bytes",
125 		PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca,
126 		     0xfe, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x00,
127 		     0x00, 0x00, 0x00),
128 		.uval = 0xcafedeadbeefcafe,
129 		.start_bit = 95,
130 		.end_bit = 32,
131 		.quirks = NO_QUIRKS,
132 	},
133 	{
134 		.desc = "no quirks, 20 bytes",
135 		PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 		     0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe,
137 		     0x00, 0x00, 0x00, 0x00),
138 		.uval = 0xcafedeadbeefcafe,
139 		.start_bit = 95,
140 		.end_bit = 32,
141 		.quirks = NO_QUIRKS,
142 	},
143 	{
144 		.desc = "no quirks, 22 bytes",
145 		PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 		     0x00, 0x00, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef,
147 		     0xca, 0xfe, 0x00, 0x00, 0x00, 0x00),
148 		.uval = 0xcafedeadbeefcafe,
149 		.start_bit = 95,
150 		.end_bit = 32,
151 		.quirks = NO_QUIRKS,
152 	},
153 	{
154 		.desc = "no quirks, 24 bytes",
155 		PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 		     0x00, 0x00, 0x00, 0x00, 0xca, 0xfe, 0xde, 0xad,
157 		     0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00),
158 		.uval = 0xcafedeadbeefcafe,
159 		.start_bit = 95,
160 		.end_bit = 32,
161 		.quirks = NO_QUIRKS,
162 	},
163 	{
164 		.desc = "lsw32 first + little endian words, 18 bytes",
165 		PBUF(0x00, 0x00, 0x00, 0x00, 0xfe, 0xca, 0xef, 0xbe,
166 		     0xad, 0xde, 0xfe, 0xca, 0x00, 0x00, 0x00, 0x00,
167 		     0x00, 0x00),
168 		.uval = 0xcafedeadbeefcafe,
169 		.start_bit = 95,
170 		.end_bit = 32,
171 		.quirks = QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
172 	},
173 	{
174 		.desc = "lsw32 first + little endian words, 19 bytes",
175 		PBUF(0x00, 0x00, 0x00, 0x00, 0xfe, 0xca, 0xef, 0xbe,
176 		     0xad, 0xde, 0xfe, 0xca, 0x00, 0x00, 0x00, 0x00,
177 		     0x00, 0x00, 0x00),
178 		.uval = 0xcafedeadbeefcafe,
179 		.start_bit = 95,
180 		.end_bit = 32,
181 		.quirks = QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
182 	},
183 	{
184 		.desc = "lsw32 first + little endian words, 20 bytes",
185 		PBUF(0x00, 0x00, 0x00, 0x00, 0xfe, 0xca, 0xef, 0xbe,
186 		     0xad, 0xde, 0xfe, 0xca, 0x00, 0x00, 0x00, 0x00,
187 		     0x00, 0x00, 0x00, 0x00),
188 		.uval = 0xcafedeadbeefcafe,
189 		.start_bit = 95,
190 		.end_bit = 32,
191 		.quirks = QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
192 	},
193 	{
194 		.desc = "lsw32 first + little endian words, 22 bytes",
195 		PBUF(0x00, 0x00, 0x00, 0x00, 0xfe, 0xca, 0xef, 0xbe,
196 		     0xad, 0xde, 0xfe, 0xca, 0x00, 0x00, 0x00, 0x00,
197 		     0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
198 		.uval = 0xcafedeadbeefcafe,
199 		.start_bit = 95,
200 		.end_bit = 32,
201 		.quirks = QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
202 	},
203 	{
204 		.desc = "lsw32 first + little endian words, 24 bytes",
205 		PBUF(0x00, 0x00, 0x00, 0x00, 0xfe, 0xca, 0xef, 0xbe,
206 		     0xad, 0xde, 0xfe, 0xca, 0x00, 0x00, 0x00, 0x00,
207 		     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
208 		.uval = 0xcafedeadbeefcafe,
209 		.start_bit = 95,
210 		.end_bit = 32,
211 		.quirks = QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
212 	},
213 	/* These tests pack and unpack a magic 64-bit value
214 	 * (0x1122334455667788) at an odd starting bit (43) within an
215 	 * otherwise zero array of 128 bits (16 bytes). They test all possible
216 	 * bit layouts of the 128 bit buffer.
217 	 */
218 	{
219 		.desc = "no quirks, 16 bytes, non-aligned",
220 		PBUF(0x00, 0x00, 0x00, 0x89, 0x11, 0x9a, 0x22, 0xab,
221 		     0x33, 0xbc, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00),
222 		.uval = 0x1122334455667788,
223 		.start_bit = 106,
224 		.end_bit = 43,
225 		.quirks = NO_QUIRKS,
226 	},
227 	{
228 		.desc = "lsw32 first, 16 bytes, non-aligned",
229 		PBUF(0x00, 0x00, 0x00, 0x00, 0x33, 0xbc, 0x40, 0x00,
230 		     0x11, 0x9a, 0x22, 0xab, 0x00, 0x00, 0x00, 0x89),
231 		.uval = 0x1122334455667788,
232 		.start_bit = 106,
233 		.end_bit = 43,
234 		.quirks = QUIRK_LSW32_IS_FIRST,
235 	},
236 	{
237 		.desc = "little endian words, 16 bytes, non-aligned",
238 		PBUF(0x89, 0x00, 0x00, 0x00, 0xab, 0x22, 0x9a, 0x11,
239 		     0x00, 0x40, 0xbc, 0x33, 0x00, 0x00, 0x00, 0x00),
240 		.uval = 0x1122334455667788,
241 		.start_bit = 106,
242 		.end_bit = 43,
243 		.quirks = QUIRK_LITTLE_ENDIAN,
244 	},
245 	{
246 		.desc = "lsw32 first + little endian words, 16 bytes, non-aligned",
247 		PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbc, 0x33,
248 		     0xab, 0x22, 0x9a, 0x11, 0x89, 0x00, 0x00, 0x00),
249 		.uval = 0x1122334455667788,
250 		.start_bit = 106,
251 		.end_bit = 43,
252 		.quirks = QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
253 	},
254 	{
255 		.desc = "msb right, 16 bytes, non-aligned",
256 		PBUF(0x00, 0x00, 0x00, 0x91, 0x88, 0x59, 0x44, 0xd5,
257 		     0xcc, 0x3d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00),
258 		.uval = 0x1122334455667788,
259 		.start_bit = 106,
260 		.end_bit = 43,
261 		.quirks = QUIRK_MSB_ON_THE_RIGHT,
262 	},
263 	{
264 		.desc = "msb right + lsw32 first, 16 bytes, non-aligned",
265 		PBUF(0x00, 0x00, 0x00, 0x00, 0xcc, 0x3d, 0x02, 0x00,
266 		     0x88, 0x59, 0x44, 0xd5, 0x00, 0x00, 0x00, 0x91),
267 		.uval = 0x1122334455667788,
268 		.start_bit = 106,
269 		.end_bit = 43,
270 		.quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LSW32_IS_FIRST,
271 	},
272 	{
273 		.desc = "msb right + little endian words, 16 bytes, non-aligned",
274 		PBUF(0x91, 0x00, 0x00, 0x00, 0xd5, 0x44, 0x59, 0x88,
275 		     0x00, 0x02, 0x3d, 0xcc, 0x00, 0x00, 0x00, 0x00),
276 		.uval = 0x1122334455667788,
277 		.start_bit = 106,
278 		.end_bit = 43,
279 		.quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LITTLE_ENDIAN,
280 	},
281 	{
282 		.desc = "msb right + lsw32 first + little endian words, 16 bytes, non-aligned",
283 		PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3d, 0xcc,
284 		     0xd5, 0x44, 0x59, 0x88, 0x91, 0x00, 0x00, 0x00),
285 		.uval = 0x1122334455667788,
286 		.start_bit = 106,
287 		.end_bit = 43,
288 		.quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
289 	},
290 	/* These tests pack and unpack a u64 with all bits set
291 	 * (0xffffffffffffffff) at an odd starting bit (43) within an
292 	 * otherwise zero array of 128 bits (16 bytes). They test all possible
293 	 * bit layouts of the 128 bit buffer.
294 	 */
295 	{
296 		.desc = "no quirks, 16 bytes, non-aligned, 0xff",
297 		PBUF(0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
298 		     0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00),
299 		.uval = 0xffffffffffffffff,
300 		.start_bit = 106,
301 		.end_bit = 43,
302 		.quirks = NO_QUIRKS,
303 	},
304 	{
305 		.desc = "lsw32 first, 16 bytes, non-aligned, 0xff",
306 		PBUF(0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x00,
307 		     0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x07, 0xff),
308 		.uval = 0xffffffffffffffff,
309 		.start_bit = 106,
310 		.end_bit = 43,
311 		.quirks = QUIRK_LSW32_IS_FIRST,
312 	},
313 	{
314 		.desc = "little endian words, 16 bytes, non-aligned, 0xff",
315 		PBUF(0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
316 		     0x00, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00),
317 		.uval = 0xffffffffffffffff,
318 		.start_bit = 106,
319 		.end_bit = 43,
320 		.quirks = QUIRK_LITTLE_ENDIAN,
321 	},
322 	{
323 		.desc = "lsw32 first + little endian words, 16 bytes, non-aligned, 0xff",
324 		PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
325 		     0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00),
326 		.uval = 0xffffffffffffffff,
327 		.start_bit = 106,
328 		.end_bit = 43,
329 		.quirks = QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
330 	},
331 	{
332 		.desc = "msb right, 16 bytes, non-aligned, 0xff",
333 		PBUF(0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff,
334 		     0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00),
335 		.uval = 0xffffffffffffffff,
336 		.start_bit = 106,
337 		.end_bit = 43,
338 		.quirks = QUIRK_MSB_ON_THE_RIGHT,
339 	},
340 	{
341 		.desc = "msb right + lsw32 first, 16 bytes, non-aligned, 0xff",
342 		PBUF(0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00,
343 		     0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xe0, 0xff),
344 		.uval = 0xffffffffffffffff,
345 		.start_bit = 106,
346 		.end_bit = 43,
347 		.quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LSW32_IS_FIRST,
348 	},
349 	{
350 		.desc = "msb right + little endian words, 16 bytes, non-aligned, 0xff",
351 		PBUF(0xff, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
352 		     0x00, 0x1f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00),
353 		.uval = 0xffffffffffffffff,
354 		.start_bit = 106,
355 		.end_bit = 43,
356 		.quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LITTLE_ENDIAN,
357 	},
358 	{
359 		.desc = "msb right + lsw32 first + little endian words, 16 bytes, non-aligned, 0xff",
360 		PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff,
361 		     0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00),
362 		.uval = 0xffffffffffffffff,
363 		.start_bit = 106,
364 		.end_bit = 43,
365 		.quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
366 	},
367 };
368 
369 KUNIT_ARRAY_PARAM_DESC(packing, cases, desc);
370 
371 static void packing_test_pack(struct kunit *test)
372 {
373 	const struct packing_test_case *params = test->param_value;
374 	u8 *pbuf;
375 	int err;
376 
377 	pbuf = kunit_kzalloc(test, params->pbuf_size, GFP_KERNEL);
378 	KUNIT_ASSERT_NOT_NULL(test, pbuf);
379 
380 	err = pack(pbuf, params->uval, params->start_bit, params->end_bit,
381 		   params->pbuf_size, params->quirks);
382 
383 	KUNIT_EXPECT_EQ_MSG(test, err, 0, "pack() returned %pe\n", ERR_PTR(err));
384 	KUNIT_EXPECT_MEMEQ(test, pbuf, params->pbuf, params->pbuf_size);
385 }
386 
387 static void packing_test_unpack(struct kunit *test)
388 {
389 	const struct packing_test_case *params = test->param_value;
390 	u64 uval;
391 	int err;
392 
393 	err = unpack(params->pbuf, &uval, params->start_bit, params->end_bit,
394 		     params->pbuf_size, params->quirks);
395 	KUNIT_EXPECT_EQ_MSG(test, err, 0, "unpack() returned %pe\n", ERR_PTR(err));
396 	KUNIT_EXPECT_EQ(test, uval, params->uval);
397 }
398 
399 static struct kunit_case packing_test_cases[] = {
400 	KUNIT_CASE_PARAM(packing_test_pack, packing_gen_params),
401 	KUNIT_CASE_PARAM(packing_test_unpack, packing_gen_params),
402 	{},
403 };
404 
405 static struct kunit_suite packing_test_suite = {
406 	.name = "packing",
407 	.test_cases = packing_test_cases,
408 };
409 
410 kunit_test_suite(packing_test_suite);
411 
412 MODULE_LICENSE("GPL");
413 MODULE_DESCRIPTION("KUnit tests for packing library");
414