xref: /linux/lib/tests/min_heap_kunit.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
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