exception_safety_testing_test.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
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 // EXPECT_NO_THROW can't inspect the thrown inspection in general.
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   // It's not guaranteed that every operator only throws *once*.  The default
00051   // ctor only throws once, though, so use it to make sure we only throw when
00052   // the countdown hits 0
00053   SetCountdown(2);
00054   ExpectNoThrow([]() { ThrowingValue<> bomb; });
00055   ExpectNoThrow([]() { ThrowingValue<> bomb; });
00056   EXPECT_THROW(ThrowingValue<> bomb, TestException);
00057 
00058   UnsetCountdown();
00059 }
00060 
00061 // Tests that an operation throws when the countdown is at 0, doesn't throw when
00062 // the countdown doesn't hit 0, and doesn't modify the state of the
00063 // ThrowingValue if it throws
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   // Test that when assignment throws, the assignment should fail (lhs != rhs)
00088   // and strong guarantee fails (lhs != lhs_copy).
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 // Tests the operator<< of ThrowingValue by forcing ConstructorTracker to emit
00182 // a nonfatal failure that contains the string representation of the Thrower
00183 TEST(ThrowingValueTest, StreamOpsOutput) {
00184   using ::testing::TypeSpec;
00185   exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
00186 
00187   // Test default spec list (kEverythingThrows)
00188   EXPECT_NONFATAL_FAILURE(
00189       {
00190         using Thrower = ThrowingValue<TypeSpec{}>;
00191         auto thrower = Thrower(123);
00192         thrower.~Thrower();
00193       },
00194       "ThrowingValue<>(123)");
00195 
00196   // Test with one item in spec list (kNoThrowCopy)
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   // Test with multiple items in spec list (kNoThrowMove, kNoThrowNew)
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   // Test with all items in spec list (kNoThrowCopy, kNoThrowMove, kNoThrowNew)
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   // make_unique calls unqualified operator new, so these exercise the
00236   // ThrowingValue overloads.
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([&nothrow_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([&nothrow_assign1, &nothrow_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([&nothrow_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([&nothrow_assign1, &nothrow_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   // We intentionally create extra space to store the tag allocated by placement
00335   // new[].
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   // Test that it's contextually convertible to bool
00370   if (t) {  // NOLINT(whitespace/empty_if_body)
00371   }
00372   EXPECT_TRUE(t);
00373 
00374   TestOp([&]() { (void)!t; });
00375 }
00376 
00377 TEST(ThrowingAllocatorTest, MemoryManagement) {
00378   // Just exercise the memory management capabilities under LSan to make sure we
00379   // don't leak.
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   // This will only throw if ThrowingValue::new is called.
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   // Test that providing operation and inveriants still does not allow for the
00549   // the invocation of .Test() and .Test(op) because it lacks a factory
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   // Test that providing contracts and factory allows the invocation of
00557   // .Test(op) but does not allow for .Test() because it lacks an operation
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   // Test that providing operation and factory still does not allow for the
00565   // the invocation of .Test() and .Test(op) because it lacks contracts
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 // Testing that function references, pointers, structs with operator() and
00609 // lambdas can all be used with ExceptionSafetyTester
00610 TEST(ExceptionSafetyTesterTest, MixedFunctionTypes) {
00611   // function reference
00612   EXPECT_TRUE(testing::MakeExceptionSafetyTester()
00613                   .WithFactory(ExampleFunctionFactory)
00614                   .WithOperation(ExampleFunctionOperation)
00615                   .WithContracts(ExampleFunctionContract)
00616                   .Test());
00617 
00618   // function pointer
00619   EXPECT_TRUE(testing::MakeExceptionSafetyTester()
00620                   .WithFactory(&ExampleFunctionFactory)
00621                   .WithOperation(&ExampleFunctionOperation)
00622                   .WithContracts(&ExampleFunctionContract)
00623                   .Test());
00624 
00625   // struct
00626   EXPECT_TRUE(testing::MakeExceptionSafetyTester()
00627                   .WithFactory(example_struct_factory)
00628                   .WithOperation(example_struct_operation)
00629                   .WithContracts(example_struct_contract)
00630                   .Test());
00631 
00632   // lambda
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   // After operator(), i is incremented.  If operator() throws, i is set to 9999
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   // If the countdown isn't reset because there were no exceptions thrown, then
00781   // this will fail with a termination from an unhandled exception
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 }  // namespace
00953 
00954 }  // namespace testing


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14