18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "min_heap_test: " fmt 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci/* 58c2ecf20Sopenharmony_ci * Test cases for the min max heap. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/log2.h> 98c2ecf20Sopenharmony_ci#include <linux/min_heap.h> 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/printk.h> 128c2ecf20Sopenharmony_ci#include <linux/random.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic __init bool less_than(const void *lhs, const void *rhs) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci return *(int *)lhs < *(int *)rhs; 178c2ecf20Sopenharmony_ci} 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic __init bool greater_than(const void *lhs, const void *rhs) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci return *(int *)lhs > *(int *)rhs; 228c2ecf20Sopenharmony_ci} 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic __init void swap_ints(void *lhs, void *rhs) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci int temp = *(int *)lhs; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci *(int *)lhs = *(int *)rhs; 298c2ecf20Sopenharmony_ci *(int *)rhs = temp; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic __init int pop_verify_heap(bool min_heap, 338c2ecf20Sopenharmony_ci struct min_heap *heap, 348c2ecf20Sopenharmony_ci const struct min_heap_callbacks *funcs) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci int *values = heap->data; 378c2ecf20Sopenharmony_ci int err = 0; 388c2ecf20Sopenharmony_ci int last; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci last = values[0]; 418c2ecf20Sopenharmony_ci min_heap_pop(heap, funcs); 428c2ecf20Sopenharmony_ci while (heap->nr > 0) { 438c2ecf20Sopenharmony_ci if (min_heap) { 448c2ecf20Sopenharmony_ci if (last > values[0]) { 458c2ecf20Sopenharmony_ci pr_err("error: expected %d <= %d\n", last, 468c2ecf20Sopenharmony_ci values[0]); 478c2ecf20Sopenharmony_ci err++; 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci } else { 508c2ecf20Sopenharmony_ci if (last < values[0]) { 518c2ecf20Sopenharmony_ci pr_err("error: expected %d >= %d\n", last, 528c2ecf20Sopenharmony_ci values[0]); 538c2ecf20Sopenharmony_ci err++; 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci last = values[0]; 578c2ecf20Sopenharmony_ci min_heap_pop(heap, funcs); 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci return err; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic __init int test_heapify_all(bool min_heap) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci int values[] = { 3, 1, 2, 4, 0x8000000, 0x7FFFFFF, 0, 658c2ecf20Sopenharmony_ci -3, -1, -2, -4, 0x8000000, 0x7FFFFFF }; 668c2ecf20Sopenharmony_ci struct min_heap heap = { 678c2ecf20Sopenharmony_ci .data = values, 688c2ecf20Sopenharmony_ci .nr = ARRAY_SIZE(values), 698c2ecf20Sopenharmony_ci .size = ARRAY_SIZE(values), 708c2ecf20Sopenharmony_ci }; 718c2ecf20Sopenharmony_ci struct min_heap_callbacks funcs = { 728c2ecf20Sopenharmony_ci .elem_size = sizeof(int), 738c2ecf20Sopenharmony_ci .less = min_heap ? less_than : greater_than, 748c2ecf20Sopenharmony_ci .swp = swap_ints, 758c2ecf20Sopenharmony_ci }; 768c2ecf20Sopenharmony_ci int i, err; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* Test with known set of values. */ 798c2ecf20Sopenharmony_ci min_heapify_all(&heap, &funcs); 808c2ecf20Sopenharmony_ci err = pop_verify_heap(min_heap, &heap, &funcs); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* Test with randomly generated values. */ 848c2ecf20Sopenharmony_ci heap.nr = ARRAY_SIZE(values); 858c2ecf20Sopenharmony_ci for (i = 0; i < heap.nr; i++) 868c2ecf20Sopenharmony_ci values[i] = get_random_int(); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci min_heapify_all(&heap, &funcs); 898c2ecf20Sopenharmony_ci err += pop_verify_heap(min_heap, &heap, &funcs); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci return err; 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic __init int test_heap_push(bool min_heap) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci const int data[] = { 3, 1, 2, 4, 0x80000000, 0x7FFFFFFF, 0, 978c2ecf20Sopenharmony_ci -3, -1, -2, -4, 0x80000000, 0x7FFFFFFF }; 988c2ecf20Sopenharmony_ci int values[ARRAY_SIZE(data)]; 998c2ecf20Sopenharmony_ci struct min_heap heap = { 1008c2ecf20Sopenharmony_ci .data = values, 1018c2ecf20Sopenharmony_ci .nr = 0, 1028c2ecf20Sopenharmony_ci .size = ARRAY_SIZE(values), 1038c2ecf20Sopenharmony_ci }; 1048c2ecf20Sopenharmony_ci struct min_heap_callbacks funcs = { 1058c2ecf20Sopenharmony_ci .elem_size = sizeof(int), 1068c2ecf20Sopenharmony_ci .less = min_heap ? less_than : greater_than, 1078c2ecf20Sopenharmony_ci .swp = swap_ints, 1088c2ecf20Sopenharmony_ci }; 1098c2ecf20Sopenharmony_ci int i, temp, err; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci /* Test with known set of values copied from data. */ 1128c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(data); i++) 1138c2ecf20Sopenharmony_ci min_heap_push(&heap, &data[i], &funcs); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci err = pop_verify_heap(min_heap, &heap, &funcs); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* Test with randomly generated values. */ 1188c2ecf20Sopenharmony_ci while (heap.nr < heap.size) { 1198c2ecf20Sopenharmony_ci temp = get_random_int(); 1208c2ecf20Sopenharmony_ci min_heap_push(&heap, &temp, &funcs); 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci err += pop_verify_heap(min_heap, &heap, &funcs); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return err; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic __init int test_heap_pop_push(bool min_heap) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci const int data[] = { 3, 1, 2, 4, 0x80000000, 0x7FFFFFFF, 0, 1308c2ecf20Sopenharmony_ci -3, -1, -2, -4, 0x80000000, 0x7FFFFFFF }; 1318c2ecf20Sopenharmony_ci int values[ARRAY_SIZE(data)]; 1328c2ecf20Sopenharmony_ci struct min_heap heap = { 1338c2ecf20Sopenharmony_ci .data = values, 1348c2ecf20Sopenharmony_ci .nr = 0, 1358c2ecf20Sopenharmony_ci .size = ARRAY_SIZE(values), 1368c2ecf20Sopenharmony_ci }; 1378c2ecf20Sopenharmony_ci struct min_heap_callbacks funcs = { 1388c2ecf20Sopenharmony_ci .elem_size = sizeof(int), 1398c2ecf20Sopenharmony_ci .less = min_heap ? less_than : greater_than, 1408c2ecf20Sopenharmony_ci .swp = swap_ints, 1418c2ecf20Sopenharmony_ci }; 1428c2ecf20Sopenharmony_ci int i, temp, err; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* Fill values with data to pop and replace. */ 1458c2ecf20Sopenharmony_ci temp = min_heap ? 0x80000000 : 0x7FFFFFFF; 1468c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(data); i++) 1478c2ecf20Sopenharmony_ci min_heap_push(&heap, &temp, &funcs); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* Test with known set of values copied from data. */ 1508c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(data); i++) 1518c2ecf20Sopenharmony_ci min_heap_pop_push(&heap, &data[i], &funcs); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci err = pop_verify_heap(min_heap, &heap, &funcs); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci heap.nr = 0; 1568c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(data); i++) 1578c2ecf20Sopenharmony_ci min_heap_push(&heap, &temp, &funcs); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* Test with randomly generated values. */ 1608c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(data); i++) { 1618c2ecf20Sopenharmony_ci temp = get_random_int(); 1628c2ecf20Sopenharmony_ci min_heap_pop_push(&heap, &temp, &funcs); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci err += pop_verify_heap(min_heap, &heap, &funcs); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci return err; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic int __init test_min_heap_init(void) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci int err = 0; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci err += test_heapify_all(true); 1748c2ecf20Sopenharmony_ci err += test_heapify_all(false); 1758c2ecf20Sopenharmony_ci err += test_heap_push(true); 1768c2ecf20Sopenharmony_ci err += test_heap_push(false); 1778c2ecf20Sopenharmony_ci err += test_heap_pop_push(true); 1788c2ecf20Sopenharmony_ci err += test_heap_pop_push(false); 1798c2ecf20Sopenharmony_ci if (err) { 1808c2ecf20Sopenharmony_ci pr_err("test failed with %d errors\n", err); 1818c2ecf20Sopenharmony_ci return -EINVAL; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci pr_info("test passed\n"); 1848c2ecf20Sopenharmony_ci return 0; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_cimodule_init(test_min_heap_init); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic void __exit test_min_heap_exit(void) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci /* do nothing */ 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_cimodule_exit(test_min_heap_exit); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 195