array_ref_ut.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #include "array_ref.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. Y_UNIT_TEST_SUITE(TestArrayRef) {
  4. Y_UNIT_TEST(TestDefaultConstructor) {
  5. TArrayRef<int> defaulted;
  6. UNIT_ASSERT_VALUES_EQUAL(defaulted.data(), nullptr);
  7. UNIT_ASSERT_VALUES_EQUAL(defaulted.size(), 0u);
  8. }
  9. Y_UNIT_TEST(TestConstructorFromArray) {
  10. int x[] = {10, 20, 30};
  11. TArrayRef<int> ref(x);
  12. UNIT_ASSERT_VALUES_EQUAL(3u, ref.size());
  13. UNIT_ASSERT_VALUES_EQUAL(30, ref[2]);
  14. ref[2] = 50;
  15. UNIT_ASSERT_VALUES_EQUAL(50, x[2]);
  16. TArrayRef<const int> constRef(x);
  17. UNIT_ASSERT_VALUES_EQUAL(3u, constRef.size());
  18. UNIT_ASSERT_VALUES_EQUAL(50, constRef[2]);
  19. ref[0] = 100;
  20. UNIT_ASSERT_VALUES_EQUAL(constRef[0], 100);
  21. }
  22. Y_UNIT_TEST(TestAccessingElements) {
  23. int a[]{1, 2, 3};
  24. TArrayRef<int> ref(a);
  25. UNIT_ASSERT_VALUES_EQUAL(ref[0], 1);
  26. UNIT_ASSERT_VALUES_EQUAL(ref.at(0), 1);
  27. ref[0] = 5;
  28. UNIT_ASSERT_VALUES_EQUAL(a[0], 5);
  29. // FIXME: size checks are implemented via Y_ASSERT, hence there is no way to test them
  30. }
  31. Y_UNIT_TEST(TestFrontBack) {
  32. const int x[] = {1, 2, 3};
  33. const TArrayRef<const int> rx{x};
  34. UNIT_ASSERT_VALUES_EQUAL(rx.front(), 1);
  35. UNIT_ASSERT_VALUES_EQUAL(rx.back(), 3);
  36. int y[] = {1, 2, 3};
  37. TArrayRef<int> ry{y};
  38. UNIT_ASSERT_VALUES_EQUAL(ry.front(), 1);
  39. UNIT_ASSERT_VALUES_EQUAL(ry.back(), 3);
  40. ry.front() = 100;
  41. ry.back() = 500;
  42. UNIT_ASSERT_VALUES_EQUAL(ry.front(), 100);
  43. UNIT_ASSERT_VALUES_EQUAL(ry.back(), 500);
  44. UNIT_ASSERT_VALUES_EQUAL(y[0], 100);
  45. UNIT_ASSERT_VALUES_EQUAL(y[2], 500);
  46. }
  47. Y_UNIT_TEST(TestIterator) {
  48. int array[] = {17, 19, 21};
  49. TArrayRef<int> r(array, 3);
  50. TArrayRef<int>::iterator iterator = r.begin();
  51. for (auto& i : array) {
  52. UNIT_ASSERT(iterator != r.end());
  53. UNIT_ASSERT_VALUES_EQUAL(i, *iterator);
  54. ++iterator;
  55. }
  56. UNIT_ASSERT(iterator == r.end());
  57. }
  58. Y_UNIT_TEST(TestReverseIterators) {
  59. const int x[] = {1, 2, 3};
  60. const TArrayRef<const int> rx{x};
  61. auto i = rx.crbegin();
  62. UNIT_ASSERT_VALUES_EQUAL(*i, 3);
  63. ++i;
  64. UNIT_ASSERT_VALUES_EQUAL(*i, 2);
  65. ++i;
  66. UNIT_ASSERT_VALUES_EQUAL(*i, 1);
  67. ++i;
  68. UNIT_ASSERT_EQUAL(i, rx.crend());
  69. }
  70. Y_UNIT_TEST(TestConstIterators) {
  71. int x[] = {1, 2, 3};
  72. TArrayRef<int> rx{x};
  73. UNIT_ASSERT_EQUAL(rx.begin(), rx.cbegin());
  74. UNIT_ASSERT_EQUAL(rx.end(), rx.cend());
  75. UNIT_ASSERT_EQUAL(rx.rbegin(), rx.crbegin());
  76. UNIT_ASSERT_EQUAL(rx.rend(), rx.crend());
  77. int w[] = {1, 2, 3};
  78. const TArrayRef<int> rw{w};
  79. UNIT_ASSERT_EQUAL(rw.begin(), rw.cbegin());
  80. UNIT_ASSERT_EQUAL(rw.end(), rw.cend());
  81. UNIT_ASSERT_EQUAL(rw.rbegin(), rw.crbegin());
  82. UNIT_ASSERT_EQUAL(rw.rend(), rw.crend());
  83. int y[] = {1, 2, 3};
  84. TArrayRef<const int> ry{y};
  85. UNIT_ASSERT_EQUAL(ry.begin(), ry.cbegin());
  86. UNIT_ASSERT_EQUAL(ry.end(), ry.cend());
  87. UNIT_ASSERT_EQUAL(ry.rbegin(), ry.crbegin());
  88. UNIT_ASSERT_EQUAL(ry.rend(), ry.crend());
  89. const int z[] = {1, 2, 3};
  90. TArrayRef<const int> rz{z};
  91. UNIT_ASSERT_EQUAL(rz.begin(), rz.cbegin());
  92. UNIT_ASSERT_EQUAL(rz.end(), rz.cend());
  93. UNIT_ASSERT_EQUAL(rz.rbegin(), rz.crbegin());
  94. UNIT_ASSERT_EQUAL(rz.rend(), rz.crend());
  95. const int q[] = {1, 2, 3};
  96. const TArrayRef<const int> rq{q};
  97. UNIT_ASSERT_EQUAL(rq.begin(), rq.cbegin());
  98. UNIT_ASSERT_EQUAL(rq.end(), rq.cend());
  99. UNIT_ASSERT_EQUAL(rq.rbegin(), rq.crbegin());
  100. UNIT_ASSERT_EQUAL(rq.rend(), rq.crend());
  101. }
  102. Y_UNIT_TEST(TestCreatingFromStringLiteral) {
  103. TConstArrayRef<char> knownSizeRef("123", 3);
  104. size_t ret = 0;
  105. for (char ch : knownSizeRef) {
  106. ret += ch - '0';
  107. }
  108. UNIT_ASSERT_VALUES_EQUAL(ret, 6);
  109. UNIT_ASSERT_VALUES_EQUAL(knownSizeRef.size(), 3);
  110. UNIT_ASSERT_VALUES_EQUAL(knownSizeRef.at(0), '1');
  111. /*
  112. * When TArrayRef is being constructed from string literal,
  113. * trailing zero will be added into it.
  114. */
  115. TConstArrayRef<char> autoSizeRef("456");
  116. UNIT_ASSERT_VALUES_EQUAL(autoSizeRef[0], '4');
  117. UNIT_ASSERT_VALUES_EQUAL(autoSizeRef[3], '\0');
  118. }
  119. Y_UNIT_TEST(TestEqualityOperator) {
  120. static constexpr size_t size = 5;
  121. int a[size]{1, 2, 3, 4, 5};
  122. int b[size]{5, 4, 3, 2, 1};
  123. int c[size - 1]{5, 4, 3, 2};
  124. float d[size]{1.f, 2.f, 3.f, 4.f, 5.f};
  125. TArrayRef<int> aRef(a);
  126. TConstArrayRef<int> aConstRef(a, size);
  127. TArrayRef<int> bRef(b);
  128. TArrayRef<int> cRef(c, size - 1);
  129. TArrayRef<float> dRef(d, size);
  130. TConstArrayRef<float> dConstRef(d, size);
  131. UNIT_ASSERT_EQUAL(aRef, aConstRef);
  132. UNIT_ASSERT_EQUAL(dRef, dConstRef);
  133. UNIT_ASSERT_UNEQUAL(aRef, cRef);
  134. UNIT_ASSERT_UNEQUAL(aRef, bRef);
  135. TArrayRef<int> bSubRef(b, size - 1);
  136. // Testing if operator== compares values, not pointers
  137. UNIT_ASSERT_EQUAL(cRef, bSubRef);
  138. }
  139. Y_UNIT_TEST(TestImplicitConstructionFromContainer) {
  140. /* Just test compilation. */
  141. auto fc = [](TArrayRef<const int>) {};
  142. auto fm = [](TArrayRef<int>) {};
  143. fc(TVector<int>({1}));
  144. const TVector<int> ac = {1};
  145. TVector<int> am = {1};
  146. fc(ac);
  147. fc(am);
  148. fm(am);
  149. // fm(ac); // This one shouldn't compile.
  150. }
  151. Y_UNIT_TEST(TestFirstLastSubspan) {
  152. const int arr[] = {1, 2, 3, 4, 5};
  153. TArrayRef<const int> aRef(arr);
  154. UNIT_ASSERT_EQUAL(aRef.first(2), MakeArrayRef(std::vector<int>{1, 2}));
  155. UNIT_ASSERT_EQUAL(aRef.last(2), MakeArrayRef(std::vector<int>{4, 5}));
  156. UNIT_ASSERT_EQUAL(aRef.subspan(2), MakeArrayRef(std::vector<int>{3, 4, 5}));
  157. UNIT_ASSERT_EQUAL(aRef.subspan(1, 3), MakeArrayRef(std::vector<int>{2, 3, 4}));
  158. }
  159. Y_UNIT_TEST(TestSlice) {
  160. const int a0[] = {1, 2, 3};
  161. TArrayRef<const int> r0(a0);
  162. TArrayRef<const int> s0 = r0.Slice(2);
  163. UNIT_ASSERT_VALUES_EQUAL(s0.size(), 1);
  164. UNIT_ASSERT_VALUES_EQUAL(s0[0], 3);
  165. const int a1[] = {1, 2, 3, 4};
  166. TArrayRef<const int> r1(a1);
  167. TArrayRef<const int> s1 = r1.Slice(2, 1);
  168. UNIT_ASSERT_VALUES_EQUAL(s1.size(), 1);
  169. UNIT_ASSERT_VALUES_EQUAL(s1[0], 3);
  170. // FIXME: size checks are implemented via Y_ASSERT, hence there is no way to test them
  171. }
  172. Y_UNIT_TEST(SubRegion) {
  173. TVector<char> x;
  174. for (size_t i = 0; i < 42; ++i) {
  175. x.push_back('a' + (i * 42424243) % 13);
  176. }
  177. TArrayRef<const char> ref(x.data(), 42);
  178. for (size_t i = 0; i <= 50; ++i) {
  179. TVector<char> expected;
  180. for (size_t j = 0; j <= 100; ++j) {
  181. UNIT_ASSERT(MakeArrayRef(expected) == ref.SubRegion(i, j));
  182. if (i + j < 42) {
  183. expected.push_back(x[i + j]);
  184. }
  185. }
  186. }
  187. }
  188. Y_UNIT_TEST(TestAsBytes) {
  189. const int16_t constArr[] = {1, 2, 3};
  190. TArrayRef<const int16_t> constRef(constArr);
  191. auto bytesRef = as_bytes(constRef);
  192. UNIT_ASSERT_VALUES_EQUAL(bytesRef.size(), sizeof(int16_t) * constRef.size());
  193. UNIT_ASSERT_EQUAL(
  194. bytesRef,
  195. MakeArrayRef(std::vector<char>{0x01, 0x00, 0x02, 0x00, 0x03, 0x00}));
  196. // should not compile
  197. // as_writable_bytes(constRef);
  198. }
  199. Y_UNIT_TEST(TestAsWritableBytes) {
  200. uint32_t uintArr[] = {0x0c'00'0d'0e};
  201. TArrayRef<uint32_t> uintRef(uintArr);
  202. auto writableBytesRef = as_writable_bytes(uintRef);
  203. UNIT_ASSERT_VALUES_EQUAL(writableBytesRef.size(), sizeof(uint32_t));
  204. UNIT_ASSERT_EQUAL(
  205. writableBytesRef,
  206. MakeArrayRef(std::vector<char>{0x0e, 0x0d, 0x00, 0x0c}));
  207. uint32_t newVal = 0xde'ad'be'ef;
  208. std::memcpy(writableBytesRef.data(), &newVal, writableBytesRef.size());
  209. UNIT_ASSERT_VALUES_EQUAL(uintArr[0], newVal);
  210. }
  211. Y_UNIT_TEST(TestTypeDeductionViaMakeArrayRef) {
  212. TVector<int> vec{17, 19, 21};
  213. TArrayRef<int> ref = MakeArrayRef(vec);
  214. UNIT_ASSERT_VALUES_EQUAL(21, ref[2]);
  215. ref[1] = 23;
  216. UNIT_ASSERT_VALUES_EQUAL(23, vec[1]);
  217. const TVector<int>& constVec(vec);
  218. TArrayRef<const int> constRef = MakeArrayRef(constVec);
  219. UNIT_ASSERT_VALUES_EQUAL(21, constRef[2]);
  220. TArrayRef<const int> constRefFromNonConst = MakeArrayRef(vec);
  221. UNIT_ASSERT_VALUES_EQUAL(23, constRefFromNonConst[1]);
  222. }
  223. static void Do(const TArrayRef<int> a) {
  224. a[0] = 8;
  225. }
  226. Y_UNIT_TEST(TestConst) {
  227. int a[] = {1, 2};
  228. Do(a);
  229. UNIT_ASSERT_VALUES_EQUAL(a[0], 8);
  230. }
  231. Y_UNIT_TEST(TestConstexpr) {
  232. static constexpr const int a[] = {1, 2, -3, -4};
  233. static constexpr const auto r0 = MakeArrayRef(a, 1);
  234. static_assert(r0.size() == 1, "r0.size() is not equal 1");
  235. static_assert(r0.data()[0] == 1, "r0.data()[0] is not equal to 1");
  236. static constexpr const TArrayRef<const int> r1{a};
  237. static_assert(r1.size() == 4, "r1.size() is not equal to 4");
  238. static_assert(r1.data()[3] == -4, "r1.data()[3] is not equal to -4");
  239. static constexpr const TArrayRef<const int> r2 = r1;
  240. static_assert(r2.size() == 4, "r2.size() is not equal to 4");
  241. static_assert(r2.data()[2] == -3, "r2.data()[2] is not equal to -3");
  242. }
  243. template <typename T>
  244. static void Foo(const TConstArrayRef<T>) {
  245. // noop
  246. }
  247. Y_UNIT_TEST(TestMakeConstArrayRef) {
  248. TVector<int> data;
  249. // Won't compile because can't deduce `T` for `Foo`
  250. // Foo(data);
  251. // Won't compile because again can't deduce `T` for `Foo`
  252. // Foo(MakeArrayRef(data));
  253. // Success!
  254. Foo(MakeConstArrayRef(data));
  255. const TVector<int> constData;
  256. Foo(MakeConstArrayRef(constData));
  257. }
  258. } // Y_UNIT_TEST_SUITE(TestArrayRef)