summaryrefslogtreecommitdiff
path: root/absl/base/exception_safety_testing_test.cc
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2018-04-18 05:56:39 -0700
committerGravatar Jon Cohen <cohenjon@google.com>2018-04-19 10:19:32 -0400
commit5b535401665cc6aa96d54a5c9b0901153d97210f (patch)
tree8d45863656540c8ec81eb7d2742c9191c33ca935 /absl/base/exception_safety_testing_test.cc
parenta7e522daf1ec9cda69b356472f662142dd0c1215 (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.cc324
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 9c52f249..041d780f 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);
}