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"); 225