Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lib/crc16_kunit.c: add KUnit tests for crc16

Add Kunit tests for the kernel's implementation of the standard CRC-16
algorithm (<linux/crc16.h>). The test data consists of 100
randomly-generated test cases, validated against a naive CRC-16
implementation.

This test follows roughly the same logic as lib/crc32test.c, but without
the performance measurements.

Link: https://lkml.kernel.org/r/20241012-crc16-kunit-v3-1-0ca75cb58ca9@lkcamp.dev
Signed-off-by: Vinicius Peixoto <vpeixoto@lkcamp.dev>
Co-developed-by: Enzo Bertoloti <ebertoloti@lkcamp.dev>
Signed-off-by: Enzo Bertoloti <ebertoloti@lkcamp.dev>
Co-developed-by: Fabricio Gasperin <fgasperin@lkcamp.dev>
Signed-off-by: Fabricio Gasperin <fgasperin@lkcamp.dev>
Suggested-by: David Laight <David.Laight@ACULAB.COM>
Cc: Brendan Higgins <brendan.higgins@linux.dev>
Cc: David Gow <davidgow@google.com>
Cc: Rae Moar <rmoar@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Vinicius Peixoto and committed by
Andrew Morton
5d042707 a9d38bcd

+165
+9
lib/Kconfig.debug
··· 2850 2850 on the copy_to/from_user infrastructure, making sure basic 2851 2851 user/kernel boundary testing is working. 2852 2852 2853 + config CRC16_KUNIT_TEST 2854 + tristate "KUnit tests for CRC16" 2855 + depends on KUNIT 2856 + default KUNIT_ALL_TESTS 2857 + select CRC16 2858 + help 2859 + Enable this option to run unit tests for the kernel's CRC16 2860 + implementation (<linux/crc16.h>). 2861 + 2853 2862 config TEST_UDELAY 2854 2863 tristate "udelay test driver" 2855 2864 help
+1
lib/Makefile
··· 389 389 obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o 390 390 obj-$(CONFIG_SIPHASH_KUNIT_TEST) += siphash_kunit.o 391 391 obj-$(CONFIG_USERCOPY_KUNIT_TEST) += usercopy_kunit.o 392 + obj-$(CONFIG_CRC16_KUNIT_TEST) += crc16_kunit.o 392 393 393 394 obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o 394 395
+155
lib/crc16_kunit.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * KUnits tests for CRC16. 4 + * 5 + * Copyright (C) 2024, LKCAMP 6 + * Author: Vinicius Peixoto <vpeixoto@lkcamp.dev> 7 + * Author: Fabricio Gasperin <fgasperin@lkcamp.dev> 8 + * Author: Enzo Bertoloti <ebertoloti@lkcamp.dev> 9 + */ 10 + #include <kunit/test.h> 11 + #include <linux/crc16.h> 12 + #include <linux/prandom.h> 13 + 14 + #define CRC16_KUNIT_DATA_SIZE 4096 15 + #define CRC16_KUNIT_TEST_SIZE 100 16 + #define CRC16_KUNIT_SEED 0x12345678 17 + 18 + /** 19 + * struct crc16_test - CRC16 test data 20 + * @crc: initial input value to CRC16 21 + * @start: Start index within the data buffer 22 + * @length: Length of the data 23 + */ 24 + static struct crc16_test { 25 + u16 crc; 26 + u16 start; 27 + u16 length; 28 + } tests[CRC16_KUNIT_TEST_SIZE]; 29 + 30 + u8 data[CRC16_KUNIT_DATA_SIZE]; 31 + 32 + 33 + /* Naive implementation of CRC16 for validation purposes */ 34 + static inline u16 _crc16_naive_byte(u16 crc, u8 data) 35 + { 36 + u8 i = 0; 37 + 38 + crc ^= (u16) data; 39 + for (i = 0; i < 8; i++) { 40 + if (crc & 0x01) 41 + crc = (crc >> 1) ^ 0xa001; 42 + else 43 + crc = crc >> 1; 44 + } 45 + 46 + return crc; 47 + } 48 + 49 + 50 + static inline u16 _crc16_naive(u16 crc, u8 *buffer, size_t len) 51 + { 52 + while (len--) 53 + crc = _crc16_naive_byte(crc, *buffer++); 54 + return crc; 55 + } 56 + 57 + 58 + /* Small helper for generating pseudorandom 16-bit data */ 59 + static inline u16 _rand16(void) 60 + { 61 + static u32 rand = CRC16_KUNIT_SEED; 62 + 63 + rand = next_pseudo_random32(rand); 64 + return rand & 0xFFFF; 65 + } 66 + 67 + 68 + static int crc16_init_test_data(struct kunit_suite *suite) 69 + { 70 + size_t i; 71 + 72 + /* Fill the data buffer with random bytes */ 73 + for (i = 0; i < CRC16_KUNIT_DATA_SIZE; i++) 74 + data[i] = _rand16() & 0xFF; 75 + 76 + /* Generate random test data while ensuring the random 77 + * start + length values won't overflow the 4096-byte 78 + * buffer (0x7FF * 2 = 0xFFE < 0x1000) 79 + */ 80 + for (size_t i = 0; i < CRC16_KUNIT_TEST_SIZE; i++) { 81 + tests[i].crc = _rand16(); 82 + tests[i].start = _rand16() & 0x7FF; 83 + tests[i].length = _rand16() & 0x7FF; 84 + } 85 + 86 + return 0; 87 + } 88 + 89 + static void crc16_test_empty(struct kunit *test) 90 + { 91 + u16 crc; 92 + 93 + /* The result for empty data should be the same as the 94 + * initial crc 95 + */ 96 + crc = crc16(0x00, data, 0); 97 + KUNIT_EXPECT_EQ(test, crc, 0); 98 + crc = crc16(0xFF, data, 0); 99 + KUNIT_EXPECT_EQ(test, crc, 0xFF); 100 + } 101 + 102 + static void crc16_test_correctness(struct kunit *test) 103 + { 104 + size_t i; 105 + u16 crc, crc_naive; 106 + 107 + for (i = 0; i < CRC16_KUNIT_TEST_SIZE; i++) { 108 + /* Compare results with the naive crc16 implementation */ 109 + crc = crc16(tests[i].crc, data + tests[i].start, 110 + tests[i].length); 111 + crc_naive = _crc16_naive(tests[i].crc, data + tests[i].start, 112 + tests[i].length); 113 + KUNIT_EXPECT_EQ(test, crc, crc_naive); 114 + } 115 + } 116 + 117 + 118 + static void crc16_test_combine(struct kunit *test) 119 + { 120 + size_t i, j; 121 + u16 crc, crc_naive; 122 + 123 + /* Make sure that combining two consecutive crc16 calculations 124 + * yields the same result as calculating the crc16 for the whole thing 125 + */ 126 + for (i = 0; i < CRC16_KUNIT_TEST_SIZE; i++) { 127 + crc_naive = crc16(tests[i].crc, data + tests[i].start, tests[i].length); 128 + for (j = 0; j < tests[i].length; j++) { 129 + crc = crc16(tests[i].crc, data + tests[i].start, j); 130 + crc = crc16(crc, data + tests[i].start + j, tests[i].length - j); 131 + KUNIT_EXPECT_EQ(test, crc, crc_naive); 132 + } 133 + } 134 + } 135 + 136 + 137 + static struct kunit_case crc16_test_cases[] = { 138 + KUNIT_CASE(crc16_test_empty), 139 + KUNIT_CASE(crc16_test_combine), 140 + KUNIT_CASE(crc16_test_correctness), 141 + {}, 142 + }; 143 + 144 + static struct kunit_suite crc16_test_suite = { 145 + .name = "crc16", 146 + .test_cases = crc16_test_cases, 147 + .suite_init = crc16_init_test_data, 148 + }; 149 + kunit_test_suite(crc16_test_suite); 150 + 151 + MODULE_AUTHOR("Fabricio Gasperin <fgasperin@lkcamp.dev>"); 152 + MODULE_AUTHOR("Vinicius Peixoto <vpeixoto@lkcamp.dev>"); 153 + MODULE_AUTHOR("Enzo Bertoloti <ebertoloti@lkcamp.dev>"); 154 + MODULE_DESCRIPTION("Unit tests for crc16"); 155 + MODULE_LICENSE("GPL");