blob: b6782f517a6cea9113572b04d9c76498f4d08896 [file] [log] [blame]
mistergc2e75482017-09-19 16:54:40 -04001// Copyright 2017 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// http://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#include <list>
19#include <memory>
20#include <numeric>
21#include <stdexcept>
22#include <string>
23#include <vector>
24
25#include "gmock/gmock.h"
26#include "gtest/gtest.h"
27#include "absl/base/internal/exception_testing.h"
28#include "absl/memory/memory.h"
29
Abseil Team6365d172018-01-02 08:53:02 -080030using ::testing::ElementsAreArray;
31
mistergc2e75482017-09-19 16:54:40 -040032namespace {
33
34// Helper routine to determine if a absl::FixedArray used stack allocation.
35template <typename ArrayType>
36static bool IsOnStack(const ArrayType& a) {
37 return a.size() <= ArrayType::inline_elements;
38}
39
40class ConstructionTester {
41 public:
42 ConstructionTester()
43 : self_ptr_(this),
44 value_(0) {
45 constructions++;
46 }
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
58 void CheckConstructed() {
59 assert(self_ptr_ == this);
60 }
61
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 {
150 // Arrays of > default size should be on the stack
151 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);
160 EXPECT_LE(sizeof(array1), sizeof(array2)+100);
161 EXPECT_LE(sizeof(array2), sizeof(array1)+100);
162 }
163
164 {
165 // Ensure that vectors are properly constructed inside a fixed array.
166 absl::FixedArray<std::vector<int> > array(2);
167 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
193TEST(FixedArrayRelationalsTest, EqualArrays) {
194 for (int i = 0; i < 10; ++i) {
195 absl::FixedArray<int, 5> a1(i);
196 std::iota(a1.begin(), a1.end(), 0);
197 absl::FixedArray<int, 5> a2(a1.begin(), a1.end());
198
199 EXPECT_TRUE(a1 == a2);
200 EXPECT_FALSE(a1 != a2);
201 EXPECT_TRUE(a2 == a1);
202 EXPECT_FALSE(a2 != a1);
203 EXPECT_FALSE(a1 < a2);
204 EXPECT_FALSE(a1 > a2);
205 EXPECT_FALSE(a2 < a1);
206 EXPECT_FALSE(a2 > a1);
207 EXPECT_TRUE(a1 <= a2);
208 EXPECT_TRUE(a1 >= a2);
209 EXPECT_TRUE(a2 <= a1);
210 EXPECT_TRUE(a2 >= a1);
211 }
212}
213
214TEST(FixedArrayRelationalsTest, UnequalArrays) {
215 for (int i = 1; i < 10; ++i) {
216 absl::FixedArray<int, 5> a1(i);
217 std::iota(a1.begin(), a1.end(), 0);
218 absl::FixedArray<int, 5> a2(a1.begin(), a1.end());
219 --a2[i / 2];
220
221 EXPECT_FALSE(a1 == a2);
222 EXPECT_TRUE(a1 != a2);
223 EXPECT_FALSE(a2 == a1);
224 EXPECT_TRUE(a2 != a1);
225 EXPECT_FALSE(a1 < a2);
226 EXPECT_TRUE(a1 > a2);
227 EXPECT_TRUE(a2 < a1);
228 EXPECT_FALSE(a2 > a1);
229 EXPECT_FALSE(a1 <= a2);
230 EXPECT_TRUE(a1 >= a2);
231 EXPECT_TRUE(a2 <= a1);
232 EXPECT_FALSE(a2 >= a1);
233 }
234}
235
236template <int stack_elements>
237static void TestArray(int n) {
238 SCOPED_TRACE(n);
239 SCOPED_TRACE(stack_elements);
240 ConstructionTester::constructions = 0;
241 ConstructionTester::destructions = 0;
242 {
243 absl::FixedArray<ConstructionTester, stack_elements> array(n);
244
245 EXPECT_THAT(array.size(), n);
246 EXPECT_THAT(array.memsize(), sizeof(ConstructionTester) * n);
247 EXPECT_THAT(array.begin() + n, array.end());
248
249 // Check that all elements were constructed
250 for (int i = 0; i < n; i++) {
251 array[i].CheckConstructed();
252 }
253 // Check that no other elements were constructed
254 EXPECT_THAT(ConstructionTester::constructions, n);
255
256 // Test operator[]
257 for (int i = 0; i < n; i++) {
258 array[i].set(i);
259 }
260 for (int i = 0; i < n; i++) {
261 EXPECT_THAT(array[i].get(), i);
262 EXPECT_THAT(array.data()[i].get(), i);
263 }
264
265 // Test data()
266 for (int i = 0; i < n; i++) {
267 array.data()[i].set(i + 1);
268 }
269 for (int i = 0; i < n; i++) {
270 EXPECT_THAT(array[i].get(), i+1);
271 EXPECT_THAT(array.data()[i].get(), i+1);
272 }
273 } // Close scope containing 'array'.
274
275 // Check that all constructed elements were destructed.
276 EXPECT_EQ(ConstructionTester::constructions,
277 ConstructionTester::destructions);
278}
279
280template <int elements_per_inner_array, int inline_elements>
281static void TestArrayOfArrays(int n) {
282 SCOPED_TRACE(n);
283 SCOPED_TRACE(inline_elements);
284 SCOPED_TRACE(elements_per_inner_array);
285 ConstructionTester::constructions = 0;
286 ConstructionTester::destructions = 0;
287 {
288 using InnerArray = ConstructionTester[elements_per_inner_array];
289 // Heap-allocate the FixedArray to avoid blowing the stack frame.
290 auto array_ptr =
291 absl::make_unique<absl::FixedArray<InnerArray, inline_elements>>(n);
292 auto& array = *array_ptr;
293
294 ASSERT_EQ(array.size(), n);
295 ASSERT_EQ(array.memsize(),
296 sizeof(ConstructionTester) * elements_per_inner_array * n);
297 ASSERT_EQ(array.begin() + n, array.end());
298
299 // Check that all elements were constructed
300 for (int i = 0; i < n; i++) {
301 for (int j = 0; j < elements_per_inner_array; j++) {
302 (array[i])[j].CheckConstructed();
303 }
304 }
305 // Check that no other elements were constructed
306 ASSERT_EQ(ConstructionTester::constructions, n * elements_per_inner_array);
307
308 // Test operator[]
309 for (int i = 0; i < n; i++) {
310 for (int j = 0; j < elements_per_inner_array; j++) {
311 (array[i])[j].set(i * elements_per_inner_array + j);
312 }
313 }
314 for (int i = 0; i < n; i++) {
315 for (int j = 0; j < elements_per_inner_array; j++) {
316 ASSERT_EQ((array[i])[j].get(), i * elements_per_inner_array + j);
317 ASSERT_EQ((array.data()[i])[j].get(), i * elements_per_inner_array + j);
318 }
319 }
320
321 // Test data()
322 for (int i = 0; i < n; i++) {
323 for (int j = 0; j < elements_per_inner_array; j++) {
324 (array.data()[i])[j].set((i + 1) * elements_per_inner_array + j);
325 }
326 }
327 for (int i = 0; i < n; i++) {
328 for (int j = 0; j < elements_per_inner_array; j++) {
329 ASSERT_EQ((array[i])[j].get(),
330 (i + 1) * elements_per_inner_array + j);
331 ASSERT_EQ((array.data()[i])[j].get(),
332 (i + 1) * elements_per_inner_array + j);
333 }
334 }
335 } // Close scope containing 'array'.
336
337 // Check that all constructed elements were destructed.
338 EXPECT_EQ(ConstructionTester::constructions,
339 ConstructionTester::destructions);
340}
341
342TEST(IteratorConstructorTest, NonInline) {
343 int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
344 absl::FixedArray<int, ABSL_ARRAYSIZE(kInput) - 1> const fixed(
345 kInput, kInput + ABSL_ARRAYSIZE(kInput));
346 ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
347 for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {
348 ASSERT_EQ(kInput[i], fixed[i]);
349 }
350}
351
352TEST(IteratorConstructorTest, Inline) {
353 int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
354 absl::FixedArray<int, ABSL_ARRAYSIZE(kInput)> const fixed(
355 kInput, kInput + ABSL_ARRAYSIZE(kInput));
356 ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
357 for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {
358 ASSERT_EQ(kInput[i], fixed[i]);
359 }
360}
361
362TEST(IteratorConstructorTest, NonPod) {
363 char const* kInput[] =
364 { "red", "orange", "yellow", "green", "blue", "indigo", "violet" };
365 absl::FixedArray<std::string> const fixed(kInput, kInput + ABSL_ARRAYSIZE(kInput));
366 ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
367 for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {
368 ASSERT_EQ(kInput[i], fixed[i]);
369 }
370}
371
372TEST(IteratorConstructorTest, FromEmptyVector) {
373 std::vector<int> const empty;
374 absl::FixedArray<int> const fixed(empty.begin(), empty.end());
375 EXPECT_EQ(0, fixed.size());
376 EXPECT_EQ(empty.size(), fixed.size());
377}
378
379TEST(IteratorConstructorTest, FromNonEmptyVector) {
380 int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
381 std::vector<int> const items(kInput, kInput + ABSL_ARRAYSIZE(kInput));
382 absl::FixedArray<int> const fixed(items.begin(), items.end());
383 ASSERT_EQ(items.size(), fixed.size());
384 for (size_t i = 0; i < items.size(); ++i) {
385 ASSERT_EQ(items[i], fixed[i]);
386 }
387}
388
389TEST(IteratorConstructorTest, FromBidirectionalIteratorRange) {
390 int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
391 std::list<int> const items(kInput, kInput + ABSL_ARRAYSIZE(kInput));
392 absl::FixedArray<int> const fixed(items.begin(), items.end());
393 EXPECT_THAT(fixed, testing::ElementsAreArray(kInput));
394}
395
396TEST(InitListConstructorTest, InitListConstruction) {
397 absl::FixedArray<int> fixed = {1, 2, 3};
398 EXPECT_THAT(fixed, testing::ElementsAreArray({1, 2, 3}));
399}
400
401TEST(FillConstructorTest, NonEmptyArrays) {
402 absl::FixedArray<int> stack_array(4, 1);
403 EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));
404
405 absl::FixedArray<int, 0> heap_array(4, 1);
406 EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));
407}
408
409TEST(FillConstructorTest, EmptyArray) {
410 absl::FixedArray<int> empty_fill(0, 1);
411 absl::FixedArray<int> empty_size(0);
412 EXPECT_EQ(empty_fill, empty_size);
413}
414
415TEST(FillConstructorTest, NotTriviallyCopyable) {
416 std::string str = "abcd";
417 absl::FixedArray<std::string> strings = {str, str, str, str};
418
419 absl::FixedArray<std::string> array(4, str);
420 EXPECT_EQ(array, strings);
421}
422
423TEST(FillConstructorTest, Disambiguation) {
424 absl::FixedArray<size_t> a(1, 2);
425 EXPECT_THAT(a, testing::ElementsAre(2));
426}
427
428TEST(FixedArrayTest, ManySizedArrays) {
429 std::vector<int> sizes;
430 for (int i = 1; i < 100; i++) sizes.push_back(i);
431 for (int i = 100; i <= 1000; i += 100) sizes.push_back(i);
432 for (int n : sizes) {
433 TestArray<0>(n);
434 TestArray<1>(n);
435 TestArray<64>(n);
436 TestArray<1000>(n);
437 }
438}
439
440TEST(FixedArrayTest, ManySizedArraysOfArraysOf1) {
441 for (int n = 1; n < 1000; n++) {
442 ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 0>(n)));
443 ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1>(n)));
444 ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 64>(n)));
445 ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1000>(n)));
446 }
447}
448
449TEST(FixedArrayTest, ManySizedArraysOfArraysOf2) {
450 for (int n = 1; n < 1000; n++) {
451 TestArrayOfArrays<2, 0>(n);
452 TestArrayOfArrays<2, 1>(n);
453 TestArrayOfArrays<2, 64>(n);
454 TestArrayOfArrays<2, 1000>(n);
455 }
456}
457
458// If value_type is put inside of a struct container,
459// we might evoke this error in a hardened build unless data() is carefully
460// written, so check on that.
461// error: call to int __builtin___sprintf_chk(etc...)
462// will always overflow destination buffer [-Werror]
463TEST(FixedArrayTest, AvoidParanoidDiagnostics) {
464 absl::FixedArray<char, 32> buf(32);
465 sprintf(buf.data(), "foo"); // NOLINT(runtime/printf)
466}
467
468TEST(FixedArrayTest, TooBigInlinedSpace) {
469 struct TooBig {
470 char c[1 << 20];
471 }; // too big for even one on the stack
472
473 // Simulate the data members of absl::FixedArray, a pointer and a size_t.
474 struct Data {
475 TooBig* p;
476 size_t size;
477 };
478
479 // Make sure TooBig objects are not inlined for 0 or default size.
480 static_assert(sizeof(absl::FixedArray<TooBig, 0>) == sizeof(Data),
481 "0-sized absl::FixedArray should have same size as Data.");
482 static_assert(alignof(absl::FixedArray<TooBig, 0>) == alignof(Data),
483 "0-sized absl::FixedArray should have same alignment as Data.");
484 static_assert(sizeof(absl::FixedArray<TooBig>) == sizeof(Data),
485 "default-sized absl::FixedArray should have same size as Data");
486 static_assert(
487 alignof(absl::FixedArray<TooBig>) == alignof(Data),
488 "default-sized absl::FixedArray should have same alignment as Data.");
489}
490
491// PickyDelete EXPECTs its class-scope deallocation funcs are unused.
492struct PickyDelete {
493 PickyDelete() {}
494 ~PickyDelete() {}
495 void operator delete(void* p) {
496 EXPECT_TRUE(false) << __FUNCTION__;
497 ::operator delete(p);
498 }
499 void operator delete[](void* p) {
500 EXPECT_TRUE(false) << __FUNCTION__;
501 ::operator delete[](p);
502 }
503};
504
505TEST(FixedArrayTest, UsesGlobalAlloc) { absl::FixedArray<PickyDelete, 0> a(5); }
506
507TEST(FixedArrayTest, Data) {
508 static const int kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
509 absl::FixedArray<int> fa(std::begin(kInput), std::end(kInput));
510 EXPECT_EQ(fa.data(), &*fa.begin());
511 EXPECT_EQ(fa.data(), &fa[0]);
512
513 const absl::FixedArray<int>& cfa = fa;
514 EXPECT_EQ(cfa.data(), &*cfa.begin());
515 EXPECT_EQ(cfa.data(), &cfa[0]);
516}
517
518TEST(FixedArrayTest, Empty) {
519 absl::FixedArray<int> empty(0);
520 absl::FixedArray<int> inline_filled(1);
521 absl::FixedArray<int, 0> heap_filled(1);
522 EXPECT_TRUE(empty.empty());
523 EXPECT_FALSE(inline_filled.empty());
524 EXPECT_FALSE(heap_filled.empty());
525}
526
527TEST(FixedArrayTest, FrontAndBack) {
528 absl::FixedArray<int, 3 * sizeof(int)> inlined = {1, 2, 3};
529 EXPECT_EQ(inlined.front(), 1);
530 EXPECT_EQ(inlined.back(), 3);
531
532 absl::FixedArray<int, 0> allocated = {1, 2, 3};
533 EXPECT_EQ(allocated.front(), 1);
534 EXPECT_EQ(allocated.back(), 3);
535
536 absl::FixedArray<int> one_element = {1};
537 EXPECT_EQ(one_element.front(), one_element.back());
538}
539
540TEST(FixedArrayTest, ReverseIteratorInlined) {
541 absl::FixedArray<int, 5 * sizeof(int)> a = {0, 1, 2, 3, 4};
542
543 int counter = 5;
544 for (absl::FixedArray<int>::reverse_iterator iter = a.rbegin();
545 iter != a.rend(); ++iter) {
546 counter--;
547 EXPECT_EQ(counter, *iter);
548 }
549 EXPECT_EQ(counter, 0);
550
551 counter = 5;
552 for (absl::FixedArray<int>::const_reverse_iterator iter = a.rbegin();
553 iter != a.rend(); ++iter) {
554 counter--;
555 EXPECT_EQ(counter, *iter);
556 }
557 EXPECT_EQ(counter, 0);
558
559 counter = 5;
560 for (auto iter = a.crbegin(); iter != a.crend(); ++iter) {
561 counter--;
562 EXPECT_EQ(counter, *iter);
563 }
564 EXPECT_EQ(counter, 0);
565}
566
567TEST(FixedArrayTest, ReverseIteratorAllocated) {
568 absl::FixedArray<int, 0> a = {0, 1, 2, 3, 4};
569
570 int counter = 5;
571 for (absl::FixedArray<int>::reverse_iterator iter = a.rbegin();
572 iter != a.rend(); ++iter) {
573 counter--;
574 EXPECT_EQ(counter, *iter);
575 }
576 EXPECT_EQ(counter, 0);
577
578 counter = 5;
579 for (absl::FixedArray<int>::const_reverse_iterator iter = a.rbegin();
580 iter != a.rend(); ++iter) {
581 counter--;
582 EXPECT_EQ(counter, *iter);
583 }
584 EXPECT_EQ(counter, 0);
585
586 counter = 5;
587 for (auto iter = a.crbegin(); iter != a.crend(); ++iter) {
588 counter--;
589 EXPECT_EQ(counter, *iter);
590 }
591 EXPECT_EQ(counter, 0);
592}
593
594TEST(FixedArrayTest, Fill) {
595 absl::FixedArray<int, 5 * sizeof(int)> inlined(5);
596 int fill_val = 42;
597 inlined.fill(fill_val);
598 for (int i : inlined) EXPECT_EQ(i, fill_val);
599
600 absl::FixedArray<int, 0> allocated(5);
601 allocated.fill(fill_val);
602 for (int i : allocated) EXPECT_EQ(i, fill_val);
603
604 // It doesn't do anything, just make sure this compiles.
605 absl::FixedArray<int> empty(0);
606 empty.fill(fill_val);
607}
608
609#ifdef ADDRESS_SANITIZER
610TEST(FixedArrayTest, AddressSanitizerAnnotations1) {
611 absl::FixedArray<int, 32> a(10);
612 int *raw = a.data();
613 raw[0] = 0;
614 raw[9] = 0;
615 EXPECT_DEATH(raw[-2] = 0, "container-overflow");
616 EXPECT_DEATH(raw[-1] = 0, "container-overflow");
617 EXPECT_DEATH(raw[10] = 0, "container-overflow");
618 EXPECT_DEATH(raw[31] = 0, "container-overflow");
619}
620
621TEST(FixedArrayTest, AddressSanitizerAnnotations2) {
622 absl::FixedArray<char, 17> a(12);
623 char *raw = a.data();
624 raw[0] = 0;
625 raw[11] = 0;
626 EXPECT_DEATH(raw[-7] = 0, "container-overflow");
627 EXPECT_DEATH(raw[-1] = 0, "container-overflow");
628 EXPECT_DEATH(raw[12] = 0, "container-overflow");
629 EXPECT_DEATH(raw[17] = 0, "container-overflow");
630}
631
632TEST(FixedArrayTest, AddressSanitizerAnnotations3) {
633 absl::FixedArray<uint64_t, 20> a(20);
634 uint64_t *raw = a.data();
635 raw[0] = 0;
636 raw[19] = 0;
637 EXPECT_DEATH(raw[-1] = 0, "container-overflow");
638 EXPECT_DEATH(raw[20] = 0, "container-overflow");
639}
640
641TEST(FixedArrayTest, AddressSanitizerAnnotations4) {
642 absl::FixedArray<ThreeInts> a(10);
643 ThreeInts *raw = a.data();
644 raw[0] = ThreeInts();
645 raw[9] = ThreeInts();
646 // Note: raw[-1] is pointing to 12 bytes before the container range. However,
647 // there is only a 8-byte red zone before the container range, so we only
648 // access the last 4 bytes of the struct to make sure it stays within the red
649 // zone.
650 EXPECT_DEATH(raw[-1].z_ = 0, "container-overflow");
651 EXPECT_DEATH(raw[10] = ThreeInts(), "container-overflow");
652 // The actual size of storage is kDefaultBytes=256, 21*12 = 252,
653 // so reading raw[21] should still trigger the correct warning.
654 EXPECT_DEATH(raw[21] = ThreeInts(), "container-overflow");
655}
656#endif // ADDRESS_SANITIZER
657
658} // namespace