File Index
Files and directories
Sign in
FILE

packing_test.c

File preview with syntax highlighting.

linux-6.19.14/lib/packing_test.c C
  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
  8struct 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
 31static 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
369KUNIT_ARRAY_PARAM_DESC(packing, cases, desc);
370
371static 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
387static 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#define PACKED_BUF_SIZE 8
400
401typedef struct __packed { u8 buf[PACKED_BUF_SIZE]; } packed_buf_t;
402
403struct test_data {
404	u32 field3;
405	u16 field2;
406	u16 field4;
407	u16 field6;
408	u8 field1;
409	u8 field5;
410};
411
412static const struct packed_field_u8 test_fields[] = {
413	PACKED_FIELD(63, 61, struct test_data, field1),
414	PACKED_FIELD(60, 52, struct test_data, field2),
415	PACKED_FIELD(51, 28, struct test_data, field3),
416	PACKED_FIELD(27, 14, struct test_data, field4),
417	PACKED_FIELD(13, 9, struct test_data, field5),
418	PACKED_FIELD(8, 0, struct test_data, field6),
419};
420
421static void packing_test_pack_fields(struct kunit *test)
422{
423	const struct test_data data = {
424		.field1 = 0x2,
425		.field2 = 0x100,
426		.field3 = 0xF00050,
427		.field4 = 0x7D3,
428		.field5 = 0x9,
429		.field6 = 0x10B,
430	};
431	packed_buf_t expect = {
432		.buf = { 0x50, 0x0F, 0x00, 0x05, 0x01, 0xF4, 0xD3, 0x0B },
433	};
434	packed_buf_t buf = {};
435
436	pack_fields(&buf, sizeof(buf), &data, test_fields, 0);
437
438	KUNIT_EXPECT_MEMEQ(test, &expect, &buf, sizeof(buf));
439}
440
441static void packing_test_unpack_fields(struct kunit *test)
442{
443	const packed_buf_t buf = {
444		.buf = { 0x17, 0x28, 0x10, 0x19, 0x3D, 0xA9, 0x07, 0x9C },
445	};
446	struct test_data data = {};
447
448	unpack_fields(&buf, sizeof(buf), &data, test_fields, 0);
449
450	KUNIT_EXPECT_EQ(test, 0, data.field1);
451	KUNIT_EXPECT_EQ(test, 0x172, data.field2);
452	KUNIT_EXPECT_EQ(test, 0x810193, data.field3);
453	KUNIT_EXPECT_EQ(test, 0x36A4, data.field4);
454	KUNIT_EXPECT_EQ(test, 0x3, data.field5);
455	KUNIT_EXPECT_EQ(test, 0x19C, data.field6);
456}
457
458static struct kunit_case packing_test_cases[] = {
459	KUNIT_CASE_PARAM(packing_test_pack, packing_gen_params),
460	KUNIT_CASE_PARAM(packing_test_unpack, packing_gen_params),
461	KUNIT_CASE(packing_test_pack_fields),
462	KUNIT_CASE(packing_test_unpack_fields),
463	{},
464};
465
466static struct kunit_suite packing_test_suite = {
467	.name = "packing",
468	.test_cases = packing_test_cases,
469};
470
471kunit_test_suite(packing_test_suite);
472
473MODULE_LICENSE("GPL");
474MODULE_DESCRIPTION("KUnit tests for packing library");
~/ Read-only file preview.