fixed_array_test.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. // Copyright 2019 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "absl/container/fixed_array.h"
  15. #include <stdio.h>
  16. #include <cstring>
  17. #include <list>
  18. #include <memory>
  19. #include <numeric>
  20. #include <scoped_allocator>
  21. #include <stdexcept>
  22. #include <string>
  23. #include <vector>
  24. #include "gmock/gmock.h"
  25. #include "gtest/gtest.h"
  26. #include "absl/base/config.h"
  27. #include "absl/base/internal/exception_testing.h"
  28. #include "absl/base/options.h"
  29. #include "absl/container/internal/counting_allocator.h"
  30. #include "absl/hash/hash_testing.h"
  31. #include "absl/memory/memory.h"
  32. using ::testing::ElementsAreArray;
  33. namespace {
  34. // Helper routine to determine if a absl::FixedArray used stack allocation.
  35. template <typename ArrayType>
  36. static bool IsOnStack(const ArrayType& a) {
  37. return a.size() <= ArrayType::inline_elements;
  38. }
  39. class ConstructionTester {
  40. public:
  41. ConstructionTester() : self_ptr_(this), value_(0) { constructions++; }
  42. ~ConstructionTester() {
  43. assert(self_ptr_ == this);
  44. self_ptr_ = nullptr;
  45. destructions++;
  46. }
  47. // These are incremented as elements are constructed and destructed so we can
  48. // be sure all elements are properly cleaned up.
  49. static int constructions;
  50. static int destructions;
  51. void CheckConstructed() { assert(self_ptr_ == this); }
  52. void set(int value) { value_ = value; }
  53. int get() { return value_; }
  54. private:
  55. // self_ptr_ should always point to 'this' -- that's how we can be sure the
  56. // constructor has been called.
  57. ConstructionTester* self_ptr_;
  58. int value_;
  59. };
  60. int ConstructionTester::constructions = 0;
  61. int ConstructionTester::destructions = 0;
  62. // ThreeInts will initialize its three ints to the value stored in
  63. // ThreeInts::counter. The constructor increments counter so that each object
  64. // in an array of ThreeInts will have different values.
  65. class ThreeInts {
  66. public:
  67. ThreeInts() {
  68. x_ = counter;
  69. y_ = counter;
  70. z_ = counter;
  71. ++counter;
  72. }
  73. static int counter;
  74. int x_, y_, z_;
  75. };
  76. int ThreeInts::counter = 0;
  77. TEST(FixedArrayTest, CopyCtor) {
  78. absl::FixedArray<int, 10> on_stack(5);
  79. std::iota(on_stack.begin(), on_stack.end(), 0);
  80. absl::FixedArray<int, 10> stack_copy = on_stack;
  81. EXPECT_THAT(stack_copy, ElementsAreArray(on_stack));
  82. EXPECT_TRUE(IsOnStack(stack_copy));
  83. absl::FixedArray<int, 10> allocated(15);
  84. std::iota(allocated.begin(), allocated.end(), 0);
  85. absl::FixedArray<int, 10> alloced_copy = allocated;
  86. EXPECT_THAT(alloced_copy, ElementsAreArray(allocated));
  87. EXPECT_FALSE(IsOnStack(alloced_copy));
  88. }
  89. TEST(FixedArrayTest, MoveCtor) {
  90. absl::FixedArray<std::unique_ptr<int>, 10> on_stack(5);
  91. for (int i = 0; i < 5; ++i) {
  92. on_stack[i] = absl::make_unique<int>(i);
  93. }
  94. absl::FixedArray<std::unique_ptr<int>, 10> stack_copy = std::move(on_stack);
  95. for (int i = 0; i < 5; ++i) EXPECT_EQ(*(stack_copy[i]), i);
  96. EXPECT_EQ(stack_copy.size(), on_stack.size());
  97. absl::FixedArray<std::unique_ptr<int>, 10> allocated(15);
  98. for (int i = 0; i < 15; ++i) {
  99. allocated[i] = absl::make_unique<int>(i);
  100. }
  101. absl::FixedArray<std::unique_ptr<int>, 10> alloced_copy =
  102. std::move(allocated);
  103. for (int i = 0; i < 15; ++i) EXPECT_EQ(*(alloced_copy[i]), i);
  104. EXPECT_EQ(allocated.size(), alloced_copy.size());
  105. }
  106. TEST(FixedArrayTest, SmallObjects) {
  107. // Small object arrays
  108. {
  109. // Short arrays should be on the stack
  110. absl::FixedArray<int> array(4);
  111. EXPECT_TRUE(IsOnStack(array));
  112. }
  113. {
  114. // Large arrays should be on the heap
  115. absl::FixedArray<int> array(1048576);
  116. EXPECT_FALSE(IsOnStack(array));
  117. }
  118. {
  119. // Arrays of <= default size should be on the stack
  120. absl::FixedArray<int, 100> array(100);
  121. EXPECT_TRUE(IsOnStack(array));
  122. }
  123. {
  124. // Arrays of > default size should be on the heap
  125. absl::FixedArray<int, 100> array(101);
  126. EXPECT_FALSE(IsOnStack(array));
  127. }
  128. {
  129. // Arrays with different size elements should use approximately
  130. // same amount of stack space
  131. absl::FixedArray<int> array1(0);
  132. absl::FixedArray<char> array2(0);
  133. EXPECT_LE(sizeof(array1), sizeof(array2) + 100);
  134. EXPECT_LE(sizeof(array2), sizeof(array1) + 100);
  135. }
  136. {
  137. // Ensure that vectors are properly constructed inside a fixed array.
  138. absl::FixedArray<std::vector<int>> array(2);
  139. EXPECT_EQ(0, array[0].size());
  140. EXPECT_EQ(0, array[1].size());
  141. }
  142. {
  143. // Regardless of absl::FixedArray implementation, check that a type with a
  144. // low alignment requirement and a non power-of-two size is initialized
  145. // correctly.
  146. ThreeInts::counter = 1;
  147. absl::FixedArray<ThreeInts> array(2);
  148. EXPECT_EQ(1, array[0].x_);
  149. EXPECT_EQ(1, array[0].y_);
  150. EXPECT_EQ(1, array[0].z_);
  151. EXPECT_EQ(2, array[1].x_);
  152. EXPECT_EQ(2, array[1].y_);
  153. EXPECT_EQ(2, array[1].z_);
  154. }
  155. }
  156. TEST(FixedArrayTest, AtThrows) {
  157. absl::FixedArray<int> a = {1, 2, 3};
  158. EXPECT_EQ(a.at(2), 3);
  159. ABSL_BASE_INTERNAL_EXPECT_FAIL(a.at(3), std::out_of_range,
  160. "failed bounds check");
  161. }
  162. TEST(FixedArrayTest, Hardened) {
  163. #if !defined(NDEBUG) || ABSL_OPTION_HARDENED
  164. absl::FixedArray<int> a = {1, 2, 3};
  165. EXPECT_EQ(a[2], 3);
  166. EXPECT_DEATH_IF_SUPPORTED(a[3], "");
  167. EXPECT_DEATH_IF_SUPPORTED(a[-1], "");
  168. absl::FixedArray<int> empty(0);
  169. EXPECT_DEATH_IF_SUPPORTED(empty[0], "");
  170. EXPECT_DEATH_IF_SUPPORTED(empty[-1], "");
  171. EXPECT_DEATH_IF_SUPPORTED(empty.front(), "");
  172. EXPECT_DEATH_IF_SUPPORTED(empty.back(), "");
  173. #endif
  174. }
  175. TEST(FixedArrayRelationalsTest, EqualArrays) {
  176. for (int i = 0; i < 10; ++i) {
  177. absl::FixedArray<int, 5> a1(i);
  178. std::iota(a1.begin(), a1.end(), 0);
  179. absl::FixedArray<int, 5> a2(a1.begin(), a1.end());
  180. EXPECT_TRUE(a1 == a2);
  181. EXPECT_FALSE(a1 != a2);
  182. EXPECT_TRUE(a2 == a1);
  183. EXPECT_FALSE(a2 != a1);
  184. EXPECT_FALSE(a1 < a2);
  185. EXPECT_FALSE(a1 > a2);
  186. EXPECT_FALSE(a2 < a1);
  187. EXPECT_FALSE(a2 > a1);
  188. EXPECT_TRUE(a1 <= a2);
  189. EXPECT_TRUE(a1 >= a2);
  190. EXPECT_TRUE(a2 <= a1);
  191. EXPECT_TRUE(a2 >= a1);
  192. }
  193. }
  194. TEST(FixedArrayRelationalsTest, UnequalArrays) {
  195. for (int i = 1; i < 10; ++i) {
  196. absl::FixedArray<int, 5> a1(i);
  197. std::iota(a1.begin(), a1.end(), 0);
  198. absl::FixedArray<int, 5> a2(a1.begin(), a1.end());
  199. --a2[i / 2];
  200. EXPECT_FALSE(a1 == a2);
  201. EXPECT_TRUE(a1 != a2);
  202. EXPECT_FALSE(a2 == a1);
  203. EXPECT_TRUE(a2 != a1);
  204. EXPECT_FALSE(a1 < a2);
  205. EXPECT_TRUE(a1 > a2);
  206. EXPECT_TRUE(a2 < a1);
  207. EXPECT_FALSE(a2 > a1);
  208. EXPECT_FALSE(a1 <= a2);
  209. EXPECT_TRUE(a1 >= a2);
  210. EXPECT_TRUE(a2 <= a1);
  211. EXPECT_FALSE(a2 >= a1);
  212. }
  213. }
  214. template <int stack_elements>
  215. static void TestArray(int n) {
  216. SCOPED_TRACE(n);
  217. SCOPED_TRACE(stack_elements);
  218. ConstructionTester::constructions = 0;
  219. ConstructionTester::destructions = 0;
  220. {
  221. absl::FixedArray<ConstructionTester, stack_elements> array(n);
  222. EXPECT_THAT(array.size(), n);
  223. EXPECT_THAT(array.memsize(), sizeof(ConstructionTester) * n);
  224. EXPECT_THAT(array.begin() + n, array.end());
  225. // Check that all elements were constructed
  226. for (int i = 0; i < n; i++) {
  227. array[i].CheckConstructed();
  228. }
  229. // Check that no other elements were constructed
  230. EXPECT_THAT(ConstructionTester::constructions, n);
  231. // Test operator[]
  232. for (int i = 0; i < n; i++) {
  233. array[i].set(i);
  234. }
  235. for (int i = 0; i < n; i++) {
  236. EXPECT_THAT(array[i].get(), i);
  237. EXPECT_THAT(array.data()[i].get(), i);
  238. }
  239. // Test data()
  240. for (int i = 0; i < n; i++) {
  241. array.data()[i].set(i + 1);
  242. }
  243. for (int i = 0; i < n; i++) {
  244. EXPECT_THAT(array[i].get(), i + 1);
  245. EXPECT_THAT(array.data()[i].get(), i + 1);
  246. }
  247. } // Close scope containing 'array'.
  248. // Check that all constructed elements were destructed.
  249. EXPECT_EQ(ConstructionTester::constructions,
  250. ConstructionTester::destructions);
  251. }
  252. template <int elements_per_inner_array, int inline_elements>
  253. static void TestArrayOfArrays(int n) {
  254. SCOPED_TRACE(n);
  255. SCOPED_TRACE(inline_elements);
  256. SCOPED_TRACE(elements_per_inner_array);
  257. ConstructionTester::constructions = 0;
  258. ConstructionTester::destructions = 0;
  259. {
  260. using InnerArray = ConstructionTester[elements_per_inner_array];
  261. // Heap-allocate the FixedArray to avoid blowing the stack frame.
  262. auto array_ptr =
  263. absl::make_unique<absl::FixedArray<InnerArray, inline_elements>>(n);
  264. auto& array = *array_ptr;
  265. ASSERT_EQ(array.size(), n);
  266. ASSERT_EQ(array.memsize(),
  267. sizeof(ConstructionTester) * elements_per_inner_array * n);
  268. ASSERT_EQ(array.begin() + n, array.end());
  269. // Check that all elements were constructed
  270. for (int i = 0; i < n; i++) {
  271. for (int j = 0; j < elements_per_inner_array; j++) {
  272. (array[i])[j].CheckConstructed();
  273. }
  274. }
  275. // Check that no other elements were constructed
  276. ASSERT_EQ(ConstructionTester::constructions, n * elements_per_inner_array);
  277. // Test operator[]
  278. for (int i = 0; i < n; i++) {
  279. for (int j = 0; j < elements_per_inner_array; j++) {
  280. (array[i])[j].set(i * elements_per_inner_array + j);
  281. }
  282. }
  283. for (int i = 0; i < n; i++) {
  284. for (int j = 0; j < elements_per_inner_array; j++) {
  285. ASSERT_EQ((array[i])[j].get(), i * elements_per_inner_array + j);
  286. ASSERT_EQ((array.data()[i])[j].get(), i * elements_per_inner_array + j);
  287. }
  288. }
  289. // Test data()
  290. for (int i = 0; i < n; i++) {
  291. for (int j = 0; j < elements_per_inner_array; j++) {
  292. (array.data()[i])[j].set((i + 1) * elements_per_inner_array + j);
  293. }
  294. }
  295. for (int i = 0; i < n; i++) {
  296. for (int j = 0; j < elements_per_inner_array; j++) {
  297. ASSERT_EQ((array[i])[j].get(), (i + 1) * elements_per_inner_array + j);
  298. ASSERT_EQ((array.data()[i])[j].get(),
  299. (i + 1) * elements_per_inner_array + j);
  300. }
  301. }
  302. } // Close scope containing 'array'.
  303. // Check that all constructed elements were destructed.
  304. EXPECT_EQ(ConstructionTester::constructions,
  305. ConstructionTester::destructions);
  306. }
  307. TEST(IteratorConstructorTest, NonInline) {
  308. int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
  309. absl::FixedArray<int, ABSL_ARRAYSIZE(kInput) - 1> const fixed(
  310. kInput, kInput + ABSL_ARRAYSIZE(kInput));
  311. ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
  312. for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {
  313. ASSERT_EQ(kInput[i], fixed[i]);
  314. }
  315. }
  316. TEST(IteratorConstructorTest, Inline) {
  317. int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
  318. absl::FixedArray<int, ABSL_ARRAYSIZE(kInput)> const fixed(
  319. kInput, kInput + ABSL_ARRAYSIZE(kInput));
  320. ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
  321. for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {
  322. ASSERT_EQ(kInput[i], fixed[i]);
  323. }
  324. }
  325. TEST(IteratorConstructorTest, NonPod) {
  326. char const* kInput[] = {"red", "orange", "yellow", "green",
  327. "blue", "indigo", "violet"};
  328. absl::FixedArray<std::string> const fixed(kInput,
  329. kInput + ABSL_ARRAYSIZE(kInput));
  330. ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
  331. for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {
  332. ASSERT_EQ(kInput[i], fixed[i]);
  333. }
  334. }
  335. TEST(IteratorConstructorTest, FromEmptyVector) {
  336. std::vector<int> const empty;
  337. absl::FixedArray<int> const fixed(empty.begin(), empty.end());
  338. EXPECT_EQ(0, fixed.size());
  339. EXPECT_EQ(empty.size(), fixed.size());
  340. }
  341. TEST(IteratorConstructorTest, FromNonEmptyVector) {
  342. int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
  343. std::vector<int> const items(kInput, kInput + ABSL_ARRAYSIZE(kInput));
  344. absl::FixedArray<int> const fixed(items.begin(), items.end());
  345. ASSERT_EQ(items.size(), fixed.size());
  346. for (size_t i = 0; i < items.size(); ++i) {
  347. ASSERT_EQ(items[i], fixed[i]);
  348. }
  349. }
  350. TEST(IteratorConstructorTest, FromBidirectionalIteratorRange) {
  351. int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
  352. std::list<int> const items(kInput, kInput + ABSL_ARRAYSIZE(kInput));
  353. absl::FixedArray<int> const fixed(items.begin(), items.end());
  354. EXPECT_THAT(fixed, testing::ElementsAreArray(kInput));
  355. }
  356. TEST(InitListConstructorTest, InitListConstruction) {
  357. absl::FixedArray<int> fixed = {1, 2, 3};
  358. EXPECT_THAT(fixed, testing::ElementsAreArray({1, 2, 3}));
  359. }
  360. TEST(FillConstructorTest, NonEmptyArrays) {
  361. absl::FixedArray<int> stack_array(4, 1);
  362. EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));
  363. absl::FixedArray<int, 0> heap_array(4, 1);
  364. EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));
  365. }
  366. TEST(FillConstructorTest, EmptyArray) {
  367. absl::FixedArray<int> empty_fill(0, 1);
  368. absl::FixedArray<int> empty_size(0);
  369. EXPECT_EQ(empty_fill, empty_size);
  370. }
  371. TEST(FillConstructorTest, NotTriviallyCopyable) {
  372. std::string str = "abcd";
  373. absl::FixedArray<std::string> strings = {str, str, str, str};
  374. absl::FixedArray<std::string> array(4, str);
  375. EXPECT_EQ(array, strings);
  376. }
  377. TEST(FillConstructorTest, Disambiguation) {
  378. absl::FixedArray<size_t> a(1, 2);
  379. EXPECT_THAT(a, testing::ElementsAre(2));
  380. }
  381. TEST(FixedArrayTest, ManySizedArrays) {
  382. std::vector<int> sizes;
  383. for (int i = 1; i < 100; i++) sizes.push_back(i);
  384. for (int i = 100; i <= 1000; i += 100) sizes.push_back(i);
  385. for (int n : sizes) {
  386. TestArray<0>(n);
  387. TestArray<1>(n);
  388. TestArray<64>(n);
  389. TestArray<1000>(n);
  390. }
  391. }
  392. TEST(FixedArrayTest, ManySizedArraysOfArraysOf1) {
  393. for (int n = 1; n < 1000; n++) {
  394. ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 0>(n)));
  395. ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1>(n)));
  396. ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 64>(n)));
  397. ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1000>(n)));
  398. }
  399. }
  400. TEST(FixedArrayTest, ManySizedArraysOfArraysOf2) {
  401. for (int n = 1; n < 1000; n++) {
  402. TestArrayOfArrays<2, 0>(n);
  403. TestArrayOfArrays<2, 1>(n);
  404. TestArrayOfArrays<2, 64>(n);
  405. TestArrayOfArrays<2, 1000>(n);
  406. }
  407. }
  408. // If value_type is put inside of a struct container,
  409. // we might evoke this error in a hardened build unless data() is carefully
  410. // written, so check on that.
  411. // error: call to int __builtin___sprintf_chk(etc...)
  412. // will always overflow destination buffer [-Werror]
  413. TEST(FixedArrayTest, AvoidParanoidDiagnostics) {
  414. absl::FixedArray<char, 32> buf(32);
  415. sprintf(buf.data(), "foo"); // NOLINT(runtime/printf)
  416. }
  417. TEST(FixedArrayTest, TooBigInlinedSpace) {
  418. struct TooBig {
  419. char c[1 << 20];
  420. }; // too big for even one on the stack
  421. // Simulate the data members of absl::FixedArray, a pointer and a size_t.
  422. struct Data {
  423. TooBig* p;
  424. size_t size;
  425. };
  426. // Make sure TooBig objects are not inlined for 0 or default size.
  427. static_assert(sizeof(absl::FixedArray<TooBig, 0>) == sizeof(Data),
  428. "0-sized absl::FixedArray should have same size as Data.");
  429. static_assert(alignof(absl::FixedArray<TooBig, 0>) == alignof(Data),
  430. "0-sized absl::FixedArray should have same alignment as Data.");
  431. static_assert(sizeof(absl::FixedArray<TooBig>) == sizeof(Data),
  432. "default-sized absl::FixedArray should have same size as Data");
  433. static_assert(
  434. alignof(absl::FixedArray<TooBig>) == alignof(Data),
  435. "default-sized absl::FixedArray should have same alignment as Data.");
  436. }
  437. // PickyDelete EXPECTs its class-scope deallocation funcs are unused.
  438. struct PickyDelete {
  439. PickyDelete() {}
  440. ~PickyDelete() {}
  441. void operator delete(void* p) {
  442. EXPECT_TRUE(false) << __FUNCTION__;
  443. ::operator delete(p);
  444. }
  445. void operator delete[](void* p) {
  446. EXPECT_TRUE(false) << __FUNCTION__;
  447. ::operator delete[](p);
  448. }
  449. };
  450. TEST(FixedArrayTest, UsesGlobalAlloc) { absl::FixedArray<PickyDelete, 0> a(5); }
  451. TEST(FixedArrayTest, Data) {
  452. static const int kInput[] = {2, 3, 5, 7, 11, 13, 17};
  453. absl::FixedArray<int> fa(std::begin(kInput), std::end(kInput));
  454. EXPECT_EQ(fa.data(), &*fa.begin());
  455. EXPECT_EQ(fa.data(), &fa[0]);
  456. const absl::FixedArray<int>& cfa = fa;
  457. EXPECT_EQ(cfa.data(), &*cfa.begin());
  458. EXPECT_EQ(cfa.data(), &cfa[0]);
  459. }
  460. TEST(FixedArrayTest, Empty) {
  461. absl::FixedArray<int> empty(0);
  462. absl::FixedArray<int> inline_filled(1);
  463. absl::FixedArray<int, 0> heap_filled(1);
  464. EXPECT_TRUE(empty.empty());
  465. EXPECT_FALSE(inline_filled.empty());
  466. EXPECT_FALSE(heap_filled.empty());
  467. }
  468. TEST(FixedArrayTest, FrontAndBack) {
  469. absl::FixedArray<int, 3 * sizeof(int)> inlined = {1, 2, 3};
  470. EXPECT_EQ(inlined.front(), 1);
  471. EXPECT_EQ(inlined.back(), 3);
  472. absl::FixedArray<int, 0> allocated = {1, 2, 3};
  473. EXPECT_EQ(allocated.front(), 1);
  474. EXPECT_EQ(allocated.back(), 3);
  475. absl::FixedArray<int> one_element = {1};
  476. EXPECT_EQ(one_element.front(), one_element.back());
  477. }
  478. TEST(FixedArrayTest, ReverseIteratorInlined) {
  479. absl::FixedArray<int, 5 * sizeof(int)> a = {0, 1, 2, 3, 4};
  480. int counter = 5;
  481. for (absl::FixedArray<int>::reverse_iterator iter = a.rbegin();
  482. iter != a.rend(); ++iter) {
  483. counter--;
  484. EXPECT_EQ(counter, *iter);
  485. }
  486. EXPECT_EQ(counter, 0);
  487. counter = 5;
  488. for (absl::FixedArray<int>::const_reverse_iterator iter = a.rbegin();
  489. iter != a.rend(); ++iter) {
  490. counter--;
  491. EXPECT_EQ(counter, *iter);
  492. }
  493. EXPECT_EQ(counter, 0);
  494. counter = 5;
  495. for (auto iter = a.crbegin(); iter != a.crend(); ++iter) {
  496. counter--;
  497. EXPECT_EQ(counter, *iter);
  498. }
  499. EXPECT_EQ(counter, 0);
  500. }
  501. TEST(FixedArrayTest, ReverseIteratorAllocated) {
  502. absl::FixedArray<int, 0> a = {0, 1, 2, 3, 4};
  503. int counter = 5;
  504. for (absl::FixedArray<int>::reverse_iterator iter = a.rbegin();
  505. iter != a.rend(); ++iter) {
  506. counter--;
  507. EXPECT_EQ(counter, *iter);
  508. }
  509. EXPECT_EQ(counter, 0);
  510. counter = 5;
  511. for (absl::FixedArray<int>::const_reverse_iterator iter = a.rbegin();
  512. iter != a.rend(); ++iter) {
  513. counter--;
  514. EXPECT_EQ(counter, *iter);
  515. }
  516. EXPECT_EQ(counter, 0);
  517. counter = 5;
  518. for (auto iter = a.crbegin(); iter != a.crend(); ++iter) {
  519. counter--;
  520. EXPECT_EQ(counter, *iter);
  521. }
  522. EXPECT_EQ(counter, 0);
  523. }
  524. TEST(FixedArrayTest, Fill) {
  525. absl::FixedArray<int, 5 * sizeof(int)> inlined(5);
  526. int fill_val = 42;
  527. inlined.fill(fill_val);
  528. for (int i : inlined) EXPECT_EQ(i, fill_val);
  529. absl::FixedArray<int, 0> allocated(5);
  530. allocated.fill(fill_val);
  531. for (int i : allocated) EXPECT_EQ(i, fill_val);
  532. // It doesn't do anything, just make sure this compiles.
  533. absl::FixedArray<int> empty(0);
  534. empty.fill(fill_val);
  535. }
  536. #ifndef __GNUC__
  537. TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) {
  538. using T = char;
  539. constexpr auto capacity = 10;
  540. using FixedArrType = absl::FixedArray<T, capacity>;
  541. constexpr auto scrubbed_bits = 0x95;
  542. constexpr auto length = capacity / 2;
  543. alignas(FixedArrType) unsigned char buff[sizeof(FixedArrType)];
  544. std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrType));
  545. FixedArrType* arr =
  546. ::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length);
  547. EXPECT_THAT(*arr, testing::Each(scrubbed_bits));
  548. arr->~FixedArrType();
  549. }
  550. #endif // __GNUC__
  551. TEST(AllocatorSupportTest, CountInlineAllocations) {
  552. constexpr size_t inlined_size = 4;
  553. using Alloc = absl::container_internal::CountingAllocator<int>;
  554. using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
  555. int64_t allocated = 0;
  556. int64_t active_instances = 0;
  557. {
  558. const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
  559. Alloc alloc(&allocated, &active_instances);
  560. AllocFxdArr arr(ia, ia + inlined_size, alloc);
  561. static_cast<void>(arr);
  562. }
  563. EXPECT_EQ(allocated, 0);
  564. EXPECT_EQ(active_instances, 0);
  565. }
  566. TEST(AllocatorSupportTest, CountOutoflineAllocations) {
  567. constexpr size_t inlined_size = 4;
  568. using Alloc = absl::container_internal::CountingAllocator<int>;
  569. using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
  570. int64_t allocated = 0;
  571. int64_t active_instances = 0;
  572. {
  573. const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
  574. Alloc alloc(&allocated, &active_instances);
  575. AllocFxdArr arr(ia, ia + ABSL_ARRAYSIZE(ia), alloc);
  576. EXPECT_EQ(allocated, arr.size() * sizeof(int));
  577. static_cast<void>(arr);
  578. }
  579. EXPECT_EQ(active_instances, 0);
  580. }
  581. TEST(AllocatorSupportTest, CountCopyInlineAllocations) {
  582. constexpr size_t inlined_size = 4;
  583. using Alloc = absl::container_internal::CountingAllocator<int>;
  584. using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
  585. int64_t allocated1 = 0;
  586. int64_t allocated2 = 0;
  587. int64_t active_instances = 0;
  588. Alloc alloc(&allocated1, &active_instances);
  589. Alloc alloc2(&allocated2, &active_instances);
  590. {
  591. int initial_value = 1;
  592. AllocFxdArr arr1(inlined_size / 2, initial_value, alloc);
  593. EXPECT_EQ(allocated1, 0);
  594. AllocFxdArr arr2(arr1, alloc2);
  595. EXPECT_EQ(allocated2, 0);
  596. static_cast<void>(arr1);
  597. static_cast<void>(arr2);
  598. }
  599. EXPECT_EQ(active_instances, 0);
  600. }
  601. TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) {
  602. constexpr size_t inlined_size = 4;
  603. using Alloc = absl::container_internal::CountingAllocator<int>;
  604. using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
  605. int64_t allocated1 = 0;
  606. int64_t allocated2 = 0;
  607. int64_t active_instances = 0;
  608. Alloc alloc(&allocated1, &active_instances);
  609. Alloc alloc2(&allocated2, &active_instances);
  610. {
  611. int initial_value = 1;
  612. AllocFxdArr arr1(inlined_size * 2, initial_value, alloc);
  613. EXPECT_EQ(allocated1, arr1.size() * sizeof(int));
  614. AllocFxdArr arr2(arr1, alloc2);
  615. EXPECT_EQ(allocated2, inlined_size * 2 * sizeof(int));
  616. static_cast<void>(arr1);
  617. static_cast<void>(arr2);
  618. }
  619. EXPECT_EQ(active_instances, 0);
  620. }
  621. TEST(AllocatorSupportTest, SizeValAllocConstructor) {
  622. using testing::AllOf;
  623. using testing::Each;
  624. using testing::SizeIs;
  625. constexpr size_t inlined_size = 4;
  626. using Alloc = absl::container_internal::CountingAllocator<int>;
  627. using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
  628. {
  629. auto len = inlined_size / 2;
  630. auto val = 0;
  631. int64_t allocated = 0;
  632. AllocFxdArr arr(len, val, Alloc(&allocated));
  633. EXPECT_EQ(allocated, 0);
  634. EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0)));
  635. }
  636. {
  637. auto len = inlined_size * 2;
  638. auto val = 0;
  639. int64_t allocated = 0;
  640. AllocFxdArr arr(len, val, Alloc(&allocated));
  641. EXPECT_EQ(allocated, len * sizeof(int));
  642. EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0)));
  643. }
  644. }
  645. #ifdef ABSL_HAVE_ADDRESS_SANITIZER
  646. TEST(FixedArrayTest, AddressSanitizerAnnotations1) {
  647. absl::FixedArray<int, 32> a(10);
  648. int* raw = a.data();
  649. raw[0] = 0;
  650. raw[9] = 0;
  651. EXPECT_DEATH_IF_SUPPORTED(raw[-2] = 0, "container-overflow");
  652. EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, "container-overflow");
  653. EXPECT_DEATH_IF_SUPPORTED(raw[10] = 0, "container-overflow");
  654. EXPECT_DEATH_IF_SUPPORTED(raw[31] = 0, "container-overflow");
  655. }
  656. TEST(FixedArrayTest, AddressSanitizerAnnotations2) {
  657. absl::FixedArray<char, 17> a(12);
  658. char* raw = a.data();
  659. raw[0] = 0;
  660. raw[11] = 0;
  661. EXPECT_DEATH_IF_SUPPORTED(raw[-7] = 0, "container-overflow");
  662. EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, "container-overflow");
  663. EXPECT_DEATH_IF_SUPPORTED(raw[12] = 0, "container-overflow");
  664. EXPECT_DEATH_IF_SUPPORTED(raw[17] = 0, "container-overflow");
  665. }
  666. TEST(FixedArrayTest, AddressSanitizerAnnotations3) {
  667. absl::FixedArray<uint64_t, 20> a(20);
  668. uint64_t* raw = a.data();
  669. raw[0] = 0;
  670. raw[19] = 0;
  671. EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, "container-overflow");
  672. EXPECT_DEATH_IF_SUPPORTED(raw[20] = 0, "container-overflow");
  673. }
  674. TEST(FixedArrayTest, AddressSanitizerAnnotations4) {
  675. absl::FixedArray<ThreeInts> a(10);
  676. ThreeInts* raw = a.data();
  677. raw[0] = ThreeInts();
  678. raw[9] = ThreeInts();
  679. // Note: raw[-1] is pointing to 12 bytes before the container range. However,
  680. // there is only a 8-byte red zone before the container range, so we only
  681. // access the last 4 bytes of the struct to make sure it stays within the red
  682. // zone.
  683. EXPECT_DEATH_IF_SUPPORTED(raw[-1].z_ = 0, "container-overflow");
  684. EXPECT_DEATH_IF_SUPPORTED(raw[10] = ThreeInts(), "container-overflow");
  685. // The actual size of storage is kDefaultBytes=256, 21*12 = 252,
  686. // so reading raw[21] should still trigger the correct warning.
  687. EXPECT_DEATH_IF_SUPPORTED(raw[21] = ThreeInts(), "container-overflow");
  688. }
  689. #endif // ABSL_HAVE_ADDRESS_SANITIZER
  690. TEST(FixedArrayTest, AbslHashValueWorks) {
  691. using V = absl::FixedArray<int>;
  692. std::vector<V> cases;
  693. // Generate a variety of vectors some of these are small enough for the inline
  694. // space but are stored out of line.
  695. for (int i = 0; i < 10; ++i) {
  696. V v(i);
  697. for (int j = 0; j < i; ++j) {
  698. v[j] = j;
  699. }
  700. cases.push_back(v);
  701. }
  702. EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
  703. }
  704. } // namespace