utility_ut.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include "utility.h"
  2. #include "ymath.h"
  3. #include <library/cpp/testing/unittest/registar.h>
  4. // DO_NOT_STYLE
  5. class TTest {
  6. public:
  7. inline TTest(int val)
  8. : Val(val)
  9. {
  10. }
  11. inline void Swap(TTest& t) {
  12. DoSwap(Val, t.Val);
  13. }
  14. int Val;
  15. private:
  16. TTest(const TTest&);
  17. TTest& operator=(const TTest&);
  18. };
  19. struct TUnorderedTag {
  20. TStringBuf Tag;
  21. };
  22. static bool operator<(const TUnorderedTag, const TUnorderedTag) {
  23. return false;
  24. }
  25. static bool operator>(const TUnorderedTag, const TUnorderedTag) = delete;
  26. Y_UNIT_TEST_SUITE(TUtilityTest) {
  27. Y_UNIT_TEST(TestSwapPrimitive) {
  28. int i = 0;
  29. int j = 1;
  30. DoSwap(i, j);
  31. UNIT_ASSERT_EQUAL(i, 1);
  32. UNIT_ASSERT_EQUAL(j, 0);
  33. }
  34. Y_UNIT_TEST(TestSwapClass) {
  35. TTest i(0);
  36. TTest j(1);
  37. DoSwap(i, j);
  38. UNIT_ASSERT_EQUAL(i.Val, 1);
  39. UNIT_ASSERT_EQUAL(j.Val, 0);
  40. }
  41. Y_UNIT_TEST(TestMaxMin) {
  42. static_assert(Min(10, 3, 8) == 3, "Min doesn't work");
  43. static_assert(Max(10, 3, 8) == 10, "Max doesn't work");
  44. UNIT_ASSERT_EQUAL(Min(10, 3, 8), 3);
  45. UNIT_ASSERT_EQUAL(Max(3.5, 4.2, 8.1, 99.025, 0.33, 29.0), 99.025);
  46. UNIT_ASSERT_VALUES_EQUAL(Min(TUnorderedTag{"first"}, TUnorderedTag{"second"}).Tag, "first");
  47. UNIT_ASSERT_VALUES_EQUAL(Max(TUnorderedTag{"first"}, TUnorderedTag{"second"}).Tag, "first");
  48. UNIT_ASSERT_VALUES_EQUAL(Min(TUnorderedTag{"first"}, TUnorderedTag{"second"}, TUnorderedTag{"third"}).Tag, "first");
  49. UNIT_ASSERT_VALUES_EQUAL(Max(TUnorderedTag{"first"}, TUnorderedTag{"second"}, TUnorderedTag{"third"}).Tag, "first");
  50. }
  51. Y_UNIT_TEST(TestMean) {
  52. UNIT_ASSERT_EQUAL(Mean(5), 5);
  53. UNIT_ASSERT_EQUAL(Mean(1, 2, 3), 2);
  54. UNIT_ASSERT_EQUAL(Mean(6, 5, 4), 5);
  55. UNIT_ASSERT_EQUAL(Mean(1, 2), 1.5);
  56. UNIT_ASSERT(Abs(Mean(1., 2., 7.5) - 3.5) < std::numeric_limits<double>::epsilon());
  57. }
  58. Y_UNIT_TEST(TestZeroInitWithDefaultZeros) {
  59. struct TStructWithPaddingBytes: public TZeroInit<TStructWithPaddingBytes> {
  60. TStructWithPaddingBytes()
  61. : TZeroInit<TStructWithPaddingBytes>() {
  62. }
  63. bool Field1_ = static_cast<bool>(0);
  64. // here between Field1_ and Field2_ will be padding bytes
  65. i64 Field2_ = 0;
  66. };
  67. TStructWithPaddingBytes foo{};
  68. // all bytes must be zeroes, and MSAN will not complain about reading from padding bytes
  69. const char* const fooPtr = (char*)&foo;
  70. for (size_t i = 0; i < sizeof(TStructWithPaddingBytes); ++i) {
  71. const char byte = fooPtr[i];
  72. UNIT_ASSERT_EQUAL(byte, 0);
  73. }
  74. }
  75. Y_UNIT_TEST(TestZeroInitWithDefaultNonZeros) {
  76. struct TStructWithPaddingBytes: public TZeroInit<TStructWithPaddingBytes> {
  77. TStructWithPaddingBytes()
  78. : TZeroInit<TStructWithPaddingBytes>() {
  79. }
  80. bool Field1_ = true;
  81. // here between Field1_ and Field2_ will be padding bytes
  82. i64 Field2_ = 100500;
  83. };
  84. TStructWithPaddingBytes foo{};
  85. // check that default values are set correctly
  86. UNIT_ASSERT_EQUAL(foo.Field1_, true);
  87. UNIT_ASSERT_EQUAL(foo.Field2_, 100500);
  88. const char* const fooPtr = (char*)&foo;
  89. // just reading all bytes, and MSAN must not complain about reading padding bytes
  90. for (size_t i = 0; i < sizeof(TStructWithPaddingBytes); ++i) {
  91. const char byte = fooPtr[i];
  92. UNIT_ASSERT_EQUAL(byte, byte);
  93. }
  94. }
  95. Y_UNIT_TEST(TestClampValNoClamp) {
  96. double val = 2;
  97. double lo = 1;
  98. double hi = 3;
  99. const double& clamped = ClampVal(val, lo, hi);
  100. UNIT_ASSERT_EQUAL(clamped, val);
  101. UNIT_ASSERT_EQUAL(&clamped, &val);
  102. }
  103. Y_UNIT_TEST(TestClampValLo) {
  104. double val = 2;
  105. double lo = 3;
  106. double hi = 4;
  107. const double& clamped = ClampVal(val, lo, hi);
  108. UNIT_ASSERT_EQUAL(clamped, lo);
  109. UNIT_ASSERT_EQUAL(&clamped, &lo);
  110. }
  111. Y_UNIT_TEST(TestClampValHi) {
  112. double val = 4;
  113. double lo = 3;
  114. double hi = 2;
  115. const double& clamped = ClampVal(val, lo, hi);
  116. UNIT_ASSERT_EQUAL(clamped, hi);
  117. UNIT_ASSERT_EQUAL(&clamped, &hi);
  118. }
  119. Y_UNIT_TEST(TestSecureZero) {
  120. constexpr size_t checkSize = 128;
  121. char test[checkSize];
  122. // fill with garbage
  123. for (size_t i = 0; i < checkSize; ++i) {
  124. test[i] = i;
  125. }
  126. SecureZero(test, checkSize);
  127. for (size_t i = 0; i < checkSize; ++i) {
  128. UNIT_ASSERT_EQUAL(test[i], 0);
  129. }
  130. }
  131. Y_UNIT_TEST(TestSecureZeroTemplate) {
  132. constexpr size_t checkSize = 128;
  133. char test[checkSize];
  134. // fill with garbage
  135. for (size_t i = 0; i < checkSize; ++i) {
  136. test[i] = i;
  137. }
  138. SecureZero(test);
  139. for (size_t i = 0; i < checkSize; ++i) {
  140. UNIT_ASSERT_EQUAL(test[i], 0);
  141. }
  142. }
  143. }