diff options
author | Abseil Team <absl-team@google.com> | 2018-04-18T12·56-0700 |
---|---|---|
committer | Jon Cohen <cohenjon@google.com> | 2018-04-19T14·19-0400 |
commit | 5b535401665cc6aa96d54a5c9b0901153d97210f (patch) | |
tree | 8d45863656540c8ec81eb7d2742c9191c33ca935 /absl/base/exception_safety_testing_test.cc | |
parent | a7e522daf1ec9cda69b356472f662142dd0c1215 (diff) |
- ed0ba496fe01eb8edfa86beade8a37768e7c12ef Updates the API for Exception Safety testing to use build... by Abseil Team <absl-team@google.com>
- c4b7a4e517c9404932c45f2f9f92eb7dc694e45d Internal change by Abseil Team <absl-team@google.com> - 76c78ed9385f65d881511645446e0bb8ababf6ec Add missing ABSL_PREDICT_FALSE to one of FixedArray::at()... by Abseil Team <absl-team@google.com> - 1204fb1c46f007dd9dfb7d9abf3e96c58835d193 Internal change. by Greg Falcon <gfalcon@google.com> - f1f47c98a026bc5e425ae83ff4a2eb391bbd3d9b Add internal-only functionality to examine the stack, to ... by Derek Mauro <dmauro@google.com> - 30d63097cd268d912f917526f6511005580465c4 fix typo by Abseil Team <absl-team@google.com> - 942d7efa6cf54cd248ca57dcaf3c245188b52a76 Remove unnecessary semicolons from comment examples. by Abseil Team <absl-team@google.com> - 7db0669cf23a06d934d3ed8c76aee4e4e23b7e04 Remove malloc_hook and malloc_extension from our internal... by Greg Falcon <gfalcon@google.com> - 0190f1063d101b1ded355019df2e1d325931f6c7 Make the maximum length of a string view equal difference... by Abseil Team <absl-team@google.com> - c8ae37cbce29449b02115a0ebd435ddc3d7ab062 Add namespace qualification. by Shaindel Schwartz <shaindel@google.com> - ff70afe2e6e3dd39f51ce9829e3e1f18231bf4d7 Fix internal/direct_mmap.h for non-linux builds. by Greg Falcon <gfalcon@google.com> GitOrigin-RevId: ed0ba496fe01eb8edfa86beade8a37768e7c12ef Change-Id: I7595ee3480d1d6724fd3797c15ba9d9be0d17e62
Diffstat (limited to 'absl/base/exception_safety_testing_test.cc')
-rw-r--r-- | absl/base/exception_safety_testing_test.cc | 324 |
1 files changed, 221 insertions, 103 deletions
diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc index 9c52f249ee16..041d780fa5be 100644 --- a/absl/base/exception_safety_testing_test.cc +++ b/absl/base/exception_safety_testing_test.cc @@ -402,29 +402,158 @@ TEST_F(ThrowingAllocatorTest, InList) { for (int i = 0; i < 20; ++i) l.pop_front(); } -struct CallOperator { - template <typename T> - void operator()(T* t) const { - (*t)(); +template <typename TesterInstance, typename = void> +struct NullaryTestValidator : public std::false_type {}; + +template <typename TesterInstance> +struct NullaryTestValidator< + TesterInstance, + absl::void_t<decltype(std::declval<TesterInstance>().Test())>> + : public std::true_type {}; + +template <typename TesterInstance> +bool HasNullaryTest(const TesterInstance&) { + return NullaryTestValidator<TesterInstance>::value; +} + +void DummyOp(void*) {} + +template <typename TesterInstance, typename = void> +struct UnaryTestValidator : public std::false_type {}; + +template <typename TesterInstance> +struct UnaryTestValidator< + TesterInstance, + absl::void_t<decltype(std::declval<TesterInstance>().Test(DummyOp))>> + : public std::true_type {}; + +template <typename TesterInstance> +bool HasUnaryTest(const TesterInstance&) { + return UnaryTestValidator<TesterInstance>::value; +} + +TEST(ExceptionSafetyTesterTest, IncompleteTypesAreNotTestable) { + using T = exceptions_internal::UninitializedT; + auto op = [](T* t) {}; + auto inv = [](T*) { return testing::AssertionSuccess(); }; + auto fac = []() { return absl::make_unique<T>(); }; + + // Test that providing operation and inveriants still does not allow for the + // the invocation of .Test() and .Test(op) because it lacks a factory + auto without_fac = + absl::MakeExceptionSafetyTester().WithOperation(op).WithInvariants( + inv, absl::strong_guarantee); + EXPECT_FALSE(HasNullaryTest(without_fac)); + EXPECT_FALSE(HasUnaryTest(without_fac)); + + // Test that providing invariants and factory allows the invocation of + // .Test(op) but does not allow for .Test() because it lacks an operation + auto without_op = absl::MakeExceptionSafetyTester() + .WithInvariants(inv, absl::strong_guarantee) + .WithFactory(fac); + EXPECT_FALSE(HasNullaryTest(without_op)); + EXPECT_TRUE(HasUnaryTest(without_op)); + + // Test that providing operation and factory still does not allow for the + // the invocation of .Test() and .Test(op) because it lacks invariants + auto without_inv = + absl::MakeExceptionSafetyTester().WithOperation(op).WithFactory(fac); + EXPECT_FALSE(HasNullaryTest(without_inv)); + EXPECT_FALSE(HasUnaryTest(without_inv)); +} + +struct ExampleStruct {}; + +std::unique_ptr<ExampleStruct> ExampleFunctionFactory() { + return absl::make_unique<ExampleStruct>(); +} + +void ExampleFunctionOperation(ExampleStruct*) {} + +testing::AssertionResult ExampleFunctionInvariant(ExampleStruct*) { + return testing::AssertionSuccess(); +} + +struct { + std::unique_ptr<ExampleStruct> operator()() const { + return ExampleFunctionFactory(); + } +} example_struct_factory; + +struct { + void operator()(ExampleStruct*) const {} +} example_struct_operation; + +struct { + testing::AssertionResult operator()(ExampleStruct* example_struct) const { + return ExampleFunctionInvariant(example_struct); } +} example_struct_invariant; + +auto example_lambda_factory = []() { return ExampleFunctionFactory(); }; + +auto example_lambda_operation = [](ExampleStruct*) {}; + +auto example_lambda_invariant = [](ExampleStruct* example_struct) { + return ExampleFunctionInvariant(example_struct); }; +// Testing that function references, pointers, structs with operator() and +// lambdas can all be used with ExceptionSafetyTester +TEST(ExceptionSafetyTesterTest, MixedFunctionTypes) { + // function reference + EXPECT_TRUE(absl::MakeExceptionSafetyTester() + .WithFactory(ExampleFunctionFactory) + .WithOperation(ExampleFunctionOperation) + .WithInvariants(ExampleFunctionInvariant) + .Test()); + + // function pointer + EXPECT_TRUE(absl::MakeExceptionSafetyTester() + .WithFactory(&ExampleFunctionFactory) + .WithOperation(&ExampleFunctionOperation) + .WithInvariants(&ExampleFunctionInvariant) + .Test()); + + // struct + EXPECT_TRUE(absl::MakeExceptionSafetyTester() + .WithFactory(example_struct_factory) + .WithOperation(example_struct_operation) + .WithInvariants(example_struct_invariant) + .Test()); + + // lambda + EXPECT_TRUE(absl::MakeExceptionSafetyTester() + .WithFactory(example_lambda_factory) + .WithOperation(example_lambda_operation) + .WithInvariants(example_lambda_invariant) + .Test()); +} + struct NonNegative { - friend testing::AssertionResult AbslCheckInvariants( - NonNegative* g, absl::InternalAbslNamespaceFinder) { - if (g->i >= 0) return testing::AssertionSuccess(); - return testing::AssertionFailure() - << "i should be non-negative but is " << g->i; - } bool operator==(const NonNegative& other) const { return i == other.i; } - int i; }; -template <typename T> -struct DefaultFactory { - std::unique_ptr<T> operator()() const { return absl::make_unique<T>(); } -}; +testing::AssertionResult CheckNonNegativeInvariants(NonNegative* g) { + if (g->i >= 0) { + return testing::AssertionSuccess(); + } + return testing::AssertionFailure() + << "i should be non-negative but is " << g->i; +} + +struct { + template <typename T> + void operator()(T* t) const { + (*t)(); + } +} invoker; + +auto tester = + absl::MakeExceptionSafetyTester().WithOperation(invoker).WithInvariants( + CheckNonNegativeInvariants); +auto strong_tester = tester.WithInvariants(absl::strong_guarantee); struct FailsBasicGuarantee : public NonNegative { void operator()() { @@ -435,8 +564,7 @@ struct FailsBasicGuarantee : public NonNegative { }; TEST(ExceptionCheckTest, BasicGuaranteeFailure) { - EXPECT_FALSE(TestExceptionSafety(DefaultFactory<FailsBasicGuarantee>(), - CallOperator{})); + EXPECT_FALSE(tester.WithInitialValue(FailsBasicGuarantee{}).Test()); } struct FollowsBasicGuarantee : public NonNegative { @@ -447,22 +575,12 @@ struct FollowsBasicGuarantee : public NonNegative { }; TEST(ExceptionCheckTest, BasicGuarantee) { - EXPECT_TRUE(TestExceptionSafety(DefaultFactory<FollowsBasicGuarantee>(), - CallOperator{})); + EXPECT_TRUE(tester.WithInitialValue(FollowsBasicGuarantee{}).Test()); } TEST(ExceptionCheckTest, StrongGuaranteeFailure) { - { - DefaultFactory<FailsBasicGuarantee> factory; - EXPECT_FALSE( - TestExceptionSafety(factory, CallOperator{}, StrongGuarantee(factory))); - } - - { - DefaultFactory<FollowsBasicGuarantee> factory; - EXPECT_FALSE( - TestExceptionSafety(factory, CallOperator{}, StrongGuarantee(factory))); - } + EXPECT_FALSE(strong_tester.WithInitialValue(FailsBasicGuarantee{}).Test()); + EXPECT_FALSE(strong_tester.WithInitialValue(FollowsBasicGuarantee{}).Test()); } struct BasicGuaranteeWithExtraInvariants : public NonNegative { @@ -479,20 +597,21 @@ struct BasicGuaranteeWithExtraInvariants : public NonNegative { constexpr int BasicGuaranteeWithExtraInvariants::kExceptionSentinel; TEST(ExceptionCheckTest, BasicGuaranteeWithInvariants) { - DefaultFactory<BasicGuaranteeWithExtraInvariants> factory; - - EXPECT_TRUE(TestExceptionSafety(factory, CallOperator{})); - - EXPECT_TRUE(TestExceptionSafety( - factory, CallOperator{}, [](BasicGuaranteeWithExtraInvariants* w) { - if (w->i == BasicGuaranteeWithExtraInvariants::kExceptionSentinel) { - return testing::AssertionSuccess(); - } - return testing::AssertionFailure() - << "i should be " - << BasicGuaranteeWithExtraInvariants::kExceptionSentinel - << ", but is " << w->i; - })); + auto tester_with_val = + tester.WithInitialValue(BasicGuaranteeWithExtraInvariants{}); + EXPECT_TRUE(tester_with_val.Test()); + EXPECT_TRUE( + tester_with_val + .WithInvariants([](BasicGuaranteeWithExtraInvariants* w) { + if (w->i == BasicGuaranteeWithExtraInvariants::kExceptionSentinel) { + return testing::AssertionSuccess(); + } + return testing::AssertionFailure() + << "i should be " + << BasicGuaranteeWithExtraInvariants::kExceptionSentinel + << ", but is " << w->i; + }) + .Test()); } struct FollowsStrongGuarantee : public NonNegative { @@ -500,10 +619,8 @@ struct FollowsStrongGuarantee : public NonNegative { }; TEST(ExceptionCheckTest, StrongGuarantee) { - DefaultFactory<FollowsStrongGuarantee> factory; - EXPECT_TRUE(TestExceptionSafety(factory, CallOperator{})); - EXPECT_TRUE( - TestExceptionSafety(factory, CallOperator{}, StrongGuarantee(factory))); + EXPECT_TRUE(tester.WithInitialValue(FollowsStrongGuarantee{}).Test()); + EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{}).Test()); } struct HasReset : public NonNegative { @@ -514,38 +631,36 @@ struct HasReset : public NonNegative { } void reset() { i = 0; } - - friend bool AbslCheckInvariants(HasReset* h, - absl::InternalAbslNamespaceFinder) { - h->reset(); - return h->i == 0; - } }; +testing::AssertionResult CheckHasResetInvariants(HasReset* h) { + h->reset(); + return testing::AssertionResult(h->i == 0); +} + TEST(ExceptionCheckTest, ModifyingChecker) { - { - DefaultFactory<FollowsBasicGuarantee> factory; - EXPECT_FALSE(TestExceptionSafety( - factory, CallOperator{}, - [](FollowsBasicGuarantee* g) { - g->i = 1000; - return true; - }, - [](FollowsBasicGuarantee* g) { return g->i == 1000; })); - } - { - DefaultFactory<FollowsStrongGuarantee> factory; - EXPECT_TRUE(TestExceptionSafety(factory, CallOperator{}, - [](FollowsStrongGuarantee* g) { - ++g->i; - return true; - }, - StrongGuarantee(factory))); - } - { - DefaultFactory<HasReset> factory; - EXPECT_TRUE(TestExceptionSafety(factory, CallOperator{})); - } + auto set_to_1000 = [](FollowsBasicGuarantee* g) { + g->i = 1000; + return testing::AssertionSuccess(); + }; + auto is_1000 = [](FollowsBasicGuarantee* g) { + return testing::AssertionResult(g->i == 1000); + }; + auto increment = [](FollowsStrongGuarantee* g) { + ++g->i; + return testing::AssertionSuccess(); + }; + + EXPECT_FALSE(tester.WithInitialValue(FollowsBasicGuarantee{}) + .WithInvariants(set_to_1000, is_1000) + .Test()); + EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{}) + .WithInvariants(increment) + .Test()); + EXPECT_TRUE(absl::MakeExceptionSafetyTester() + .WithInitialValue(HasReset{}) + .WithInvariants(CheckHasResetInvariants) + .Test(invoker)); } struct NonCopyable : public NonNegative { @@ -556,10 +671,9 @@ struct NonCopyable : public NonNegative { }; TEST(ExceptionCheckTest, NonCopyable) { - DefaultFactory<NonCopyable> factory; - EXPECT_TRUE(TestExceptionSafety(factory, CallOperator{})); - EXPECT_TRUE( - TestExceptionSafety(factory, CallOperator{}, StrongGuarantee(factory))); + auto factory = []() { return absl::make_unique<NonCopyable>(); }; + EXPECT_TRUE(tester.WithFactory(factory).Test()); + EXPECT_TRUE(strong_tester.WithFactory(factory).Test()); } struct NonEqualityComparable : public NonNegative { @@ -574,15 +688,15 @@ struct NonEqualityComparable : public NonNegative { }; TEST(ExceptionCheckTest, NonEqualityComparable) { - DefaultFactory<NonEqualityComparable> factory; - auto comp = [](const NonEqualityComparable& a, - const NonEqualityComparable& b) { return a.i == b.i; }; - EXPECT_TRUE(TestExceptionSafety(factory, CallOperator{})); - EXPECT_TRUE(TestExceptionSafety(factory, CallOperator{}, - absl::StrongGuarantee(factory, comp))); - EXPECT_FALSE(TestExceptionSafety( - factory, [&](NonEqualityComparable* n) { n->ModifyOnThrow(); }, - absl::StrongGuarantee(factory, comp))); + auto nec_is_strong = [](NonEqualityComparable* nec) { + return testing::AssertionResult(nec->i == NonEqualityComparable().i); + }; + auto strong_nec_tester = tester.WithInitialValue(NonEqualityComparable{}) + .WithInvariants(nec_is_strong); + + EXPECT_TRUE(strong_nec_tester.Test()); + EXPECT_FALSE(strong_nec_tester.Test( + [](NonEqualityComparable* n) { n->ModifyOnThrow(); })); } template <typename T> @@ -604,28 +718,32 @@ struct ExhaustivenessTester { return true; } - friend testing::AssertionResult AbslCheckInvariants( - ExhaustivenessTester*, absl::InternalAbslNamespaceFinder) { + static unsigned char successes; +}; + +struct { + template <typename T> + testing::AssertionResult operator()(ExhaustivenessTester<T>*) const { return testing::AssertionSuccess(); } +} CheckExhaustivenessTesterInvariants; - static unsigned char successes; -}; template <typename T> unsigned char ExhaustivenessTester<T>::successes = 0; TEST(ExceptionCheckTest, Exhaustiveness) { - DefaultFactory<ExhaustivenessTester<int>> int_factory; - EXPECT_TRUE(TestExceptionSafety(int_factory, CallOperator{})); - EXPECT_EQ(ExhaustivenessTester<int>::successes, 0xF); + auto exhaust_tester = absl::MakeExceptionSafetyTester() + .WithInvariants(CheckExhaustivenessTesterInvariants) + .WithOperation(invoker); - DefaultFactory<ExhaustivenessTester<ThrowingValue<>>> bomb_factory; - EXPECT_TRUE(TestExceptionSafety(bomb_factory, CallOperator{})); - EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::successes, 0xF); + EXPECT_TRUE( + exhaust_tester.WithInitialValue(ExhaustivenessTester<int>{}).Test()); + EXPECT_EQ(ExhaustivenessTester<int>::successes, 0xF); - ExhaustivenessTester<ThrowingValue<>>::successes = 0; - EXPECT_TRUE(TestExceptionSafety(bomb_factory, CallOperator{}, - StrongGuarantee(bomb_factory))); + EXPECT_TRUE( + exhaust_tester.WithInitialValue(ExhaustivenessTester<ThrowingValue<>>{}) + .WithInvariants(absl::strong_guarantee) + .Test()); EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::successes, 0xF); } |