1*d30aca3eSRyota Sakamoto // SPDX-License-Identifier: GPL-2.0-only 2*d30aca3eSRyota Sakamoto /* 3*d30aca3eSRyota Sakamoto * Test cases for the min max heap. 4*d30aca3eSRyota Sakamoto */ 5*d30aca3eSRyota Sakamoto 6*d30aca3eSRyota Sakamoto #include <kunit/test.h> 7*d30aca3eSRyota Sakamoto #include <linux/min_heap.h> 8*d30aca3eSRyota Sakamoto #include <linux/module.h> 9*d30aca3eSRyota Sakamoto #include <linux/random.h> 10*d30aca3eSRyota Sakamoto 11*d30aca3eSRyota Sakamoto struct min_heap_test_case { 12*d30aca3eSRyota Sakamoto const char *str; 13*d30aca3eSRyota Sakamoto bool min_heap; 14*d30aca3eSRyota Sakamoto }; 15*d30aca3eSRyota Sakamoto 16*d30aca3eSRyota Sakamoto static struct min_heap_test_case min_heap_cases[] = { 17*d30aca3eSRyota Sakamoto { 18*d30aca3eSRyota Sakamoto .str = "min", 19*d30aca3eSRyota Sakamoto .min_heap = true, 20*d30aca3eSRyota Sakamoto }, 21*d30aca3eSRyota Sakamoto { 22*d30aca3eSRyota Sakamoto .str = "max", 23*d30aca3eSRyota Sakamoto .min_heap = false, 24*d30aca3eSRyota Sakamoto }, 25*d30aca3eSRyota Sakamoto }; 26*d30aca3eSRyota Sakamoto 27*d30aca3eSRyota Sakamoto KUNIT_ARRAY_PARAM_DESC(min_heap, min_heap_cases, str); 28*d30aca3eSRyota Sakamoto 29*d30aca3eSRyota Sakamoto DEFINE_MIN_HEAP(int, min_heap_test); 30*d30aca3eSRyota Sakamoto 31*d30aca3eSRyota Sakamoto static bool less_than(const void *lhs, const void *rhs, void __always_unused *args) 32*d30aca3eSRyota Sakamoto { 33*d30aca3eSRyota Sakamoto return *(int *)lhs < *(int *)rhs; 34*d30aca3eSRyota Sakamoto } 35*d30aca3eSRyota Sakamoto 36*d30aca3eSRyota Sakamoto static bool greater_than(const void *lhs, const void *rhs, void __always_unused *args) 37*d30aca3eSRyota Sakamoto { 38*d30aca3eSRyota Sakamoto return *(int *)lhs > *(int *)rhs; 39*d30aca3eSRyota Sakamoto } 40*d30aca3eSRyota Sakamoto 41*d30aca3eSRyota Sakamoto static void pop_verify_heap(struct kunit *test, 42*d30aca3eSRyota Sakamoto bool min_heap, 43*d30aca3eSRyota Sakamoto struct min_heap_test *heap, 44*d30aca3eSRyota Sakamoto const struct min_heap_callbacks *funcs) 45*d30aca3eSRyota Sakamoto { 46*d30aca3eSRyota Sakamoto int *values = heap->data; 47*d30aca3eSRyota Sakamoto int last; 48*d30aca3eSRyota Sakamoto 49*d30aca3eSRyota Sakamoto last = values[0]; 50*d30aca3eSRyota Sakamoto min_heap_pop_inline(heap, funcs, NULL); 51*d30aca3eSRyota Sakamoto while (heap->nr > 0) { 52*d30aca3eSRyota Sakamoto if (min_heap) 53*d30aca3eSRyota Sakamoto KUNIT_EXPECT_LE(test, last, values[0]); 54*d30aca3eSRyota Sakamoto else 55*d30aca3eSRyota Sakamoto KUNIT_EXPECT_GE(test, last, values[0]); 56*d30aca3eSRyota Sakamoto last = values[0]; 57*d30aca3eSRyota Sakamoto min_heap_pop_inline(heap, funcs, NULL); 58*d30aca3eSRyota Sakamoto } 59*d30aca3eSRyota Sakamoto } 60*d30aca3eSRyota Sakamoto 61*d30aca3eSRyota Sakamoto static void test_heapify_all(struct kunit *test) 62*d30aca3eSRyota Sakamoto { 63*d30aca3eSRyota Sakamoto const struct min_heap_test_case *params = test->param_value; 64*d30aca3eSRyota Sakamoto int values[] = { 3, 1, 2, 4, 0x8000000, 0x7FFFFFF, 0, 65*d30aca3eSRyota Sakamoto -3, -1, -2, -4, 0x8000000, 0x7FFFFFF }; 66*d30aca3eSRyota Sakamoto struct min_heap_test heap = { 67*d30aca3eSRyota Sakamoto .data = values, 68*d30aca3eSRyota Sakamoto .nr = ARRAY_SIZE(values), 69*d30aca3eSRyota Sakamoto .size = ARRAY_SIZE(values), 70*d30aca3eSRyota Sakamoto }; 71*d30aca3eSRyota Sakamoto struct min_heap_callbacks funcs = { 72*d30aca3eSRyota Sakamoto .less = params->min_heap ? less_than : greater_than, 73*d30aca3eSRyota Sakamoto .swp = NULL, 74*d30aca3eSRyota Sakamoto }; 75*d30aca3eSRyota Sakamoto int i; 76*d30aca3eSRyota Sakamoto 77*d30aca3eSRyota Sakamoto /* Test with known set of values. */ 78*d30aca3eSRyota Sakamoto min_heapify_all_inline(&heap, &funcs, NULL); 79*d30aca3eSRyota Sakamoto pop_verify_heap(test, params->min_heap, &heap, &funcs); 80*d30aca3eSRyota Sakamoto 81*d30aca3eSRyota Sakamoto /* Test with randomly generated values. */ 82*d30aca3eSRyota Sakamoto heap.nr = ARRAY_SIZE(values); 83*d30aca3eSRyota Sakamoto for (i = 0; i < heap.nr; i++) 84*d30aca3eSRyota Sakamoto values[i] = get_random_u32(); 85*d30aca3eSRyota Sakamoto 86*d30aca3eSRyota Sakamoto min_heapify_all_inline(&heap, &funcs, NULL); 87*d30aca3eSRyota Sakamoto pop_verify_heap(test, params->min_heap, &heap, &funcs); 88*d30aca3eSRyota Sakamoto } 89*d30aca3eSRyota Sakamoto 90*d30aca3eSRyota Sakamoto static void test_heap_push(struct kunit *test) 91*d30aca3eSRyota Sakamoto { 92*d30aca3eSRyota Sakamoto const struct min_heap_test_case *params = test->param_value; 93*d30aca3eSRyota Sakamoto const int data[] = { 3, 1, 2, 4, 0x80000000, 0x7FFFFFFF, 0, 94*d30aca3eSRyota Sakamoto -3, -1, -2, -4, 0x80000000, 0x7FFFFFFF }; 95*d30aca3eSRyota Sakamoto int values[ARRAY_SIZE(data)]; 96*d30aca3eSRyota Sakamoto struct min_heap_test heap = { 97*d30aca3eSRyota Sakamoto .data = values, 98*d30aca3eSRyota Sakamoto .nr = 0, 99*d30aca3eSRyota Sakamoto .size = ARRAY_SIZE(values), 100*d30aca3eSRyota Sakamoto }; 101*d30aca3eSRyota Sakamoto struct min_heap_callbacks funcs = { 102*d30aca3eSRyota Sakamoto .less = params->min_heap ? less_than : greater_than, 103*d30aca3eSRyota Sakamoto .swp = NULL, 104*d30aca3eSRyota Sakamoto }; 105*d30aca3eSRyota Sakamoto int i, temp; 106*d30aca3eSRyota Sakamoto 107*d30aca3eSRyota Sakamoto /* Test with known set of values copied from data. */ 108*d30aca3eSRyota Sakamoto for (i = 0; i < ARRAY_SIZE(data); i++) 109*d30aca3eSRyota Sakamoto min_heap_push_inline(&heap, &data[i], &funcs, NULL); 110*d30aca3eSRyota Sakamoto 111*d30aca3eSRyota Sakamoto pop_verify_heap(test, params->min_heap, &heap, &funcs); 112*d30aca3eSRyota Sakamoto 113*d30aca3eSRyota Sakamoto /* Test with randomly generated values. */ 114*d30aca3eSRyota Sakamoto while (heap.nr < heap.size) { 115*d30aca3eSRyota Sakamoto temp = get_random_u32(); 116*d30aca3eSRyota Sakamoto min_heap_push_inline(&heap, &temp, &funcs, NULL); 117*d30aca3eSRyota Sakamoto } 118*d30aca3eSRyota Sakamoto pop_verify_heap(test, params->min_heap, &heap, &funcs); 119*d30aca3eSRyota Sakamoto } 120*d30aca3eSRyota Sakamoto 121*d30aca3eSRyota Sakamoto static void test_heap_pop_push(struct kunit *test) 122*d30aca3eSRyota Sakamoto { 123*d30aca3eSRyota Sakamoto const struct min_heap_test_case *params = test->param_value; 124*d30aca3eSRyota Sakamoto const int data[] = { 3, 1, 2, 4, 0x80000000, 0x7FFFFFFF, 0, 125*d30aca3eSRyota Sakamoto -3, -1, -2, -4, 0x80000000, 0x7FFFFFFF }; 126*d30aca3eSRyota Sakamoto int values[ARRAY_SIZE(data)]; 127*d30aca3eSRyota Sakamoto struct min_heap_test heap = { 128*d30aca3eSRyota Sakamoto .data = values, 129*d30aca3eSRyota Sakamoto .nr = 0, 130*d30aca3eSRyota Sakamoto .size = ARRAY_SIZE(values), 131*d30aca3eSRyota Sakamoto }; 132*d30aca3eSRyota Sakamoto struct min_heap_callbacks funcs = { 133*d30aca3eSRyota Sakamoto .less = params->min_heap ? less_than : greater_than, 134*d30aca3eSRyota Sakamoto .swp = NULL, 135*d30aca3eSRyota Sakamoto }; 136*d30aca3eSRyota Sakamoto int i, temp; 137*d30aca3eSRyota Sakamoto 138*d30aca3eSRyota Sakamoto /* Fill values with data to pop and replace. */ 139*d30aca3eSRyota Sakamoto temp = params->min_heap ? 0x80000000 : 0x7FFFFFFF; 140*d30aca3eSRyota Sakamoto for (i = 0; i < ARRAY_SIZE(data); i++) 141*d30aca3eSRyota Sakamoto min_heap_push_inline(&heap, &temp, &funcs, NULL); 142*d30aca3eSRyota Sakamoto 143*d30aca3eSRyota Sakamoto /* Test with known set of values copied from data. */ 144*d30aca3eSRyota Sakamoto for (i = 0; i < ARRAY_SIZE(data); i++) 145*d30aca3eSRyota Sakamoto min_heap_pop_push_inline(&heap, &data[i], &funcs, NULL); 146*d30aca3eSRyota Sakamoto 147*d30aca3eSRyota Sakamoto pop_verify_heap(test, params->min_heap, &heap, &funcs); 148*d30aca3eSRyota Sakamoto 149*d30aca3eSRyota Sakamoto heap.nr = 0; 150*d30aca3eSRyota Sakamoto for (i = 0; i < ARRAY_SIZE(data); i++) 151*d30aca3eSRyota Sakamoto min_heap_push_inline(&heap, &temp, &funcs, NULL); 152*d30aca3eSRyota Sakamoto 153*d30aca3eSRyota Sakamoto /* Test with randomly generated values. */ 154*d30aca3eSRyota Sakamoto for (i = 0; i < ARRAY_SIZE(data); i++) { 155*d30aca3eSRyota Sakamoto temp = get_random_u32(); 156*d30aca3eSRyota Sakamoto min_heap_pop_push_inline(&heap, &temp, &funcs, NULL); 157*d30aca3eSRyota Sakamoto } 158*d30aca3eSRyota Sakamoto pop_verify_heap(test, params->min_heap, &heap, &funcs); 159*d30aca3eSRyota Sakamoto } 160*d30aca3eSRyota Sakamoto 161*d30aca3eSRyota Sakamoto static void test_heap_del(struct kunit *test) 162*d30aca3eSRyota Sakamoto { 163*d30aca3eSRyota Sakamoto const struct min_heap_test_case *params = test->param_value; 164*d30aca3eSRyota Sakamoto int values[] = { 3, 1, 2, 4, 0x8000000, 0x7FFFFFF, 0, 165*d30aca3eSRyota Sakamoto -3, -1, -2, -4, 0x8000000, 0x7FFFFFF }; 166*d30aca3eSRyota Sakamoto struct min_heap_test heap; 167*d30aca3eSRyota Sakamoto 168*d30aca3eSRyota Sakamoto min_heap_init_inline(&heap, values, ARRAY_SIZE(values)); 169*d30aca3eSRyota Sakamoto heap.nr = ARRAY_SIZE(values); 170*d30aca3eSRyota Sakamoto struct min_heap_callbacks funcs = { 171*d30aca3eSRyota Sakamoto .less = params->min_heap ? less_than : greater_than, 172*d30aca3eSRyota Sakamoto .swp = NULL, 173*d30aca3eSRyota Sakamoto }; 174*d30aca3eSRyota Sakamoto int i; 175*d30aca3eSRyota Sakamoto 176*d30aca3eSRyota Sakamoto /* Test with known set of values. */ 177*d30aca3eSRyota Sakamoto min_heapify_all_inline(&heap, &funcs, NULL); 178*d30aca3eSRyota Sakamoto for (i = 0; i < ARRAY_SIZE(values) / 2; i++) 179*d30aca3eSRyota Sakamoto min_heap_del_inline(&heap, get_random_u32() % heap.nr, &funcs, NULL); 180*d30aca3eSRyota Sakamoto pop_verify_heap(test, params->min_heap, &heap, &funcs); 181*d30aca3eSRyota Sakamoto 182*d30aca3eSRyota Sakamoto /* Test with randomly generated values. */ 183*d30aca3eSRyota Sakamoto heap.nr = ARRAY_SIZE(values); 184*d30aca3eSRyota Sakamoto for (i = 0; i < heap.nr; i++) 185*d30aca3eSRyota Sakamoto values[i] = get_random_u32(); 186*d30aca3eSRyota Sakamoto min_heapify_all_inline(&heap, &funcs, NULL); 187*d30aca3eSRyota Sakamoto 188*d30aca3eSRyota Sakamoto for (i = 0; i < ARRAY_SIZE(values) / 2; i++) 189*d30aca3eSRyota Sakamoto min_heap_del_inline(&heap, get_random_u32() % heap.nr, &funcs, NULL); 190*d30aca3eSRyota Sakamoto pop_verify_heap(test, params->min_heap, &heap, &funcs); 191*d30aca3eSRyota Sakamoto } 192*d30aca3eSRyota Sakamoto 193*d30aca3eSRyota Sakamoto static struct kunit_case min_heap_test_cases[] = { 194*d30aca3eSRyota Sakamoto KUNIT_CASE_PARAM(test_heapify_all, min_heap_gen_params), 195*d30aca3eSRyota Sakamoto KUNIT_CASE_PARAM(test_heap_push, min_heap_gen_params), 196*d30aca3eSRyota Sakamoto KUNIT_CASE_PARAM(test_heap_pop_push, min_heap_gen_params), 197*d30aca3eSRyota Sakamoto KUNIT_CASE_PARAM(test_heap_del, min_heap_gen_params), 198*d30aca3eSRyota Sakamoto {}, 199*d30aca3eSRyota Sakamoto }; 200*d30aca3eSRyota Sakamoto 201*d30aca3eSRyota Sakamoto static struct kunit_suite min_heap_test_suite = { 202*d30aca3eSRyota Sakamoto .name = "min_heap", 203*d30aca3eSRyota Sakamoto .test_cases = min_heap_test_cases, 204*d30aca3eSRyota Sakamoto }; 205*d30aca3eSRyota Sakamoto 206*d30aca3eSRyota Sakamoto kunit_test_suite(min_heap_test_suite); 207*d30aca3eSRyota Sakamoto 208*d30aca3eSRyota Sakamoto MODULE_DESCRIPTION("Test cases for the min max heap"); 209*d30aca3eSRyota Sakamoto MODULE_LICENSE("GPL"); 210