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