#ifndef UNITTEST_H #define UNITTEST_H #include #include #include #include #include #include #include /* to use this file elsewhere, you may want to change OUTPUT */ #include static inline void _assert_equal( int (*cmp)(const void *, const void *), void (*diff)(const void *, const void *), const void *v1, const void *v2, const char *file, const int line, const char *fname ) { if ( cmp( v1, v2 ) == 0 ) { fprintf( stderr, "%s:%d:%s() Equality assertion failed:\n", file, line, fname ); diff( v1, v2 ); exit( -1 ); } } static inline void _assert_different( int (*cmp)(const void *, const void *), void (*diff)(const void *, const void *), const void *v1, const void *v2, const char *file, const int line, const char *fname ) { if ( cmp( v1, v2 ) != 0 ) { fprintf( stderr, "%s:%d:%s() Inequality assertion failed:\n", file, line, fname ); diff( v1, v2 ); exit( -1 ); } } #define assert_equal( cmp, diff, type, v1, v2 ) \ ({\ sametype( (v1), (v2) ); \ typecheck( type, (v1) ); \ __typeof__(v1) _v1 = (v1); \ __typeof__(v2) _v2 = (v2); \ _assert_equal( (cmp), (diff), (void*)(&_v1), (void*)(&_v2), \ __FILE__, __LINE__, __FUNCTION__ ); \ }) #define assert_different( cmp, diff, type, v1, v2 ) \ ({\ sametype( (v1), (v2) ); \ typecheck( type, (v1) ); \ __typeof__(v1) _v1 = (v1); \ __typeof__(v2) _v2 = (v2); \ _assert_different( (cmp), (diff), (void*)(&_v1), (void*)(&_v2), \ __FILE__, __LINE__, __FUNCTION__ ); \ }) static inline void no_diff( const void *a, const void *b ) { fprintf( stderr, "DIFF: ????????\n" ); } static inline void string_diff( const void *v1, const void *v2 ) { unsigned long i; const char *s1 = *(char**)v1; const char *s2 = *(char**)v2; if ( ( s1 == NULL ) && ( s2 != NULL ) ) { fprintf( stderr, "DIFF: first string is NULL, but the second is not\n" ); return; } if ( ( s1 != NULL ) && ( s2 == NULL ) ) { fprintf( stderr, "DIFF: first string is not NULL, but the second is\n" ); return; } for ( i = 0; ( ( s1[ i ] != '\0' ) && ( s2[ i ] != '\0' ) && ( s1[ i ] == s2[ i ] ) ); i ++ ); if ( s1[ i ] != s2[ i ] ) { unsigned long begin, end, j; fprintf( stderr, "DIFF: strings differ at position %lu\n", i ); if ( i < 20 ) begin = 0; else begin = i - 20; end = i + 20; fprintf( stderr, "DIFF: 1) \"%s", ( begin != 0 ) ? "... " : " " ); for ( j = begin; ( j < end ) && ( s1[ j ] != '\0' ); j++ ) fprintf( stderr, "%c", s1[ j ] ); fprintf( stderr, "%s\"\n", ( s1[ j ] != '\0' ) ? " ..." : "" ); fprintf( stderr, "DIFF: 2) \"%s", ( begin != 0 ) ? "... " : " " ); for ( j = begin; ( j < end ) && ( s2[ j ] != '\0' ); j++ ) fprintf( stderr, "%c", s2[ j ] ); fprintf( stderr, "%s\"\n", ( s2[ j ] != '\0' ) ? " ..." : "" ); fprintf( stderr, "DIFF: " ); for ( j = begin; j < i; j ++ ) fprintf( stderr, "-" ); fprintf( stderr, "^\n" ); } else fprintf( stderr, "DIFF: strings are equal!\n" ); } static inline int cmp_str( const void *a, const void *b ) { const char *i = *(char **)a; const char *j = *(char **)b; return strcmp( i, j ) == 0; } #define assert_equal_str( a, b ) \ assert_equal( cmp_str, string_diff, char*, (a), (b) ) #define assert_different_str( a, b ) \ assert_different( cmp_str, string_diff, char*, (a), (b) ) static inline void int_diff( const void *a, const void *b ) { int i = *(int*)a; int j = *(int*)b; fprintf( stderr, "DIFF: 1) %d\nDIFF: 2) %d\n", i, j ); } static inline int cmp_int( const void *a, const void *b ) { const int i = *(int*)a; const int j = *(int*)b; return i == j; } #define assert_equal_int( a, b ) \ assert_equal( cmp_int, int_diff, int, (a), (b) ) #define assert_different_int( a, b ) \ assert_different( cmp_int, int_diff, int, (a), (b) ) static inline void uint_diff( const void *a, const void *b ) { unsigned int i = *(unsigned int*)a; unsigned int j = *(unsigned int*)b; fprintf( stderr, "DIFF: 1) %u\nDIFF: 2) %u\n", i, j ); } static inline int cmp_uint( const void *a, const void *b ) { const unsigned int i = *(unsigned int*)a; const unsigned int j = *(unsigned int*)b; return i == j; } #define assert_equal_uint( a, b ) \ assert_equal( cmp_uint, uint_diff, unsigned int, (a), (b) ) #define assert_different_uint( a, b ) \ assert_different( cmp_uint, uint_diff, unsigned int, (a), (b) ) static inline void hex_diff( const void *a, const void *b ) { unsigned int i = *(unsigned int*)a; unsigned int j = *(unsigned int*)b; fprintf( stderr, "DIFF: 1) %x\nDIFF: 2) %x\n", i, j ); } #define assert_equal_hex( a, b ) \ assert_equal( cmp_uint, hex_diff, unsigned int, (a), (b) ) #define assert_different_hex( a, b ) \ assert_different( cmp_uint, hex_diff, unsigned int, (a), (b) ) static inline void uint8_diff( const void *a, const void *b ) { uint8_t i = *(uint8_t*)a; uint8_t j = *(uint8_t*)b; fprintf( stderr, "DIFF: 1) %u\nDIFF: 2) %u\n", i, j ); } static inline int cmp_uint8( const void *a, const void *b ) { const uint8_t i = *(uint8_t*)a; const uint8_t j = *(uint8_t*)b; return i == j; } #define assert_equal_uint8( a, b ) \ assert_equal( cmp_uint8, uint8_diff, uint8_t, (a), (b) ) #define assert_different_uint8( a, b ) \ assert_different( cmp_uint8, uint8_diff, uint8_t, (a), (b) ) static inline void hex8_diff( const void *a, const void *b ) { uint8_t i = *(uint8_t*)a; uint8_t j = *(uint8_t*)b; fprintf( stderr, "DIFF: 1) %x\nDIFF: 2) %x\n", i, j ); } #define assert_equal_hex8( a, b ) \ assert_equal( cmp_uint8, hex8_diff, uint8_t, (a), (b) ) #define assert_different_hex8( a, b ) \ assert_different( cmp_uint8, hex8_diff, uint8_t, (a), (b) ) static inline void uint16_diff( const void *a, const void *b ) { uint16_t i = *(uint16_t*)a; uint16_t j = *(uint16_t*)b; fprintf( stderr, "DIFF: 1) %u\nDIFF: 2) %u\n", i, j ); } static inline int cmp_uint16( const void *a, const void *b ) { uint16_t i = *(uint16_t*)a; uint16_t j = *(uint16_t*)b; return i == j; } #define assert_equal_uint16( a, b ) \ assert_equal( cmp_uint16, uint16_diff, uint16_t, (a), (b) ) #define assert_different_uint16( a, b ) \ assert_different( cmp_uint16, uint16_diff, uint16_t, (a), (b) ) static inline void hex16_diff( const void *a, const void *b ) { uint16_t i = *(uint16_t*)a; uint16_t j = *(uint16_t*)b; fprintf( stderr, "DIFF: 1) %x\nDIFF: 2) %x\n", i, j ); } #define assert_equal_hex16( a, b ) \ assert_equal( cmp_uint16, hex16_diff, uint16_t, (a), (b) ) #define assert_different_hex16( a, b ) \ assert_different( cmp_uint16, hex16_diff, uint16_t, (a), (b) ) static inline void uint32_diff( const void *a, const void *b ) { uint32_t i = *(uint32_t*)a; uint32_t j = *(uint32_t*)b; fprintf( stderr, "DIFF: 1) %u\nDIFF: 2) %u\n", i, j ); } static inline int cmp_uint32( const void *a, const void *b ) { uint32_t i = *(uint32_t*)a; uint32_t j = *(uint32_t*)b; return i == j; } #define assert_equal_uint32( a, b ) \ assert_equal( cmp_uint32, uint32_diff, uint32_t, (a), (b) ) #define assert_different_uint32( a, b ) \ assert_different( cmp_uint32, uint32_diff, uint32_t, (a), (b) ) static inline void hex32_diff( const void *a, const void *b ) { uint32_t i = *(uint32_t*)a; uint32_t j = *(uint32_t*)b; fprintf( stderr, "DIFF: 1) %x\nDIFF: 2) %x\n", i, j ); } #define assert_equal_hex32( a, b ) \ assert_equal( cmp_uint32, hex32_diff, uint32_t, (a), (b) ) #define assert_different_hex32( a, b ) \ assert_different( cmp_uint32, hex32_diff, uint32_t, (a), (b) ) static inline void long_diff( const void *a, const void *b ) { long i = *(long*)a; long j = *(long*)b; fprintf( stderr, "DIFF: 1) %ld\nDIFF: 2) %ld\n", i, j ); } static inline int cmp_long( const void *a, const void *b ) { long i = *(long*)a; long j = *(long*)b; return i == j; } #define assert_equal_long( a, b ) \ assert_equal( cmp_long, long_diff, long, (a), (b) ) #define assert_different_long( a, b ) \ assert_different( cmp_long, long_diff, long, (a), (b) ) static inline void ulong_diff( const void *a, const void *b ) { unsigned long i = *(unsigned long*)a; unsigned long j = *(unsigned long*)b; fprintf( stderr, "DIFF: 1) %lu\nDIFF: 2) %lu\n", i, j ); } static inline int cmp_ulong( const void *a, const void *b ) { unsigned long i = *(unsigned long*)a; unsigned long j = *(unsigned long*)b; return i == j; } #define assert_equal_ulong( a, b ) \ assert_equal( cmp_ulong, ulong_diff, unsigned long, (a), (b) ) #define assert_different_ulong( a, b ) \ assert_different( cmp_ulong, ulong_diff, unsigned long, (a), (b) ) static inline void longlong_diff( const void *a, const void *b ) { long long i = *(long long*)a; long long j = *(long long*)b; fprintf( stderr, "DIFF: 1) %lld\nDIFF: 2) %lld\n", i, j ); } static inline int cmp_longlong( const void *a, const void *b ) { long long i = *(long long*)a; long long j = *(long long*)b; return i == j; } #define assert_equal_longlong( a, b ) \ assert_equal( cmp_longlong, longlong_diff, long long, (a), (b) ) #define assert_different_longlong( a, b ) \ assert_different( cmp_longlong, longlong_diff, long long, (a), (b) ) static inline void ulonglong_diff( const void *a, const void *b ) { unsigned long long i = *(unsigned long long*)a; unsigned long long j = *(unsigned long long*)b; fprintf( stderr, "DIFF: 1) %llu\nDIFF: 2) %llu\n", i, j ); } static inline int cmp_ulonglong( const void *a, const void *b ) { unsigned long long i = *(unsigned long long*)a; unsigned long long j = *(unsigned long long*)b; return i == j; } #define assert_equal_ulonglong( a, b ) \ assert_equal( cmp_ulonglong, ulonglong_diff, unsigned long long, (a), (b) ) #define assert_different_ulonglong( a, b ) \ assert_different( cmp_ulonglong, ulonglong_diff, unsigned long long, (a),(b)) static inline void _assert_equal_double( const double a, const double b, const double threshold, const char *file, const int line, const char *fname ) { if ( ! double_is_equal( a, b, threshold ) ) { fprintf( stderr, "%s:%d:%s() Equality assertion failed:\n", file, line, fname ); fprintf( stderr, "DIFF: 1) %lf\nDIFF: 2) %lf\n", a, b ); exit( -1 ); } } #define assert_equal_double( a, b, threshold ) \ _assert_equal_double( a, b, threshold, __FILE__, __LINE__, __FUNCTION__ ) static inline void _assert_different_double( const double a, const double b, const double threshold, const char *file, const int line, const char *fname ) { if ( double_is_equal( a, b, threshold ) ) { fprintf( stderr, "%s:%d:%s() Inequality assertion failed:\n", file, line, fname ); fprintf( stderr, "DIFF: 1) %lf\nDIFF: 2) %lf\n", a, b ); exit( -1 ); } } #define assert_different_double( a, b, threshold ) \ _assert_different_double( a, b, threshold, __FILE__, __LINE__, __FUNCTION__ ) static inline void pointer_diff( const void *a, const void *b ) { int *i = *(int**)a; int *j = *(int**)b; fprintf( stderr, "DIFF: 1) %p\nDIFF: 2) %p\n", i, j ); } static inline int cmp_pointer( const void *a, const void *b ) { int *p1 = *(int**)a; int *p2 = *(int**)b; return p1 == p2; } #define assert_equal_pointer( a, b ) \ assert_equal( cmp_pointer, pointer_diff, void *, (void*)(a), (void*)(b) ) #define assert_different_pointer( a, b ) \ assert_different( cmp_pointer, pointer_diff, void *, (void*)(a), (void*)(b) ) #define assert_not_null( p ) \ assert_different( cmp_pointer, pointer_diff, void *, (void*)(p), NULL ) #define assert_null( p ) \ assert_equal( cmp_pointer, pointer_diff, void *, (void*)(p), NULL ) /* * Some programs have results hard to verify automatically, it's easier to * ask the user if the result looks ok. * * We provide this facility here. */ /** * Ask the user a Yes/No question. * * @param yn_msg the message * * @return 1 if it 'Yes', 0 if 'No' */ int ask_user_yn( const char *yn_msg ) { assert( yn_msg != NULL); printf( "%s [Y/n] ", yn_msg ); int k; do k = getchar(); while ( ( k != EOF ) && ( k != '\n' ) && ( k != '\r' ) && ( k != 'y' ) && ( k != 'Y' ) && ( k != 'n' ) && ( k != 'N' ) ); if ( ( k == EOF ) || ( k == '\n' ) || ( k == '\r' ) ) k = 'y'; printf( "%c\n", k ); return tolower( k ) == 'y'; } #endif /* UNITTEST_H */