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