diff options
| author | Martin BaĆinka <marun1@email.cz> | 2021-05-03 12:43:54 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-03 13:43:54 +0300 |
| commit | 0c88e55fa8f132e8ac15426911d155f136078302 (patch) | |
| tree | 03fc1b22c0582bd57ae3a14095d3d9c9f949f0c9 /tests | |
| parent | 4ea8f3ff12da61a5ceba690bf1e39d9385b42880 (diff) | |
| download | libfixmath-0c88e55fa8f132e8ac15426911d155f136078302.tar.gz | |
fixed division, undefined behaviors and some improvements (#33)
* testing using ctest
* emove old testing script
* added github workflow CI
* updated CI
* added unit test for macros
* F16() and F16C() are both rounding allways, so fix16_from_dbl should as well
* added tests for strign operations, but these functions are in my opinion unreliable and tests are failing
* removed old unittests
* removed old unittests from cmake
* problem with division using gcc
* improved benchmark
* clarification of problem with division
* attempt to fix
* fixed some undefined behaviors, fixed division
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/tests.c | 38 | ||||
| -rw-r--r-- | tests/tests.cmake | 7 | ||||
| -rw-r--r-- | tests/tests.h | 33 | ||||
| -rw-r--r-- | tests/tests_basic.c | 10 | ||||
| -rw-r--r-- | tests/tests_macros.c | 100 | ||||
| -rw-r--r-- | tests/tests_macros.h | 6 | ||||
| -rw-r--r-- | tests/tests_str.c | 108 | ||||
| -rw-r--r-- | tests/tests_str.h | 6 |
8 files changed, 298 insertions, 10 deletions
diff --git a/tests/tests.c b/tests/tests.c index cef9710..d06ee26 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -1,7 +1,9 @@ #include "tests.h" #include "tests_basic.h" #include "tests_lerp.h" +#include "tests_macros.h" #include "tests_sqrt.h" +#include "tests_str.h" #include <stdio.h> const fix16_t testcases[] = { @@ -32,14 +34,41 @@ const fix16_t testcases[] = { // Tiny random numbers -171, -359, 491, 844, 158, -413, -422, -737, -575, -330, -376, 435, -311, - 116, 715, -1024, -487, 59, 724, 993 -}; + 116, 715, -1024, -487, 59, 724, 993}; unsigned stack_depth = 0; int main() { - printf("\033[1;34m\nVARIANT: \033[39m"STR2(PREFIX)"\033[0m\n"); + printf("\033[1;34m\nVARIANT: \033[39m" STR2(PREFIX) "\033[0m\n"); +#if 0 + fix16_t a = 65536; + fix16_t b = -2147483648; + fix16_t result = fix16_div(a, b); + + double fa = fix16_to_dbl(a); + double fb = fix16_to_dbl(b); + double fresult = fa / fb; + + double max = fix16_to_dbl(fix16_maximum); + double min = fix16_to_dbl(fix16_minimum); + + printf("result %i, %.20f\n", result, fix16_to_dbl(result)); + printf("fresult %i, %.20f\n", fix16_from_dbl(fresult), fresult); + + if ((fa / fb) > max || (fa / fb) < min) + { +#ifndef FIXMATH_NO_OVERFLOW + ASSERT_EQ_INT(result, fix16_overflow); +#endif + } + else + { + ASSERT_NEAR_DOUBLE(fresult, fix16_to_dbl(result), + fix16_to_dbl(fix16_eps), "%i / %i \n", a, b); + } + +#else TEST(test_abs()); TEST(test_add()); TEST(test_mul()); @@ -47,5 +76,8 @@ int main() TEST(test_sub()); TEST(test_sqrt()); TEST(test_lerp()); + TEST(test_macros()); + //TEST(test_str()); +#endif return 0; } diff --git a/tests/tests.cmake b/tests/tests.cmake index 5f6c90b..c07b69d 100644 --- a/tests/tests.cmake +++ b/tests/tests.cmake @@ -15,15 +15,22 @@ set(nn08 PREFIX=nn08 FIXMATH_NO_OVERFLOW FIXMATH_NO_ROUNDING FIXMATH_OPTIMIZE_8B enable_testing() +#-fno-sanitize-recover +set(sanitizer_opts -fsanitize=undefined) + add_custom_target(make_tests) function(create_variant name defs) add_library(libfixmath_${name} STATIC ${libfixmath-srcs}) target_compile_definitions(libfixmath_${name} PRIVATE ${defs}) + target_compile_options(libfixmath_${name} PRIVATE ${sanitizer_opts}) + target_link_options(libfixmath_${name} PRIVATE ${sanitizer_opts}) add_executable(tests_${name} ${tests-srcs}) target_link_libraries(tests_${name} PRIVATE libfixmath_${name} m) target_include_directories(tests_${name} PRIVATE ${CMAKE_SOURCE_DIR}) target_compile_definitions(tests_${name} PRIVATE ${defs}) + target_compile_options(tests_${name} PRIVATE ${sanitizer_opts}) + target_link_options(tests_${name} PRIVATE ${sanitizer_opts}) add_dependencies(make_tests tests_${name}) add_test(NAME tests_${name} COMMAND tests_${name}) endfunction() diff --git a/tests/tests.h b/tests/tests.h index 6bd8e4d..72e7801 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -5,14 +5,15 @@ #include <math.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> extern unsigned stack_depth; #define delta(a, b) (((a) >= (b)) ? (a) - (b) : (b) - (a)) #define COMMENT(x) printf("\n----" x "----\n"); -#define STR(x) #x -#define STR2(x) STR(x) +#define STR(x) #x +#define STR2(x) STR(x) #define TEST(x) \ do \ { \ @@ -71,6 +72,34 @@ extern unsigned stack_depth; } \ } while (0) +#define ASSERT_EQ_STR(a, b) \ + do \ + { \ + size_t la = strlen(a); \ + size_t lb = strlen(b); \ + if (la != lb) \ + { \ + fflush(stdout); \ + fflush(stderr); \ + fprintf(stderr, \ + "\033[31;1m FAILED:\033[22;39m%*sASSERT_EQ a: %s, b: " \ + "%s\033[0m at: %s(), " __FILE__ ":" STR2(__LINE__) "\n", \ + stack_depth, "", (a), (b), __func__); \ + return 1; \ + } \ + int res = strncmp((a), (b), la); \ + if (res != 0) \ + { \ + fflush(stdout); \ + fflush(stderr); \ + fprintf(stderr, \ + "\033[31;1m FAILED:\033[22;39m%*sASSERT_EQ a: %s, b: " \ + "%s\033[0m at: %s(), " __FILE__ ":" STR2(__LINE__) "\n", \ + stack_depth, "", (a), (b), __func__); \ + return 1; \ + } \ + } while (0) + extern const fix16_t testcases[102]; #define TESTCASES_COUNT (sizeof(testcases) / sizeof(testcases[0])) diff --git a/tests/tests_basic.c b/tests/tests_basic.c index 6037ae2..8fd3580 100644 --- a/tests/tests_basic.c +++ b/tests/tests_basic.c @@ -5,11 +5,11 @@ int test_abs_short(void) { for (unsigned i = 0; i < TESTCASES_COUNT; ++i) { - fix16_t a = testcases[i]; - double fa = fix16_to_dbl(a); - fix16_t result = fix16_abs(a); - double fresult = fabs(fa); - double min = fix16_to_dbl(fix16_minimum); + fix16_t a = testcases[i]; + double fa = fix16_to_dbl(a); + fix16_t result = fix16_abs(a); + double fresult = fabs(fa); + double min = fix16_to_dbl(fix16_minimum); if (fa <= min) { #ifndef FIXMATH_NO_OVERFLOW diff --git a/tests/tests_macros.c b/tests/tests_macros.c new file mode 100644 index 0000000..bb80c79 --- /dev/null +++ b/tests/tests_macros.c @@ -0,0 +1,100 @@ +#include "tests_macros.h" +#include "tests.h" + +#define DO_TEST(i, m) \ + do \ + { \ + ASSERT_EQ_INT(F16(i##.##m), F16C(i, m)); \ + ASSERT_EQ_INT(F16(i##.##m), fix16_from_dbl(i##.##m)); \ + } while (0) + +int test_macros() +{ + DO_TEST(1, 234); + DO_TEST(0, 0); + DO_TEST(1, 0); + DO_TEST(-1, 0); + DO_TEST(1, 5); + DO_TEST(-1, 5); + DO_TEST(000000, 00000); + DO_TEST(0, 00001); + DO_TEST(0, 00010); + DO_TEST(0, 1); + DO_TEST(0, 10001); + DO_TEST(0, 11000); + DO_TEST(25, 133); + DO_TEST(32767, 00000); + DO_TEST(32767, 00001); + DO_TEST(32767, 99999); + DO_TEST(0, 25); + DO_TEST(0, 99555); + DO_TEST(0, 99998); + DO_TEST(0, 99999); + DO_TEST(-1, 1); + DO_TEST(-25, 133); + DO_TEST(-32767, 00001); + DO_TEST(-32768, 00000); + + /* Random values */ + DO_TEST(0, 02267); + DO_TEST(1, 49887); + DO_TEST(0, 27589); + DO_TEST(0, 38393); + DO_TEST(0, 08934); + DO_TEST(0, 95820); + DO_TEST(0, 95596); + DO_TEST(72, 10642); + DO_TEST(0, 48939); + DO_TEST(3, 37797); + DO_TEST(1, 09194); + DO_TEST(0, 08605); + DO_TEST(3, 04349); + DO_TEST(3, 95401); + DO_TEST(15, 36292); + DO_TEST(56, 09242); + DO_TEST(0, 54071); + DO_TEST(27, 08953); + DO_TEST(0, 03913); + DO_TEST(1, 32707); + DO_TEST(4, 50117); + DO_TEST(0, 24990); + DO_TEST(44, 77319); + DO_TEST(2, 59139); + DO_TEST(0, 16279); + DO_TEST(17, 14712); + DO_TEST(11, 54281); + DO_TEST(0, 02768); + DO_TEST(0, 39278); + DO_TEST(0, 19369); + DO_TEST(-0, 04534); + DO_TEST(-0, 00349); + DO_TEST(-2, 30380); + DO_TEST(-0, 03061); + DO_TEST(-7, 50065); + DO_TEST(-3, 97050); + DO_TEST(-0, 43898); + DO_TEST(-3, 49876); + DO_TEST(-1, 35942); + DO_TEST(-10, 81154); + DO_TEST(-0, 26676); + DO_TEST(-9, 52134); + DO_TEST(-0, 42592); + DO_TEST(-0, 05424); + DO_TEST(-0, 62461); + DO_TEST(-0, 21562); + DO_TEST(-0, 22366); + DO_TEST(-0, 09074); + DO_TEST(-1, 29527); + DO_TEST(-4, 98427); + DO_TEST(-0, 10721); + DO_TEST(-11, 39446); + DO_TEST(-451, 53916); + DO_TEST(-0, 04279); + DO_TEST(-3, 36543); + DO_TEST(-0, 01003); + DO_TEST(-12, 08326); + DO_TEST(-1, 07143); + DO_TEST(-1, 07737); + DO_TEST(-0, 22957); + return 0; +} diff --git a/tests/tests_macros.h b/tests/tests_macros.h new file mode 100644 index 0000000..75ab0f3 --- /dev/null +++ b/tests/tests_macros.h @@ -0,0 +1,6 @@ +#ifndef TESTS_MACROS_H +#define TESTS_MACROS_H + +int test_macros(); + +#endif // TESTS_MACROS_H diff --git a/tests/tests_str.c b/tests/tests_str.c new file mode 100644 index 0000000..d893ffb --- /dev/null +++ b/tests/tests_str.c @@ -0,0 +1,108 @@ +#include "tests_str.h" +#include "tests.h" + +int test_str_to() +{ + char buf[13]; + fix16_to_str(fix16_from_dbl(1234.5678), buf, 4); + ASSERT_EQ_STR(buf, "1234.5678"); + + fix16_to_str(fix16_from_dbl(-1234.5678), buf, 4); + ASSERT_EQ_STR(buf, "-1234.5678"); + + fix16_to_str(0, buf, 0); + ASSERT_EQ_STR(buf, "0"); + + fix16_to_str(fix16_from_dbl(0.9), buf, 0); + ASSERT_EQ_STR(buf, "1"); + + fix16_to_str(1, buf, 5); + ASSERT_EQ_STR(buf, "0.00002"); + + fix16_to_str(-1, buf, 5); + ASSERT_EQ_STR(buf, "-0.00002"); + + fix16_to_str(65535, buf, 5); + ASSERT_EQ_STR(buf, "0.99998"); + + fix16_to_str(65535, buf, 4); + ASSERT_EQ_STR(buf, "1.0000"); + + fix16_to_str(fix16_maximum, buf, 5); + ASSERT_EQ_STR(buf, "32767.99998"); + + fix16_to_str(fix16_minimum, buf, 5); + ASSERT_EQ_STR(buf, "-32768.00000"); + + return 0; +} + +int test_str_from() +{ + ASSERT_EQ_INT(fix16_from_str("1234.5678"), fix16_from_dbl(1234.5678)); + ASSERT_EQ_INT(fix16_from_str("-1234.5678"), fix16_from_dbl(-1234.5678)); + ASSERT_EQ_INT(fix16_from_str(" +1234,56780 "), + fix16_from_dbl(1234.5678)); + + ASSERT_EQ_INT(fix16_from_str("0"), 0); + ASSERT_EQ_INT(fix16_from_str("1"), fix16_one); + ASSERT_EQ_INT(fix16_from_str("1.0"), fix16_one); + ASSERT_EQ_INT(fix16_from_str("1.0000000000"), fix16_one); + + ASSERT_EQ_INT(fix16_from_str("0.00002"), 1); + ASSERT_EQ_INT(fix16_from_str("0.99998"), 65535); + + ASSERT_EQ_INT(fix16_from_str("32767.99998"), fix16_maximum); + ASSERT_EQ_INT(fix16_from_str("-32768.00000"), fix16_minimum); + + return 0; +} + +int test_str_extended() +{ + + fix16_t value = fix16_minimum; + char testbuf[13]; + char goodbuf[13]; + + while (value < fix16_maximum) + { + double fvalue = fix16_to_dbl(value); + + /* Turns out we have to jump through some hoops to round + doubles perfectly for printing: + http://stackoverflow.com/questions/994764/rounding-doubles-5-sprintf + */ + fvalue = round(fvalue * 100000.) / 100000.; + + snprintf(goodbuf, 13, "%0.5f", fvalue); + fix16_to_str(value, testbuf, 5); + + if (strcmp(goodbuf, testbuf) != 0) + { + printf("Value (fix16_t)%d gave %s, should be %s\n", value, testbuf, + goodbuf); + return 1; + } + + fix16_t roundtrip = fix16_from_str(testbuf); + if (roundtrip != value) + { + printf("Roundtrip failed: (fix16_t)%d -> %s -> (fix16_t)%d\n", + value, testbuf, roundtrip); + return 1; + } + + value += 0x10001; + } + + return 0; +} + +int test_str() +{ + TEST(test_str_to()); + TEST(test_str_from()); + TEST(test_str_extended()); + return 0; +} diff --git a/tests/tests_str.h b/tests/tests_str.h new file mode 100644 index 0000000..bb072ea --- /dev/null +++ b/tests/tests_str.h @@ -0,0 +1,6 @@ +#ifndef TESTS_STR_H +#define TESTS_STR_H + +int test_str(); + +#endif // TESTS_STR_H |
