2018-01-09 19:22:31 -07:00
/* SPDX-License-Identifier: GPL-2.0 */
2014-10-03 09:04:23 -06:00
/*
2020-06-22 11:16:48 -07:00
* kselftest . h : low - level kselftest framework to include from
* selftest programs . When possible , please use
* kselftest_harness . h instead .
2014-10-03 09:04:23 -06:00
*
* Copyright ( c ) 2014 Shuah Khan < shuahkh @ osg . samsung . com >
* Copyright ( c ) 2014 Samsung Electronics Co . , Ltd .
*
2020-06-22 11:16:47 -07:00
* Using this API consists of first counting how many tests your code
* has to run , and then starting up the reporting :
*
* ksft_print_header ( ) ;
* ksft_set_plan ( total_number_of_tests ) ;
*
* For each test , report any progress , debugging , etc with :
*
* ksft_print_msg ( fmt , . . . ) ;
2024-04-04 20:55:10 +05:00
* ksft_perror ( msg ) ;
2020-06-22 11:16:47 -07:00
*
* and finally report the pass / fail / skip / xfail state of the test with one of :
*
* ksft_test_result ( condition , fmt , . . . ) ;
2024-03-06 19:21:25 +00:00
* ksft_test_result_report ( result , fmt , . . . ) ;
2020-06-22 11:16:47 -07:00
* ksft_test_result_pass ( fmt , . . . ) ;
* ksft_test_result_fail ( fmt , . . . ) ;
* ksft_test_result_skip ( fmt , . . . ) ;
* ksft_test_result_xfail ( fmt , . . . ) ;
* ksft_test_result_error ( fmt , . . . ) ;
2024-02-28 16:59:14 -08:00
* ksft_test_result_code ( exit_code , test_name , fmt , . . . ) ;
2020-06-22 11:16:47 -07:00
*
* When all tests are finished , clean up and exit the program with one of :
*
2022-03-24 18:14:18 -07:00
* ksft_finished ( ) ;
2020-06-22 11:16:47 -07:00
* ksft_exit ( condition ) ;
* ksft_exit_pass ( ) ;
* ksft_exit_fail ( ) ;
*
* If the program wants to report details on why the entire program has
* failed , it can instead exit with a message ( this is usually done when
* the program is aborting before finishing all tests ) :
*
* ksft_exit_fail_msg ( fmt , . . . ) ;
2024-04-04 21:14:32 +05:00
* ksft_exit_fail_perror ( msg ) ;
2020-06-22 11:16:47 -07:00
*
2014-10-03 09:04:23 -06:00
*/
# ifndef __KSELFTEST_H
# define __KSELFTEST_H
2023-04-06 17:19:11 +01:00
# ifndef NOLIBC
2019-07-20 10:03:32 +10:00
# include <errno.h>
2014-10-03 09:04:23 -06:00
# include <stdlib.h>
# include <unistd.h>
2017-06-28 23:40:20 +09:00
# include <stdarg.h>
2023-09-28 16:38:11 +02:00
# include <string.h>
2019-01-18 17:12:14 -07:00
# include <stdio.h>
2024-04-09 15:38:03 +02:00
# include <sys/utsname.h>
2023-04-06 17:19:11 +01:00
# endif
2014-10-03 09:04:23 -06:00
2021-12-08 10:47:42 -07:00
# ifndef ARRAY_SIZE
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
# endif
2022-04-25 14:01:11 -07:00
/*
* gcc cpuid . h provides __cpuid_count ( ) since v4 .4 .
* Clang / LLVM cpuid . h provides __cpuid_count ( ) since v3 .4 .0 .
*
* Provide local define for tests needing __cpuid_count ( ) because
* selftests need to work in older environments that do not yet
* have __cpuid_count ( ) .
*/
# ifndef __cpuid_count
# define __cpuid_count(level, count, a, b, c, d) \
__asm__ __volatile__ ( " cpuid \n \t " \
: " =a " ( a ) , " =b " ( b ) , " =c " ( c ) , " =d " ( d ) \
: " 0 " ( level ) , " 2 " ( count ) )
# endif
2015-05-12 21:07:56 -07:00
/* define kselftest exit codes */
# define KSFT_PASS 0
# define KSFT_FAIL 1
# define KSFT_XFAIL 2
# define KSFT_XPASS 3
2018-05-01 16:03:28 -06:00
# define KSFT_SKIP 4
2015-05-12 21:07:56 -07:00
selftests: kselftest: Mark functions that unconditionally call exit() as __noreturn
After commit 6d029c25b71f ("selftests/timers/posix_timers: Reimplement
check_timer_distribution()"), clang warns:
tools/testing/selftests/timers/../kselftest.h:398:6: warning: variable 'major' is used uninitialized whenever '||' condition is true [-Wsometimes-uninitialized]
398 | if (uname(&info) || sscanf(info.release, "%u.%u.", &major, &minor) != 2)
| ^~~~~~~~~~~~
tools/testing/selftests/timers/../kselftest.h:401:9: note: uninitialized use occurs here
401 | return major > min_major || (major == min_major && minor >= min_minor);
| ^~~~~
tools/testing/selftests/timers/../kselftest.h:398:6: note: remove the '||' if its condition is always false
398 | if (uname(&info) || sscanf(info.release, "%u.%u.", &major, &minor) != 2)
| ^~~~~~~~~~~~~~~
tools/testing/selftests/timers/../kselftest.h:395:20: note: initialize the variable 'major' to silence this warning
395 | unsigned int major, minor;
| ^
| = 0
This is a false positive because if uname() fails, ksft_exit_fail_msg()
will be called, which unconditionally calls exit(), a noreturn function.
However, clang does not know that ksft_exit_fail_msg() will call exit() at
the point in the pipeline that the warning is emitted because inlining has
not occurred, so it assumes control flow will resume normally after
ksft_exit_fail_msg() is called.
Make it clear to clang that all of the functions that call exit()
unconditionally in kselftest.h are noreturn transitively by marking them
explicitly with '__attribute__((__noreturn__))', which clears up the
warning above and any future warnings that may appear for the same reason.
Fixes: 6d029c25b71f ("selftests/timers/posix_timers: Reimplement check_timer_distribution()")
Reported-by: John Stultz <jstultz@google.com>
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Shuah Khan <skhan@linuxfoundation.org>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20240411-mark-kselftest-exit-funcs-noreturn-v1-1-b027c948f586@kernel.org
Closes: https://lore.kernel.org/all/20240410232637.4135564-2-jstultz@google.com/
2024-04-11 11:45:40 -07:00
# ifndef __noreturn
# define __noreturn __attribute__((__noreturn__))
# endif
2023-10-13 13:36:25 +02:00
# define __printf(a, b) __attribute__((format(printf, a, b)))
2014-10-03 09:04:23 -06:00
/* counters */
struct ksft_count {
unsigned int ksft_pass ;
unsigned int ksft_fail ;
unsigned int ksft_xfail ;
unsigned int ksft_xpass ;
unsigned int ksft_xskip ;
2017-08-04 15:07:19 -06:00
unsigned int ksft_error ;
2014-10-03 09:04:23 -06:00
} ;
static struct ksft_count ksft_cnt ;
2019-04-24 16:12:37 -07:00
static unsigned int ksft_plan ;
2014-10-03 09:04:23 -06:00
2020-06-22 20:07:37 -04:00
static inline unsigned int ksft_test_num ( void )
2017-06-12 08:56:47 +02:00
{
return ksft_cnt . ksft_pass + ksft_cnt . ksft_fail +
ksft_cnt . ksft_xfail + ksft_cnt . ksft_xpass +
2017-08-04 15:07:19 -06:00
ksft_cnt . ksft_xskip + ksft_cnt . ksft_error ;
2017-06-12 08:56:47 +02:00
}
2014-10-03 09:04:23 -06:00
static inline void ksft_inc_pass_cnt ( void ) { ksft_cnt . ksft_pass + + ; }
static inline void ksft_inc_fail_cnt ( void ) { ksft_cnt . ksft_fail + + ; }
static inline void ksft_inc_xfail_cnt ( void ) { ksft_cnt . ksft_xfail + + ; }
static inline void ksft_inc_xpass_cnt ( void ) { ksft_cnt . ksft_xpass + + ; }
static inline void ksft_inc_xskip_cnt ( void ) { ksft_cnt . ksft_xskip + + ; }
2017-08-04 15:07:19 -06:00
static inline void ksft_inc_error_cnt ( void ) { ksft_cnt . ksft_error + + ; }
2014-10-03 09:04:23 -06:00
2017-07-24 13:55:18 -06:00
static inline int ksft_get_pass_cnt ( void ) { return ksft_cnt . ksft_pass ; }
static inline int ksft_get_fail_cnt ( void ) { return ksft_cnt . ksft_fail ; }
static inline int ksft_get_xfail_cnt ( void ) { return ksft_cnt . ksft_xfail ; }
static inline int ksft_get_xpass_cnt ( void ) { return ksft_cnt . ksft_xpass ; }
static inline int ksft_get_xskip_cnt ( void ) { return ksft_cnt . ksft_xskip ; }
2017-08-04 15:07:19 -06:00
static inline int ksft_get_error_cnt ( void ) { return ksft_cnt . ksft_error ; }
2017-07-24 13:55:18 -06:00
2017-06-12 08:56:47 +02:00
static inline void ksft_print_header ( void )
{
2023-07-24 09:25:15 +01:00
/*
* Force line buffering ; If stdout is not connected to a terminal , it
* will otherwise default to fully buffered , which can cause output
* duplication if there is content in the buffer when fork ( ) ing . If
* there is a crash , line buffering also means the most recent output
* line will be visible .
*/
setvbuf ( stdout , NULL , _IOLBF , 0 ) ;
2018-02-21 17:11:54 -07:00
if ( ! ( getenv ( " KSFT_TAP_LEVEL " ) ) )
printf ( " TAP version 13 \n " ) ;
2017-06-12 08:56:47 +02:00
}
2019-04-24 16:12:37 -07:00
static inline void ksft_set_plan ( unsigned int plan )
{
ksft_plan = plan ;
2023-10-16 19:08:56 -07:00
printf ( " 1..%u \n " , ksft_plan ) ;
2019-04-24 16:12:37 -07:00
}
2014-10-03 09:04:23 -06:00
static inline void ksft_print_cnts ( void )
{
2019-04-24 16:12:37 -07:00
if ( ksft_plan ! = ksft_test_num ( ) )
printf ( " # Planned tests != run tests (%u != %u) \n " ,
ksft_plan , ksft_test_num ( ) ) ;
2023-10-16 19:08:56 -07:00
printf ( " # Totals: pass:%u fail:%u xfail:%u xpass:%u skip:%u error:%u \n " ,
2017-07-24 13:55:18 -06:00
ksft_cnt . ksft_pass , ksft_cnt . ksft_fail ,
ksft_cnt . ksft_xfail , ksft_cnt . ksft_xpass ,
2017-08-04 15:07:19 -06:00
ksft_cnt . ksft_xskip , ksft_cnt . ksft_error ) ;
2017-06-12 08:56:47 +02:00
}
2023-10-13 13:36:25 +02:00
static inline __printf ( 1 , 2 ) void ksft_print_msg ( const char * msg , . . . )
2017-06-28 23:40:21 +09:00
{
2019-07-20 10:03:32 +10:00
int saved_errno = errno ;
2017-06-28 23:40:21 +09:00
va_list args ;
va_start ( args , msg ) ;
printf ( " # " ) ;
2019-07-20 10:03:32 +10:00
errno = saved_errno ;
2017-06-28 23:40:21 +09:00
vprintf ( msg , args ) ;
va_end ( args ) ;
}
2023-09-28 16:38:11 +02:00
static inline void ksft_perror ( const char * msg )
{
# ifndef NOLIBC
ksft_print_msg ( " %s: %s (%d) \n " , msg , strerror ( errno ) , errno ) ;
# else
/*
* nolibc doesn ' t provide strerror ( ) and it seems
* inappropriate to add one , just print the errno .
*/
ksft_print_msg ( " %s: %d) \n " , msg , errno ) ;
# endif
}
2023-10-13 13:36:25 +02:00
static inline __printf ( 1 , 2 ) void ksft_test_result_pass ( const char * msg , . . . )
2017-06-12 08:56:47 +02:00
{
2019-07-20 10:03:32 +10:00
int saved_errno = errno ;
2017-06-28 23:40:20 +09:00
va_list args ;
2017-06-12 08:56:47 +02:00
ksft_cnt . ksft_pass + + ;
2017-06-28 23:40:20 +09:00
va_start ( args , msg ) ;
2023-10-16 19:08:56 -07:00
printf ( " ok %u " , ksft_test_num ( ) ) ;
2019-07-20 10:03:32 +10:00
errno = saved_errno ;
2017-06-28 23:40:20 +09:00
vprintf ( msg , args ) ;
va_end ( args ) ;
2017-06-12 08:56:47 +02:00
}
2023-10-13 13:36:25 +02:00
static inline __printf ( 1 , 2 ) void ksft_test_result_fail ( const char * msg , . . . )
2017-06-12 08:56:47 +02:00
{
2019-07-20 10:03:32 +10:00
int saved_errno = errno ;
2017-06-28 23:40:20 +09:00
va_list args ;
2017-06-12 08:56:47 +02:00
ksft_cnt . ksft_fail + + ;
2017-06-28 23:40:20 +09:00
va_start ( args , msg ) ;
2023-10-16 19:08:56 -07:00
printf ( " not ok %u " , ksft_test_num ( ) ) ;
2019-07-20 10:03:32 +10:00
errno = saved_errno ;
2017-06-28 23:40:20 +09:00
vprintf ( msg , args ) ;
va_end ( args ) ;
2017-06-12 08:56:47 +02:00
}
2020-06-22 11:16:47 -07:00
/**
* ksft_test_result ( ) - Report test success based on truth of condition
*
* @ condition : if true , report test success , otherwise failure .
*/
# define ksft_test_result(condition, fmt, ...) do { \
if ( ! ! ( condition ) ) \
ksft_test_result_pass ( fmt , # # __VA_ARGS__ ) ; \
else \
ksft_test_result_fail ( fmt , # # __VA_ARGS__ ) ; \
} while ( 0 )
2023-10-13 13:36:25 +02:00
static inline __printf ( 1 , 2 ) void ksft_test_result_xfail ( const char * msg , . . . )
2020-06-22 11:16:47 -07:00
{
int saved_errno = errno ;
va_list args ;
ksft_cnt . ksft_xfail + + ;
va_start ( args , msg ) ;
2023-10-16 19:08:56 -07:00
printf ( " ok %u # XFAIL " , ksft_test_num ( ) ) ;
2020-06-22 11:16:47 -07:00
errno = saved_errno ;
vprintf ( msg , args ) ;
va_end ( args ) ;
}
2023-10-13 13:36:25 +02:00
static inline __printf ( 1 , 2 ) void ksft_test_result_skip ( const char * msg , . . . )
2017-06-12 08:56:47 +02:00
{
2019-07-20 10:03:32 +10:00
int saved_errno = errno ;
2017-06-28 23:40:20 +09:00
va_list args ;
2017-06-12 08:56:47 +02:00
ksft_cnt . ksft_xskip + + ;
2017-06-28 23:40:20 +09:00
va_start ( args , msg ) ;
2023-10-16 19:08:56 -07:00
printf ( " ok %u # SKIP " , ksft_test_num ( ) ) ;
2019-07-20 10:03:32 +10:00
errno = saved_errno ;
2017-06-28 23:40:20 +09:00
vprintf ( msg , args ) ;
va_end ( args ) ;
2014-10-03 09:04:23 -06:00
}
2020-06-22 11:16:47 -07:00
/* TODO: how does "error" differ from "fail" or "skip"? */
2023-10-13 13:36:25 +02:00
static inline __printf ( 1 , 2 ) void ksft_test_result_error ( const char * msg , . . . )
2017-08-04 15:07:19 -06:00
{
2019-07-20 10:03:32 +10:00
int saved_errno = errno ;
2017-08-04 15:07:19 -06:00
va_list args ;
ksft_cnt . ksft_error + + ;
va_start ( args , msg ) ;
2023-10-16 19:08:56 -07:00
printf ( " not ok %u # error " , ksft_test_num ( ) ) ;
2019-07-20 10:03:32 +10:00
errno = saved_errno ;
2017-08-04 15:07:19 -06:00
vprintf ( msg , args ) ;
va_end ( args ) ;
}
2024-02-28 16:59:15 -08:00
static inline __printf ( 3 , 4 )
void ksft_test_result_code ( int exit_code , const char * test_name ,
const char * msg , . . . )
2024-02-28 16:59:14 -08:00
{
const char * tap_code = " ok " ;
const char * directive = " " ;
int saved_errno = errno ;
va_list args ;
switch ( exit_code ) {
case KSFT_PASS :
ksft_cnt . ksft_pass + + ;
break ;
case KSFT_XFAIL :
directive = " # XFAIL " ;
ksft_cnt . ksft_xfail + + ;
break ;
case KSFT_XPASS :
directive = " # XPASS " ;
ksft_cnt . ksft_xpass + + ;
break ;
case KSFT_SKIP :
directive = " # SKIP " ;
ksft_cnt . ksft_xskip + + ;
break ;
case KSFT_FAIL :
default :
tap_code = " not ok " ;
ksft_cnt . ksft_fail + + ;
break ;
}
2024-02-28 16:59:16 -08:00
/* Docs seem to call for double space if directive is absent */
2024-04-16 08:10:48 -07:00
if ( ! directive [ 0 ] & & msg )
2024-02-28 16:59:16 -08:00
directive = " # " ;
2024-02-28 16:59:15 -08:00
printf ( " %s %u %s%s " , tap_code , ksft_test_num ( ) , test_name , directive ) ;
2024-02-28 16:59:14 -08:00
errno = saved_errno ;
2024-04-16 08:10:48 -07:00
if ( msg ) {
va_start ( args , msg ) ;
vprintf ( msg , args ) ;
va_end ( args ) ;
}
2024-02-28 16:59:16 -08:00
printf ( " \n " ) ;
2024-02-28 16:59:14 -08:00
}
2024-03-06 19:21:25 +00:00
/**
* ksft_test_result ( ) - Report test success based on truth of condition
*
* @ condition : if true , report test success , otherwise failure .
*/
# define ksft_test_result_report(result, fmt, ...) do { \
switch ( result ) { \
case KSFT_PASS : \
ksft_test_result_pass ( fmt , # # __VA_ARGS__ ) ; \
break ; \
case KSFT_FAIL : \
ksft_test_result_fail ( fmt , # # __VA_ARGS__ ) ; \
break ; \
case KSFT_XFAIL : \
ksft_test_result_xfail ( fmt , # # __VA_ARGS__ ) ; \
break ; \
case KSFT_SKIP : \
ksft_test_result_skip ( fmt , # # __VA_ARGS__ ) ; \
break ; \
} } while ( 0 )
2024-04-24 10:24:13 -07:00
static inline __noreturn void ksft_exit_pass ( void )
2014-10-03 09:04:23 -06:00
{
2017-06-12 08:56:47 +02:00
ksft_print_cnts ( ) ;
2015-05-12 21:07:56 -07:00
exit ( KSFT_PASS ) ;
2014-10-03 09:04:23 -06:00
}
2017-06-12 08:56:47 +02:00
2024-04-24 10:24:13 -07:00
static inline __noreturn void ksft_exit_fail ( void )
2014-10-03 09:04:23 -06:00
{
2017-06-12 08:56:47 +02:00
ksft_print_cnts ( ) ;
2015-05-12 21:07:56 -07:00
exit ( KSFT_FAIL ) ;
2014-10-03 09:04:23 -06:00
}
2017-06-12 08:56:47 +02:00
2020-06-22 11:16:47 -07:00
/**
* ksft_exit ( ) - Exit selftest based on truth of condition
*
* @ condition : if true , exit self test with success , otherwise fail .
*/
# define ksft_exit(condition) do { \
if ( ! ! ( condition ) ) \
ksft_exit_pass ( ) ; \
else \
ksft_exit_fail ( ) ; \
} while ( 0 )
2022-03-24 18:14:18 -07:00
/**
* ksft_finished ( ) - Exit selftest with success if all tests passed
*/
# define ksft_finished() \
ksft_exit ( ksft_plan = = \
ksft_cnt . ksft_pass + \
ksft_cnt . ksft_xfail + \
ksft_cnt . ksft_xskip )
2024-04-24 10:24:13 -07:00
static inline __noreturn __printf ( 1 , 2 ) void ksft_exit_fail_msg ( const char * msg , . . . )
2017-06-12 08:56:47 +02:00
{
2019-07-20 10:03:32 +10:00
int saved_errno = errno ;
2017-06-28 23:40:20 +09:00
va_list args ;
va_start ( args , msg ) ;
printf ( " Bail out! " ) ;
2019-07-20 10:03:32 +10:00
errno = saved_errno ;
2017-06-28 23:40:20 +09:00
vprintf ( msg , args ) ;
va_end ( args ) ;
2017-06-12 08:56:47 +02:00
ksft_print_cnts ( ) ;
exit ( KSFT_FAIL ) ;
}
2024-04-14 11:26:53 +05:00
static inline __noreturn void ksft_exit_fail_perror ( const char * msg )
2024-04-04 21:14:32 +05:00
{
# ifndef NOLIBC
ksft_exit_fail_msg ( " %s: %s (%d) \n " , msg , strerror ( errno ) , errno ) ;
# else
/*
* nolibc doesn ' t provide strerror ( ) and it seems
* inappropriate to add one , just print the errno .
*/
ksft_exit_fail_msg ( " %s: %d) \n " , msg , errno ) ;
# endif
}
2024-04-24 10:24:13 -07:00
static inline __noreturn void ksft_exit_xfail ( void )
2014-10-03 09:04:23 -06:00
{
2017-06-12 08:56:47 +02:00
ksft_print_cnts ( ) ;
2015-05-12 21:07:56 -07:00
exit ( KSFT_XFAIL ) ;
2014-10-03 09:04:23 -06:00
}
2017-06-12 08:56:47 +02:00
2024-04-24 10:24:13 -07:00
static inline __noreturn void ksft_exit_xpass ( void )
2014-10-03 09:04:23 -06:00
{
2017-06-12 08:56:47 +02:00
ksft_print_cnts ( ) ;
2015-05-12 21:07:56 -07:00
exit ( KSFT_XPASS ) ;
2014-10-03 09:04:23 -06:00
}
2017-06-12 08:56:47 +02:00
2024-04-24 10:24:13 -07:00
static inline __noreturn __printf ( 1 , 2 ) void ksft_exit_skip ( const char * msg , . . . )
2014-10-03 09:04:23 -06:00
{
2020-06-22 20:15:42 -04:00
int saved_errno = errno ;
va_list args ;
2017-06-28 23:40:20 +09:00
2020-06-22 20:15:42 -04:00
va_start ( args , msg ) ;
2017-06-28 23:40:20 +09:00
2020-06-22 20:15:42 -04:00
/*
* FIXME : several tests misuse ksft_exit_skip so produce
* something sensible if some tests have already been run
* or a plan has been printed . Those tests should use
* ksft_test_result_skip or ksft_exit_fail_msg instead .
*/
if ( ksft_plan | | ksft_test_num ( ) ) {
ksft_cnt . ksft_xskip + + ;
printf ( " ok %d # SKIP " , 1 + ksft_test_num ( ) ) ;
} else {
printf ( " 1..0 # SKIP " ) ;
}
if ( msg ) {
2019-07-20 10:03:32 +10:00
errno = saved_errno ;
2017-06-28 23:40:20 +09:00
vprintf ( msg , args ) ;
va_end ( args ) ;
}
2020-06-22 20:15:42 -04:00
if ( ksft_test_num ( ) )
ksft_print_cnts ( ) ;
2015-05-12 21:07:56 -07:00
exit ( KSFT_SKIP ) ;
2014-10-03 09:04:23 -06:00
}
2024-04-09 15:38:03 +02:00
static inline int ksft_min_kernel_version ( unsigned int min_major ,
unsigned int min_minor )
{
2024-04-12 14:35:36 +02:00
# ifdef NOLIBC
ksft_print_msg ( " NOLIBC: Can't check kernel version: Function not implemented \n " ) ;
return 0 ;
# else
2024-04-09 15:38:03 +02:00
unsigned int major , minor ;
struct utsname info ;
if ( uname ( & info ) | | sscanf ( info . release , " %u.%u. " , & major , & minor ) ! = 2 )
ksft_exit_fail_msg ( " Can't parse kernel version \n " ) ;
return major > min_major | | ( major = = min_major & & minor > = min_minor ) ;
2024-04-12 14:35:36 +02:00
# endif
2024-04-09 15:38:03 +02:00
}
2014-10-03 09:04:23 -06:00
# endif /* __KSELFTEST_H */