xrange_ut.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include "xrange.h"
  2. #include "algorithm.h"
  3. #include "maybe.h"
  4. #include "vector.h"
  5. #include <library/cpp/testing/unittest/registar.h>
  6. #include <util/string/builder.h>
  7. Y_UNIT_TEST_SUITE(XRange) {
  8. void TestXRangeImpl(size_t begin, size_t end) {
  9. size_t count = 0;
  10. size_t sum = 0;
  11. size_t first = 42;
  12. bool firstInited = false;
  13. size_t last = 0;
  14. for (auto i : xrange(begin, end)) {
  15. ++count;
  16. sum += i;
  17. last = i;
  18. if (!firstInited) {
  19. first = i;
  20. firstInited = true;
  21. }
  22. }
  23. UNIT_ASSERT_VALUES_EQUAL(count, end - begin);
  24. UNIT_ASSERT_VALUES_EQUAL(first, begin);
  25. UNIT_ASSERT_VALUES_EQUAL(last, end - 1);
  26. UNIT_ASSERT_VALUES_EQUAL(sum, count * (first + last) / 2);
  27. }
  28. void TestSteppedXRangeImpl(int begin, int end, int step, const TVector<int>& expected) {
  29. size_t expInd = 0;
  30. for (auto i : xrange(begin, end, step)) {
  31. UNIT_ASSERT(expInd < expected.size());
  32. UNIT_ASSERT_VALUES_EQUAL(i, expected[expInd]);
  33. ++expInd;
  34. }
  35. UNIT_ASSERT_VALUES_EQUAL(expInd, expected.size());
  36. }
  37. Y_UNIT_TEST(IncrementWorks) {
  38. TestXRangeImpl(0, 10);
  39. TestXRangeImpl(10, 20);
  40. }
  41. Y_UNIT_TEST(DecrementWorks) {
  42. TestSteppedXRangeImpl(10, 0, -1, {10, 9, 8, 7, 6, 5, 4, 3, 2, 1});
  43. TestSteppedXRangeImpl(10, -1, -1, {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0});
  44. TestSteppedXRangeImpl(20, 9, -1, {20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10});
  45. }
  46. Y_UNIT_TEST(StepWorks) {
  47. TestSteppedXRangeImpl(0, 0, 1, {});
  48. TestSteppedXRangeImpl(0, 9, 3, {0, 3, 6});
  49. TestSteppedXRangeImpl(0, 10, 3, {0, 3, 6, 9});
  50. TestSteppedXRangeImpl(0, 11, 3, {0, 3, 6, 9});
  51. TestSteppedXRangeImpl(0, 12, 3, {0, 3, 6, 9});
  52. TestSteppedXRangeImpl(0, 13, 3, {0, 3, 6, 9, 12});
  53. TestSteppedXRangeImpl(0, 10, 2, {0, 2, 4, 6, 8});
  54. TestSteppedXRangeImpl(15, 0, -4, {15, 11, 7, 3});
  55. TestSteppedXRangeImpl(15, -1, -4, {15, 11, 7, 3});
  56. TestSteppedXRangeImpl(15, -2, -4, {15, 11, 7, 3, -1});
  57. }
  58. Y_UNIT_TEST(PointersWorks) {
  59. TVector<size_t> data = {3, 1, 4, 1, 5, 9, 2, 6};
  60. const size_t digSumExpected = Accumulate(data.begin(), data.end(), static_cast<size_t>(0));
  61. size_t digSumByIt = 0;
  62. for (auto ptr : xrange(data.begin(), data.end())) {
  63. digSumByIt += *ptr;
  64. }
  65. UNIT_ASSERT_VALUES_EQUAL(digSumByIt, digSumExpected);
  66. size_t digSumByPtr = 0;
  67. for (auto ptr : xrange(&data[0], &data[0] + data.size())) {
  68. digSumByPtr += *ptr;
  69. }
  70. UNIT_ASSERT_VALUES_EQUAL(digSumByPtr, digSumExpected);
  71. }
  72. Y_UNIT_TEST(SizeMethodCheck) {
  73. UNIT_ASSERT_VALUES_EQUAL(xrange(5).size(), 5);
  74. UNIT_ASSERT_VALUES_EQUAL(xrange(0, 5, 2).size(), 3);
  75. UNIT_ASSERT_VALUES_EQUAL(xrange(0, 6, 2).size(), 3);
  76. }
  77. class TVectorChild: public TVector<size_t> {
  78. public:
  79. template <typename TIterator>
  80. TVectorChild(TIterator a, TIterator b)
  81. : TVector<size_t>(a, b)
  82. {
  83. }
  84. };
  85. Y_UNIT_TEST(ConvertionWorks) {
  86. TVector<size_t> data = {0, 1, 2, 3, 4, 5, 6, 7, 8};
  87. TVector<size_t> convertionResults[] = {xrange<size_t>(9),
  88. xrange<ui32>(0, 9),
  89. xrange(0, 9, 1)};
  90. for (const auto& arr : convertionResults) {
  91. UNIT_ASSERT(arr == data);
  92. }
  93. TVectorChild sons[] = {xrange(0, 9),
  94. xrange(0, 9, 1)};
  95. for (const auto& arr : sons) {
  96. UNIT_ASSERT(arr == data);
  97. }
  98. }
  99. template <class XRangeContainer>
  100. void TestEmptyRanges(const XRangeContainer& c) {
  101. for (const auto& emptyRange : c) {
  102. UNIT_ASSERT_VALUES_EQUAL(emptyRange.size(), 0);
  103. for (auto i : emptyRange) {
  104. Y_UNUSED(i);
  105. UNIT_ASSERT(false);
  106. }
  107. using TValueType = decltype(*emptyRange.begin());
  108. const TVector<TValueType> asVector = emptyRange;
  109. UNIT_ASSERT(asVector.empty());
  110. }
  111. }
  112. Y_UNIT_TEST(EmptySimpleRange) {
  113. using TSimpleRange = decltype(xrange(1));
  114. const TSimpleRange emptySimpleRanges[] = {
  115. xrange(-1),
  116. xrange(-10),
  117. xrange(0, -5),
  118. xrange(10, 10),
  119. xrange(10, 9),
  120. };
  121. TestEmptyRanges(emptySimpleRanges);
  122. }
  123. Y_UNIT_TEST(EmptySteppedRange) {
  124. using TSteppedRange = decltype(xrange(1, 10, 1));
  125. const TSteppedRange emptySteppedRanges[] = {
  126. xrange(5, 5, 1),
  127. xrange(5, 0, 5),
  128. xrange(0, -1, 5),
  129. xrange(0, 1, -1),
  130. xrange(0, -10, 10),
  131. };
  132. TestEmptyRanges(emptySteppedRanges);
  133. }
  134. template <class TRange>
  135. static void TestIteratorDifferenceImpl(TRange range, int a, int b, TMaybe<int> step) {
  136. auto fmtCase = [&]() -> TString { return TStringBuilder() << "xrange(" << a << ", " << b << (step ? ", " + ToString(*step) : TString{}) << ")"; };
  137. auto begin = std::begin(range);
  138. auto end = std::end(range);
  139. auto distance = end - begin;
  140. UNIT_ASSERT_VALUES_EQUAL_C(range.size(), distance, fmtCase());
  141. UNIT_ASSERT_EQUAL_C(end, begin + distance, fmtCase());
  142. }
  143. Y_UNIT_TEST(IteratorDifference) {
  144. for (int a = -20; a <= 20; ++a) {
  145. for (int b = -20; b <= 20; ++b) {
  146. for (int step = -25; step <= 25; ++step) {
  147. if (step != 0) {
  148. TestIteratorDifferenceImpl(xrange(a, b, step), a, b, step);
  149. }
  150. }
  151. TestIteratorDifferenceImpl(xrange(a, b), a, b, Nothing());
  152. }
  153. }
  154. }
  155. Y_UNIT_TEST(Advance) {
  156. {
  157. auto range = xrange(30, 160, 7);
  158. auto it = std::begin(range);
  159. it += 5;
  160. UNIT_ASSERT_VALUES_EQUAL(*(std::begin(range) + 5), *it);
  161. UNIT_ASSERT_VALUES_EQUAL(65, *it);
  162. it -= 2;
  163. UNIT_ASSERT_VALUES_EQUAL(*(std::begin(range) + 3), *it);
  164. UNIT_ASSERT_VALUES_EQUAL(51, *it);
  165. std::advance(it, 10);
  166. UNIT_ASSERT_VALUES_EQUAL(*(std::begin(range) + 13), *it);
  167. UNIT_ASSERT_VALUES_EQUAL(121, *it);
  168. std::advance(it, -5);
  169. UNIT_ASSERT_VALUES_EQUAL(*(std::begin(range) + 8), *it);
  170. UNIT_ASSERT_VALUES_EQUAL(86, *it);
  171. }
  172. {
  173. auto range = xrange(-20, 100);
  174. auto it = std::begin(range);
  175. it += 5;
  176. UNIT_ASSERT_VALUES_EQUAL(*(std::begin(range) + 5), *it);
  177. UNIT_ASSERT_VALUES_EQUAL(-15, *it);
  178. it -= 2;
  179. UNIT_ASSERT_VALUES_EQUAL(*(std::begin(range) + 3), *it);
  180. UNIT_ASSERT_VALUES_EQUAL(-17, *it);
  181. std::advance(it, 30);
  182. UNIT_ASSERT_VALUES_EQUAL(*(std::begin(range) + 33), *it);
  183. UNIT_ASSERT_VALUES_EQUAL(13, *it);
  184. std::advance(it, -8);
  185. UNIT_ASSERT_VALUES_EQUAL(*(std::begin(range) + 25), *it);
  186. UNIT_ASSERT_VALUES_EQUAL(5, *it);
  187. }
  188. }
  189. } // Y_UNIT_TEST_SUITE(XRange)