diff options
author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/generic/ylimits_ut.cpp |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/generic/ylimits_ut.cpp')
-rw-r--r-- | util/generic/ylimits_ut.cpp | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/util/generic/ylimits_ut.cpp b/util/generic/ylimits_ut.cpp new file mode 100644 index 00000000000..f1b3c6858cf --- /dev/null +++ b/util/generic/ylimits_ut.cpp @@ -0,0 +1,157 @@ +#include "cast.h" +#include "ylimits.h" + +#include <library/cpp/testing/unittest/registar.h> + +#include <util/string/cast.h> +#include <util/system/valgrind.h> + +class TLimitTest: public TTestBase { + UNIT_TEST_SUITE(TLimitTest); + UNIT_TEST(TestLimits); + UNIT_TEST(TestNan); + UNIT_TEST(TestMaxDouble); + UNIT_TEST_SUITE_END(); + +protected: + void TestLimits(); + void TestNan(); + void TestMaxDouble(); +}; + +UNIT_TEST_SUITE_REGISTRATION(TLimitTest); + +#define CHECK_COND(X) UNIT_ASSERT(X) + +static inline bool ValidSignInfo(bool, bool) { + return true; +} + +template <class T> +static inline bool ValidSignInfo(bool limitIsSigned, const T&) { + return limitIsSigned && IsNegative(T(-1)) || !limitIsSigned && !IsNegative(T(-1)); +} + +template <class T> +static inline bool TestIntegralLimits(const T&, bool unknownSign = true, bool isSigned = true) { + using lim = std::numeric_limits<T>; + + CHECK_COND(lim::is_specialized); + CHECK_COND(lim::is_integer); + CHECK_COND(lim::min() < lim::max()); + CHECK_COND((unknownSign && ((lim::is_signed && (lim::min() != 0)) || (!lim::is_signed && (lim::min() == 0)))) || + (!unknownSign && ((lim::is_signed && isSigned) || (!lim::is_signed && !isSigned)))); + + T min = Min(); + UNIT_ASSERT_EQUAL(lim::min(), min); + T max = Max(); + UNIT_ASSERT_EQUAL(lim::max(), max); + + if (unknownSign) { + CHECK_COND(ValidSignInfo(lim::is_signed, T())); + } + + return true; +} + +template <class T> +static inline bool TestSignedIntegralLimits(const T& val) { + return TestIntegralLimits(val, false, true); +} + +template <class T> +static inline bool TestUnsignedIntegralLimits(const T& val) { + return TestIntegralLimits(val, false, false); +} + +template <class T> +static inline bool TestFloatLimits(const T&) { + using lim = std::numeric_limits<T>; + + CHECK_COND(lim::is_specialized); + CHECK_COND(!lim::is_modulo); + CHECK_COND(!lim::is_integer); + CHECK_COND(lim::is_signed); + + CHECK_COND(lim::max() > 1000); + CHECK_COND(lim::min() > 0); + CHECK_COND(lim::min() < 0.001); + CHECK_COND(lim::epsilon() > 0); + + if (lim::is_iec559) { + CHECK_COND(lim::has_infinity); + CHECK_COND(lim::has_quiet_NaN); + CHECK_COND(lim::has_signaling_NaN); + } + + if (lim::has_infinity) { + const T infinity = lim::infinity(); + + CHECK_COND(infinity > lim::max()); + CHECK_COND(-infinity < -lim::max()); + } + + return true; +} + +template <class T> +static inline bool TestNan(const T&) { + using lim = std::numeric_limits<T>; + + if (lim::has_quiet_NaN) { + const T qnan = lim::quiet_NaN(); + + CHECK_COND(!(qnan == 42)); + CHECK_COND(!(qnan == qnan)); + CHECK_COND(qnan != 42); + CHECK_COND(qnan != qnan); + } + + return true; +} + +void TLimitTest::TestLimits() { + UNIT_ASSERT(TestIntegralLimits(bool())); + UNIT_ASSERT(TestIntegralLimits(char())); + using signed_char = signed char; + UNIT_ASSERT(TestSignedIntegralLimits(signed_char())); + using unsigned_char = unsigned char; + UNIT_ASSERT(TestUnsignedIntegralLimits(unsigned_char())); + UNIT_ASSERT(TestSignedIntegralLimits(short())); + using unsigned_short = unsigned short; + UNIT_ASSERT(TestUnsignedIntegralLimits(unsigned_short())); + UNIT_ASSERT(TestSignedIntegralLimits(int())); + using unsigned_int = unsigned int; + UNIT_ASSERT(TestUnsignedIntegralLimits(unsigned_int())); + UNIT_ASSERT(TestSignedIntegralLimits(long())); + using unsigned_long = unsigned long; + UNIT_ASSERT(TestUnsignedIntegralLimits(unsigned_long())); + using long_long = long long; + UNIT_ASSERT(TestSignedIntegralLimits(long_long())); + using unsigned_long_long = unsigned long long; + UNIT_ASSERT(TestUnsignedIntegralLimits(unsigned_long_long())); + UNIT_ASSERT(TestFloatLimits(float())); + UNIT_ASSERT(TestFloatLimits(double())); + using long_double = long double; + UNIT_ASSERT(RUNNING_ON_VALGRIND || TestFloatLimits(long_double())); +} + +void TLimitTest::TestNan() { + UNIT_ASSERT(::TestNan(float())); + UNIT_ASSERT(::TestNan(double())); + using long_double = long double; + UNIT_ASSERT(::TestNan(long_double())); +} + +void TLimitTest::TestMaxDouble() { + UNIT_ASSERT_VALUES_EQUAL(MaxCeil<i8>(), 127.0); + UNIT_ASSERT_VALUES_EQUAL(MaxFloor<i8>(), 127.0); + UNIT_ASSERT_VALUES_EQUAL(MaxCeil<ui8>(), 255.0); + UNIT_ASSERT_VALUES_EQUAL(MaxFloor<ui8>(), 255.0); + double d = 1ull << 63; + UNIT_ASSERT_VALUES_EQUAL(MaxCeil<i64>(), d); + UNIT_ASSERT_VALUES_EQUAL(MaxFloor<i64>(), nextafter(d, 0)); + d *= 2; + UNIT_ASSERT_VALUES_EQUAL(MaxCeil<ui64>(), d); + UNIT_ASSERT_VALUES_EQUAL(MaxFloor<ui64>(), nextafter(d, 0)); +} |