summaryrefslogtreecommitdiffstats
path: root/util/generic/utility_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/utility_ut.cpp
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/generic/utility_ut.cpp')
-rw-r--r--util/generic/utility_ut.cpp180
1 files changed, 180 insertions, 0 deletions
diff --git a/util/generic/utility_ut.cpp b/util/generic/utility_ut.cpp
new file mode 100644
index 00000000000..8e9d5afff9b
--- /dev/null
+++ b/util/generic/utility_ut.cpp
@@ -0,0 +1,180 @@
+#include "utility.h"
+#include "ymath.h"
+
+#include <library/cpp/testing/unittest/registar.h>
+
+// DO_NOT_STYLE
+
+class TTest {
+public:
+ inline TTest(int val)
+ : Val(val)
+ {
+ }
+
+ inline void Swap(TTest& t) {
+ DoSwap(Val, t.Val);
+ }
+
+ int Val;
+
+private:
+ TTest(const TTest&);
+ TTest& operator=(const TTest&);
+};
+
+struct TUnorderedTag {
+ TStringBuf Tag;
+};
+
+static bool operator<(const TUnorderedTag, const TUnorderedTag) {
+ return false;
+}
+
+static bool operator>(const TUnorderedTag, const TUnorderedTag) = delete;
+
+Y_UNIT_TEST_SUITE(TUtilityTest) {
+
+ Y_UNIT_TEST(TestSwapPrimitive) {
+ int i = 0;
+ int j = 1;
+
+ DoSwap(i, j);
+
+ UNIT_ASSERT_EQUAL(i, 1);
+ UNIT_ASSERT_EQUAL(j, 0);
+ }
+
+ Y_UNIT_TEST(TestSwapClass) {
+ TTest i(0);
+ TTest j(1);
+
+ DoSwap(i, j);
+
+ UNIT_ASSERT_EQUAL(i.Val, 1);
+ UNIT_ASSERT_EQUAL(j.Val, 0);
+ }
+
+ Y_UNIT_TEST(TestMaxMin) {
+ static_assert(Min(10, 3, 8) == 3, "Min doesn't work");
+ static_assert(Max(10, 3, 8) == 10, "Max doesn't work");
+ UNIT_ASSERT_EQUAL(Min(10, 3, 8), 3);
+ UNIT_ASSERT_EQUAL(Max(3.5, 4.2, 8.1, 99.025, 0.33, 29.0), 99.025);
+
+ UNIT_ASSERT_VALUES_EQUAL(Min(TUnorderedTag{"first"}, TUnorderedTag{"second"}).Tag, "first");
+ UNIT_ASSERT_VALUES_EQUAL(Max(TUnorderedTag{"first"}, TUnorderedTag{"second"}).Tag, "first");
+ UNIT_ASSERT_VALUES_EQUAL(Min(TUnorderedTag{"first"}, TUnorderedTag{"second"}, TUnorderedTag{"third"}).Tag, "first");
+ UNIT_ASSERT_VALUES_EQUAL(Max(TUnorderedTag{"first"}, TUnorderedTag{"second"}, TUnorderedTag{"third"}).Tag, "first");
+ }
+
+ Y_UNIT_TEST(TestMean) {
+ UNIT_ASSERT_EQUAL(Mean(5), 5);
+ UNIT_ASSERT_EQUAL(Mean(1, 2, 3), 2);
+ UNIT_ASSERT_EQUAL(Mean(6, 5, 4), 5);
+ UNIT_ASSERT_EQUAL(Mean(1, 2), 1.5);
+ UNIT_ASSERT(Abs(Mean(1., 2., 7.5) - 3.5) < std::numeric_limits<double>::epsilon());
+ }
+
+ Y_UNIT_TEST(TestZeroInitWithDefaultZeros) {
+ struct TStructWithPaddingBytes: public TZeroInit<TStructWithPaddingBytes> {
+ TStructWithPaddingBytes()
+ : TZeroInit<TStructWithPaddingBytes>() {
+ }
+ bool Field1_ = static_cast<bool>(0);
+ // here between Field1_ and Field2_ will be padding bytes
+ i64 Field2_ = 0;
+ };
+
+ TStructWithPaddingBytes foo{};
+
+ // all bytes must be zeroes, and MSAN will not complain about reading from padding bytes
+ const char* const fooPtr = (char*)&foo;
+ for (size_t i = 0; i < sizeof(TStructWithPaddingBytes); ++i) {
+ const char byte = fooPtr[i];
+ UNIT_ASSERT_EQUAL(byte, 0);
+ }
+ }
+
+ Y_UNIT_TEST(TestZeroInitWithDefaultNonZeros) {
+ struct TStructWithPaddingBytes: public TZeroInit<TStructWithPaddingBytes> {
+ TStructWithPaddingBytes()
+ : TZeroInit<TStructWithPaddingBytes>() {
+ }
+ bool Field1_ = true;
+ // here between Field1_ and Field2_ will be padding bytes
+ i64 Field2_ = 100500;
+ };
+
+ TStructWithPaddingBytes foo{};
+
+ // check that default values are set correctly
+ UNIT_ASSERT_EQUAL(foo.Field1_, true);
+ UNIT_ASSERT_EQUAL(foo.Field2_, 100500);
+
+ const char* const fooPtr = (char*)&foo;
+ // just reading all bytes, and MSAN must not complain about reading padding bytes
+ for (size_t i = 0; i < sizeof(TStructWithPaddingBytes); ++i) {
+ const char byte = fooPtr[i];
+ UNIT_ASSERT_EQUAL(byte, byte);
+ }
+ }
+
+ Y_UNIT_TEST(TestClampValNoClamp) {
+ double val = 2;
+ double lo = 1;
+ double hi = 3;
+ const double& clamped = ClampVal(val, lo, hi);
+ UNIT_ASSERT_EQUAL(clamped, val);
+ UNIT_ASSERT_EQUAL(&clamped, &val);
+ }
+
+ Y_UNIT_TEST(TestClampValLo) {
+ double val = 2;
+ double lo = 3;
+ double hi = 4;
+ const double& clamped = ClampVal(val, lo, hi);
+ UNIT_ASSERT_EQUAL(clamped, lo);
+ UNIT_ASSERT_EQUAL(&clamped, &lo);
+ }
+
+ Y_UNIT_TEST(TestClampValHi) {
+ double val = 4;
+ double lo = 3;
+ double hi = 2;
+ const double& clamped = ClampVal(val, lo, hi);
+ UNIT_ASSERT_EQUAL(clamped, hi);
+ UNIT_ASSERT_EQUAL(&clamped, &hi);
+ }
+
+ Y_UNIT_TEST(TestSecureZero) {
+ constexpr size_t checkSize = 128;
+ char test[checkSize];
+
+ // fill with garbage
+ for (size_t i = 0; i < checkSize; ++i) {
+ test[i] = i;
+ }
+
+ SecureZero(test, checkSize);
+
+ for (size_t i = 0; i < checkSize; ++i) {
+ UNIT_ASSERT_EQUAL(test[i], 0);
+ }
+ }
+
+ Y_UNIT_TEST(TestSecureZeroTemplate) {
+ constexpr size_t checkSize = 128;
+ char test[checkSize];
+
+ // fill with garbage
+ for (size_t i = 0; i < checkSize; ++i) {
+ test[i] = i;
+ }
+
+ SecureZero(test);
+
+ for (size_t i = 0; i < checkSize; ++i) {
+ UNIT_ASSERT_EQUAL(test[i], 0);
+ }
+ }
+};