mirror of
				https://github.com/red0124/ssp.git
				synced 2025-11-04 06:36:45 +01:00 
			
		
		
		
	add unit tests for conversion without the fast float library
This commit is contained in:
		
							parent
							
								
									d328f7d59d
								
							
						
					
					
						commit
						c214975ca0
					
				@ -2,7 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "type_traits.hpp"
 | 
					#include "type_traits.hpp"
 | 
				
			||||||
#include <cstring>
 | 
					#include <cstring>
 | 
				
			||||||
#include <fast_float/fast_float.h>
 | 
					 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
#include <limits>
 | 
					#include <limits>
 | 
				
			||||||
#include <optional>
 | 
					#include <optional>
 | 
				
			||||||
@ -11,13 +10,18 @@
 | 
				
			|||||||
#include <string_view>
 | 
					#include <string_view>
 | 
				
			||||||
#include <variant>
 | 
					#include <variant>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SSP_DISABLE_FAST_FLOAT
 | 
				
			||||||
 | 
					#include <fast_float/fast_float.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#include <charconv>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ss {
 | 
					namespace ss {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
////////////////
 | 
					////////////////
 | 
				
			||||||
// number converters
 | 
					// number converters
 | 
				
			||||||
////////////////
 | 
					////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SSP_DISABLE_FAST_FLOAT
 | 
					 | 
				
			||||||
#ifndef SSP_DISABLE_FAST_FLOAT
 | 
					#ifndef SSP_DISABLE_FAST_FLOAT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
@ -38,20 +42,11 @@ template <typename T>
 | 
				
			|||||||
std::enable_if_t<std::is_floating_point_v<T>, std::optional<T>> to_num(
 | 
					std::enable_if_t<std::is_floating_point_v<T>, std::optional<T>> to_num(
 | 
				
			||||||
    const char* const begin, const char* const end) {
 | 
					    const char* const begin, const char* const end) {
 | 
				
			||||||
    T ret;
 | 
					    T ret;
 | 
				
			||||||
    try {
 | 
					    auto [ptr, ec] = std::from_chars(begin, end, ret);
 | 
				
			||||||
        if constexpr (std::is_same_v<T, float>) {
 | 
					
 | 
				
			||||||
            ret = std::stof(std::string{begin, end});
 | 
					    if (ec != std::errc() || ptr != end) {
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if constexpr (std::is_same_v<T, double>) {
 | 
					 | 
				
			||||||
            ret = std::stod(std::string{begin, end});
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if constexpr (std::is_same_v<T, long double>) {
 | 
					 | 
				
			||||||
            ret = std::stold(std::string{begin, end});
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } catch (...) {
 | 
					 | 
				
			||||||
        return std::nullopt;
 | 
					        return std::nullopt;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ test_sources = files([
 | 
				
			|||||||
      'test_converter.cpp',
 | 
					      'test_converter.cpp',
 | 
				
			||||||
      'test_parser.cpp',
 | 
					      'test_parser.cpp',
 | 
				
			||||||
      'test_extractions.cpp',
 | 
					      'test_extractions.cpp',
 | 
				
			||||||
 | 
					      'test_extractions_without_fast_float.cpp',
 | 
				
			||||||
      ])
 | 
					      ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
doctest_proj = subproject('doctest')
 | 
					doctest_proj = subproject('doctest')
 | 
				
			||||||
 | 
				
			|||||||
@ -2,23 +2,6 @@
 | 
				
			|||||||
#include <algorithm>
 | 
					#include <algorithm>
 | 
				
			||||||
#include <ss/extract.hpp>
 | 
					#include <ss/extract.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CHECK_FLOATING_CONVERSION(input, type)                                 \
 | 
					 | 
				
			||||||
    {                                                                          \
 | 
					 | 
				
			||||||
        auto eps = std::numeric_limits<type>::min();                           \
 | 
					 | 
				
			||||||
        std::string s = #input;                                                \
 | 
					 | 
				
			||||||
        auto t = ss::to_num<type>(s.c_str(), s.c_str() + s.size());            \
 | 
					 | 
				
			||||||
        REQUIRE(t.has_value());                                                \
 | 
					 | 
				
			||||||
        CHECK_LT(std::abs(t.value() - type(input)), eps);                      \
 | 
					 | 
				
			||||||
    }                                                                          \
 | 
					 | 
				
			||||||
    {                                                                          \
 | 
					 | 
				
			||||||
        /* check negative too */                                               \
 | 
					 | 
				
			||||||
        auto eps = std::numeric_limits<type>::min();                           \
 | 
					 | 
				
			||||||
        auto s = std::string("-") + #input;                                    \
 | 
					 | 
				
			||||||
        auto t = ss::to_num<type>(s.c_str(), s.c_str() + s.size());            \
 | 
					 | 
				
			||||||
        REQUIRE(t.has_value());                                                \
 | 
					 | 
				
			||||||
        CHECK_LT(std::abs(t.value() - type(-input)), eps);                     \
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST_CASE("testing extract functions for floating point values") {
 | 
					TEST_CASE("testing extract functions for floating point values") {
 | 
				
			||||||
    CHECK_FLOATING_CONVERSION(123.456, float);
 | 
					    CHECK_FLOATING_CONVERSION(123.456, float);
 | 
				
			||||||
    CHECK_FLOATING_CONVERSION(123.456, double);
 | 
					    CHECK_FLOATING_CONVERSION(123.456, double);
 | 
				
			||||||
@ -70,13 +53,6 @@ TEST_CASE("extract test functions for decimal values") {
 | 
				
			|||||||
    CHECK_DECIMAL_CONVERSION(1234567891011, ull);
 | 
					    CHECK_DECIMAL_CONVERSION(1234567891011, ull);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CHECK_INVALID_CONVERSION(input, type)                                  \
 | 
					 | 
				
			||||||
    {                                                                          \
 | 
					 | 
				
			||||||
        std::string s = input;                                                 \
 | 
					 | 
				
			||||||
        auto t = ss::to_num<type>(s.c_str(), s.c_str() + s.size());            \
 | 
					 | 
				
			||||||
        CHECK_FALSE(t.has_value());                                            \
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST_CASE("extract test functions for numbers with invalid inputs") {
 | 
					TEST_CASE("extract test functions for numbers with invalid inputs") {
 | 
				
			||||||
    // negative unsigned value
 | 
					    // negative unsigned value
 | 
				
			||||||
    CHECK_INVALID_CONVERSION("-1234", ul);
 | 
					    CHECK_INVALID_CONVERSION("-1234", ul);
 | 
				
			||||||
@ -200,15 +176,6 @@ TEST_CASE("extract test functions for std::optional") {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define REQUIRE_VARIANT(var, el, type)                                         \
 | 
					 | 
				
			||||||
    {                                                                          \
 | 
					 | 
				
			||||||
        auto ptr = std::get_if<type>(&var);                                    \
 | 
					 | 
				
			||||||
        REQUIRE(ptr);                                                          \
 | 
					 | 
				
			||||||
        REQUIRE_EQ(el, *ptr);                                                  \
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define CHECK_NOT_VARIANT(var, type) CHECK(!std::holds_alternative<type>(var));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST_CASE("extract test functions for std::variant") {
 | 
					TEST_CASE("extract test functions for std::variant") {
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::string s = "22";
 | 
					        std::string s = "22";
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										132
									
								
								test/test_extractions_without_fast_float.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								test/test_extractions_without_fast_float.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,132 @@
 | 
				
			|||||||
 | 
					#include "test_helpers.hpp"
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SSP_DISABLE_FAST_FLOAT
 | 
				
			||||||
 | 
					#include <ss/extract.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE(
 | 
				
			||||||
 | 
					    "testing extract functions for floating point values without fast float") {
 | 
				
			||||||
 | 
					    CHECK_FLOATING_CONVERSION(123.456, float);
 | 
				
			||||||
 | 
					    CHECK_FLOATING_CONVERSION(123.456, double);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CHECK_FLOATING_CONVERSION(69, float);
 | 
				
			||||||
 | 
					    CHECK_FLOATING_CONVERSION(69, double);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CHECK_FLOATING_CONVERSION(420., float);
 | 
				
			||||||
 | 
					    CHECK_FLOATING_CONVERSION(420., double);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CHECK_FLOATING_CONVERSION(0.123, float);
 | 
				
			||||||
 | 
					    CHECK_FLOATING_CONVERSION(0.123, double);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CHECK_FLOATING_CONVERSION(123e4, float);
 | 
				
			||||||
 | 
					    CHECK_FLOATING_CONVERSION(123e4, double);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE("extract test functions for numbers with invalid inputs without fast "
 | 
				
			||||||
 | 
					          "float") {
 | 
				
			||||||
 | 
					    // floating pint for int
 | 
				
			||||||
 | 
					    CHECK_INVALID_CONVERSION("123.4", int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // random input for float
 | 
				
			||||||
 | 
					    CHECK_INVALID_CONVERSION("xxx1", float);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE("extract test functions for std::variant without fast float") {
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::string s = "22";
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<int, double, std::string> var;
 | 
				
			||||||
 | 
					            REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, double);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, std::string);
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, 22, int);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<double, int, std::string> var;
 | 
				
			||||||
 | 
					            REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, int);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, std::string);
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, 22, double);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<std::string, double, int> var;
 | 
				
			||||||
 | 
					            REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, int);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, double);
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, "22", std::string);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<int> var;
 | 
				
			||||||
 | 
					            REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, 22, int);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::string s = "22.2";
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<int, double, std::string> var;
 | 
				
			||||||
 | 
					            REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, int);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, std::string);
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, 22.2, double);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<double, int, std::string> var;
 | 
				
			||||||
 | 
					            REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, int);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, std::string);
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, 22.2, double);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<std::string, double, int> var;
 | 
				
			||||||
 | 
					            REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, int);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, double);
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, "22.2", std::string);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::string s = "2.2.2";
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<int, double, std::string> var;
 | 
				
			||||||
 | 
					            REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, int);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, double);
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, "2.2.2", std::string);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<double, std::string, int> var;
 | 
				
			||||||
 | 
					            REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, int);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, double);
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, "2.2.2", std::string);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<std::string, double, int> var;
 | 
				
			||||||
 | 
					            REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, int);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, double);
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, "2.2.2", std::string);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<int, double> var;
 | 
				
			||||||
 | 
					            REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, int{}, int);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, double);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<double, int> var;
 | 
				
			||||||
 | 
					            REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, double{}, double);
 | 
				
			||||||
 | 
					            CHECK_NOT_VARIANT(var, int);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::variant<int> var;
 | 
				
			||||||
 | 
					            REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            REQUIRE_VARIANT(var, int{}, int);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -46,3 +46,36 @@ struct buffer {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[maybe_unused]] inline buffer buff;
 | 
					[[maybe_unused]] inline buffer buff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CHECK_FLOATING_CONVERSION(input, type)                                 \
 | 
				
			||||||
 | 
					    {                                                                          \
 | 
				
			||||||
 | 
					        auto eps = std::numeric_limits<type>::min();                           \
 | 
				
			||||||
 | 
					        std::string s = #input;                                                \
 | 
				
			||||||
 | 
					        auto t = ss::to_num<type>(s.c_str(), s.c_str() + s.size());            \
 | 
				
			||||||
 | 
					        REQUIRE(t.has_value());                                                \
 | 
				
			||||||
 | 
					        CHECK_LT(std::abs(t.value() - type(input)), eps);                      \
 | 
				
			||||||
 | 
					    }                                                                          \
 | 
				
			||||||
 | 
					    {                                                                          \
 | 
				
			||||||
 | 
					        /* check negative too */                                               \
 | 
				
			||||||
 | 
					        auto eps = std::numeric_limits<type>::min();                           \
 | 
				
			||||||
 | 
					        auto s = std::string("-") + #input;                                    \
 | 
				
			||||||
 | 
					        auto t = ss::to_num<type>(s.c_str(), s.c_str() + s.size());            \
 | 
				
			||||||
 | 
					        REQUIRE(t.has_value());                                                \
 | 
				
			||||||
 | 
					        CHECK_LT(std::abs(t.value() - type(-input)), eps);                     \
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CHECK_INVALID_CONVERSION(input, type)                                  \
 | 
				
			||||||
 | 
					    {                                                                          \
 | 
				
			||||||
 | 
					        std::string s = input;                                                 \
 | 
				
			||||||
 | 
					        auto t = ss::to_num<type>(s.c_str(), s.c_str() + s.size());            \
 | 
				
			||||||
 | 
					        CHECK_FALSE(t.has_value());                                            \
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define REQUIRE_VARIANT(var, el, type)                                         \
 | 
				
			||||||
 | 
					    {                                                                          \
 | 
				
			||||||
 | 
					        auto ptr = std::get_if<type>(&var);                                    \
 | 
				
			||||||
 | 
					        REQUIRE(ptr);                                                          \
 | 
				
			||||||
 | 
					        REQUIRE_EQ(el, *ptr);                                                  \
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CHECK_NOT_VARIANT(var, type) CHECK(!std::holds_alternative<type>(var));
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user