diff options
Diffstat (limited to 'absl/container/inlined_vector_exception_safety_test.cc')
-rw-r--r-- | absl/container/inlined_vector_exception_safety_test.cc | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/absl/container/inlined_vector_exception_safety_test.cc b/absl/container/inlined_vector_exception_safety_test.cc index 1aae0b0493ec..0a9649250302 100644 --- a/absl/container/inlined_vector_exception_safety_test.cc +++ b/absl/container/inlined_vector_exception_safety_test.cc @@ -36,6 +36,26 @@ using ThrowAllocThrowerVec = using ThrowAllocMovableThrowerVec = absl::InlinedVector<MovableThrower, kInlinedCapacity, ThrowAlloc>; +// In GCC, if an element of a `std::initializer_list` throws during construction +// the elements that were constructed before it are not destroyed. This causes +// incorrect exception safety test failures. Thus, `testing::nothrow_ctor` is +// required. See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66139 +#define ABSL_INTERNAL_MAKE_INIT_LIST(T, N) \ + (N > kInlinedCapacity \ + ? std::initializer_list<T>{T(0, testing::nothrow_ctor), \ + T(1, testing::nothrow_ctor), \ + T(2, testing::nothrow_ctor), \ + T(3, testing::nothrow_ctor), \ + T(4, testing::nothrow_ctor), \ + T(5, testing::nothrow_ctor), \ + T(6, testing::nothrow_ctor), \ + T(7, testing::nothrow_ctor)} \ + \ + : std::initializer_list<T>{T(0, testing::nothrow_ctor), \ + T(1, testing::nothrow_ctor)}) +static_assert((kLargeSize == 8 || kSmallSize == 2), + "Must update ABSL_INTERNAL_MAKE_INIT_LIST(...)."); + template <typename TheVecT, size_t... TheSizes> class TestParams { public: @@ -88,6 +108,90 @@ TYPED_TEST(NoSizeTest, DefaultConstructor) { testing::TestThrowingCtor<VecT>(allocator_type{}); } +TYPED_TEST(OneSizeTest, SizeConstructor) { + using VecT = typename TypeParam::VecT; + using allocator_type = typename VecT::allocator_type; + constexpr static auto size = TypeParam::GetSizeAt(0); + + testing::TestThrowingCtor<VecT>(size); + + testing::TestThrowingCtor<VecT>(size, allocator_type{}); +} + +TYPED_TEST(OneSizeTest, SizeRefConstructor) { + using VecT = typename TypeParam::VecT; + using value_type = typename VecT::value_type; + using allocator_type = typename VecT::allocator_type; + constexpr static auto size = TypeParam::GetSizeAt(0); + + testing::TestThrowingCtor<VecT>(size, value_type{}); + + testing::TestThrowingCtor<VecT>(size, value_type{}, allocator_type{}); +} + +TYPED_TEST(OneSizeTest, InitializerListConstructor) { + using VecT = typename TypeParam::VecT; + using value_type = typename VecT::value_type; + using allocator_type = typename VecT::allocator_type; + constexpr static auto size = TypeParam::GetSizeAt(0); + + testing::TestThrowingCtor<VecT>( + ABSL_INTERNAL_MAKE_INIT_LIST(value_type, size)); + + testing::TestThrowingCtor<VecT>( + ABSL_INTERNAL_MAKE_INIT_LIST(value_type, size), allocator_type{}); +} + +TYPED_TEST(OneSizeTest, RangeConstructor) { + using VecT = typename TypeParam::VecT; + using value_type = typename VecT::value_type; + using allocator_type = typename VecT::allocator_type; + constexpr static auto size = TypeParam::GetSizeAt(0); + + std::array<value_type, size> arr{}; + + testing::TestThrowingCtor<VecT>(arr.begin(), arr.end()); + + testing::TestThrowingCtor<VecT>(arr.begin(), arr.end(), allocator_type{}); +} + +TYPED_TEST(OneSizeTest, CopyConstructor) { + using VecT = typename TypeParam::VecT; + using allocator_type = typename VecT::allocator_type; + constexpr static auto size = TypeParam::GetSizeAt(0); + + VecT other_vec{size}; + + testing::TestThrowingCtor<VecT>(other_vec); + + testing::TestThrowingCtor<VecT>(other_vec, allocator_type{}); +} + +TYPED_TEST(OneSizeTest, MoveConstructor) { + using VecT = typename TypeParam::VecT; + using allocator_type = typename VecT::allocator_type; + constexpr static auto size = TypeParam::GetSizeAt(0); + + if (!absl::allocator_is_nothrow<allocator_type>::value) { + testing::TestThrowingCtor<VecT>(VecT{size}); + + testing::TestThrowingCtor<VecT>(VecT{size}, allocator_type{}); + } +} + +TYPED_TEST(OneSizeTest, PopBack) { + using VecT = typename TypeParam::VecT; + constexpr static auto size = TypeParam::GetSizeAt(0); + + auto tester = testing::MakeExceptionSafetyTester() + .WithInitialValue(VecT(size)) + .WithContracts(NoThrowGuarantee<VecT>); + + EXPECT_TRUE(tester.Test([](VecT* vec) { + vec->pop_back(); // + })); +} + TYPED_TEST(OneSizeTest, Clear) { using VecT = typename TypeParam::VecT; constexpr static auto size = TypeParam::GetSizeAt(0); |