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/tests/kfifo_kunit.c: add tests for the kfifo structure

Add KUnit tests for the kfifo data structure.
They test the vast majority of macros defined in the kfifo
header (include/linux/kfifo.h).

These are inspired by the existing tests for the doubly
linked list in lib/tests/list-test.c (previously at lib/list-test.c) [1].

Note that this patch depends on the patch that moves the KUnit tests on
lib/ into lib/tests/ [2].

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/list-test.c?h=v6.11-rc6
[2] https://lore.kernel.org/all/20240720181025.work.002-kees@kernel.org/

Signed-off-by: Diego Vieira <diego.daniel.professional@gmail.com>
Reviewed-by: David Gow <davidgow@google.com>
Reviewed-by: Rae Moar <rmoar@google.com>
Link: https://lore.kernel.org/r/20241202075545.3648096-5-davidgow@google.com
Signed-off-by: Kees Cook <kees@kernel.org>

authored by

Diego Vieira and committed by
Kees Cook
4d557cb4 db6fe4d6

+239
+14
lib/Kconfig.debug
··· 2691 2691 2692 2692 If unsure, say N. 2693 2693 2694 + config KFIFO_KUNIT_TEST 2695 + tristate "KUnit Test for the generic kernel FIFO implementation" if !KUNIT_ALL_TESTS 2696 + depends on KUNIT 2697 + default KUNIT_ALL_TESTS 2698 + help 2699 + This builds the generic FIFO implementation KUnit test suite. 2700 + It tests that the API and basic functionality of the kfifo type 2701 + and associated macros. 2702 + 2703 + For more information on KUnit and unit tests in general please refer 2704 + to the KUnit documentation in Documentation/dev-tools/kunit/. 2705 + 2706 + If unsure, say N. 2707 + 2694 2708 config LIST_KUNIT_TEST 2695 2709 tristate "KUnit Test for Kernel Linked-list structures" if !KUNIT_ALL_TESTS 2696 2710 depends on KUNIT
+1
lib/tests/Makefile
··· 23 23 obj-$(CONFIG_IS_SIGNED_TYPE_KUNIT_TEST) += is_signed_type_kunit.o 24 24 obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o 25 25 obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o 26 + obj-$(CONFIG_KFIFO_KUNIT_TEST) += kfifo_kunit.o 26 27 obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o 27 28 obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o 28 29 obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
+224
lib/tests/kfifo_kunit.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * KUnit test for the generic kernel FIFO implementation. 4 + * 5 + * Copyright (C) 2024 Diego Vieira <diego.daniel.professional@gmail.com> 6 + */ 7 + #include <kunit/test.h> 8 + 9 + #include <linux/kfifo.h> 10 + 11 + #define KFIFO_SIZE 32 12 + #define N_ELEMENTS 5 13 + 14 + static void kfifo_test_reset_should_clear_the_fifo(struct kunit *test) 15 + { 16 + DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE); 17 + 18 + kfifo_put(&my_fifo, 1); 19 + kfifo_put(&my_fifo, 2); 20 + kfifo_put(&my_fifo, 3); 21 + KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 3); 22 + 23 + kfifo_reset(&my_fifo); 24 + 25 + KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 0); 26 + KUNIT_EXPECT_TRUE(test, kfifo_is_empty(&my_fifo)); 27 + } 28 + 29 + static void kfifo_test_define_should_define_an_empty_fifo(struct kunit *test) 30 + { 31 + DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE); 32 + 33 + KUNIT_EXPECT_TRUE(test, kfifo_initialized(&my_fifo)); 34 + KUNIT_EXPECT_TRUE(test, kfifo_is_empty(&my_fifo)); 35 + KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 0); 36 + } 37 + 38 + static void kfifo_test_len_should_ret_n_of_stored_elements(struct kunit *test) 39 + { 40 + u8 buffer1[N_ELEMENTS]; 41 + 42 + for (int i = 0; i < N_ELEMENTS; i++) 43 + buffer1[i] = i + 1; 44 + 45 + DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE); 46 + 47 + KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 0); 48 + 49 + kfifo_in(&my_fifo, buffer1, N_ELEMENTS); 50 + KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), N_ELEMENTS); 51 + 52 + kfifo_in(&my_fifo, buffer1, N_ELEMENTS); 53 + KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), N_ELEMENTS * 2); 54 + 55 + kfifo_reset(&my_fifo); 56 + KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 0); 57 + } 58 + 59 + static void kfifo_test_put_should_insert_and_get_should_pop(struct kunit *test) 60 + { 61 + u8 out_data = 0; 62 + int processed_elements; 63 + u8 elements[] = { 3, 5, 11 }; 64 + 65 + DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE); 66 + 67 + // If the fifo is empty, get returns 0 68 + processed_elements = kfifo_get(&my_fifo, &out_data); 69 + KUNIT_EXPECT_EQ(test, processed_elements, 0); 70 + KUNIT_EXPECT_EQ(test, out_data, 0); 71 + 72 + for (int i = 0; i < 3; i++) 73 + kfifo_put(&my_fifo, elements[i]); 74 + 75 + for (int i = 0; i < 3; i++) { 76 + processed_elements = kfifo_get(&my_fifo, &out_data); 77 + KUNIT_EXPECT_EQ(test, processed_elements, 1); 78 + KUNIT_EXPECT_EQ(test, out_data, elements[i]); 79 + } 80 + } 81 + 82 + static void kfifo_test_in_should_insert_multiple_elements(struct kunit *test) 83 + { 84 + u8 in_buffer[] = { 11, 25, 65 }; 85 + u8 out_data; 86 + int processed_elements; 87 + 88 + DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE); 89 + 90 + kfifo_in(&my_fifo, in_buffer, 3); 91 + 92 + for (int i = 0; i < 3; i++) { 93 + processed_elements = kfifo_get(&my_fifo, &out_data); 94 + KUNIT_EXPECT_EQ(test, processed_elements, 1); 95 + KUNIT_EXPECT_EQ(test, out_data, in_buffer[i]); 96 + } 97 + } 98 + 99 + static void kfifo_test_out_should_pop_multiple_elements(struct kunit *test) 100 + { 101 + u8 in_buffer[] = { 11, 25, 65 }; 102 + u8 out_buffer[3]; 103 + int copied_elements; 104 + 105 + DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE); 106 + 107 + for (int i = 0; i < 3; i++) 108 + kfifo_put(&my_fifo, in_buffer[i]); 109 + 110 + copied_elements = kfifo_out(&my_fifo, out_buffer, 3); 111 + KUNIT_EXPECT_EQ(test, copied_elements, 3); 112 + 113 + for (int i = 0; i < 3; i++) 114 + KUNIT_EXPECT_EQ(test, out_buffer[i], in_buffer[i]); 115 + KUNIT_EXPECT_TRUE(test, kfifo_is_empty(&my_fifo)); 116 + } 117 + 118 + static void kfifo_test_dec_init_should_define_an_empty_fifo(struct kunit *test) 119 + { 120 + DECLARE_KFIFO(my_fifo, u8, KFIFO_SIZE); 121 + 122 + INIT_KFIFO(my_fifo); 123 + 124 + // my_fifo is a struct with an inplace buffer 125 + KUNIT_EXPECT_FALSE(test, __is_kfifo_ptr(&my_fifo)); 126 + 127 + KUNIT_EXPECT_TRUE(test, kfifo_initialized(&my_fifo)); 128 + } 129 + 130 + static void kfifo_test_define_should_equal_declare_init(struct kunit *test) 131 + { 132 + // declare a variable my_fifo of type struct kfifo of u8 133 + DECLARE_KFIFO(my_fifo1, u8, KFIFO_SIZE); 134 + // initialize the my_fifo variable 135 + INIT_KFIFO(my_fifo1); 136 + 137 + // DEFINE_KFIFO declares the variable with the initial value 138 + // essentially the same as calling DECLARE_KFIFO and INIT_KFIFO 139 + DEFINE_KFIFO(my_fifo2, u8, KFIFO_SIZE); 140 + 141 + // my_fifo1 and my_fifo2 have the same size 142 + KUNIT_EXPECT_EQ(test, sizeof(my_fifo1), sizeof(my_fifo2)); 143 + KUNIT_EXPECT_EQ(test, kfifo_initialized(&my_fifo1), 144 + kfifo_initialized(&my_fifo2)); 145 + KUNIT_EXPECT_EQ(test, kfifo_is_empty(&my_fifo1), 146 + kfifo_is_empty(&my_fifo2)); 147 + } 148 + 149 + static void kfifo_test_alloc_should_initiliaze_a_ptr_fifo(struct kunit *test) 150 + { 151 + int ret; 152 + DECLARE_KFIFO_PTR(my_fifo, u8); 153 + 154 + INIT_KFIFO(my_fifo); 155 + 156 + // kfifo_initialized returns false signaling the buffer pointer is NULL 157 + KUNIT_EXPECT_FALSE(test, kfifo_initialized(&my_fifo)); 158 + 159 + // kfifo_alloc allocates the buffer 160 + ret = kfifo_alloc(&my_fifo, KFIFO_SIZE, GFP_KERNEL); 161 + KUNIT_EXPECT_EQ_MSG(test, ret, 0, "Memory allocation should succeed"); 162 + KUNIT_EXPECT_TRUE(test, kfifo_initialized(&my_fifo)); 163 + 164 + // kfifo_free frees the buffer 165 + kfifo_free(&my_fifo); 166 + } 167 + 168 + static void kfifo_test_peek_should_not_remove_elements(struct kunit *test) 169 + { 170 + u8 out_data; 171 + int processed_elements; 172 + 173 + DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE); 174 + 175 + // If the fifo is empty, peek returns 0 176 + processed_elements = kfifo_peek(&my_fifo, &out_data); 177 + KUNIT_EXPECT_EQ(test, processed_elements, 0); 178 + 179 + kfifo_put(&my_fifo, 3); 180 + kfifo_put(&my_fifo, 5); 181 + kfifo_put(&my_fifo, 11); 182 + 183 + KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 3); 184 + 185 + processed_elements = kfifo_peek(&my_fifo, &out_data); 186 + KUNIT_EXPECT_EQ(test, processed_elements, 1); 187 + KUNIT_EXPECT_EQ(test, out_data, 3); 188 + 189 + KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 3); 190 + 191 + // Using peek doesn't remove the element 192 + // so the read element and the fifo length 193 + // remains the same 194 + processed_elements = kfifo_peek(&my_fifo, &out_data); 195 + KUNIT_EXPECT_EQ(test, processed_elements, 1); 196 + KUNIT_EXPECT_EQ(test, out_data, 3); 197 + 198 + KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 3); 199 + } 200 + 201 + static struct kunit_case kfifo_test_cases[] = { 202 + KUNIT_CASE(kfifo_test_reset_should_clear_the_fifo), 203 + KUNIT_CASE(kfifo_test_define_should_define_an_empty_fifo), 204 + KUNIT_CASE(kfifo_test_len_should_ret_n_of_stored_elements), 205 + KUNIT_CASE(kfifo_test_put_should_insert_and_get_should_pop), 206 + KUNIT_CASE(kfifo_test_in_should_insert_multiple_elements), 207 + KUNIT_CASE(kfifo_test_out_should_pop_multiple_elements), 208 + KUNIT_CASE(kfifo_test_dec_init_should_define_an_empty_fifo), 209 + KUNIT_CASE(kfifo_test_define_should_equal_declare_init), 210 + KUNIT_CASE(kfifo_test_alloc_should_initiliaze_a_ptr_fifo), 211 + KUNIT_CASE(kfifo_test_peek_should_not_remove_elements), 212 + {}, 213 + }; 214 + 215 + static struct kunit_suite kfifo_test_module = { 216 + .name = "kfifo", 217 + .test_cases = kfifo_test_cases, 218 + }; 219 + 220 + kunit_test_suites(&kfifo_test_module); 221 + 222 + MODULE_LICENSE("GPL"); 223 + MODULE_AUTHOR("Diego Vieira <diego.daniel.professional@gmail.com>"); 224 + MODULE_DESCRIPTION("KUnit test for the kernel FIFO");