2020-02-14 10:51:29 +03:00
// SPDX-License-Identifier: GPL-2.0-only
# define pr_fmt(fmt) "min_heap_test: " fmt
/*
* Test cases for the min max heap .
*/
# include <linux/log2.h>
# include <linux/min_heap.h>
# include <linux/module.h>
# include <linux/printk.h>
# include <linux/random.h>
2024-05-24 18:29:46 +03:00
DEFINE_MIN_HEAP ( int , min_heap_test ) ;
2024-05-24 18:29:50 +03:00
static __init bool less_than ( const void * lhs , const void * rhs , void __always_unused * args )
2020-02-14 10:51:29 +03:00
{
return * ( int * ) lhs < * ( int * ) rhs ;
}
2024-05-24 18:29:50 +03:00
static __init bool greater_than ( const void * lhs , const void * rhs , void __always_unused * args )
2020-02-14 10:51:29 +03:00
{
return * ( int * ) lhs > * ( int * ) rhs ;
}
2024-05-24 18:29:50 +03:00
static __init void swap_ints ( void * lhs , void * rhs , void __always_unused * args )
2020-02-14 10:51:29 +03:00
{
int temp = * ( int * ) lhs ;
* ( int * ) lhs = * ( int * ) rhs ;
* ( int * ) rhs = temp ;
}
static __init int pop_verify_heap ( bool min_heap ,
2024-05-24 18:29:46 +03:00
struct min_heap_test * heap ,
2020-02-14 10:51:29 +03:00
const struct min_heap_callbacks * funcs )
{
int * values = heap - > data ;
int err = 0 ;
int last ;
last = values [ 0 ] ;
2024-05-24 18:29:50 +03:00
min_heap_pop ( heap , funcs , NULL ) ;
2020-02-14 10:51:29 +03:00
while ( heap - > nr > 0 ) {
if ( min_heap ) {
if ( last > values [ 0 ] ) {
pr_err ( " error: expected %d <= %d \n " , last ,
values [ 0 ] ) ;
err + + ;
}
} else {
if ( last < values [ 0 ] ) {
pr_err ( " error: expected %d >= %d \n " , last ,
values [ 0 ] ) ;
err + + ;
}
}
last = values [ 0 ] ;
2024-05-24 18:29:50 +03:00
min_heap_pop ( heap , funcs , NULL ) ;
2020-02-14 10:51:29 +03:00
}
return err ;
}
static __init int test_heapify_all ( bool min_heap )
{
int values [ ] = { 3 , 1 , 2 , 4 , 0x8000000 , 0x7FFFFFF , 0 ,
- 3 , - 1 , - 2 , - 4 , 0x8000000 , 0x7FFFFFF } ;
2024-05-24 18:29:46 +03:00
struct min_heap_test heap = {
2020-02-14 10:51:29 +03:00
. data = values ,
. nr = ARRAY_SIZE ( values ) ,
. size = ARRAY_SIZE ( values ) ,
} ;
struct min_heap_callbacks funcs = {
. less = min_heap ? less_than : greater_than ,
. swp = swap_ints ,
} ;
int i , err ;
/* Test with known set of values. */
2024-05-24 18:29:50 +03:00
min_heapify_all ( & heap , & funcs , NULL ) ;
2020-02-14 10:51:29 +03:00
err = pop_verify_heap ( min_heap , & heap , & funcs ) ;
/* Test with randomly generated values. */
heap . nr = ARRAY_SIZE ( values ) ;
for ( i = 0 ; i < heap . nr ; i + + )
2022-10-05 18:43:22 +03:00
values [ i ] = get_random_u32 ( ) ;
2020-02-14 10:51:29 +03:00
2024-05-24 18:29:50 +03:00
min_heapify_all ( & heap , & funcs , NULL ) ;
2020-02-14 10:51:29 +03:00
err + = pop_verify_heap ( min_heap , & heap , & funcs ) ;
return err ;
}
static __init int test_heap_push ( bool min_heap )
{
const int data [ ] = { 3 , 1 , 2 , 4 , 0x80000000 , 0x7FFFFFFF , 0 ,
- 3 , - 1 , - 2 , - 4 , 0x80000000 , 0x7FFFFFFF } ;
int values [ ARRAY_SIZE ( data ) ] ;
2024-05-24 18:29:46 +03:00
struct min_heap_test heap = {
2020-02-14 10:51:29 +03:00
. data = values ,
. nr = 0 ,
. size = ARRAY_SIZE ( values ) ,
} ;
struct min_heap_callbacks funcs = {
. less = min_heap ? less_than : greater_than ,
. swp = swap_ints ,
} ;
int i , temp , err ;
/* Test with known set of values copied from data. */
for ( i = 0 ; i < ARRAY_SIZE ( data ) ; i + + )
2024-05-24 18:29:50 +03:00
min_heap_push ( & heap , & data [ i ] , & funcs , NULL ) ;
2020-02-14 10:51:29 +03:00
err = pop_verify_heap ( min_heap , & heap , & funcs ) ;
/* Test with randomly generated values. */
while ( heap . nr < heap . size ) {
2022-10-05 18:43:22 +03:00
temp = get_random_u32 ( ) ;
2024-05-24 18:29:50 +03:00
min_heap_push ( & heap , & temp , & funcs , NULL ) ;
2020-02-14 10:51:29 +03:00
}
err + = pop_verify_heap ( min_heap , & heap , & funcs ) ;
return err ;
}
static __init int test_heap_pop_push ( bool min_heap )
{
const int data [ ] = { 3 , 1 , 2 , 4 , 0x80000000 , 0x7FFFFFFF , 0 ,
- 3 , - 1 , - 2 , - 4 , 0x80000000 , 0x7FFFFFFF } ;
int values [ ARRAY_SIZE ( data ) ] ;
2024-05-24 18:29:46 +03:00
struct min_heap_test heap = {
2020-02-14 10:51:29 +03:00
. data = values ,
. nr = 0 ,
. size = ARRAY_SIZE ( values ) ,
} ;
struct min_heap_callbacks funcs = {
. less = min_heap ? less_than : greater_than ,
. swp = swap_ints ,
} ;
int i , temp , err ;
/* Fill values with data to pop and replace. */
temp = min_heap ? 0x80000000 : 0x7FFFFFFF ;
for ( i = 0 ; i < ARRAY_SIZE ( data ) ; i + + )
2024-05-24 18:29:50 +03:00
min_heap_push ( & heap , & temp , & funcs , NULL ) ;
2020-02-14 10:51:29 +03:00
/* Test with known set of values copied from data. */
for ( i = 0 ; i < ARRAY_SIZE ( data ) ; i + + )
2024-05-24 18:29:50 +03:00
min_heap_pop_push ( & heap , & data [ i ] , & funcs , NULL ) ;
2020-02-14 10:51:29 +03:00
err = pop_verify_heap ( min_heap , & heap , & funcs ) ;
heap . nr = 0 ;
for ( i = 0 ; i < ARRAY_SIZE ( data ) ; i + + )
2024-05-24 18:29:50 +03:00
min_heap_push ( & heap , & temp , & funcs , NULL ) ;
2020-02-14 10:51:29 +03:00
/* Test with randomly generated values. */
for ( i = 0 ; i < ARRAY_SIZE ( data ) ; i + + ) {
2022-10-05 18:43:22 +03:00
temp = get_random_u32 ( ) ;
2024-05-24 18:29:50 +03:00
min_heap_pop_push ( & heap , & temp , & funcs , NULL ) ;
2020-02-14 10:51:29 +03:00
}
err + = pop_verify_heap ( min_heap , & heap , & funcs ) ;
return err ;
}
2024-05-24 18:29:56 +03:00
static __init int test_heap_del ( bool min_heap )
{
int values [ ] = { 3 , 1 , 2 , 4 , 0x8000000 , 0x7FFFFFF , 0 ,
- 3 , - 1 , - 2 , - 4 , 0x8000000 , 0x7FFFFFF } ;
struct min_heap_test heap ;
min_heap_init ( & heap , values , ARRAY_SIZE ( values ) ) ;
heap . nr = ARRAY_SIZE ( values ) ;
struct min_heap_callbacks funcs = {
. less = min_heap ? less_than : greater_than ,
. swp = swap_ints ,
} ;
int i , err ;
/* Test with known set of values. */
min_heapify_all ( & heap , & funcs , NULL ) ;
for ( i = 0 ; i < ARRAY_SIZE ( values ) / 2 ; i + + )
min_heap_del ( & heap , get_random_u32 ( ) % heap . nr , & funcs , NULL ) ;
err = pop_verify_heap ( min_heap , & heap , & funcs ) ;
/* Test with randomly generated values. */
heap . nr = ARRAY_SIZE ( values ) ;
for ( i = 0 ; i < heap . nr ; i + + )
values [ i ] = get_random_u32 ( ) ;
min_heapify_all ( & heap , & funcs , NULL ) ;
for ( i = 0 ; i < ARRAY_SIZE ( values ) / 2 ; i + + )
min_heap_del ( & heap , get_random_u32 ( ) % heap . nr , & funcs , NULL ) ;
err + = pop_verify_heap ( min_heap , & heap , & funcs ) ;
return err ;
}
2020-02-14 10:51:29 +03:00
static int __init test_min_heap_init ( void )
{
int err = 0 ;
err + = test_heapify_all ( true ) ;
err + = test_heapify_all ( false ) ;
err + = test_heap_push ( true ) ;
err + = test_heap_push ( false ) ;
err + = test_heap_pop_push ( true ) ;
err + = test_heap_pop_push ( false ) ;
2024-05-24 18:29:56 +03:00
err + = test_heap_del ( true ) ;
err + = test_heap_del ( false ) ;
2020-02-14 10:51:29 +03:00
if ( err ) {
pr_err ( " test failed with %d errors \n " , err ) ;
return - EINVAL ;
}
pr_info ( " test passed \n " ) ;
return 0 ;
}
module_init ( test_min_heap_init ) ;
static void __exit test_min_heap_exit ( void )
{
/* do nothing */
}
module_exit ( test_min_heap_exit ) ;
2024-06-19 23:59:15 +03:00
MODULE_DESCRIPTION ( " Test cases for the min max heap " ) ;
2020-02-14 10:51:29 +03:00
MODULE_LICENSE ( " GPL " ) ;