fixed_array_exception_safety_test.cc (6994B)
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/base/config.h" 16 #include "absl/container/fixed_array.h" 17 18 #ifdef ABSL_HAVE_EXCEPTIONS 19 20 #include <initializer_list> 21 22 #include "gtest/gtest.h" 23 #include "absl/base/internal/exception_safety_testing.h" 24 25 namespace absl { 26 ABSL_NAMESPACE_BEGIN 27 28 namespace { 29 30 constexpr size_t kInlined = 25; 31 constexpr size_t kSmallSize = kInlined / 2; 32 constexpr size_t kLargeSize = kInlined * 2; 33 34 constexpr int kInitialValue = 5; 35 constexpr int kUpdatedValue = 10; 36 37 using ::testing::TestThrowingCtor; 38 39 using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>; 40 using ThrowAlloc = 41 testing::ThrowingAllocator<Thrower, testing::AllocSpec::kEverythingThrows>; 42 using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>; 43 using MoveThrowAlloc = 44 testing::ThrowingAllocator<MoveThrower, 45 testing::AllocSpec::kEverythingThrows>; 46 47 using FixedArr = absl::FixedArray<Thrower, kInlined>; 48 using FixedArrWithAlloc = absl::FixedArray<Thrower, kInlined, ThrowAlloc>; 49 50 using MoveFixedArr = absl::FixedArray<MoveThrower, kInlined>; 51 using MoveFixedArrWithAlloc = 52 absl::FixedArray<MoveThrower, kInlined, MoveThrowAlloc>; 53 54 TEST(FixedArrayExceptionSafety, CopyConstructor) { 55 auto small = FixedArr(kSmallSize); 56 TestThrowingCtor<FixedArr>(small); 57 58 auto large = FixedArr(kLargeSize); 59 TestThrowingCtor<FixedArr>(large); 60 } 61 62 TEST(FixedArrayExceptionSafety, CopyConstructorWithAlloc) { 63 auto small = FixedArrWithAlloc(kSmallSize); 64 TestThrowingCtor<FixedArrWithAlloc>(small); 65 66 auto large = FixedArrWithAlloc(kLargeSize); 67 TestThrowingCtor<FixedArrWithAlloc>(large); 68 } 69 70 TEST(FixedArrayExceptionSafety, MoveConstructor) { 71 TestThrowingCtor<FixedArr>(FixedArr(kSmallSize)); 72 TestThrowingCtor<FixedArr>(FixedArr(kLargeSize)); 73 74 // TypeSpec::kNoThrowMove 75 TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kSmallSize)); 76 TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kLargeSize)); 77 } 78 79 TEST(FixedArrayExceptionSafety, MoveConstructorWithAlloc) { 80 TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kSmallSize)); 81 TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kLargeSize)); 82 83 // TypeSpec::kNoThrowMove 84 TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kSmallSize)); 85 TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kLargeSize)); 86 } 87 88 TEST(FixedArrayExceptionSafety, SizeConstructor) { 89 TestThrowingCtor<FixedArr>(kSmallSize); 90 TestThrowingCtor<FixedArr>(kLargeSize); 91 } 92 93 TEST(FixedArrayExceptionSafety, SizeConstructorWithAlloc) { 94 TestThrowingCtor<FixedArrWithAlloc>(kSmallSize); 95 TestThrowingCtor<FixedArrWithAlloc>(kLargeSize); 96 } 97 98 TEST(FixedArrayExceptionSafety, SizeValueConstructor) { 99 TestThrowingCtor<FixedArr>(kSmallSize, Thrower()); 100 TestThrowingCtor<FixedArr>(kLargeSize, Thrower()); 101 } 102 103 TEST(FixedArrayExceptionSafety, SizeValueConstructorWithAlloc) { 104 TestThrowingCtor<FixedArrWithAlloc>(kSmallSize, Thrower()); 105 TestThrowingCtor<FixedArrWithAlloc>(kLargeSize, Thrower()); 106 } 107 108 TEST(FixedArrayExceptionSafety, IteratorConstructor) { 109 auto small = FixedArr(kSmallSize); 110 TestThrowingCtor<FixedArr>(small.begin(), small.end()); 111 112 auto large = FixedArr(kLargeSize); 113 TestThrowingCtor<FixedArr>(large.begin(), large.end()); 114 } 115 116 TEST(FixedArrayExceptionSafety, IteratorConstructorWithAlloc) { 117 auto small = FixedArrWithAlloc(kSmallSize); 118 TestThrowingCtor<FixedArrWithAlloc>(small.begin(), small.end()); 119 120 auto large = FixedArrWithAlloc(kLargeSize); 121 TestThrowingCtor<FixedArrWithAlloc>(large.begin(), large.end()); 122 } 123 124 TEST(FixedArrayExceptionSafety, InitListConstructor) { 125 constexpr int small_inlined = 3; 126 using SmallFixedArr = absl::FixedArray<Thrower, small_inlined>; 127 128 TestThrowingCtor<SmallFixedArr>(std::initializer_list<Thrower>{}); 129 // Test inlined allocation 130 TestThrowingCtor<SmallFixedArr>( 131 std::initializer_list<Thrower>{Thrower{}, Thrower{}}); 132 // Test out of line allocation 133 TestThrowingCtor<SmallFixedArr>(std::initializer_list<Thrower>{ 134 Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}}); 135 } 136 137 TEST(FixedArrayExceptionSafety, InitListConstructorWithAlloc) { 138 constexpr int small_inlined = 3; 139 using SmallFixedArrWithAlloc = 140 absl::FixedArray<Thrower, small_inlined, ThrowAlloc>; 141 142 TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{}); 143 // Test inlined allocation 144 TestThrowingCtor<SmallFixedArrWithAlloc>( 145 std::initializer_list<Thrower>{Thrower{}, Thrower{}}); 146 // Test out of line allocation 147 TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{ 148 Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}}); 149 } 150 151 template <typename FixedArrT> 152 testing::AssertionResult ReadMemory(FixedArrT* fixed_arr) { 153 int sum = 0; 154 for (const auto& thrower : *fixed_arr) { 155 sum += thrower.Get(); 156 } 157 return testing::AssertionSuccess() << "Values sum to [" << sum << "]"; 158 } 159 160 TEST(FixedArrayExceptionSafety, Fill) { 161 auto test_fill = testing::MakeExceptionSafetyTester() 162 .WithContracts(ReadMemory<FixedArr>) 163 .WithOperation([&](FixedArr* fixed_arr_ptr) { 164 auto thrower = 165 Thrower(kUpdatedValue, testing::nothrow_ctor); 166 fixed_arr_ptr->fill(thrower); 167 }); 168 169 EXPECT_TRUE( 170 test_fill.WithInitialValue(FixedArr(kSmallSize, Thrower(kInitialValue))) 171 .Test()); 172 EXPECT_TRUE( 173 test_fill.WithInitialValue(FixedArr(kLargeSize, Thrower(kInitialValue))) 174 .Test()); 175 } 176 177 TEST(FixedArrayExceptionSafety, FillWithAlloc) { 178 auto test_fill = testing::MakeExceptionSafetyTester() 179 .WithContracts(ReadMemory<FixedArrWithAlloc>) 180 .WithOperation([&](FixedArrWithAlloc* fixed_arr_ptr) { 181 auto thrower = 182 Thrower(kUpdatedValue, testing::nothrow_ctor); 183 fixed_arr_ptr->fill(thrower); 184 }); 185 186 EXPECT_TRUE(test_fill 187 .WithInitialValue( 188 FixedArrWithAlloc(kSmallSize, Thrower(kInitialValue))) 189 .Test()); 190 EXPECT_TRUE(test_fill 191 .WithInitialValue( 192 FixedArrWithAlloc(kLargeSize, Thrower(kInitialValue))) 193 .Test()); 194 } 195 196 } // namespace 197 198 ABSL_NAMESPACE_END 199 } // namespace absl 200 201 #endif // ABSL_HAVE_EXCEPTIONS