- 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
This commit is contained in:
Abseil Team 2018-04-18 05:56:39 -07:00 committed by Jon Cohen
parent a7e522daf1
commit 5b53540166
35 changed files with 831 additions and 2601 deletions

View file

@ -402,29 +402,158 @@ TEST_F(ThrowingAllocatorTest, InList) {
for (int i = 0; i < 20; ++i) l.pop_front();
}
struct CallOperator {
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 {
bool operator==(const NonNegative& other) const { return i == other.i; }
int i;
};
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;
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>(); }
};
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) {
return testing::AssertionSuccess();
}
static unsigned char successes;
};
struct {
template <typename T>
testing::AssertionResult operator()(ExhaustivenessTester<T>*) const {
return testing::AssertionSuccess();
}
} CheckExhaustivenessTesterInvariants;
template <typename T>
unsigned char ExhaustivenessTester<T>::successes = 0;
TEST(ExceptionCheckTest, Exhaustiveness) {
DefaultFactory<ExhaustivenessTester<int>> int_factory;
EXPECT_TRUE(TestExceptionSafety(int_factory, CallOperator{}));
auto exhaust_tester = absl::MakeExceptionSafetyTester()
.WithInvariants(CheckExhaustivenessTesterInvariants)
.WithOperation(invoker);
EXPECT_TRUE(
exhaust_tester.WithInitialValue(ExhaustivenessTester<int>{}).Test());
EXPECT_EQ(ExhaustivenessTester<int>::successes, 0xF);
DefaultFactory<ExhaustivenessTester<ThrowingValue<>>> bomb_factory;
EXPECT_TRUE(TestExceptionSafety(bomb_factory, CallOperator{}));
EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::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);
}