22 #include "gmock/gmock.h" 23 #include "gtest/gtest.h" 29 #if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) 43 using ThrowerVec = std::vector<Thrower, ThrowingAlloc>;
44 using ThrowingVariant =
47 struct ConversionException {};
50 struct ExceptionOnConversion {
52 throw ConversionException();
57 void ToValuelessByException(ThrowingVariant&
v) {
60 v.emplace<
Thrower>(ExceptionOnConversion<Thrower>());
61 }
catch (
const ConversionException&) {
67 testing::AssertionResult VariantInvariants(ThrowingVariant*
v) {
68 using testing::AssertionFailure;
69 using testing::AssertionSuccess;
72 if (absl::holds_alternative<Thrower>(*v)) {
73 auto& t = absl::get<Thrower>(*v);
75 if (t.Get() != -100) {
76 return AssertionFailure() <<
"Thrower should be assigned -100";
78 }
else if (absl::holds_alternative<ThrowerVec>(*v)) {
79 auto& tv = absl::get<ThrowerVec>(*v);
81 tv.emplace_back(-100);
82 if (tv.size() != 1 || tv[0].Get() != -100) {
83 return AssertionFailure() <<
"ThrowerVec should be {Thrower{-100}}";
85 }
else if (absl::holds_alternative<CopyNothrow>(*v)) {
86 auto& t = absl::get<CopyNothrow>(*v);
87 t = CopyNothrow{-100};
88 if (t.Get() != -100) {
89 return AssertionFailure() <<
"CopyNothrow should be assigned -100";
91 }
else if (absl::holds_alternative<MoveNothrow>(*v)) {
92 auto& t = absl::get<MoveNothrow>(*v);
93 t = MoveNothrow{-100};
94 if (t.Get() != -100) {
95 return AssertionFailure() <<
"MoveNothrow should be assigned -100";
100 if (!v->valueless_by_exception()) ToValuelessByException(*v);
101 if (!v->valueless_by_exception()) {
102 return AssertionFailure() <<
"Variant should be valueless_by_exception";
105 auto unused = absl::get<Thrower>(*v);
106 static_cast<void>(unused);
107 return AssertionFailure() <<
"Variant should not contain Thrower";
110 return AssertionFailure() <<
"Unexpected exception throw from absl::get";
115 if (!absl::holds_alternative<Thrower>(*v) ||
116 absl::get<Thrower>(*v) !=
Thrower(100)) {
117 return AssertionFailure() <<
"Variant should contain Thrower(100)";
120 if (!absl::holds_alternative<ThrowerVec>(*v) ||
121 absl::get<ThrowerVec>(*v)[0] !=
Thrower(100)) {
122 return AssertionFailure()
123 <<
"Variant should contain ThrowerVec{Thrower(100)}";
125 return AssertionSuccess();
128 template <
typename... Args>
129 Thrower ExpectedThrower(Args&&... args) {
134 ThrowingVariant ValuelessByException() {
136 ToValuelessByException(v);
139 ThrowingVariant WithThrower() {
return Thrower(39); }
140 ThrowingVariant WithThrowerVec() {
143 ThrowingVariant WithCopyNoThrow() {
return CopyNothrow(39); }
144 ThrowingVariant WithMoveNoThrow() {
return MoveNothrow(39); }
146 TEST(VariantExceptionSafetyTest, DefaultConstructor) {
147 TestThrowingCtor<ThrowingVariant>();
150 TEST(VariantExceptionSafetyTest, CopyConstructor) {
152 ThrowingVariant
v(ExpectedThrower());
153 TestThrowingCtor<ThrowingVariant>(
v);
156 ThrowingVariant
v(ExpectedThrowerVec());
157 TestThrowingCtor<ThrowingVariant>(
v);
160 ThrowingVariant
v(ValuelessByException());
161 TestThrowingCtor<ThrowingVariant>(
v);
165 TEST(VariantExceptionSafetyTest, MoveConstructor) {
167 ThrowingVariant
v(ExpectedThrower());
168 TestThrowingCtor<ThrowingVariant>(
std::move(v));
171 ThrowingVariant
v(ExpectedThrowerVec());
172 TestThrowingCtor<ThrowingVariant>(
std::move(v));
175 ThrowingVariant
v(ValuelessByException());
176 TestThrowingCtor<ThrowingVariant>(
std::move(v));
180 TEST(VariantExceptionSafetyTest, ValueConstructor) {
181 TestThrowingCtor<ThrowingVariant>(ExpectedThrower());
182 TestThrowingCtor<ThrowingVariant>(ExpectedThrowerVec());
185 TEST(VariantExceptionSafetyTest, InPlaceTypeConstructor) {
189 ExpectedThrowerVec());
192 TEST(VariantExceptionSafetyTest, InPlaceIndexConstructor) {
196 ExpectedThrowerVec());
199 TEST(VariantExceptionSafetyTest, CopyAssign) {
204 const ThrowingVariant rhs = ValuelessByException();
205 ThrowingVariant lhs = ValuelessByException();
210 const ThrowingVariant rhs = ValuelessByException();
211 ThrowingVariant lhs = WithThrower();
216 const ThrowingVariant rhs(ExpectedThrower());
220 .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; });
221 EXPECT_TRUE(tester.WithContracts(VariantInvariants).Test());
225 const ThrowingVariant rhs(ExpectedThrowerVec());
229 .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; });
230 EXPECT_TRUE(tester.WithContracts(VariantInvariants).Test());
235 #if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__)) 244 const ThrowingVariant rhs(CopyNothrow{});
245 ThrowingVariant lhs = WithThrower();
253 const ThrowingVariant rhs(ExpectedThrower());
257 .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; });
259 .WithContracts(VariantInvariants,
260 [](ThrowingVariant* lhs) {
261 return lhs->valueless_by_exception();
266 #endif // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__)) 273 const ThrowingVariant rhs(MoveNothrow{});
275 .WithInitialValue(WithThrower())
277 .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }));
281 TEST(VariantExceptionSafetyTest, MoveAssign) {
286 ThrowingVariant rhs = ValuelessByException();
287 ThrowingVariant lhs = ValuelessByException();
292 ThrowingVariant rhs = ValuelessByException();
293 ThrowingVariant lhs = WithThrower();
302 ThrowingVariant rhs(ExpectedThrower());
303 size_t j = rhs.index();
307 .WithOperation([&](ThrowingVariant* lhs) {
314 [&](ThrowingVariant* lhs) {
return lhs->index() == j; })
323 #if !(defined(ABSL_HAVE_STD_VARIANT) && \ 324 defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8) 329 ThrowingVariant rhs(CopyNothrow{});
331 .WithInitialValue(WithThrower())
332 .WithContracts(VariantInvariants,
333 [](ThrowingVariant* lhs) {
334 return lhs->valueless_by_exception();
336 .Test([&](ThrowingVariant* lhs) {
340 #endif // !(defined(ABSL_HAVE_STD_VARIANT) && 345 TEST(VariantExceptionSafetyTest, ValueAssign) {
356 Thrower rhs = ExpectedThrower();
361 .WithOperation([rhs](ThrowingVariant* lhs) { *lhs = rhs; });
362 EXPECT_TRUE(copy_tester
363 .WithContracts(VariantInvariants,
364 [](ThrowingVariant* lhs) {
365 return !lhs->valueless_by_exception();
372 .WithOperation([&](ThrowingVariant* lhs) {
376 EXPECT_TRUE(move_tester
377 .WithContracts(VariantInvariants,
378 [](ThrowingVariant* lhs) {
379 return !lhs->valueless_by_exception();
395 const CopyNothrow rhs;
396 ThrowingVariant lhs = WithThrower();
401 ThrowingVariant lhs = WithThrower();
409 Thrower rhs = ExpectedThrower();
414 .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; });
415 EXPECT_TRUE(copy_tester
416 .WithContracts(VariantInvariants,
417 [](ThrowingVariant* lhs) {
418 return lhs->valueless_by_exception();
425 .WithOperation([](ThrowingVariant* lhs) {
428 EXPECT_TRUE(move_tester
429 .WithContracts(VariantInvariants,
430 [](ThrowingVariant* lhs) {
431 return lhs->valueless_by_exception();
443 #if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__)) 447 .WithInitialValue(WithThrower())
449 .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }));
451 #endif // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__)) 454 TEST(VariantExceptionSafetyTest, Emplace) {
459 Thrower args = ExpectedThrower();
462 .WithOperation([&args](ThrowingVariant* v) {
466 .WithContracts(VariantInvariants,
467 [](ThrowingVariant* v) {
468 return v->valueless_by_exception();
475 TEST(VariantExceptionSafetyTest,
Swap) {
478 ThrowingVariant rhs = ValuelessByException();
479 ThrowingVariant lhs = ValuelessByException();
485 ThrowingVariant rhs = ExpectedThrower();
487 .WithInitialValue(WithThrower())
488 .WithContracts(VariantInvariants)
489 .Test([&](ThrowingVariant* lhs) {
499 ThrowingVariant rhs = ExpectedThrower();
501 .WithInitialValue(WithCopyNoThrow())
502 .WithContracts(VariantInvariants)
503 .Test([&](ThrowingVariant* lhs) {
509 ThrowingVariant rhs = ExpectedThrower();
511 .WithInitialValue(WithCopyNoThrow())
512 .WithContracts(VariantInvariants)
513 .Test([&](ThrowingVariant* lhs) {
523 #endif // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
exceptions_internal::StrongGuaranteeTagType strong_guarantee
TEST(NotificationTest, SanityTest)
exceptions_internal::ExceptionSafetyTestBuilder MakeExceptionSafetyTester()
testing::ThrowingValue<> Thrower
void(*)(utility_internal::InPlaceTypeTag< T >) in_place_type_t
void Swap(T &lhs, T &rhs) noexcept(IsNothrowSwappable< T >::value)
void TestThrowingCtor(Args &&...args)
void(*)(utility_internal::InPlaceIndexTag< I >) in_place_index_t
exceptions_internal::NoThrowTag nothrow_ctor
testing::AssertionResult TestNothrowOp(const Operation &operation)
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
ExceptionSafetyTestBuilder< DefaultFactory< T >, Operation, Contracts... > WithInitialValue(const T &t) const
std::vector< Thrower > ThrowerVec