From 541e5feef1ea3c02c0907d3f1ed5258ab13ee72c Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 27 Jan 2021 19:57:00 -0500 Subject: [PATCH] Adding supplemental tests. --- CMakeLists.txt | 6 ++- tests/CMakeLists.txt | 53 ++++++++++++++++++-------- tests/basictest.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 69c863d..99486dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.9) project(fast_float VERSION 0.7.0 LANGUAGES CXX) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED OFF) @@ -31,4 +31,6 @@ endif() if(FASTFLOAT_TEST) enable_testing() add_subdirectory(tests) +else(FASTFLOAT_TEST) + message(STATUS "Tests are disabled. Set FASTFLOAT_TEST to ON to run tests.") endif(FASTFLOAT_TEST) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index edba1f9..37a659e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,6 +7,11 @@ include(FetchContent) FetchContent_Declare(doctest GIT_REPOSITORY https://github.com/onqtam/doctest.git GIT_TAG 2.4.1) +FetchContent_Declare(supplemental_test_files + GIT_REPOSITORY https://github.com/fastfloat/supplemental_test_files.git + GIT_TAG origin/main) + + # FetchContent_MakeAvailable() was only introduced in 3.14 # https://cmake.org/cmake/help/v3.14/release/3.14.html#modules @@ -16,8 +21,15 @@ if(NOT doctest_POPULATED) FetchContent_Populate(doctest) add_subdirectory(${doctest_SOURCE_DIR} ${doctest_BINARY_DIR}) endif() - - +FetchContent_GetProperties(supplemental_test_files) +if(NOT supplemental_test_files_POPULATED) + message(STATUS "Tests enabled. Retrieving test files.") + FetchContent_Populate(supplemental_test_files) + message(STATUS "Test files retrieved.") + add_subdirectory(${supplemental_test_files_SOURCE_DIR} ${supplemental_test_files_BINARY_DIR}) +endif() +add_library(supplemental-data INTERFACE) +target_compile_definitions(supplemental-data INTERFACE SUPPLEMENTAL_TEST_DATA_DIR="${supplemental_test_files_BINARY_DIR}/data") function(fast_float_add_cpp_test TEST_NAME) add_executable(${TEST_NAME} ${TEST_NAME}.cpp) add_test(${TEST_NAME} ${TEST_NAME}) @@ -25,18 +37,29 @@ function(fast_float_add_cpp_test TEST_NAME) target_compile_options(${TEST_NAME} PUBLIC -Werror -Wall -Wextra -Weffc++) target_compile_options(${TEST_NAME} PUBLIC -Wsign-compare -Wshadow -Wwrite-strings -Wpointer-arith -Winit-self -Wconversion -Wsign-conversion) endif() - target_link_libraries(${TEST_NAME} PUBLIC fast_float doctest) + target_link_libraries(${TEST_NAME} PUBLIC fast_float doctest supplemental-data) + target_compile_features(${TEST_NAME} PUBLIC cxx_std_11) endfunction(fast_float_add_cpp_test) -fast_float_add_cpp_test(powersoffive_hardround) -fast_float_add_cpp_test(short_random_string) -fast_float_add_cpp_test(exhaustive32_midpoint) -fast_float_add_cpp_test(random_string) -fast_float_add_cpp_test(string_test) -fast_float_add_cpp_test(exhaustive32) -fast_float_add_cpp_test(exhaustive32_64) -fast_float_add_cpp_test(long_exhaustive32) -fast_float_add_cpp_test(long_exhaustive32_64) -fast_float_add_cpp_test(long_random64) -fast_float_add_cpp_test(random64) -fast_float_add_cpp_test(basictest) + + fast_float_add_cpp_test(example_test) +fast_float_add_cpp_test(basictest) + + + +option(FASTFLOAT_EXHAUSTIVE "Exhaustive tests" OFF) + +if (FASTFLOAT_EXHAUSTIVE) + fast_float_add_cpp_test(powersoffive_hardround) + fast_float_add_cpp_test(short_random_string) + fast_float_add_cpp_test(exhaustive32_midpoint) + fast_float_add_cpp_test(random_string) + fast_float_add_cpp_test(string_test) + fast_float_add_cpp_test(exhaustive32) + fast_float_add_cpp_test(exhaustive32_64) + fast_float_add_cpp_test(long_exhaustive32) + fast_float_add_cpp_test(long_exhaustive32_64) + fast_float_add_cpp_test(long_random64) + fast_float_add_cpp_test(random64) +endif(FASTFLOAT_EXHAUSTIVE) + diff --git a/tests/basictest.cpp b/tests/basictest.cpp index e29ecd4..59211e6 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -4,6 +4,96 @@ #include "fast_float/fast_float.h" #include +#include + +#ifndef SUPPLEMENTAL_TEST_DATA_DIR +#define SUPPLEMENTAL_TEST_DATA_DIR "data/" +#endif + +#ifndef __cplusplus +#error fastfloat requires a C++ compiler +#endif + +#ifndef FASTFLOAT_CPLUSPLUS +#if defined(_MSVC_LANG) && !defined(__clang__) +#define FASTFLOAT_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG) +#else +#define FASTFLOAT_CPLUSPLUS __cplusplus +#endif +#endif + +// C++ 17 because it is otherwise annoying to browse all files in a directory. +// We also only run these tests on little endian systems. +#if (FASTFLOAT_CPLUSPLUS >= 201703L) && (FASTFLOAT_IS_BIG_ENDIAN == 0) +#include +#include +#include + + +// return true on succcess +bool check_file(std::string file_name) { + std::cout << "Checking " << file_name << std::endl; + size_t number{0}; + std::fstream newfile(file_name, std::ios::in); + if (newfile.is_open()) { + std::string str; + while (std::getline(newfile, str)) { + if (str.size() > 0) { + // Read 32-bit hex + uint32_t float32; + auto r32 = std::from_chars(str.data() + 5, str.data() + str.size(), + float32, 16); + if(r32.ec != std::errc()) { std::cerr << "32-bit parsing failure\n"; return false; } + // Read 64-bit hex + uint64_t float64; + auto r64 = std::from_chars(str.data() + 14, str.data() + str.size(), + float64, 16); + if(r64.ec != std::errc()) { std::cerr << "64-bit parsing failure\n"; return false; } + // The string to parse: + const char *number_string = str.data() + 31; + const char *end_of_string = str.data() + str.size(); + // Parse as 32-bit float + float parsed_32; + auto fast_float_r32 = fast_float::from_chars(number_string, end_of_string, parsed_32); + if(fast_float_r32.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; } + // Parse as 64-bit float + double parsed_64; + auto fast_float_r64 = fast_float::from_chars(number_string, end_of_string, parsed_64); + if(fast_float_r64.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; } + // Convert the floats to unsigned ints. + uint32_t float32_parsed; + uint64_t float64_parsed; + ::memcpy(&float32_parsed, &parsed_32, sizeof(parsed_32)); + ::memcpy(&float64_parsed, &parsed_64, sizeof(parsed_64)); + // Compare with expected results + if (float32_parsed != float32) { + std::cout << "bad 32 " << str << std::endl; + return false; + } + if (float64_parsed != float64) { + std::cout << "bad 64 " << str << std::endl; + return false; + } + number++; + } + } + std::cout << "checked " << std::defaultfloat << number << " values" << std::endl; + newfile.close(); // close the file object + } else { + std::cout << "Could not read " << file_name << std::endl; + return false; + } + return true; +} + +TEST_CASE("supplemental") { + std::string path = SUPPLEMENTAL_TEST_DATA_DIR; + for (const auto & entry : std::filesystem::directory_iterator(path)) { + CHECK(check_file(entry.path())); + } +} + +#endif TEST_CASE("leading_zeroes") {