00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/base/internal/exception_safety_testing.h"
00016
00017 #include <cstddef>
00018 #include <exception>
00019 #include <iostream>
00020 #include <list>
00021 #include <type_traits>
00022 #include <vector>
00023
00024 #include "gtest/gtest-spi.h"
00025 #include "gtest/gtest.h"
00026 #include "absl/memory/memory.h"
00027
00028 namespace testing {
00029
00030 namespace {
00031
00032 using ::testing::exceptions_internal::SetCountdown;
00033 using ::testing::exceptions_internal::TestException;
00034 using ::testing::exceptions_internal::UnsetCountdown;
00035
00036
00037 template <typename F>
00038 void ExpectNoThrow(const F& f) {
00039 try {
00040 f();
00041 } catch (const TestException& e) {
00042 ADD_FAILURE() << "Unexpected exception thrown from " << e.what();
00043 }
00044 }
00045
00046 TEST(ThrowingValueTest, Throws) {
00047 SetCountdown();
00048 EXPECT_THROW(ThrowingValue<> bomb, TestException);
00049
00050
00051
00052
00053 SetCountdown(2);
00054 ExpectNoThrow([]() { ThrowingValue<> bomb; });
00055 ExpectNoThrow([]() { ThrowingValue<> bomb; });
00056 EXPECT_THROW(ThrowingValue<> bomb, TestException);
00057
00058 UnsetCountdown();
00059 }
00060
00061
00062
00063
00064 template <typename F>
00065 void TestOp(const F& f) {
00066 ExpectNoThrow(f);
00067
00068 SetCountdown();
00069 EXPECT_THROW(f(), TestException);
00070 UnsetCountdown();
00071 }
00072
00073 TEST(ThrowingValueTest, ThrowingCtors) {
00074 ThrowingValue<> bomb;
00075
00076 TestOp([]() { ThrowingValue<> bomb(1); });
00077 TestOp([&]() { ThrowingValue<> bomb1 = bomb; });
00078 TestOp([&]() { ThrowingValue<> bomb1 = std::move(bomb); });
00079 }
00080
00081 TEST(ThrowingValueTest, ThrowingAssignment) {
00082 ThrowingValue<> bomb, bomb1;
00083
00084 TestOp([&]() { bomb = bomb1; });
00085 TestOp([&]() { bomb = std::move(bomb1); });
00086
00087
00088
00089 {
00090 ThrowingValue<> lhs(39), rhs(42);
00091 ThrowingValue<> lhs_copy(lhs);
00092 SetCountdown();
00093 EXPECT_THROW(lhs = rhs, TestException);
00094 UnsetCountdown();
00095 EXPECT_NE(lhs, rhs);
00096 EXPECT_NE(lhs_copy, lhs);
00097 }
00098 {
00099 ThrowingValue<> lhs(39), rhs(42);
00100 ThrowingValue<> lhs_copy(lhs), rhs_copy(rhs);
00101 SetCountdown();
00102 EXPECT_THROW(lhs = std::move(rhs), TestException);
00103 UnsetCountdown();
00104 EXPECT_NE(lhs, rhs_copy);
00105 EXPECT_NE(lhs_copy, lhs);
00106 }
00107 }
00108
00109 TEST(ThrowingValueTest, ThrowingComparisons) {
00110 ThrowingValue<> bomb1, bomb2;
00111 TestOp([&]() { return bomb1 == bomb2; });
00112 TestOp([&]() { return bomb1 != bomb2; });
00113 TestOp([&]() { return bomb1 < bomb2; });
00114 TestOp([&]() { return bomb1 <= bomb2; });
00115 TestOp([&]() { return bomb1 > bomb2; });
00116 TestOp([&]() { return bomb1 >= bomb2; });
00117 }
00118
00119 TEST(ThrowingValueTest, ThrowingArithmeticOps) {
00120 ThrowingValue<> bomb1(1), bomb2(2);
00121
00122 TestOp([&bomb1]() { +bomb1; });
00123 TestOp([&bomb1]() { -bomb1; });
00124 TestOp([&bomb1]() { ++bomb1; });
00125 TestOp([&bomb1]() { bomb1++; });
00126 TestOp([&bomb1]() { --bomb1; });
00127 TestOp([&bomb1]() { bomb1--; });
00128
00129 TestOp([&]() { bomb1 + bomb2; });
00130 TestOp([&]() { bomb1 - bomb2; });
00131 TestOp([&]() { bomb1* bomb2; });
00132 TestOp([&]() { bomb1 / bomb2; });
00133 TestOp([&]() { bomb1 << 1; });
00134 TestOp([&]() { bomb1 >> 1; });
00135 }
00136
00137 TEST(ThrowingValueTest, ThrowingLogicalOps) {
00138 ThrowingValue<> bomb1, bomb2;
00139
00140 TestOp([&bomb1]() { !bomb1; });
00141 TestOp([&]() { bomb1&& bomb2; });
00142 TestOp([&]() { bomb1 || bomb2; });
00143 }
00144
00145 TEST(ThrowingValueTest, ThrowingBitwiseOps) {
00146 ThrowingValue<> bomb1, bomb2;
00147
00148 TestOp([&bomb1]() { ~bomb1; });
00149 TestOp([&]() { bomb1& bomb2; });
00150 TestOp([&]() { bomb1 | bomb2; });
00151 TestOp([&]() { bomb1 ^ bomb2; });
00152 }
00153
00154 TEST(ThrowingValueTest, ThrowingCompoundAssignmentOps) {
00155 ThrowingValue<> bomb1(1), bomb2(2);
00156
00157 TestOp([&]() { bomb1 += bomb2; });
00158 TestOp([&]() { bomb1 -= bomb2; });
00159 TestOp([&]() { bomb1 *= bomb2; });
00160 TestOp([&]() { bomb1 /= bomb2; });
00161 TestOp([&]() { bomb1 %= bomb2; });
00162 TestOp([&]() { bomb1 &= bomb2; });
00163 TestOp([&]() { bomb1 |= bomb2; });
00164 TestOp([&]() { bomb1 ^= bomb2; });
00165 TestOp([&]() { bomb1 *= bomb2; });
00166 }
00167
00168 TEST(ThrowingValueTest, ThrowingStreamOps) {
00169 ThrowingValue<> bomb;
00170
00171 TestOp([&]() {
00172 std::istringstream stream;
00173 stream >> bomb;
00174 });
00175 TestOp([&]() {
00176 std::stringstream stream;
00177 stream << bomb;
00178 });
00179 }
00180
00181
00182
00183 TEST(ThrowingValueTest, StreamOpsOutput) {
00184 using ::testing::TypeSpec;
00185 exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
00186
00187
00188 EXPECT_NONFATAL_FAILURE(
00189 {
00190 using Thrower = ThrowingValue<TypeSpec{}>;
00191 auto thrower = Thrower(123);
00192 thrower.~Thrower();
00193 },
00194 "ThrowingValue<>(123)");
00195
00196
00197 EXPECT_NONFATAL_FAILURE(
00198 {
00199 using Thrower = ThrowingValue<TypeSpec::kNoThrowCopy>;
00200 auto thrower = Thrower(234);
00201 thrower.~Thrower();
00202 },
00203 "ThrowingValue<kNoThrowCopy>(234)");
00204
00205
00206 EXPECT_NONFATAL_FAILURE(
00207 {
00208 using Thrower =
00209 ThrowingValue<TypeSpec::kNoThrowMove | TypeSpec::kNoThrowNew>;
00210 auto thrower = Thrower(345);
00211 thrower.~Thrower();
00212 },
00213 "ThrowingValue<kNoThrowMove | kNoThrowNew>(345)");
00214
00215
00216 EXPECT_NONFATAL_FAILURE(
00217 {
00218 using Thrower = ThrowingValue<static_cast<TypeSpec>(-1)>;
00219 auto thrower = Thrower(456);
00220 thrower.~Thrower();
00221 },
00222 "ThrowingValue<kNoThrowCopy | kNoThrowMove | kNoThrowNew>(456)");
00223 }
00224
00225 template <typename F>
00226 void TestAllocatingOp(const F& f) {
00227 ExpectNoThrow(f);
00228
00229 SetCountdown();
00230 EXPECT_THROW(f(), exceptions_internal::TestBadAllocException);
00231 UnsetCountdown();
00232 }
00233
00234 TEST(ThrowingValueTest, ThrowingAllocatingOps) {
00235
00236
00237 TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>>(1); });
00238 TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>[]>(2); });
00239 }
00240
00241 TEST(ThrowingValueTest, NonThrowingMoveCtor) {
00242 ThrowingValue<TypeSpec::kNoThrowMove> nothrow_ctor;
00243
00244 SetCountdown();
00245 ExpectNoThrow([¬hrow_ctor]() {
00246 ThrowingValue<TypeSpec::kNoThrowMove> nothrow1 = std::move(nothrow_ctor);
00247 });
00248 UnsetCountdown();
00249 }
00250
00251 TEST(ThrowingValueTest, NonThrowingMoveAssign) {
00252 ThrowingValue<TypeSpec::kNoThrowMove> nothrow_assign1, nothrow_assign2;
00253
00254 SetCountdown();
00255 ExpectNoThrow([¬hrow_assign1, ¬hrow_assign2]() {
00256 nothrow_assign1 = std::move(nothrow_assign2);
00257 });
00258 UnsetCountdown();
00259 }
00260
00261 TEST(ThrowingValueTest, ThrowingCopyCtor) {
00262 ThrowingValue<> tv;
00263
00264 TestOp([&]() { ThrowingValue<> tv_copy(tv); });
00265 }
00266
00267 TEST(ThrowingValueTest, ThrowingCopyAssign) {
00268 ThrowingValue<> tv1, tv2;
00269
00270 TestOp([&]() { tv1 = tv2; });
00271 }
00272
00273 TEST(ThrowingValueTest, NonThrowingCopyCtor) {
00274 ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_ctor;
00275
00276 SetCountdown();
00277 ExpectNoThrow([¬hrow_ctor]() {
00278 ThrowingValue<TypeSpec::kNoThrowCopy> nothrow1(nothrow_ctor);
00279 });
00280 UnsetCountdown();
00281 }
00282
00283 TEST(ThrowingValueTest, NonThrowingCopyAssign) {
00284 ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_assign1, nothrow_assign2;
00285
00286 SetCountdown();
00287 ExpectNoThrow([¬hrow_assign1, ¬hrow_assign2]() {
00288 nothrow_assign1 = nothrow_assign2;
00289 });
00290 UnsetCountdown();
00291 }
00292
00293 TEST(ThrowingValueTest, ThrowingSwap) {
00294 ThrowingValue<> bomb1, bomb2;
00295 TestOp([&]() { std::swap(bomb1, bomb2); });
00296 }
00297
00298 TEST(ThrowingValueTest, NonThrowingSwap) {
00299 ThrowingValue<TypeSpec::kNoThrowMove> bomb1, bomb2;
00300 ExpectNoThrow([&]() { std::swap(bomb1, bomb2); });
00301 }
00302
00303 TEST(ThrowingValueTest, NonThrowingAllocation) {
00304 ThrowingValue<TypeSpec::kNoThrowNew>* allocated;
00305 ThrowingValue<TypeSpec::kNoThrowNew>* array;
00306
00307 ExpectNoThrow([&allocated]() {
00308 allocated = new ThrowingValue<TypeSpec::kNoThrowNew>(1);
00309 delete allocated;
00310 });
00311 ExpectNoThrow([&array]() {
00312 array = new ThrowingValue<TypeSpec::kNoThrowNew>[2];
00313 delete[] array;
00314 });
00315 }
00316
00317 TEST(ThrowingValueTest, NonThrowingDelete) {
00318 auto* allocated = new ThrowingValue<>(1);
00319 auto* array = new ThrowingValue<>[2];
00320
00321 SetCountdown();
00322 ExpectNoThrow([allocated]() { delete allocated; });
00323 SetCountdown();
00324 ExpectNoThrow([array]() { delete[] array; });
00325
00326 UnsetCountdown();
00327 }
00328
00329 using Storage =
00330 absl::aligned_storage_t<sizeof(ThrowingValue<>), alignof(ThrowingValue<>)>;
00331
00332 TEST(ThrowingValueTest, NonThrowingPlacementDelete) {
00333 constexpr int kArrayLen = 2;
00334
00335
00336 constexpr int kStorageLen = 4;
00337
00338 Storage buf;
00339 Storage array_buf[kStorageLen];
00340 auto* placed = new (&buf) ThrowingValue<>(1);
00341 auto placed_array = new (&array_buf) ThrowingValue<>[kArrayLen];
00342
00343 SetCountdown();
00344 ExpectNoThrow([placed, &buf]() {
00345 placed->~ThrowingValue<>();
00346 ThrowingValue<>::operator delete(placed, &buf);
00347 });
00348
00349 SetCountdown();
00350 ExpectNoThrow([&, placed_array]() {
00351 for (int i = 0; i < kArrayLen; ++i) placed_array[i].~ThrowingValue<>();
00352 ThrowingValue<>::operator delete[](placed_array, &array_buf);
00353 });
00354
00355 UnsetCountdown();
00356 }
00357
00358 TEST(ThrowingValueTest, NonThrowingDestructor) {
00359 auto* allocated = new ThrowingValue<>();
00360
00361 SetCountdown();
00362 ExpectNoThrow([allocated]() { delete allocated; });
00363 UnsetCountdown();
00364 }
00365
00366 TEST(ThrowingBoolTest, ThrowingBool) {
00367 ThrowingBool t = true;
00368
00369
00370 if (t) {
00371 }
00372 EXPECT_TRUE(t);
00373
00374 TestOp([&]() { (void)!t; });
00375 }
00376
00377 TEST(ThrowingAllocatorTest, MemoryManagement) {
00378
00379
00380 ThrowingAllocator<int> int_alloc;
00381 int* ip = int_alloc.allocate(1);
00382 int_alloc.deallocate(ip, 1);
00383 int* i_array = int_alloc.allocate(2);
00384 int_alloc.deallocate(i_array, 2);
00385
00386 ThrowingAllocator<ThrowingValue<>> tv_alloc;
00387 ThrowingValue<>* ptr = tv_alloc.allocate(1);
00388 tv_alloc.deallocate(ptr, 1);
00389 ThrowingValue<>* tv_array = tv_alloc.allocate(2);
00390 tv_alloc.deallocate(tv_array, 2);
00391 }
00392
00393 TEST(ThrowingAllocatorTest, CallsGlobalNew) {
00394 ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate> nothrow_alloc;
00395 ThrowingValue<>* ptr;
00396
00397 SetCountdown();
00398
00399 ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); });
00400 nothrow_alloc.deallocate(ptr, 1);
00401
00402 UnsetCountdown();
00403 }
00404
00405 TEST(ThrowingAllocatorTest, ThrowingConstructors) {
00406 ThrowingAllocator<int> int_alloc;
00407 int* ip = nullptr;
00408
00409 SetCountdown();
00410 EXPECT_THROW(ip = int_alloc.allocate(1), TestException);
00411 ExpectNoThrow([&]() { ip = int_alloc.allocate(1); });
00412
00413 *ip = 1;
00414 SetCountdown();
00415 EXPECT_THROW(int_alloc.construct(ip, 2), TestException);
00416 EXPECT_EQ(*ip, 1);
00417 int_alloc.deallocate(ip, 1);
00418
00419 UnsetCountdown();
00420 }
00421
00422 TEST(ThrowingAllocatorTest, NonThrowingConstruction) {
00423 {
00424 ThrowingAllocator<int, AllocSpec::kNoThrowAllocate> int_alloc;
00425 int* ip = nullptr;
00426
00427 SetCountdown();
00428 ExpectNoThrow([&]() { ip = int_alloc.allocate(1); });
00429
00430 SetCountdown();
00431 ExpectNoThrow([&]() { int_alloc.construct(ip, 2); });
00432
00433 EXPECT_EQ(*ip, 2);
00434 int_alloc.deallocate(ip, 1);
00435
00436 UnsetCountdown();
00437 }
00438
00439 {
00440 ThrowingAllocator<int> int_alloc;
00441 int* ip = nullptr;
00442 ExpectNoThrow([&]() { ip = int_alloc.allocate(1); });
00443 ExpectNoThrow([&]() { int_alloc.construct(ip, 2); });
00444 EXPECT_EQ(*ip, 2);
00445 int_alloc.deallocate(ip, 1);
00446 }
00447
00448 {
00449 ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate>
00450 nothrow_alloc;
00451 ThrowingValue<>* ptr;
00452
00453 SetCountdown();
00454 ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); });
00455
00456 SetCountdown();
00457 ExpectNoThrow(
00458 [&]() { nothrow_alloc.construct(ptr, 2, testing::nothrow_ctor); });
00459
00460 EXPECT_EQ(ptr->Get(), 2);
00461 nothrow_alloc.destroy(ptr);
00462 nothrow_alloc.deallocate(ptr, 1);
00463
00464 UnsetCountdown();
00465 }
00466
00467 {
00468 ThrowingAllocator<int> a;
00469
00470 SetCountdown();
00471 ExpectNoThrow([&]() { ThrowingAllocator<double> a1 = a; });
00472
00473 SetCountdown();
00474 ExpectNoThrow([&]() { ThrowingAllocator<double> a1 = std::move(a); });
00475
00476 UnsetCountdown();
00477 }
00478 }
00479
00480 TEST(ThrowingAllocatorTest, ThrowingAllocatorConstruction) {
00481 ThrowingAllocator<int> a;
00482 TestOp([]() { ThrowingAllocator<int> a; });
00483 TestOp([&]() { a.select_on_container_copy_construction(); });
00484 }
00485
00486 TEST(ThrowingAllocatorTest, State) {
00487 ThrowingAllocator<int> a1, a2;
00488 EXPECT_NE(a1, a2);
00489
00490 auto a3 = a1;
00491 EXPECT_EQ(a3, a1);
00492 int* ip = a1.allocate(1);
00493 EXPECT_EQ(a3, a1);
00494 a3.deallocate(ip, 1);
00495 EXPECT_EQ(a3, a1);
00496 }
00497
00498 TEST(ThrowingAllocatorTest, InVector) {
00499 std::vector<ThrowingValue<>, ThrowingAllocator<ThrowingValue<>>> v;
00500 for (int i = 0; i < 20; ++i) v.push_back({});
00501 for (int i = 0; i < 20; ++i) v.pop_back();
00502 }
00503
00504 TEST(ThrowingAllocatorTest, InList) {
00505 std::list<ThrowingValue<>, ThrowingAllocator<ThrowingValue<>>> l;
00506 for (int i = 0; i < 20; ++i) l.push_back({});
00507 for (int i = 0; i < 20; ++i) l.pop_back();
00508 for (int i = 0; i < 20; ++i) l.push_front({});
00509 for (int i = 0; i < 20; ++i) l.pop_front();
00510 }
00511
00512 template <typename TesterInstance, typename = void>
00513 struct NullaryTestValidator : public std::false_type {};
00514
00515 template <typename TesterInstance>
00516 struct NullaryTestValidator<
00517 TesterInstance,
00518 absl::void_t<decltype(std::declval<TesterInstance>().Test())>>
00519 : public std::true_type {};
00520
00521 template <typename TesterInstance>
00522 bool HasNullaryTest(const TesterInstance&) {
00523 return NullaryTestValidator<TesterInstance>::value;
00524 }
00525
00526 void DummyOp(void*) {}
00527
00528 template <typename TesterInstance, typename = void>
00529 struct UnaryTestValidator : public std::false_type {};
00530
00531 template <typename TesterInstance>
00532 struct UnaryTestValidator<
00533 TesterInstance,
00534 absl::void_t<decltype(std::declval<TesterInstance>().Test(DummyOp))>>
00535 : public std::true_type {};
00536
00537 template <typename TesterInstance>
00538 bool HasUnaryTest(const TesterInstance&) {
00539 return UnaryTestValidator<TesterInstance>::value;
00540 }
00541
00542 TEST(ExceptionSafetyTesterTest, IncompleteTypesAreNotTestable) {
00543 using T = exceptions_internal::UninitializedT;
00544 auto op = [](T* t) {};
00545 auto inv = [](T*) { return testing::AssertionSuccess(); };
00546 auto fac = []() { return absl::make_unique<T>(); };
00547
00548
00549
00550 auto without_fac =
00551 testing::MakeExceptionSafetyTester().WithOperation(op).WithContracts(
00552 inv, testing::strong_guarantee);
00553 EXPECT_FALSE(HasNullaryTest(without_fac));
00554 EXPECT_FALSE(HasUnaryTest(without_fac));
00555
00556
00557
00558 auto without_op = testing::MakeExceptionSafetyTester()
00559 .WithContracts(inv, testing::strong_guarantee)
00560 .WithFactory(fac);
00561 EXPECT_FALSE(HasNullaryTest(without_op));
00562 EXPECT_TRUE(HasUnaryTest(without_op));
00563
00564
00565
00566 auto without_inv =
00567 testing::MakeExceptionSafetyTester().WithOperation(op).WithFactory(fac);
00568 EXPECT_FALSE(HasNullaryTest(without_inv));
00569 EXPECT_FALSE(HasUnaryTest(without_inv));
00570 }
00571
00572 struct ExampleStruct {};
00573
00574 std::unique_ptr<ExampleStruct> ExampleFunctionFactory() {
00575 return absl::make_unique<ExampleStruct>();
00576 }
00577
00578 void ExampleFunctionOperation(ExampleStruct*) {}
00579
00580 testing::AssertionResult ExampleFunctionContract(ExampleStruct*) {
00581 return testing::AssertionSuccess();
00582 }
00583
00584 struct {
00585 std::unique_ptr<ExampleStruct> operator()() const {
00586 return ExampleFunctionFactory();
00587 }
00588 } example_struct_factory;
00589
00590 struct {
00591 void operator()(ExampleStruct*) const {}
00592 } example_struct_operation;
00593
00594 struct {
00595 testing::AssertionResult operator()(ExampleStruct* example_struct) const {
00596 return ExampleFunctionContract(example_struct);
00597 }
00598 } example_struct_contract;
00599
00600 auto example_lambda_factory = []() { return ExampleFunctionFactory(); };
00601
00602 auto example_lambda_operation = [](ExampleStruct*) {};
00603
00604 auto example_lambda_contract = [](ExampleStruct* example_struct) {
00605 return ExampleFunctionContract(example_struct);
00606 };
00607
00608
00609
00610 TEST(ExceptionSafetyTesterTest, MixedFunctionTypes) {
00611
00612 EXPECT_TRUE(testing::MakeExceptionSafetyTester()
00613 .WithFactory(ExampleFunctionFactory)
00614 .WithOperation(ExampleFunctionOperation)
00615 .WithContracts(ExampleFunctionContract)
00616 .Test());
00617
00618
00619 EXPECT_TRUE(testing::MakeExceptionSafetyTester()
00620 .WithFactory(&ExampleFunctionFactory)
00621 .WithOperation(&ExampleFunctionOperation)
00622 .WithContracts(&ExampleFunctionContract)
00623 .Test());
00624
00625
00626 EXPECT_TRUE(testing::MakeExceptionSafetyTester()
00627 .WithFactory(example_struct_factory)
00628 .WithOperation(example_struct_operation)
00629 .WithContracts(example_struct_contract)
00630 .Test());
00631
00632
00633 EXPECT_TRUE(testing::MakeExceptionSafetyTester()
00634 .WithFactory(example_lambda_factory)
00635 .WithOperation(example_lambda_operation)
00636 .WithContracts(example_lambda_contract)
00637 .Test());
00638 }
00639
00640 struct NonNegative {
00641 bool operator==(const NonNegative& other) const { return i == other.i; }
00642 int i;
00643 };
00644
00645 testing::AssertionResult CheckNonNegativeInvariants(NonNegative* g) {
00646 if (g->i >= 0) {
00647 return testing::AssertionSuccess();
00648 }
00649 return testing::AssertionFailure()
00650 << "i should be non-negative but is " << g->i;
00651 }
00652
00653 struct {
00654 template <typename T>
00655 void operator()(T* t) const {
00656 (*t)();
00657 }
00658 } invoker;
00659
00660 auto tester =
00661 testing::MakeExceptionSafetyTester().WithOperation(invoker).WithContracts(
00662 CheckNonNegativeInvariants);
00663 auto strong_tester = tester.WithContracts(testing::strong_guarantee);
00664
00665 struct FailsBasicGuarantee : public NonNegative {
00666 void operator()() {
00667 --i;
00668 ThrowingValue<> bomb;
00669 ++i;
00670 }
00671 };
00672
00673 TEST(ExceptionCheckTest, BasicGuaranteeFailure) {
00674 EXPECT_FALSE(tester.WithInitialValue(FailsBasicGuarantee{}).Test());
00675 }
00676
00677 struct FollowsBasicGuarantee : public NonNegative {
00678 void operator()() {
00679 ++i;
00680 ThrowingValue<> bomb;
00681 }
00682 };
00683
00684 TEST(ExceptionCheckTest, BasicGuarantee) {
00685 EXPECT_TRUE(tester.WithInitialValue(FollowsBasicGuarantee{}).Test());
00686 }
00687
00688 TEST(ExceptionCheckTest, StrongGuaranteeFailure) {
00689 EXPECT_FALSE(strong_tester.WithInitialValue(FailsBasicGuarantee{}).Test());
00690 EXPECT_FALSE(strong_tester.WithInitialValue(FollowsBasicGuarantee{}).Test());
00691 }
00692
00693 struct BasicGuaranteeWithExtraContracts : public NonNegative {
00694
00695 void operator()() {
00696 int old_i = i;
00697 i = kExceptionSentinel;
00698 ThrowingValue<> bomb;
00699 i = ++old_i;
00700 }
00701
00702 static constexpr int kExceptionSentinel = 9999;
00703 };
00704 constexpr int BasicGuaranteeWithExtraContracts::kExceptionSentinel;
00705
00706 TEST(ExceptionCheckTest, BasicGuaranteeWithExtraContracts) {
00707 auto tester_with_val =
00708 tester.WithInitialValue(BasicGuaranteeWithExtraContracts{});
00709 EXPECT_TRUE(tester_with_val.Test());
00710 EXPECT_TRUE(
00711 tester_with_val
00712 .WithContracts([](BasicGuaranteeWithExtraContracts* o) {
00713 if (o->i == BasicGuaranteeWithExtraContracts::kExceptionSentinel) {
00714 return testing::AssertionSuccess();
00715 }
00716 return testing::AssertionFailure()
00717 << "i should be "
00718 << BasicGuaranteeWithExtraContracts::kExceptionSentinel
00719 << ", but is " << o->i;
00720 })
00721 .Test());
00722 }
00723
00724 struct FollowsStrongGuarantee : public NonNegative {
00725 void operator()() { ThrowingValue<> bomb; }
00726 };
00727
00728 TEST(ExceptionCheckTest, StrongGuarantee) {
00729 EXPECT_TRUE(tester.WithInitialValue(FollowsStrongGuarantee{}).Test());
00730 EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{}).Test());
00731 }
00732
00733 struct HasReset : public NonNegative {
00734 void operator()() {
00735 i = -1;
00736 ThrowingValue<> bomb;
00737 i = 1;
00738 }
00739
00740 void reset() { i = 0; }
00741 };
00742
00743 testing::AssertionResult CheckHasResetContracts(HasReset* h) {
00744 h->reset();
00745 return testing::AssertionResult(h->i == 0);
00746 }
00747
00748 TEST(ExceptionCheckTest, ModifyingChecker) {
00749 auto set_to_1000 = [](FollowsBasicGuarantee* g) {
00750 g->i = 1000;
00751 return testing::AssertionSuccess();
00752 };
00753 auto is_1000 = [](FollowsBasicGuarantee* g) {
00754 return testing::AssertionResult(g->i == 1000);
00755 };
00756 auto increment = [](FollowsStrongGuarantee* g) {
00757 ++g->i;
00758 return testing::AssertionSuccess();
00759 };
00760
00761 EXPECT_FALSE(tester.WithInitialValue(FollowsBasicGuarantee{})
00762 .WithContracts(set_to_1000, is_1000)
00763 .Test());
00764 EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{})
00765 .WithContracts(increment)
00766 .Test());
00767 EXPECT_TRUE(testing::MakeExceptionSafetyTester()
00768 .WithInitialValue(HasReset{})
00769 .WithContracts(CheckHasResetContracts)
00770 .Test(invoker));
00771 }
00772
00773 TEST(ExceptionSafetyTesterTest, ResetsCountdown) {
00774 auto test =
00775 testing::MakeExceptionSafetyTester()
00776 .WithInitialValue(ThrowingValue<>())
00777 .WithContracts([](ThrowingValue<>*) { return AssertionSuccess(); })
00778 .WithOperation([](ThrowingValue<>*) {});
00779 ASSERT_TRUE(test.Test());
00780
00781
00782 EXPECT_TRUE(test.Test());
00783 }
00784
00785 struct NonCopyable : public NonNegative {
00786 NonCopyable(const NonCopyable&) = delete;
00787 NonCopyable() : NonNegative{0} {}
00788
00789 void operator()() { ThrowingValue<> bomb; }
00790 };
00791
00792 TEST(ExceptionCheckTest, NonCopyable) {
00793 auto factory = []() { return absl::make_unique<NonCopyable>(); };
00794 EXPECT_TRUE(tester.WithFactory(factory).Test());
00795 EXPECT_TRUE(strong_tester.WithFactory(factory).Test());
00796 }
00797
00798 struct NonEqualityComparable : public NonNegative {
00799 void operator()() { ThrowingValue<> bomb; }
00800
00801 void ModifyOnThrow() {
00802 ++i;
00803 ThrowingValue<> bomb;
00804 static_cast<void>(bomb);
00805 --i;
00806 }
00807 };
00808
00809 TEST(ExceptionCheckTest, NonEqualityComparable) {
00810 auto nec_is_strong = [](NonEqualityComparable* nec) {
00811 return testing::AssertionResult(nec->i == NonEqualityComparable().i);
00812 };
00813 auto strong_nec_tester = tester.WithInitialValue(NonEqualityComparable{})
00814 .WithContracts(nec_is_strong);
00815
00816 EXPECT_TRUE(strong_nec_tester.Test());
00817 EXPECT_FALSE(strong_nec_tester.Test(
00818 [](NonEqualityComparable* n) { n->ModifyOnThrow(); }));
00819 }
00820
00821 template <typename T>
00822 struct ExhaustivenessTester {
00823 void operator()() {
00824 successes |= 1;
00825 T b1;
00826 static_cast<void>(b1);
00827 successes |= (1 << 1);
00828 T b2;
00829 static_cast<void>(b2);
00830 successes |= (1 << 2);
00831 T b3;
00832 static_cast<void>(b3);
00833 successes |= (1 << 3);
00834 }
00835
00836 bool operator==(const ExhaustivenessTester<ThrowingValue<>>&) const {
00837 return true;
00838 }
00839
00840 static unsigned char successes;
00841 };
00842
00843 struct {
00844 template <typename T>
00845 testing::AssertionResult operator()(ExhaustivenessTester<T>*) const {
00846 return testing::AssertionSuccess();
00847 }
00848 } CheckExhaustivenessTesterContracts;
00849
00850 template <typename T>
00851 unsigned char ExhaustivenessTester<T>::successes = 0;
00852
00853 TEST(ExceptionCheckTest, Exhaustiveness) {
00854 auto exhaust_tester = testing::MakeExceptionSafetyTester()
00855 .WithContracts(CheckExhaustivenessTesterContracts)
00856 .WithOperation(invoker);
00857
00858 EXPECT_TRUE(
00859 exhaust_tester.WithInitialValue(ExhaustivenessTester<int>{}).Test());
00860 EXPECT_EQ(ExhaustivenessTester<int>::successes, 0xF);
00861
00862 EXPECT_TRUE(
00863 exhaust_tester.WithInitialValue(ExhaustivenessTester<ThrowingValue<>>{})
00864 .WithContracts(testing::strong_guarantee)
00865 .Test());
00866 EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::successes, 0xF);
00867 }
00868
00869 struct LeaksIfCtorThrows : private exceptions_internal::TrackedObject {
00870 LeaksIfCtorThrows() : TrackedObject(ABSL_PRETTY_FUNCTION) {
00871 ++counter;
00872 ThrowingValue<> v;
00873 static_cast<void>(v);
00874 --counter;
00875 }
00876 LeaksIfCtorThrows(const LeaksIfCtorThrows&) noexcept
00877 : TrackedObject(ABSL_PRETTY_FUNCTION) {}
00878 static int counter;
00879 };
00880 int LeaksIfCtorThrows::counter = 0;
00881
00882 TEST(ExceptionCheckTest, TestLeakyCtor) {
00883 testing::TestThrowingCtor<LeaksIfCtorThrows>();
00884 EXPECT_EQ(LeaksIfCtorThrows::counter, 1);
00885 LeaksIfCtorThrows::counter = 0;
00886 }
00887
00888 struct Tracked : private exceptions_internal::TrackedObject {
00889 Tracked() : TrackedObject(ABSL_PRETTY_FUNCTION) {}
00890 };
00891
00892 TEST(ConstructorTrackerTest, CreatedBefore) {
00893 Tracked a, b, c;
00894 exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
00895 }
00896
00897 TEST(ConstructorTrackerTest, CreatedAfter) {
00898 exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
00899 Tracked a, b, c;
00900 }
00901
00902 TEST(ConstructorTrackerTest, NotDestroyedAfter) {
00903 absl::aligned_storage_t<sizeof(Tracked), alignof(Tracked)> storage;
00904 EXPECT_NONFATAL_FAILURE(
00905 {
00906 exceptions_internal::ConstructorTracker ct(
00907 exceptions_internal::countdown);
00908 new (&storage) Tracked;
00909 },
00910 "not destroyed");
00911 }
00912
00913 TEST(ConstructorTrackerTest, DestroyedTwice) {
00914 exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
00915 EXPECT_NONFATAL_FAILURE(
00916 {
00917 Tracked t;
00918 t.~Tracked();
00919 },
00920 "re-destroyed");
00921 }
00922
00923 TEST(ConstructorTrackerTest, ConstructedTwice) {
00924 exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
00925 absl::aligned_storage_t<sizeof(Tracked), alignof(Tracked)> storage;
00926 EXPECT_NONFATAL_FAILURE(
00927 {
00928 new (&storage) Tracked;
00929 new (&storage) Tracked;
00930 reinterpret_cast<Tracked*>(&storage)->~Tracked();
00931 },
00932 "re-constructed");
00933 }
00934
00935 TEST(ThrowingValueTraitsTest, RelationalOperators) {
00936 ThrowingValue<> a, b;
00937 EXPECT_TRUE((std::is_convertible<decltype(a == b), bool>::value));
00938 EXPECT_TRUE((std::is_convertible<decltype(a != b), bool>::value));
00939 EXPECT_TRUE((std::is_convertible<decltype(a < b), bool>::value));
00940 EXPECT_TRUE((std::is_convertible<decltype(a <= b), bool>::value));
00941 EXPECT_TRUE((std::is_convertible<decltype(a > b), bool>::value));
00942 EXPECT_TRUE((std::is_convertible<decltype(a >= b), bool>::value));
00943 }
00944
00945 TEST(ThrowingAllocatorTraitsTest, Assignablility) {
00946 EXPECT_TRUE(absl::is_move_assignable<ThrowingAllocator<int>>::value);
00947 EXPECT_TRUE(absl::is_copy_assignable<ThrowingAllocator<int>>::value);
00948 EXPECT_TRUE(std::is_nothrow_move_assignable<ThrowingAllocator<int>>::value);
00949 EXPECT_TRUE(std::is_nothrow_copy_assignable<ThrowingAllocator<int>>::value);
00950 }
00951
00952 }
00953
00954 }