22 #include <scoped_allocator> 27 #include "gmock/gmock.h" 28 #include "gtest/gtest.h" 33 using ::testing::ElementsAreArray;
38 template <
typename ArrayType>
39 static bool IsOnStack(
const ArrayType&
a) {
40 return a.size() <= ArrayType::inline_elements;
43 class ConstructionTester {
50 ~ConstructionTester() {
51 assert(self_ptr_ ==
this);
58 static int constructions;
59 static int destructions;
61 void CheckConstructed() {
62 assert(self_ptr_ ==
this);
66 int get() {
return value_; }
71 ConstructionTester* self_ptr_;
75 int ConstructionTester::constructions = 0;
76 int ConstructionTester::destructions = 0;
97 TEST(FixedArrayTest, CopyCtor) {
99 std::iota(on_stack.begin(), on_stack.end(), 0);
101 EXPECT_THAT(stack_copy, ElementsAreArray(on_stack));
102 EXPECT_TRUE(IsOnStack(stack_copy));
105 std::iota(allocated.begin(), allocated.end(), 0);
107 EXPECT_THAT(alloced_copy, ElementsAreArray(allocated));
108 EXPECT_FALSE(IsOnStack(alloced_copy));
111 TEST(FixedArrayTest, MoveCtor) {
113 for (
int i = 0;
i < 5; ++
i) {
114 on_stack[
i] = absl::make_unique<int>(
i);
118 for (
int i = 0;
i < 5; ++
i) EXPECT_EQ(*(stack_copy[
i]), i);
119 EXPECT_EQ(stack_copy.size(), on_stack.size());
121 absl::FixedArray<std::unique_ptr<int>, 10> allocated(15);
122 for (
int i = 0; i < 15; ++
i) {
123 allocated[
i] = absl::make_unique<int>(
i);
126 absl::FixedArray<std::unique_ptr<int>, 10> alloced_copy =
128 for (
int i = 0; i < 15; ++
i) EXPECT_EQ(*(alloced_copy[i]), i);
129 EXPECT_EQ(allocated.size(), alloced_copy.size());
132 TEST(FixedArrayTest, SmallObjects) {
137 EXPECT_TRUE(IsOnStack(array));
143 EXPECT_FALSE(IsOnStack(array));
149 EXPECT_TRUE(IsOnStack(array));
155 EXPECT_FALSE(IsOnStack(array));
163 EXPECT_LE(
sizeof(array1),
sizeof(array2)+100);
164 EXPECT_LE(
sizeof(array2),
sizeof(array1)+100);
170 EXPECT_EQ(0, array[0].
size());
171 EXPECT_EQ(0, array[1].
size());
178 ThreeInts::counter = 1;
180 EXPECT_EQ(1, array[0].x_);
181 EXPECT_EQ(1, array[0].y_);
182 EXPECT_EQ(1, array[0].z_);
183 EXPECT_EQ(2, array[1].x_);
184 EXPECT_EQ(2, array[1].y_);
185 EXPECT_EQ(2, array[1].z_);
189 TEST(FixedArrayTest, AtThrows) {
191 EXPECT_EQ(a.
at(2), 3);
193 "failed bounds check");
196 TEST(FixedArrayRelationalsTest, EqualArrays) {
197 for (
int i = 0; i < 10; ++
i) {
199 std::iota(
a1.begin(),
a1.end(), 0);
202 EXPECT_TRUE(
a1 ==
a2);
203 EXPECT_FALSE(
a1 !=
a2);
204 EXPECT_TRUE(
a2 ==
a1);
205 EXPECT_FALSE(
a2 !=
a1);
206 EXPECT_FALSE(
a1 <
a2);
207 EXPECT_FALSE(
a1 >
a2);
208 EXPECT_FALSE(
a2 <
a1);
209 EXPECT_FALSE(
a2 >
a1);
210 EXPECT_TRUE(
a1 <=
a2);
211 EXPECT_TRUE(
a1 >=
a2);
212 EXPECT_TRUE(
a2 <=
a1);
213 EXPECT_TRUE(
a2 >=
a1);
217 TEST(FixedArrayRelationalsTest, UnequalArrays) {
218 for (
int i = 1; i < 10; ++
i) {
220 std::iota(
a1.begin(),
a1.end(), 0);
224 EXPECT_FALSE(
a1 == a2);
225 EXPECT_TRUE(
a1 != a2);
226 EXPECT_FALSE(a2 ==
a1);
227 EXPECT_TRUE(a2 !=
a1);
228 EXPECT_FALSE(
a1 < a2);
229 EXPECT_TRUE(
a1 > a2);
230 EXPECT_TRUE(a2 <
a1);
231 EXPECT_FALSE(a2 >
a1);
232 EXPECT_FALSE(
a1 <= a2);
233 EXPECT_TRUE(
a1 >= a2);
234 EXPECT_TRUE(a2 <=
a1);
235 EXPECT_FALSE(a2 >=
a1);
239 template <
int stack_elements>
240 static void TestArray(
int n) {
242 SCOPED_TRACE(stack_elements);
243 ConstructionTester::constructions = 0;
244 ConstructionTester::destructions = 0;
248 EXPECT_THAT(array.size(),
n);
249 EXPECT_THAT(array.memsize(),
sizeof(ConstructionTester) * n);
250 EXPECT_THAT(array.begin() +
n, array.end());
253 for (
int i = 0; i <
n; i++) {
254 array[
i].CheckConstructed();
257 EXPECT_THAT(ConstructionTester::constructions, n);
260 for (
int i = 0; i <
n; i++) {
263 for (
int i = 0; i <
n; i++) {
264 EXPECT_THAT(array[i].
get(), i);
265 EXPECT_THAT(array.data()[
i].get(),
i);
269 for (
int i = 0; i <
n; i++) {
270 array.data()[
i].set(i + 1);
272 for (
int i = 0; i <
n; i++) {
273 EXPECT_THAT(array[i].
get(), i+1);
274 EXPECT_THAT(array.data()[
i].get(), i+1);
279 EXPECT_EQ(ConstructionTester::constructions,
280 ConstructionTester::destructions);
283 template <
int elements_per_inner_array,
int inline_elements>
284 static void TestArrayOfArrays(
int n) {
286 SCOPED_TRACE(inline_elements);
287 SCOPED_TRACE(elements_per_inner_array);
288 ConstructionTester::constructions = 0;
289 ConstructionTester::destructions = 0;
291 using InnerArray = ConstructionTester[elements_per_inner_array];
294 absl::make_unique<absl::FixedArray<InnerArray, inline_elements>>(
n);
295 auto& array = *array_ptr;
297 ASSERT_EQ(array.size(),
n);
298 ASSERT_EQ(array.memsize(),
299 sizeof(ConstructionTester) * elements_per_inner_array * n);
300 ASSERT_EQ(array.begin() +
n, array.end());
303 for (
int i = 0; i <
n; i++) {
304 for (
int j = 0; j < elements_per_inner_array; j++) {
305 (array[
i])[j].CheckConstructed();
309 ASSERT_EQ(ConstructionTester::constructions, n * elements_per_inner_array);
312 for (
int i = 0; i <
n; i++) {
313 for (
int j = 0; j < elements_per_inner_array; j++) {
314 (array[
i])[j].
set(i * elements_per_inner_array + j);
317 for (
int i = 0; i <
n; i++) {
318 for (
int j = 0; j < elements_per_inner_array; j++) {
319 ASSERT_EQ((array[i])[j].
get(), i * elements_per_inner_array + j);
320 ASSERT_EQ((array.data()[
i])[j].
get(), i * elements_per_inner_array + j);
325 for (
int i = 0; i <
n; i++) {
326 for (
int j = 0; j < elements_per_inner_array; j++) {
327 (array.data()[
i])[j].
set((i + 1) * elements_per_inner_array + j);
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(),
333 (i + 1) * elements_per_inner_array + j);
334 ASSERT_EQ((array.data()[
i])[j].
get(),
335 (i + 1) * elements_per_inner_array + j);
341 EXPECT_EQ(ConstructionTester::constructions,
342 ConstructionTester::destructions);
345 TEST(IteratorConstructorTest, NonInline) {
346 int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
351 ASSERT_EQ(kInput[i], fixed[i]);
355 TEST(IteratorConstructorTest, Inline) {
356 int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
361 ASSERT_EQ(kInput[i], fixed[i]);
365 TEST(IteratorConstructorTest, NonPod) {
366 char const* kInput[] =
367 {
"red",
"orange",
"yellow",
"green",
"blue",
"indigo",
"violet" };
372 ASSERT_EQ(kInput[i], fixed[i]);
376 TEST(IteratorConstructorTest, FromEmptyVector) {
377 std::vector<int>
const empty;
379 EXPECT_EQ(0,
fixed.size());
380 EXPECT_EQ(empty.size(),
fixed.size());
383 TEST(IteratorConstructorTest, FromNonEmptyVector) {
384 int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
388 for (
size_t i = 0; i <
items.size(); ++
i) {
389 ASSERT_EQ(
items[i], fixed[i]);
393 TEST(IteratorConstructorTest, FromBidirectionalIteratorRange) {
394 int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
397 EXPECT_THAT(fixed, testing::ElementsAreArray(kInput));
400 TEST(InitListConstructorTest, InitListConstruction) {
402 EXPECT_THAT(fixed, testing::ElementsAreArray({1, 2, 3}));
405 TEST(FillConstructorTest, NonEmptyArrays) {
407 EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));
410 EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));
413 TEST(FillConstructorTest, EmptyArray) {
416 EXPECT_EQ(empty_fill, empty_size);
419 TEST(FillConstructorTest, NotTriviallyCopyable) {
420 std::string str =
"abcd";
424 EXPECT_EQ(array, strings);
427 TEST(FillConstructorTest, Disambiguation) {
429 EXPECT_THAT(a, testing::ElementsAre(2));
432 TEST(FixedArrayTest, ManySizedArrays) {
433 std::vector<int> sizes;
434 for (
int i = 1; i < 100; i++) sizes.push_back(i);
435 for (
int i = 100; i <= 1000; i += 100) sizes.push_back(i);
436 for (
int n : sizes) {
444 TEST(FixedArrayTest, ManySizedArraysOfArraysOf1) {
445 for (
int n = 1; n < 1000; n++) {
446 ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 0>(n)));
447 ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1>(n)));
448 ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 64>(n)));
449 ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1000>(n)));
453 TEST(FixedArrayTest, ManySizedArraysOfArraysOf2) {
454 for (
int n = 1; n < 1000; n++) {
455 TestArrayOfArrays<2, 0>(
n);
456 TestArrayOfArrays<2, 1>(
n);
457 TestArrayOfArrays<2, 64>(
n);
458 TestArrayOfArrays<2, 1000>(
n);
467 TEST(FixedArrayTest, AvoidParanoidDiagnostics) {
469 sprintf(
buf.data(),
"foo");
472 TEST(FixedArrayTest, TooBigInlinedSpace) {
485 "0-sized absl::FixedArray should have same size as Data.");
487 "0-sized absl::FixedArray should have same alignment as Data.");
489 "default-sized absl::FixedArray should have same size as Data");
492 "default-sized absl::FixedArray should have same alignment as Data.");
499 void operator delete(
void* p) {
500 EXPECT_TRUE(
false) << __FUNCTION__;
501 ::operator
delete(p);
503 void operator delete[](
void* p) {
504 EXPECT_TRUE(
false) << __FUNCTION__;
505 ::operator
delete[](p);
512 TEST(FixedArrayTest, Data) {
513 static const int kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
515 EXPECT_EQ(fa.data(), &*fa.begin());
516 EXPECT_EQ(fa.data(), &fa[0]);
519 EXPECT_EQ(cfa.data(), &*cfa.begin());
520 EXPECT_EQ(cfa.data(), &cfa[0]);
523 TEST(FixedArrayTest, Empty) {
527 EXPECT_TRUE(empty.empty());
528 EXPECT_FALSE(inline_filled.empty());
529 EXPECT_FALSE(heap_filled.empty());
532 TEST(FixedArrayTest, FrontAndBack) {
534 EXPECT_EQ(inlined.
front(), 1);
535 EXPECT_EQ(inlined.
back(), 3);
538 EXPECT_EQ(allocated.front(), 1);
539 EXPECT_EQ(allocated.back(), 3);
542 EXPECT_EQ(one_element.front(), one_element.back());
545 TEST(FixedArrayTest, ReverseIteratorInlined) {
550 iter != a.
rend(); ++iter) {
552 EXPECT_EQ(counter, *iter);
554 EXPECT_EQ(counter, 0);
558 iter != a.
rend(); ++iter) {
560 EXPECT_EQ(counter, *iter);
562 EXPECT_EQ(counter, 0);
565 for (
auto iter = a.
crbegin(); iter != a.
crend(); ++iter) {
567 EXPECT_EQ(counter, *iter);
569 EXPECT_EQ(counter, 0);
572 TEST(FixedArrayTest, ReverseIteratorAllocated) {
577 iter != a.
rend(); ++iter) {
579 EXPECT_EQ(counter, *iter);
581 EXPECT_EQ(counter, 0);
585 iter != a.
rend(); ++iter) {
587 EXPECT_EQ(counter, *iter);
589 EXPECT_EQ(counter, 0);
592 for (
auto iter = a.
crbegin(); iter != a.
crend(); ++iter) {
594 EXPECT_EQ(counter, *iter);
596 EXPECT_EQ(counter, 0);
599 TEST(FixedArrayTest, Fill) {
602 inlined.
fill(fill_val);
603 for (
int i : inlined) EXPECT_EQ(i, fill_val);
606 allocated.fill(fill_val);
607 for (
int i : allocated) EXPECT_EQ(i, fill_val);
611 empty.fill(fill_val);
616 TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) {
618 constexpr
auto capacity = 10;
620 using FixedArrBuffType =
622 constexpr
auto scrubbed_bits = 0x95;
623 constexpr
auto length = capacity / 2;
625 FixedArrBuffType buff;
626 std::memset(std::addressof(buff), scrubbed_bits,
sizeof(FixedArrBuffType));
629 ::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length);
630 EXPECT_THAT(*arr, testing::Each(scrubbed_bits));
631 arr->~FixedArrType();
640 template <
typename T>
641 class CountingAllocator :
public std::allocator<T> {
643 using Alloc = std::allocator<T>;
644 using pointer =
typename Alloc::pointer;
645 using size_type =
typename Alloc::size_type;
647 CountingAllocator() : bytes_used_(nullptr), instance_count_(nullptr) {}
648 explicit CountingAllocator(int64_t*
b)
649 : bytes_used_(b), instance_count_(nullptr) {}
650 CountingAllocator(int64_t*
b, int64_t* a)
651 : bytes_used_(b), instance_count_(a) {}
653 template <
typename U>
654 explicit CountingAllocator(
const CountingAllocator<U>& x)
656 bytes_used_(x.bytes_used_),
657 instance_count_(x.instance_count_) {}
659 pointer allocate(size_type n,
const void*
const hint =
nullptr) {
660 assert(bytes_used_ !=
nullptr);
661 *bytes_used_ += n *
sizeof(T);
662 return Alloc::allocate(n, hint);
665 void deallocate(pointer p, size_type n) {
666 Alloc::deallocate(p, n);
667 assert(bytes_used_ !=
nullptr);
668 *bytes_used_ -= n *
sizeof(T);
671 template <
typename... Args>
672 void construct(pointer p, Args&&... args) {
674 if (instance_count_) {
675 *instance_count_ += 1;
681 if (instance_count_) {
682 *instance_count_ -= 1;
686 template <
typename U>
689 using other = CountingAllocator<U>;
692 int64_t* bytes_used_;
693 int64_t* instance_count_;
696 TEST(AllocatorSupportTest, CountInlineAllocations) {
697 constexpr
size_t inlined_size = 4;
698 using Alloc = CountingAllocator<int>;
701 int64_t allocated = 0;
702 int64_t active_instances = 0;
705 const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
707 Alloc
alloc(&allocated, &active_instances);
709 AllocFxdArr arr(ia, ia + inlined_size,
alloc);
710 static_cast<void>(arr);
713 EXPECT_EQ(allocated, 0);
714 EXPECT_EQ(active_instances, 0);
717 TEST(AllocatorSupportTest, CountOutoflineAllocations) {
718 constexpr
size_t inlined_size = 4;
719 using Alloc = CountingAllocator<int>;
722 int64_t allocated = 0;
723 int64_t active_instances = 0;
726 const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
727 Alloc
alloc(&allocated, &active_instances);
731 EXPECT_EQ(allocated, arr.size() *
sizeof(int));
732 static_cast<void>(arr);
735 EXPECT_EQ(active_instances, 0);
738 TEST(AllocatorSupportTest, CountCopyInlineAllocations) {
739 constexpr
size_t inlined_size = 4;
740 using Alloc = CountingAllocator<int>;
743 int64_t allocated1 = 0;
744 int64_t allocated2 = 0;
745 int64_t active_instances = 0;
746 Alloc
alloc(&allocated1, &active_instances);
747 Alloc alloc2(&allocated2, &active_instances);
750 int initial_value = 1;
752 AllocFxdArr arr1(inlined_size / 2, initial_value,
alloc);
754 EXPECT_EQ(allocated1, 0);
756 AllocFxdArr arr2(arr1, alloc2);
758 EXPECT_EQ(allocated2, 0);
759 static_cast<void>(arr1);
760 static_cast<void>(arr2);
763 EXPECT_EQ(active_instances, 0);
766 TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) {
767 constexpr
size_t inlined_size = 4;
768 using Alloc = CountingAllocator<int>;
771 int64_t allocated1 = 0;
772 int64_t allocated2 = 0;
773 int64_t active_instances = 0;
774 Alloc
alloc(&allocated1, &active_instances);
775 Alloc alloc2(&allocated2, &active_instances);
778 int initial_value = 1;
780 AllocFxdArr arr1(inlined_size * 2, initial_value,
alloc);
782 EXPECT_EQ(allocated1, arr1.size() *
sizeof(int));
784 AllocFxdArr arr2(arr1, alloc2);
786 EXPECT_EQ(allocated2, inlined_size * 2 *
sizeof(
int));
787 static_cast<void>(arr1);
788 static_cast<void>(arr2);
791 EXPECT_EQ(active_instances, 0);
794 TEST(AllocatorSupportTest, SizeValAllocConstructor) {
797 using testing::SizeIs;
799 constexpr
size_t inlined_size = 4;
800 using Alloc = CountingAllocator<int>;
804 auto len = inlined_size / 2;
806 int64_t allocated = 0;
807 AllocFxdArr arr(
len, val, Alloc(&allocated));
809 EXPECT_EQ(allocated, 0);
810 EXPECT_THAT(arr,
AllOf(SizeIs(
len), Each(0)));
814 auto len = inlined_size * 2;
816 int64_t allocated = 0;
817 AllocFxdArr arr(
len, val, Alloc(&allocated));
819 EXPECT_EQ(allocated,
len *
sizeof(
int));
820 EXPECT_THAT(arr,
AllOf(SizeIs(
len), Each(0)));
824 #ifdef ADDRESS_SANITIZER 825 TEST(FixedArrayTest, AddressSanitizerAnnotations1) {
830 EXPECT_DEATH(raw[-2] = 0,
"container-overflow");
831 EXPECT_DEATH(raw[-1] = 0,
"container-overflow");
832 EXPECT_DEATH(raw[10] = 0,
"container-overflow");
833 EXPECT_DEATH(raw[31] = 0,
"container-overflow");
836 TEST(FixedArrayTest, AddressSanitizerAnnotations2) {
838 char *raw = a.
data();
841 EXPECT_DEATH(raw[-7] = 0,
"container-overflow");
842 EXPECT_DEATH(raw[-1] = 0,
"container-overflow");
843 EXPECT_DEATH(raw[12] = 0,
"container-overflow");
844 EXPECT_DEATH(raw[17] = 0,
"container-overflow");
847 TEST(FixedArrayTest, AddressSanitizerAnnotations3) {
849 uint64_t *raw = a.
data();
852 EXPECT_DEATH(raw[-1] = 0,
"container-overflow");
853 EXPECT_DEATH(raw[20] = 0,
"container-overflow");
856 TEST(FixedArrayTest, AddressSanitizerAnnotations4) {
858 ThreeInts *raw = a.
data();
859 raw[0] = ThreeInts();
860 raw[9] = ThreeInts();
865 EXPECT_DEATH(raw[-1].z_ = 0,
"container-overflow");
866 EXPECT_DEATH(raw[10] = ThreeInts(),
"container-overflow");
869 EXPECT_DEATH(raw[21] = ThreeInts(),
"container-overflow");
871 #endif // ADDRESS_SANITIZER 873 TEST(FixedArrayTest, AbslHashValueWorks) {
875 std::vector<V> cases;
879 for (
int i = 0; i < 10; ++
i) {
881 for (
int j = 0; j <
i; ++j) {
std::reverse_iterator< iterator > reverse_iterator
auto items(const Map &m) -> std::vector< std::pair< typename Map::key_type, typename Map::mapped_type >>
std::reverse_iterator< const_iterator > const_reverse_iterator
typename std::aligned_storage< Len, Align >::type aligned_storage_t
reverse_iterator rbegin()
const_reverse_iterator crend() const
void fill(const value_type &val)
reference at(size_type i)
static std::function< void(void *, Slot *)> destroy
#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text)
static std::function< void(void *, Slot *, Slot)> construct
ABSL_MUST_USE_RESULT testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(const Container &values)
const_reverse_iterator crbegin() const
#define ABSL_ARRAYSIZE(array)
TEST(Symbolize, Unimplemented)
const_pointer data() const
std::allocator< int > alloc
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept