summaryrefslogtreecommitdiffstats
path: root/util/generic/ylimits_ut.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/generic/ylimits_ut.cpp
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/generic/ylimits_ut.cpp')
-rw-r--r--util/generic/ylimits_ut.cpp157
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));
+}