21 #include <type_traits> 24 #include "gtest/gtest-spi.h" 25 #include "gtest/gtest.h" 33 using ::testing::exceptions_internal::TestException;
38 void ExpectNoThrow(
const F& f) {
41 }
catch (
const TestException& e) {
42 ADD_FAILURE() <<
"Unexpected exception thrown from " << e.what();
46 TEST(ThrowingValueTest, Throws) {
65 void TestOp(
const F& f) {
69 EXPECT_THROW(f(), TestException);
73 TEST(ThrowingValueTest, ThrowingCtors) {
81 TEST(ThrowingValueTest, ThrowingAssignment) {
84 TestOp([&]() { bomb = bomb1; });
85 TestOp([&]() { bomb =
std::move(bomb1); });
93 EXPECT_THROW(lhs = rhs, TestException);
96 EXPECT_NE(lhs_copy, lhs);
102 EXPECT_THROW(lhs =
std::move(rhs), TestException);
104 EXPECT_NE(lhs, rhs_copy);
105 EXPECT_NE(lhs_copy, lhs);
109 TEST(ThrowingValueTest, ThrowingComparisons) {
111 TestOp([&]() {
return bomb1 == bomb2; });
112 TestOp([&]() {
return bomb1 != bomb2; });
113 TestOp([&]() {
return bomb1 < bomb2; });
114 TestOp([&]() {
return bomb1 <= bomb2; });
115 TestOp([&]() {
return bomb1 > bomb2; });
116 TestOp([&]() {
return bomb1 >= bomb2; });
119 TEST(ThrowingValueTest, ThrowingArithmeticOps) {
122 TestOp([&bomb1]() { +bomb1; });
123 TestOp([&bomb1]() { -bomb1; });
124 TestOp([&bomb1]() { ++bomb1; });
125 TestOp([&bomb1]() { bomb1++; });
126 TestOp([&bomb1]() { --bomb1; });
127 TestOp([&bomb1]() { bomb1--; });
129 TestOp([&]() { bomb1 + bomb2; });
130 TestOp([&]() { bomb1 - bomb2; });
131 TestOp([&]() { bomb1* bomb2; });
132 TestOp([&]() { bomb1 / bomb2; });
133 TestOp([&]() { bomb1 << 1; });
134 TestOp([&]() { bomb1 >> 1; });
137 TEST(ThrowingValueTest, ThrowingLogicalOps) {
140 TestOp([&bomb1]() { !bomb1; });
141 TestOp([&]() { bomb1&& bomb2; });
142 TestOp([&]() { bomb1 || bomb2; });
145 TEST(ThrowingValueTest, ThrowingBitwiseOps) {
148 TestOp([&bomb1]() { ~bomb1; });
149 TestOp([&]() { bomb1& bomb2; });
150 TestOp([&]() { bomb1 | bomb2; });
151 TestOp([&]() { bomb1 ^ bomb2; });
154 TEST(ThrowingValueTest, ThrowingCompoundAssignmentOps) {
157 TestOp([&]() { bomb1 += bomb2; });
158 TestOp([&]() { bomb1 -= bomb2; });
159 TestOp([&]() { bomb1 *= bomb2; });
160 TestOp([&]() { bomb1 /= bomb2; });
161 TestOp([&]() { bomb1 %= bomb2; });
162 TestOp([&]() { bomb1 &= bomb2; });
163 TestOp([&]() { bomb1 |= bomb2; });
164 TestOp([&]() { bomb1 ^= bomb2; });
165 TestOp([&]() { bomb1 *= bomb2; });
168 TEST(ThrowingValueTest, ThrowingStreamOps) {
172 std::istringstream stream;
176 std::stringstream stream;
183 TEST(ThrowingValueTest, StreamOpsOutput) {
188 EXPECT_NONFATAL_FAILURE(
194 "ThrowingValue<>(123)");
197 EXPECT_NONFATAL_FAILURE(
203 "ThrowingValue<kNoThrowCopy>(234)");
206 EXPECT_NONFATAL_FAILURE(
213 "ThrowingValue<kNoThrowMove | kNoThrowNew>(345)");
216 EXPECT_NONFATAL_FAILURE(
222 "ThrowingValue<kNoThrowCopy | kNoThrowMove | kNoThrowNew>(456)");
225 template <
typename F>
226 void TestAllocatingOp(
const F& f) {
234 TEST(ThrowingValueTest, ThrowingAllocatingOps) {
237 TestAllocatingOp([]() {
return absl::make_unique<ThrowingValue<>>(1); });
238 TestAllocatingOp([]() {
return absl::make_unique<ThrowingValue<>[]>(2); });
241 TEST(ThrowingValueTest, NonThrowingMoveCtor) {
245 ExpectNoThrow([¬hrow_ctor]() {
251 TEST(ThrowingValueTest, NonThrowingMoveAssign) {
255 ExpectNoThrow([¬hrow_assign1, ¬hrow_assign2]() {
256 nothrow_assign1 =
std::move(nothrow_assign2);
261 TEST(ThrowingValueTest, ThrowingCopyCtor) {
267 TEST(ThrowingValueTest, ThrowingCopyAssign) {
270 TestOp([&]() { tv1 = tv2; });
273 TEST(ThrowingValueTest, NonThrowingCopyCtor) {
277 ExpectNoThrow([¬hrow_ctor]() {
283 TEST(ThrowingValueTest, NonThrowingCopyAssign) {
287 ExpectNoThrow([¬hrow_assign1, ¬hrow_assign2]() {
288 nothrow_assign1 = nothrow_assign2;
293 TEST(ThrowingValueTest, ThrowingSwap) {
295 TestOp([&]() {
std::swap(bomb1, bomb2); });
298 TEST(ThrowingValueTest, NonThrowingSwap) {
300 ExpectNoThrow([&]() {
std::swap(bomb1, bomb2); });
303 TEST(ThrowingValueTest, NonThrowingAllocation) {
307 ExpectNoThrow([&allocated]() {
311 ExpectNoThrow([&array]() {
317 TEST(ThrowingValueTest, NonThrowingDelete) {
322 ExpectNoThrow([allocated]() {
delete allocated; });
324 ExpectNoThrow([array]() {
delete[] array; });
332 TEST(ThrowingValueTest, NonThrowingPlacementDelete) {
333 constexpr
int kArrayLen = 2;
336 constexpr
int kStorageLen = 4;
339 Storage array_buf[kStorageLen];
344 ExpectNoThrow([placed, &buf]() {
345 placed->~ThrowingValue<>();
350 ExpectNoThrow([&, placed_array]() {
358 TEST(ThrowingValueTest, NonThrowingDestructor) {
362 ExpectNoThrow([allocated]() {
delete allocated; });
374 TestOp([&]() { (void)!t; });
377 TEST(ThrowingAllocatorTest, MemoryManagement) {
383 int* i_array = int_alloc.
allocate(2);
393 TEST(ThrowingAllocatorTest, CallsGlobalNew) {
399 ExpectNoThrow([&]() { ptr = nothrow_alloc.
allocate(1); });
405 TEST(ThrowingAllocatorTest, ThrowingConstructors) {
410 EXPECT_THROW(ip = int_alloc.
allocate(1), TestException);
411 ExpectNoThrow([&]() { ip = int_alloc.
allocate(1); });
415 EXPECT_THROW(int_alloc.
construct(ip, 2), TestException);
422 TEST(ThrowingAllocatorTest, NonThrowingConstruction) {
428 ExpectNoThrow([&]() { ip = int_alloc.
allocate(1); });
431 ExpectNoThrow([&]() { int_alloc.
construct(ip, 2); });
442 ExpectNoThrow([&]() { ip = int_alloc.
allocate(1); });
443 ExpectNoThrow([&]() { int_alloc.
construct(ip, 2); });
454 ExpectNoThrow([&]() { ptr = nothrow_alloc.
allocate(1); });
460 EXPECT_EQ(ptr->
Get(), 2);
480 TEST(ThrowingAllocatorTest, ThrowingAllocatorConstruction) {
486 TEST(ThrowingAllocatorTest, State) {
494 a3.deallocate(ip, 1);
498 TEST(ThrowingAllocatorTest, InVector) {
500 for (
int i = 0;
i < 20; ++
i) v.push_back({});
501 for (
int i = 0;
i < 20; ++
i) v.pop_back();
504 TEST(ThrowingAllocatorTest, InList) {
506 for (
int i = 0;
i < 20; ++
i) l.push_back({});
507 for (
int i = 0;
i < 20; ++
i) l.pop_back();
508 for (
int i = 0;
i < 20; ++
i) l.push_front({});
509 for (
int i = 0;
i < 20; ++
i) l.pop_front();
512 template <
typename TesterInstance,
typename =
void>
513 struct NullaryTestValidator :
public std::false_type {};
515 template <
typename TesterInstance>
516 struct NullaryTestValidator<
518 absl::
void_t<decltype(std::declval<TesterInstance>().Test())>>
519 :
public std::true_type {};
521 template <
typename TesterInstance>
522 bool HasNullaryTest(
const TesterInstance&) {
526 void DummyOp(
void*) {}
528 template <
typename TesterInstance,
typename =
void>
529 struct UnaryTestValidator :
public std::false_type {};
531 template <
typename TesterInstance>
532 struct UnaryTestValidator<
534 absl::
void_t<decltype(std::declval<TesterInstance>().Test(DummyOp))>>
535 :
public std::true_type {};
537 template <
typename TesterInstance>
538 bool HasUnaryTest(
const TesterInstance&) {
542 TEST(ExceptionSafetyTesterTest, IncompleteTypesAreNotTestable) {
544 auto op = [](T* t) {};
545 auto inv = [](T*) {
return testing::AssertionSuccess(); };
546 auto fac = []() {
return absl::make_unique<T>(); };
553 EXPECT_FALSE(HasNullaryTest(without_fac));
554 EXPECT_FALSE(HasUnaryTest(without_fac));
561 EXPECT_FALSE(HasNullaryTest(without_op));
562 EXPECT_TRUE(HasUnaryTest(without_op));
568 EXPECT_FALSE(HasNullaryTest(without_inv));
569 EXPECT_FALSE(HasUnaryTest(without_inv));
572 struct ExampleStruct {};
574 std::unique_ptr<ExampleStruct> ExampleFunctionFactory() {
575 return absl::make_unique<ExampleStruct>();
578 void ExampleFunctionOperation(ExampleStruct*) {}
580 testing::AssertionResult ExampleFunctionContract(ExampleStruct*) {
581 return testing::AssertionSuccess();
585 std::unique_ptr<ExampleStruct> operator()()
const {
586 return ExampleFunctionFactory();
588 } example_struct_factory;
591 void operator()(ExampleStruct*)
const {}
592 } example_struct_operation;
595 testing::AssertionResult operator()(ExampleStruct* example_struct)
const {
596 return ExampleFunctionContract(example_struct);
598 } example_struct_contract;
600 auto example_lambda_factory = []() {
return ExampleFunctionFactory(); };
602 auto example_lambda_operation = [](ExampleStruct*) {};
604 auto example_lambda_contract = [](ExampleStruct* example_struct) {
605 return ExampleFunctionContract(example_struct);
610 TEST(ExceptionSafetyTesterTest, MixedFunctionTypes) {
613 .WithFactory(ExampleFunctionFactory)
614 .WithOperation(ExampleFunctionOperation)
615 .WithContracts(ExampleFunctionContract)
620 .WithFactory(&ExampleFunctionFactory)
621 .WithOperation(&ExampleFunctionOperation)
622 .WithContracts(&ExampleFunctionContract)
627 .WithFactory(example_struct_factory)
628 .WithOperation(example_struct_operation)
629 .WithContracts(example_struct_contract)
634 .WithFactory(example_lambda_factory)
635 .WithOperation(example_lambda_operation)
636 .WithContracts(example_lambda_contract)
641 bool operator==(
const NonNegative& other)
const {
return i == other.i; }
645 testing::AssertionResult CheckNonNegativeInvariants(NonNegative* g) {
647 return testing::AssertionSuccess();
649 return testing::AssertionFailure()
650 <<
"i should be non-negative but is " << g->i;
654 template <
typename T>
655 void operator()(T* t)
const {
662 CheckNonNegativeInvariants);
665 struct FailsBasicGuarantee :
public NonNegative {
668 ThrowingValue<> bomb;
673 TEST(ExceptionCheckTest, BasicGuaranteeFailure) {
674 EXPECT_FALSE(tester.WithInitialValue(FailsBasicGuarantee{}).Test());
677 struct FollowsBasicGuarantee :
public NonNegative {
680 ThrowingValue<> bomb;
684 TEST(ExceptionCheckTest, BasicGuarantee) {
685 EXPECT_TRUE(tester.WithInitialValue(FollowsBasicGuarantee{}).Test());
688 TEST(ExceptionCheckTest, StrongGuaranteeFailure) {
689 EXPECT_FALSE(strong_tester.WithInitialValue(FailsBasicGuarantee{}).Test());
690 EXPECT_FALSE(strong_tester.WithInitialValue(FollowsBasicGuarantee{}).Test());
693 struct BasicGuaranteeWithExtraContracts :
public NonNegative {
698 ThrowingValue<> bomb;
706 TEST(ExceptionCheckTest, BasicGuaranteeWithExtraContracts) {
707 auto tester_with_val =
708 tester.WithInitialValue(BasicGuaranteeWithExtraContracts{});
709 EXPECT_TRUE(tester_with_val.Test());
712 .WithContracts([](BasicGuaranteeWithExtraContracts*
o) {
713 if (o->i == BasicGuaranteeWithExtraContracts::kExceptionSentinel) {
714 return testing::AssertionSuccess();
716 return testing::AssertionFailure()
718 << BasicGuaranteeWithExtraContracts::kExceptionSentinel
719 <<
", but is " << o->i;
724 struct FollowsStrongGuarantee :
public NonNegative {
725 void operator()() { ThrowingValue<> bomb; }
728 TEST(ExceptionCheckTest, StrongGuarantee) {
729 EXPECT_TRUE(tester.WithInitialValue(FollowsStrongGuarantee{}).Test());
730 EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{}).Test());
733 struct HasReset :
public NonNegative {
736 ThrowingValue<> bomb;
740 void reset() {
i = 0; }
743 testing::AssertionResult CheckHasResetContracts(HasReset* h) {
745 return testing::AssertionResult(h->i == 0);
748 TEST(ExceptionCheckTest, ModifyingChecker) {
749 auto set_to_1000 = [](FollowsBasicGuarantee* g) {
751 return testing::AssertionSuccess();
753 auto is_1000 = [](FollowsBasicGuarantee* g) {
754 return testing::AssertionResult(g->i == 1000);
756 auto increment = [](FollowsStrongGuarantee* g) {
758 return testing::AssertionSuccess();
761 EXPECT_FALSE(tester.WithInitialValue(FollowsBasicGuarantee{})
762 .WithContracts(set_to_1000, is_1000)
764 EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{})
765 .WithContracts(increment)
768 .WithInitialValue(HasReset{})
769 .WithContracts(CheckHasResetContracts)
773 TEST(ExceptionSafetyTesterTest, ResetsCountdown) {
777 .WithContracts([](ThrowingValue<>*) {
return AssertionSuccess(); })
778 .WithOperation([](ThrowingValue<>*) {});
779 ASSERT_TRUE(test.Test());
782 EXPECT_TRUE(test.Test());
785 struct NonCopyable :
public NonNegative {
786 NonCopyable(
const NonCopyable&) =
delete;
787 NonCopyable() : NonNegative{0} {}
789 void operator()() { ThrowingValue<> bomb; }
792 TEST(ExceptionCheckTest, NonCopyable) {
793 auto factory = []() {
return absl::make_unique<NonCopyable>(); };
794 EXPECT_TRUE(tester.WithFactory(factory).Test());
795 EXPECT_TRUE(strong_tester.WithFactory(factory).Test());
798 struct NonEqualityComparable :
public NonNegative {
799 void operator()() { ThrowingValue<> bomb; }
801 void ModifyOnThrow() {
803 ThrowingValue<> bomb;
804 static_cast<void>(bomb);
809 TEST(ExceptionCheckTest, NonEqualityComparable) {
810 auto nec_is_strong = [](NonEqualityComparable* nec) {
811 return testing::AssertionResult(nec->i == NonEqualityComparable().
i);
813 auto strong_nec_tester = tester.WithInitialValue(NonEqualityComparable{})
814 .WithContracts(nec_is_strong);
816 EXPECT_TRUE(strong_nec_tester.Test());
817 EXPECT_FALSE(strong_nec_tester.Test(
818 [](NonEqualityComparable*
n) { n->ModifyOnThrow(); }));
821 template <
typename T>
822 struct ExhaustivenessTester {
826 static_cast<void>(
b1);
829 static_cast<void>(
b2);
832 static_cast<void>(b3);
836 bool operator==(
const ExhaustivenessTester<ThrowingValue<>>&)
const {
844 template <
typename T>
845 testing::AssertionResult operator()(ExhaustivenessTester<T>*)
const {
846 return testing::AssertionSuccess();
848 } CheckExhaustivenessTesterContracts;
850 template <
typename T>
853 TEST(ExceptionCheckTest, Exhaustiveness) {
856 .WithOperation(invoker);
859 exhaust_tester.WithInitialValue(ExhaustivenessTester<int>{}).Test());
863 exhaust_tester.WithInitialValue(ExhaustivenessTester<ThrowingValue<>>{})
866 EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::
successes, 0xF);
869 struct LeaksIfCtorThrows :
private exceptions_internal::TrackedObject {
870 LeaksIfCtorThrows() : TrackedObject(ABSL_PRETTY_FUNCTION) {
873 static_cast<void>(
v);
876 LeaksIfCtorThrows(
const LeaksIfCtorThrows&) noexcept
877 : TrackedObject(ABSL_PRETTY_FUNCTION) {}
882 TEST(ExceptionCheckTest, TestLeakyCtor) {
883 testing::TestThrowingCtor<LeaksIfCtorThrows>();
884 EXPECT_EQ(LeaksIfCtorThrows::counter, 1);
885 LeaksIfCtorThrows::counter = 0;
888 struct Tracked :
private exceptions_internal::TrackedObject {
889 Tracked() : TrackedObject(ABSL_PRETTY_FUNCTION) {}
892 TEST(ConstructorTrackerTest, CreatedBefore) {
897 TEST(ConstructorTrackerTest, CreatedAfter) {
902 TEST(ConstructorTrackerTest, NotDestroyedAfter) {
904 EXPECT_NONFATAL_FAILURE(
906 exceptions_internal::ConstructorTracker ct(
908 new (&storage) Tracked;
913 TEST(ConstructorTrackerTest, DestroyedTwice) {
915 EXPECT_NONFATAL_FAILURE(
923 TEST(ConstructorTrackerTest, ConstructedTwice) {
926 EXPECT_NONFATAL_FAILURE(
928 new (&storage) Tracked;
929 new (&storage) Tracked;
930 reinterpret_cast<Tracked*
>(&storage)->~Tracked();
935 TEST(ThrowingValueTraitsTest, RelationalOperators) {
936 ThrowingValue<>
a,
b;
937 EXPECT_TRUE((std::is_convertible<decltype(a == b),
bool>::
value));
938 EXPECT_TRUE((std::is_convertible<decltype(a != b),
bool>::
value));
939 EXPECT_TRUE((std::is_convertible<decltype(a < b),
bool>::
value));
940 EXPECT_TRUE((std::is_convertible<decltype(a <= b),
bool>::
value));
941 EXPECT_TRUE((std::is_convertible<decltype(a > b),
bool>::
value));
942 EXPECT_TRUE((std::is_convertible<decltype(a >= b),
bool>::
value));
945 TEST(ThrowingAllocatorTraitsTest, Assignablility) {
948 EXPECT_TRUE(std::is_nothrow_move_assignable<ThrowingAllocator<int>>::
value);
949 EXPECT_TRUE(std::is_nothrow_copy_assignable<ThrowingAllocator<int>>::
value);
exceptions_internal::StrongGuaranteeTagType strong_guarantee
typename std::aligned_storage< Len, Align >::type aligned_storage_t
void SetCountdown(int i=0)
exceptions_internal::ExceptionSafetyTestBuilder MakeExceptionSafetyTester()
testing::ThrowingValue<> Thrower
pointer allocate(size_type n) noexcept(IsSpecified(AllocSpec::kNoThrowAllocate))
bool operator==(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)
ThrowingAllocator select_on_container_copy_construction() noexcept(IsSpecified(AllocSpec::kNoThrowAllocate))
void construct(U *ptr, Args &&... args) noexcept(IsSpecified(AllocSpec::kNoThrowAllocate))
void swap(absl::InlinedVector< T, N, A > &a, absl::InlinedVector< T, N, A > &b) noexcept(noexcept(a.swap(b)))
void deallocate(pointer ptr, size_type) noexcept
typename type_traits_internal::VoidTImpl< Ts... >::type void_t
static unsigned char successes
exceptions_internal::NoThrowTag nothrow_ctor
static constexpr int kExceptionSentinel
ExceptionSafetyTestBuilder< Factory, Operation, Contracts..., absl::decay_t< MoreContracts >... > WithContracts(const MoreContracts &... more_contracts) const
TEST(Symbolize, Unimplemented)
ExceptionSafetyTestBuilder< DefaultFactory< T >, Operation, Contracts... > WithInitialValue(const T &t) const
ExceptionSafetyTestBuilder< Factory, absl::decay_t< NewOperation >, Contracts... > WithOperation(const NewOperation &new_operation) const
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
void destroy(U *p) noexcept