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