- 60c1f40a5e0bc33f93392ff6827528072d749a29 Move ExceptionSafetyTester from the absl:: namespace to t... by Abseil Team <absl-team@google.com>

- abd40a98f8ae746eb151e777ea8a8b5223d68a4b Splits the NoThrow flags into TypeSpec and AllocSpec flag... by Abseil Team <absl-team@google.com>
  - c16d0b5509b36679b384147b474135e7951afccf Change the abbreviation for the breakdowns of InfinitePas... by Abseil Team <absl-team@google.com>
  - 8ac104351764f23d666b52dce7536a34c05abf00 Use ABSL_CONST_INIT with std::atomic variables in static ... by Matt Armstrong <marmstrong@google.com>

GitOrigin-RevId: 60c1f40a5e0bc33f93392ff6827528072d749a29
Change-Id: I9d45a6ed30ed32ae57e9eff93f4205dbcd71feb2
This commit is contained in:
Abseil Team 2018-04-30 11:44:26 -07:00 committed by vslashg
parent 28f5b89070
commit 9613678332
13 changed files with 303 additions and 218 deletions

View file

@ -25,11 +25,13 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
namespace absl { namespace testing {
namespace { namespace {
using ::absl::exceptions_internal::SetCountdown;
using ::absl::exceptions_internal::TestException; using ::testing::exceptions_internal::SetCountdown;
using ::absl::exceptions_internal::UnsetCountdown; using ::testing::exceptions_internal::TestException;
using ::testing::exceptions_internal::UnsetCountdown;
// EXPECT_NO_THROW can't inspect the thrown inspection in general. // EXPECT_NO_THROW can't inspect the thrown inspection in general.
template <typename F> template <typename F>
@ -166,17 +168,17 @@ TEST(ThrowingValueTest, ThrowingAllocatingOps) {
} }
TEST(ThrowingValueTest, NonThrowingMoveCtor) { TEST(ThrowingValueTest, NonThrowingMoveCtor) {
ThrowingValue<NoThrow::kMoveCtor> nothrow_ctor; ThrowingValue<TypeSpec::kNoThrowMove> nothrow_ctor;
SetCountdown(); SetCountdown();
ExpectNoThrow([&nothrow_ctor]() { ExpectNoThrow([&nothrow_ctor]() {
ThrowingValue<NoThrow::kMoveCtor> nothrow1 = std::move(nothrow_ctor); ThrowingValue<TypeSpec::kNoThrowMove> nothrow1 = std::move(nothrow_ctor);
}); });
UnsetCountdown(); UnsetCountdown();
} }
TEST(ThrowingValueTest, NonThrowingMoveAssign) { TEST(ThrowingValueTest, NonThrowingMoveAssign) {
ThrowingValue<NoThrow::kMoveAssign> nothrow_assign1, nothrow_assign2; ThrowingValue<TypeSpec::kNoThrowMove> nothrow_assign1, nothrow_assign2;
SetCountdown(); SetCountdown();
ExpectNoThrow([&nothrow_assign1, &nothrow_assign2]() { ExpectNoThrow([&nothrow_assign1, &nothrow_assign2]() {
@ -185,32 +187,58 @@ TEST(ThrowingValueTest, NonThrowingMoveAssign) {
UnsetCountdown(); UnsetCountdown();
} }
TEST(ThrowingValueTest, ThrowingCopyCtor) {
ThrowingValue<> tv;
TestOp([&]() { ThrowingValue<> tv_copy(tv); });
}
TEST(ThrowingValueTest, ThrowingCopyAssign) {
ThrowingValue<> tv1, tv2;
TestOp([&]() { tv1 = tv2; });
}
TEST(ThrowingValueTest, NonThrowingCopyCtor) {
ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_ctor;
SetCountdown();
ExpectNoThrow([&nothrow_ctor]() {
ThrowingValue<TypeSpec::kNoThrowCopy> nothrow1(nothrow_ctor);
});
UnsetCountdown();
}
TEST(ThrowingValueTest, NonThrowingCopyAssign) {
ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_assign1, nothrow_assign2;
SetCountdown();
ExpectNoThrow([&nothrow_assign1, &nothrow_assign2]() {
nothrow_assign1 = nothrow_assign2;
});
UnsetCountdown();
}
TEST(ThrowingValueTest, ThrowingSwap) { TEST(ThrowingValueTest, ThrowingSwap) {
ThrowingValue<> bomb1, bomb2; ThrowingValue<> bomb1, bomb2;
TestOp([&]() { std::swap(bomb1, bomb2); }); TestOp([&]() { std::swap(bomb1, bomb2); });
ThrowingValue<NoThrow::kMoveCtor> bomb3, bomb4;
TestOp([&]() { std::swap(bomb3, bomb4); });
ThrowingValue<NoThrow::kMoveAssign> bomb5, bomb6;
TestOp([&]() { std::swap(bomb5, bomb6); });
} }
TEST(ThrowingValueTest, NonThrowingSwap) { TEST(ThrowingValueTest, NonThrowingSwap) {
ThrowingValue<NoThrow::kMoveAssign | NoThrow::kMoveCtor> bomb1, bomb2; ThrowingValue<TypeSpec::kNoThrowMove> bomb1, bomb2;
ExpectNoThrow([&]() { std::swap(bomb1, bomb2); }); ExpectNoThrow([&]() { std::swap(bomb1, bomb2); });
} }
TEST(ThrowingValueTest, NonThrowingAllocation) { TEST(ThrowingValueTest, NonThrowingAllocation) {
ThrowingValue<NoThrow::kAllocation>* allocated; ThrowingValue<TypeSpec::kNoThrowNew>* allocated;
ThrowingValue<NoThrow::kAllocation>* array; ThrowingValue<TypeSpec::kNoThrowNew>* array;
ExpectNoThrow([&allocated]() { ExpectNoThrow([&allocated]() {
allocated = new ThrowingValue<NoThrow::kAllocation>(1); allocated = new ThrowingValue<TypeSpec::kNoThrowNew>(1);
delete allocated; delete allocated;
}); });
ExpectNoThrow([&array]() { ExpectNoThrow([&array]() {
array = new ThrowingValue<NoThrow::kAllocation>[2]; array = new ThrowingValue<TypeSpec::kNoThrowNew>[2];
delete[] array; delete[] array;
}); });
} }
@ -284,15 +312,15 @@ TEST(ThrowingAllocatorTest, MemoryManagement) {
int* i_array = int_alloc.allocate(2); int* i_array = int_alloc.allocate(2);
int_alloc.deallocate(i_array, 2); int_alloc.deallocate(i_array, 2);
ThrowingAllocator<ThrowingValue<>> ef_alloc; ThrowingAllocator<ThrowingValue<>> tv_alloc;
ThrowingValue<>* efp = ef_alloc.allocate(1); ThrowingValue<>* ptr = tv_alloc.allocate(1);
ef_alloc.deallocate(efp, 1); tv_alloc.deallocate(ptr, 1);
ThrowingValue<>* ef_array = ef_alloc.allocate(2); ThrowingValue<>* tv_array = tv_alloc.allocate(2);
ef_alloc.deallocate(ef_array, 2); tv_alloc.deallocate(tv_array, 2);
} }
TEST(ThrowingAllocatorTest, CallsGlobalNew) { TEST(ThrowingAllocatorTest, CallsGlobalNew) {
ThrowingAllocator<ThrowingValue<>, NoThrow::kNoThrow> nothrow_alloc; ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate> nothrow_alloc;
ThrowingValue<>* ptr; ThrowingValue<>* ptr;
SetCountdown(); SetCountdown();
@ -322,7 +350,7 @@ TEST(ThrowingAllocatorTest, ThrowingConstructors) {
TEST(ThrowingAllocatorTest, NonThrowingConstruction) { TEST(ThrowingAllocatorTest, NonThrowingConstruction) {
{ {
ThrowingAllocator<int, NoThrow::kNoThrow> int_alloc; ThrowingAllocator<int, AllocSpec::kNoThrowAllocate> int_alloc;
int* ip = nullptr; int* ip = nullptr;
SetCountdown(); SetCountdown();
@ -347,19 +375,20 @@ TEST(ThrowingAllocatorTest, NonThrowingConstruction) {
} }
{ {
ThrowingAllocator<ThrowingValue<NoThrow::kIntCtor>, NoThrow::kNoThrow> ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate>
ef_alloc; nothrow_alloc;
ThrowingValue<NoThrow::kIntCtor>* efp; ThrowingValue<>* ptr;
SetCountdown(); SetCountdown();
ExpectNoThrow([&]() { efp = ef_alloc.allocate(1); }); ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); });
SetCountdown(); SetCountdown();
ExpectNoThrow([&]() { ef_alloc.construct(efp, 2); }); ExpectNoThrow(
[&]() { nothrow_alloc.construct(ptr, 2, testing::no_throw_ctor); });
EXPECT_EQ(efp->Get(), 2); EXPECT_EQ(ptr->Get(), 2);
ef_alloc.destroy(efp); nothrow_alloc.destroy(ptr);
ef_alloc.deallocate(efp, 1); nothrow_alloc.deallocate(ptr, 1);
UnsetCountdown(); UnsetCountdown();
} }
@ -448,15 +477,15 @@ TEST(ExceptionSafetyTesterTest, IncompleteTypesAreNotTestable) {
// Test that providing operation and inveriants still does not allow for the // Test that providing operation and inveriants still does not allow for the
// the invocation of .Test() and .Test(op) because it lacks a factory // the invocation of .Test() and .Test(op) because it lacks a factory
auto without_fac = auto without_fac =
absl::MakeExceptionSafetyTester().WithOperation(op).WithInvariants( testing::MakeExceptionSafetyTester().WithOperation(op).WithInvariants(
inv, absl::strong_guarantee); inv, testing::strong_guarantee);
EXPECT_FALSE(HasNullaryTest(without_fac)); EXPECT_FALSE(HasNullaryTest(without_fac));
EXPECT_FALSE(HasUnaryTest(without_fac)); EXPECT_FALSE(HasUnaryTest(without_fac));
// Test that providing invariants and factory allows the invocation of // Test that providing invariants and factory allows the invocation of
// .Test(op) but does not allow for .Test() because it lacks an operation // .Test(op) but does not allow for .Test() because it lacks an operation
auto without_op = absl::MakeExceptionSafetyTester() auto without_op = testing::MakeExceptionSafetyTester()
.WithInvariants(inv, absl::strong_guarantee) .WithInvariants(inv, testing::strong_guarantee)
.WithFactory(fac); .WithFactory(fac);
EXPECT_FALSE(HasNullaryTest(without_op)); EXPECT_FALSE(HasNullaryTest(without_op));
EXPECT_TRUE(HasUnaryTest(without_op)); EXPECT_TRUE(HasUnaryTest(without_op));
@ -464,7 +493,7 @@ TEST(ExceptionSafetyTesterTest, IncompleteTypesAreNotTestable) {
// Test that providing operation and factory still does not allow for the // Test that providing operation and factory still does not allow for the
// the invocation of .Test() and .Test(op) because it lacks invariants // the invocation of .Test() and .Test(op) because it lacks invariants
auto without_inv = auto without_inv =
absl::MakeExceptionSafetyTester().WithOperation(op).WithFactory(fac); testing::MakeExceptionSafetyTester().WithOperation(op).WithFactory(fac);
EXPECT_FALSE(HasNullaryTest(without_inv)); EXPECT_FALSE(HasNullaryTest(without_inv));
EXPECT_FALSE(HasUnaryTest(without_inv)); EXPECT_FALSE(HasUnaryTest(without_inv));
} }
@ -509,28 +538,28 @@ auto example_lambda_invariant = [](ExampleStruct* example_struct) {
// lambdas can all be used with ExceptionSafetyTester // lambdas can all be used with ExceptionSafetyTester
TEST(ExceptionSafetyTesterTest, MixedFunctionTypes) { TEST(ExceptionSafetyTesterTest, MixedFunctionTypes) {
// function reference // function reference
EXPECT_TRUE(absl::MakeExceptionSafetyTester() EXPECT_TRUE(testing::MakeExceptionSafetyTester()
.WithFactory(ExampleFunctionFactory) .WithFactory(ExampleFunctionFactory)
.WithOperation(ExampleFunctionOperation) .WithOperation(ExampleFunctionOperation)
.WithInvariants(ExampleFunctionInvariant) .WithInvariants(ExampleFunctionInvariant)
.Test()); .Test());
// function pointer // function pointer
EXPECT_TRUE(absl::MakeExceptionSafetyTester() EXPECT_TRUE(testing::MakeExceptionSafetyTester()
.WithFactory(&ExampleFunctionFactory) .WithFactory(&ExampleFunctionFactory)
.WithOperation(&ExampleFunctionOperation) .WithOperation(&ExampleFunctionOperation)
.WithInvariants(&ExampleFunctionInvariant) .WithInvariants(&ExampleFunctionInvariant)
.Test()); .Test());
// struct // struct
EXPECT_TRUE(absl::MakeExceptionSafetyTester() EXPECT_TRUE(testing::MakeExceptionSafetyTester()
.WithFactory(example_struct_factory) .WithFactory(example_struct_factory)
.WithOperation(example_struct_operation) .WithOperation(example_struct_operation)
.WithInvariants(example_struct_invariant) .WithInvariants(example_struct_invariant)
.Test()); .Test());
// lambda // lambda
EXPECT_TRUE(absl::MakeExceptionSafetyTester() EXPECT_TRUE(testing::MakeExceptionSafetyTester()
.WithFactory(example_lambda_factory) .WithFactory(example_lambda_factory)
.WithOperation(example_lambda_operation) .WithOperation(example_lambda_operation)
.WithInvariants(example_lambda_invariant) .WithInvariants(example_lambda_invariant)
@ -558,9 +587,9 @@ struct {
} invoker; } invoker;
auto tester = auto tester =
absl::MakeExceptionSafetyTester().WithOperation(invoker).WithInvariants( testing::MakeExceptionSafetyTester().WithOperation(invoker).WithInvariants(
CheckNonNegativeInvariants); CheckNonNegativeInvariants);
auto strong_tester = tester.WithInvariants(absl::strong_guarantee); auto strong_tester = tester.WithInvariants(testing::strong_guarantee);
struct FailsBasicGuarantee : public NonNegative { struct FailsBasicGuarantee : public NonNegative {
void operator()() { void operator()() {
@ -664,7 +693,7 @@ TEST(ExceptionCheckTest, ModifyingChecker) {
EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{}) EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{})
.WithInvariants(increment) .WithInvariants(increment)
.Test()); .Test());
EXPECT_TRUE(absl::MakeExceptionSafetyTester() EXPECT_TRUE(testing::MakeExceptionSafetyTester()
.WithInitialValue(HasReset{}) .WithInitialValue(HasReset{})
.WithInvariants(CheckHasResetInvariants) .WithInvariants(CheckHasResetInvariants)
.Test(invoker)); .Test(invoker));
@ -739,7 +768,7 @@ template <typename T>
unsigned char ExhaustivenessTester<T>::successes = 0; unsigned char ExhaustivenessTester<T>::successes = 0;
TEST(ExceptionCheckTest, Exhaustiveness) { TEST(ExceptionCheckTest, Exhaustiveness) {
auto exhaust_tester = absl::MakeExceptionSafetyTester() auto exhaust_tester = testing::MakeExceptionSafetyTester()
.WithInvariants(CheckExhaustivenessTesterInvariants) .WithInvariants(CheckExhaustivenessTesterInvariants)
.WithOperation(invoker); .WithOperation(invoker);
@ -749,7 +778,7 @@ TEST(ExceptionCheckTest, Exhaustiveness) {
EXPECT_TRUE( EXPECT_TRUE(
exhaust_tester.WithInitialValue(ExhaustivenessTester<ThrowingValue<>>{}) exhaust_tester.WithInitialValue(ExhaustivenessTester<ThrowingValue<>>{})
.WithInvariants(absl::strong_guarantee) .WithInvariants(testing::strong_guarantee)
.Test()); .Test());
EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::successes, 0xF); EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::successes, 0xF);
} }
@ -768,7 +797,7 @@ struct LeaksIfCtorThrows : private exceptions_internal::TrackedObject {
int LeaksIfCtorThrows::counter = 0; int LeaksIfCtorThrows::counter = 0;
TEST(ExceptionCheckTest, TestLeakyCtor) { TEST(ExceptionCheckTest, TestLeakyCtor) {
absl::TestThrowingCtor<LeaksIfCtorThrows>(); testing::TestThrowingCtor<LeaksIfCtorThrows>();
EXPECT_EQ(LeaksIfCtorThrows::counter, 1); EXPECT_EQ(LeaksIfCtorThrows::counter, 1);
LeaksIfCtorThrows::counter = 0; LeaksIfCtorThrows::counter = 0;
} }
@ -839,4 +868,5 @@ TEST(ThrowingAllocatorTraitsTest, Assignablility) {
} }
} // namespace } // namespace
} // namespace absl
} // namespace testing

View file

@ -17,7 +17,7 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
namespace absl { namespace testing {
exceptions_internal::NoThrowTag no_throw_ctor; exceptions_internal::NoThrowTag no_throw_ctor;
exceptions_internal::StrongGuaranteeTagType strong_guarantee; exceptions_internal::StrongGuaranteeTagType strong_guarantee;
@ -37,5 +37,7 @@ testing::AssertionResult FailureMessage(const TestException& e,
int countdown) noexcept { int countdown) noexcept {
return testing::AssertionFailure() << "Exception thrown from " << e.what(); return testing::AssertionFailure() << "Exception thrown from " << e.what();
} }
} // namespace exceptions_internal } // namespace exceptions_internal
} // namespace absl
} // namespace testing

View file

@ -35,38 +35,36 @@
#include "absl/strings/substitute.h" #include "absl/strings/substitute.h"
#include "absl/types/optional.h" #include "absl/types/optional.h"
namespace absl { namespace testing {
// A configuration enum for Throwing*. Operations whose flags are set will enum class TypeSpec;
// throw, everything else won't. This isn't meant to be exhaustive, more flags enum class AllocSpec;
// can always be made in the future.
enum class NoThrow : uint8_t {
kNone = 0,
kMoveCtor = 1,
kMoveAssign = 1 << 1,
kAllocation = 1 << 2,
kIntCtor = 1 << 3,
kNoThrow = static_cast<uint8_t>(-1)
};
constexpr NoThrow operator|(NoThrow a, NoThrow b) { constexpr TypeSpec operator|(TypeSpec a, TypeSpec b) {
using T = absl::underlying_type_t<NoThrow>; using T = absl::underlying_type_t<TypeSpec>;
return static_cast<NoThrow>(static_cast<T>(a) | static_cast<T>(b)); return static_cast<TypeSpec>(static_cast<T>(a) | static_cast<T>(b));
} }
constexpr NoThrow operator&(NoThrow a, NoThrow b) { constexpr TypeSpec operator&(TypeSpec a, TypeSpec b) {
using T = absl::underlying_type_t<NoThrow>; using T = absl::underlying_type_t<TypeSpec>;
return static_cast<NoThrow>(static_cast<T>(a) & static_cast<T>(b)); return static_cast<TypeSpec>(static_cast<T>(a) & static_cast<T>(b));
}
constexpr AllocSpec operator|(AllocSpec a, AllocSpec b) {
using T = absl::underlying_type_t<AllocSpec>;
return static_cast<AllocSpec>(static_cast<T>(a) | static_cast<T>(b));
}
constexpr AllocSpec operator&(AllocSpec a, AllocSpec b) {
using T = absl::underlying_type_t<AllocSpec>;
return static_cast<AllocSpec>(static_cast<T>(a) & static_cast<T>(b));
} }
namespace exceptions_internal { namespace exceptions_internal {
struct NoThrowTag {}; struct NoThrowTag {};
struct StrongGuaranteeTagType {}; struct StrongGuaranteeTagType {};
constexpr bool ThrowingAllowed(NoThrow flags, NoThrow flag) {
return !static_cast<bool>(flags & flag);
}
// A simple exception class. We throw this so that test code can catch // A simple exception class. We throw this so that test code can catch
// exceptions specifically thrown by ThrowingValue. // exceptions specifically thrown by ThrowingValue.
class TestException { class TestException {
@ -246,47 +244,69 @@ class ThrowingBool {
bool b_; bool b_;
}; };
// A testing class instrumented to throw an exception at a controlled time. /*
// * Configuration enum for the ThrowingValue type that defines behavior for the
// ThrowingValue implements a slightly relaxed version of the Regular concept -- * lifetime of the instance. Use testing::no_throw_ctor to prevent the integer
// that is it's a value type with the expected semantics. It also implements * constructor from throwing.
// arithmetic operations. It doesn't implement member and pointer operators *
// like operator-> or operator[]. * kEverythingThrows: Every operation can throw an exception
// * kNoThrowCopy: Copy construction and copy assignment will not throw
// ThrowingValue can be instrumented to have certain operations be noexcept by * kNoThrowMove: Move construction and move assignment will not throw
// using compile-time bitfield flag template arguments. That is, to make an * kNoThrowNew: Overloaded operators new and new[] will not throw
// ThrowingValue which has a noexcept move constructor and noexcept move */
// assignment, use enum class TypeSpec {
// ThrowingValue<absl::NoThrow::kMoveCtor | absl::NoThrow::kMoveAssign>. kEverythingThrows = 0,
template <NoThrow Flags = NoThrow::kNone> kNoThrowCopy = 1,
kNoThrowMove = 1 << 1,
kNoThrowNew = 1 << 2,
};
/*
* A testing class instrumented to throw an exception at a controlled time.
*
* ThrowingValue implements a slightly relaxed version of the Regular concept --
* that is it's a value type with the expected semantics. It also implements
* arithmetic operations. It doesn't implement member and pointer operators
* like operator-> or operator[].
*
* ThrowingValue can be instrumented to have certain operations be noexcept by
* using compile-time bitfield template arguments. That is, to make an
* ThrowingValue which has noexcept move construction/assignment and noexcept
* copy construction/assignment, use the following:
* ThrowingValue<testing::kNoThrowMove | testing::kNoThrowCopy> my_thrwr{val};
*/
template <TypeSpec Spec = TypeSpec::kEverythingThrows>
class ThrowingValue : private exceptions_internal::TrackedObject { class ThrowingValue : private exceptions_internal::TrackedObject {
constexpr static bool IsSpecified(TypeSpec spec) {
return static_cast<bool>(Spec & spec);
}
public: public:
ThrowingValue() : TrackedObject(ABSL_PRETTY_FUNCTION) { ThrowingValue() : TrackedObject(ABSL_PRETTY_FUNCTION) {
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
dummy_ = 0; dummy_ = 0;
} }
ThrowingValue(const ThrowingValue& other) ThrowingValue(const ThrowingValue& other) noexcept(
IsSpecified(TypeSpec::kNoThrowCopy))
: TrackedObject(ABSL_PRETTY_FUNCTION) { : TrackedObject(ABSL_PRETTY_FUNCTION) {
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); if (!IsSpecified(TypeSpec::kNoThrowCopy)) {
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
}
dummy_ = other.dummy_; dummy_ = other.dummy_;
} }
ThrowingValue(ThrowingValue&& other) noexcept( ThrowingValue(ThrowingValue&& other) noexcept(
!exceptions_internal::ThrowingAllowed(Flags, NoThrow::kMoveCtor)) IsSpecified(TypeSpec::kNoThrowMove))
: TrackedObject(ABSL_PRETTY_FUNCTION) { : TrackedObject(ABSL_PRETTY_FUNCTION) {
if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kMoveCtor)) { if (!IsSpecified(TypeSpec::kNoThrowMove)) {
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
} }
dummy_ = other.dummy_; dummy_ = other.dummy_;
} }
explicit ThrowingValue(int i) noexcept( explicit ThrowingValue(int i) : TrackedObject(ABSL_PRETTY_FUNCTION) {
!exceptions_internal::ThrowingAllowed(Flags, NoThrow::kIntCtor)) exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
: TrackedObject(ABSL_PRETTY_FUNCTION) {
if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kIntCtor)) {
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
}
dummy_ = i; dummy_ = i;
} }
@ -296,15 +316,18 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
// absl expects nothrow destructors // absl expects nothrow destructors
~ThrowingValue() noexcept = default; ~ThrowingValue() noexcept = default;
ThrowingValue& operator=(const ThrowingValue& other) { ThrowingValue& operator=(const ThrowingValue& other) noexcept(
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); IsSpecified(TypeSpec::kNoThrowCopy)) {
if (!IsSpecified(TypeSpec::kNoThrowCopy)) {
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
}
dummy_ = other.dummy_; dummy_ = other.dummy_;
return *this; return *this;
} }
ThrowingValue& operator=(ThrowingValue&& other) noexcept( ThrowingValue& operator=(ThrowingValue&& other) noexcept(
!exceptions_internal::ThrowingAllowed(Flags, NoThrow::kMoveAssign)) { IsSpecified(TypeSpec::kNoThrowMove)) {
if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kMoveAssign)) { if (!IsSpecified(TypeSpec::kNoThrowMove)) {
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
} }
dummy_ = other.dummy_; dummy_ = other.dummy_;
@ -533,8 +556,8 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
// Args.. allows us to overload regular and placement new in one shot // Args.. allows us to overload regular and placement new in one shot
template <typename... Args> template <typename... Args>
static void* operator new(size_t s, Args&&... args) noexcept( static void* operator new(size_t s, Args&&... args) noexcept(
!exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) { IsSpecified(TypeSpec::kNoThrowNew)) {
if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) { if (!IsSpecified(TypeSpec::kNoThrowNew)) {
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true); exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
} }
return ::operator new(s, std::forward<Args>(args)...); return ::operator new(s, std::forward<Args>(args)...);
@ -542,8 +565,8 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
template <typename... Args> template <typename... Args>
static void* operator new[](size_t s, Args&&... args) noexcept( static void* operator new[](size_t s, Args&&... args) noexcept(
!exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) { IsSpecified(TypeSpec::kNoThrowNew)) {
if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) { if (!IsSpecified(TypeSpec::kNoThrowNew)) {
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true); exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
} }
return ::operator new[](s, std::forward<Args>(args)...); return ::operator new[](s, std::forward<Args>(args)...);
@ -581,20 +604,35 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
}; };
// While not having to do with exceptions, explicitly delete comma operator, to // While not having to do with exceptions, explicitly delete comma operator, to
// make sure we don't use it on user-supplied types. // make sure we don't use it on user-supplied types.
template <NoThrow N, typename T> template <TypeSpec Spec, typename T>
void operator,(const ThrowingValue<N>& ef, T&& t) = delete; void operator,(const ThrowingValue<Spec>&, T&&) = delete;
template <NoThrow N, typename T> template <TypeSpec Spec, typename T>
void operator,(T&& t, const ThrowingValue<N>& ef) = delete; void operator,(T&&, const ThrowingValue<Spec>&) = delete;
// An allocator type which is instrumented to throw at a controlled time, or not /*
// to throw, using NoThrow. The supported settings are the default of every * Configuration enum for the ThrowingAllocator type that defines behavior for
// function which is allowed to throw in a conforming allocator possibly * the lifetime of the instance.
// throwing, or nothing throws, in line with the ABSL_ALLOCATOR_THROWS *
// configuration macro. * kEverythingThrows: Calls to the member functions may throw
template <typename T, NoThrow Flags = NoThrow::kNone> * kNoThrowAllocate: Calls to the member functions will not throw
*/
enum class AllocSpec {
kEverythingThrows = 0,
kNoThrowAllocate = 1,
};
/*
* An allocator type which is instrumented to throw at a controlled time, or not
* to throw, using AllocSpec. The supported settings are the default of every
* function which is allowed to throw in a conforming allocator possibly
* throwing, or nothing throws, in line with the ABSL_ALLOCATOR_THROWS
* configuration macro.
*/
template <typename T, AllocSpec Spec = AllocSpec::kEverythingThrows>
class ThrowingAllocator : private exceptions_internal::TrackedObject { class ThrowingAllocator : private exceptions_internal::TrackedObject {
static_assert(Flags == NoThrow::kNone || Flags == NoThrow::kNoThrow, constexpr static bool IsSpecified(AllocSpec spec) {
"Invalid flag"); return static_cast<bool>(Spec & spec);
}
public: public:
using pointer = T*; using pointer = T*;
@ -607,7 +645,8 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
using size_type = size_t; using size_type = size_t;
using difference_type = ptrdiff_t; using difference_type = ptrdiff_t;
using is_nothrow = std::integral_constant<bool, Flags == NoThrow::kNoThrow>; using is_nothrow =
std::integral_constant<bool, Spec == AllocSpec::kNoThrowAllocate>;
using propagate_on_container_copy_assignment = std::true_type; using propagate_on_container_copy_assignment = std::true_type;
using propagate_on_container_move_assignment = std::true_type; using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type; using propagate_on_container_swap = std::true_type;
@ -619,8 +658,7 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
} }
template <typename U> template <typename U>
ThrowingAllocator( // NOLINT ThrowingAllocator(const ThrowingAllocator<U, Spec>& other) noexcept // NOLINT
const ThrowingAllocator<U, Flags>& other) noexcept
: TrackedObject(ABSL_PRETTY_FUNCTION), dummy_(other.State()) {} : TrackedObject(ABSL_PRETTY_FUNCTION), dummy_(other.State()) {}
// According to C++11 standard [17.6.3.5], Table 28, the move/copy ctors of // According to C++11 standard [17.6.3.5], Table 28, the move/copy ctors of
@ -629,8 +667,7 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
: TrackedObject(ABSL_PRETTY_FUNCTION), dummy_(other.State()) {} : TrackedObject(ABSL_PRETTY_FUNCTION), dummy_(other.State()) {}
template <typename U> template <typename U>
ThrowingAllocator( // NOLINT ThrowingAllocator(ThrowingAllocator<U, Spec>&& other) noexcept // NOLINT
ThrowingAllocator<U, Flags>&& other) noexcept
: TrackedObject(ABSL_PRETTY_FUNCTION), dummy_(std::move(other.State())) {} : TrackedObject(ABSL_PRETTY_FUNCTION), dummy_(std::move(other.State())) {}
ThrowingAllocator(ThrowingAllocator&& other) noexcept ThrowingAllocator(ThrowingAllocator&& other) noexcept
@ -645,29 +682,30 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
template <typename U> template <typename U>
ThrowingAllocator& operator=( ThrowingAllocator& operator=(
const ThrowingAllocator<U, Flags>& other) noexcept { const ThrowingAllocator<U, Spec>& other) noexcept {
dummy_ = other.State(); dummy_ = other.State();
return *this; return *this;
} }
template <typename U> template <typename U>
ThrowingAllocator& operator=(ThrowingAllocator<U, Flags>&& other) noexcept { ThrowingAllocator& operator=(ThrowingAllocator<U, Spec>&& other) noexcept {
dummy_ = std::move(other.State()); dummy_ = std::move(other.State());
return *this; return *this;
} }
template <typename U> template <typename U>
struct rebind { struct rebind {
using other = ThrowingAllocator<U, Flags>; using other = ThrowingAllocator<U, Spec>;
}; };
pointer allocate(size_type n) noexcept( pointer allocate(size_type n) noexcept(
!exceptions_internal::ThrowingAllowed(Flags, NoThrow::kNoThrow)) { IsSpecified(AllocSpec::kNoThrowAllocate)) {
ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION); ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
return static_cast<pointer>(::operator new(n * sizeof(T))); return static_cast<pointer>(::operator new(n * sizeof(T)));
} }
pointer allocate(size_type n, const_void_pointer) noexcept( pointer allocate(size_type n, const_void_pointer) noexcept(
!exceptions_internal::ThrowingAllowed(Flags, NoThrow::kNoThrow)) { IsSpecified(AllocSpec::kNoThrowAllocate)) {
return allocate(n); return allocate(n);
} }
@ -678,7 +716,7 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
template <typename U, typename... Args> template <typename U, typename... Args>
void construct(U* ptr, Args&&... args) noexcept( void construct(U* ptr, Args&&... args) noexcept(
!exceptions_internal::ThrowingAllowed(Flags, NoThrow::kNoThrow)) { IsSpecified(AllocSpec::kNoThrowAllocate)) {
ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION); ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
::new (static_cast<void*>(ptr)) U(std::forward<Args>(args)...); ::new (static_cast<void*>(ptr)) U(std::forward<Args>(args)...);
} }
@ -694,23 +732,23 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
} }
ThrowingAllocator select_on_container_copy_construction() noexcept( ThrowingAllocator select_on_container_copy_construction() noexcept(
!exceptions_internal::ThrowingAllowed(Flags, NoThrow::kNoThrow)) { IsSpecified(AllocSpec::kNoThrowAllocate)) {
auto& out = *this; auto& out = *this;
ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION); ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
return out; return out;
} }
template <typename U> template <typename U>
bool operator==(const ThrowingAllocator<U, Flags>& other) const noexcept { bool operator==(const ThrowingAllocator<U, Spec>& other) const noexcept {
return dummy_ == other.dummy_; return dummy_ == other.dummy_;
} }
template <typename U> template <typename U>
bool operator!=(const ThrowingAllocator<U, Flags>& other) const noexcept { bool operator!=(const ThrowingAllocator<U, Spec>& other) const noexcept {
return dummy_ != other.dummy_; return dummy_ != other.dummy_;
} }
template <typename U, NoThrow B> template <typename, AllocSpec>
friend class ThrowingAllocator; friend class ThrowingAllocator;
private: private:
@ -724,7 +762,7 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
} }
void ReadStateAndMaybeThrow(absl::string_view msg) const { void ReadStateAndMaybeThrow(absl::string_view msg) const {
if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kNoThrow)) { if (!IsSpecified(AllocSpec::kNoThrowAllocate)) {
exceptions_internal::MaybeThrow( exceptions_internal::MaybeThrow(
absl::Substitute("Allocator id $0 threw from $1", *dummy_, msg)); absl::Substitute("Allocator id $0 threw from $1", *dummy_, msg));
} }
@ -734,8 +772,8 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
std::shared_ptr<const int> dummy_; std::shared_ptr<const int> dummy_;
}; };
template <typename T, NoThrow Throws> template <typename T, AllocSpec Spec>
int ThrowingAllocator<T, Throws>::next_id_ = 0; int ThrowingAllocator<T, Spec>::next_id_ = 0;
// Tests for resource leaks by attempting to construct a T using args repeatedly // Tests for resource leaks by attempting to construct a T using args repeatedly
// until successful, using the countdown method. Side effects can then be // until successful, using the countdown method. Side effects can then be
@ -873,7 +911,7 @@ class ExceptionSafetyTester {
* created in order to get an empty Invariants... list. * created in order to get an empty Invariants... list.
* *
* In addition to passing in custom invariant assertion callbacks, this method * In addition to passing in custom invariant assertion callbacks, this method
* accepts `absl::strong_guarantee` as an argument which checks T instances * accepts `testing::strong_guarantee` as an argument which checks T instances
* post-throw against freshly created T instances via operator== to verify * post-throw against freshly created T instances via operator== to verify
* that any state changes made during the execution of the operation were * that any state changes made during the execution of the operation were
* properly rolled back. * properly rolled back.
@ -934,7 +972,7 @@ class ExceptionSafetyTester {
template <typename, typename, typename...> template <typename, typename, typename...>
friend class ExceptionSafetyTester; friend class ExceptionSafetyTester;
friend ExceptionSafetyTester<> absl::MakeExceptionSafetyTester(); friend ExceptionSafetyTester<> testing::MakeExceptionSafetyTester();
ExceptionSafetyTester() {} ExceptionSafetyTester() {}
@ -992,6 +1030,6 @@ MakeExceptionSafetyTester() {
return {}; return {};
} }
} // namespace absl } // namespace testing
#endif // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_ #endif // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_

View file

@ -14,6 +14,7 @@
#include <cstdint> #include <cstdint>
#include <iostream> #include <iostream>
#include "absl/base/attributes.h"
#include "absl/debugging/internal/address_is_readable.h" #include "absl/debugging/internal/address_is_readable.h"
#include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems #include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems
#include "absl/debugging/stacktrace.h" #include "absl/debugging/stacktrace.h"
@ -24,7 +25,7 @@ static const uintptr_t kUnknownFrameSize = 0;
// Returns the address of the VDSO __kernel_rt_sigreturn function, if present. // Returns the address of the VDSO __kernel_rt_sigreturn function, if present.
static const unsigned char* GetKernelRtSigreturnAddress() { static const unsigned char* GetKernelRtSigreturnAddress() {
constexpr uintptr_t kImpossibleAddress = 1; constexpr uintptr_t kImpossibleAddress = 1;
static std::atomic<uintptr_t> memoized{kImpossibleAddress}; ABSL_CONST_INIT static std::atomic<uintptr_t> memoized{kImpossibleAddress};
uintptr_t address = memoized.load(std::memory_order_relaxed); uintptr_t address = memoized.load(std::memory_order_relaxed);
if (address != kImpossibleAddress) { if (address != kImpossibleAddress) {
return reinterpret_cast<const unsigned char*>(address); return reinterpret_cast<const unsigned char*>(address);

View file

@ -41,6 +41,7 @@
#include <atomic> #include <atomic>
#include "absl/base/attributes.h"
#include "absl/debugging/internal/elf_mem_image.h" #include "absl/debugging/internal/elf_mem_image.h"
#ifdef ABSL_HAVE_ELF_MEM_IMAGE #ifdef ABSL_HAVE_ELF_MEM_IMAGE
@ -132,7 +133,7 @@ class VDSOSupport {
// This function pointer may point to InitAndGetCPU, // This function pointer may point to InitAndGetCPU,
// GetCPUViaSyscall, or __vdso_getcpu at different stages of initialization. // GetCPUViaSyscall, or __vdso_getcpu at different stages of initialization.
static std::atomic<GetCpuFn> getcpu_fn_; ABSL_CONST_INIT static std::atomic<GetCpuFn> getcpu_fn_;
friend int GetCPU(void); // Needs access to getcpu_fn_. friend int GetCPU(void); // Needs access to getcpu_fn_.

View file

@ -51,6 +51,7 @@ cc_library(
cc_library( cc_library(
name = "test_util", name = "test_util",
testonly = 1,
srcs = [ srcs = [
"internal/test_util.cc", "internal/test_util.cc",
"internal/zoneinfo.inc", "internal/zoneinfo.inc",
@ -64,6 +65,7 @@ cc_library(
":time", ":time",
"//absl/base", "//absl/base",
"//absl/time/internal/cctz:time_zone", "//absl/time/internal/cctz:time_zone",
"@com_google_googletest//:gtest",
], ],
) )

View file

@ -155,8 +155,7 @@ TEST(ParseTime, Basics) {
"2013-06-28 19:08:09 -0800", &t, &err)) "2013-06-28 19:08:09 -0800", &t, &err))
<< err; << err;
absl::Time::Breakdown bd = t.In(absl::FixedTimeZone(-8 * 60 * 60)); absl::Time::Breakdown bd = t.In(absl::FixedTimeZone(-8 * 60 * 60));
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, -8 * 60 * 60, false, ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, -8 * 60 * 60, false);
"UTC-8");
EXPECT_EQ(absl::ZeroDuration(), bd.subsecond); EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
} }
@ -179,8 +178,7 @@ TEST(ParseTime, WithTimeZone) {
absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e)) absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e))
<< e; << e;
absl::Time::Breakdown bd = t.In(tz); absl::Time::Breakdown bd = t.In(tz);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true, ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true);
"PDT");
EXPECT_EQ(absl::ZeroDuration(), bd.subsecond); EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
// But the timezone is ignored when a UTC offset is present. // But the timezone is ignored when a UTC offset is present.
@ -188,8 +186,7 @@ TEST(ParseTime, WithTimeZone) {
"2013-06-28 19:08:09 +0800", tz, &t, &e)) "2013-06-28 19:08:09 +0800", tz, &t, &e))
<< e; << e;
bd = t.In(absl::FixedTimeZone(8 * 60 * 60)); bd = t.In(absl::FixedTimeZone(8 * 60 * 60));
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, 8 * 60 * 60, false, ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, 8 * 60 * 60, false);
"UTC+8");
EXPECT_EQ(absl::ZeroDuration(), bd.subsecond); EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
} }

View file

@ -26,6 +26,13 @@ namespace cctz = absl::time_internal::cctz;
namespace absl { namespace absl {
namespace time_internal { namespace time_internal {
// TODO(bww): Reinstate when the FixedTimeZone() abbreviations are updated.
#if 1 || GTEST_USES_SIMPLE_RE
extern const char kZoneAbbrRE[] = ".*"; // just punt
#else
extern const char kZoneAbbrRE[] = "[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?";
#endif
TimeZone LoadTimeZone(const std::string& name) { TimeZone LoadTimeZone(const std::string& name) {
TimeZone tz; TimeZone tz;
ABSL_RAW_CHECK(LoadTimeZone(name, &tz), name.c_str()); ABSL_RAW_CHECK(LoadTimeZone(name, &tz), name.c_str());

View file

@ -17,6 +17,8 @@
#include <string> #include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/time/time.h" #include "absl/time/time.h"
// This helper is a macro so that failed expectations show up with the // This helper is a macro so that failed expectations show up with the
@ -24,22 +26,26 @@
// //
// This is for internal testing of the Base Time library itself. This is not // This is for internal testing of the Base Time library itself. This is not
// part of a public API. // part of a public API.
#define ABSL_INTERNAL_EXPECT_TIME(bd, y, m, d, h, min, s, off, isdst, zone) \ #define ABSL_INTERNAL_EXPECT_TIME(bd, y, m, d, h, min, s, off, isdst) \
do { \ do { \
EXPECT_EQ(y, bd.year); \ EXPECT_EQ(y, bd.year); \
EXPECT_EQ(m, bd.month); \ EXPECT_EQ(m, bd.month); \
EXPECT_EQ(d, bd.day); \ EXPECT_EQ(d, bd.day); \
EXPECT_EQ(h, bd.hour); \ EXPECT_EQ(h, bd.hour); \
EXPECT_EQ(min, bd.minute); \ EXPECT_EQ(min, bd.minute); \
EXPECT_EQ(s, bd.second); \ EXPECT_EQ(s, bd.second); \
EXPECT_EQ(off, bd.offset); \ EXPECT_EQ(off, bd.offset); \
EXPECT_EQ(isdst, bd.is_dst); \ EXPECT_EQ(isdst, bd.is_dst); \
EXPECT_STREQ(zone, bd.zone_abbr); \ EXPECT_THAT(bd.zone_abbr, \
testing::MatchesRegex(absl::time_internal::kZoneAbbrRE)); \
} while (0) } while (0)
namespace absl { namespace absl {
namespace time_internal { namespace time_internal {
// A regular expression that matches all zone abbreviations (%Z).
extern const char kZoneAbbrRE[];
// Loads the named timezone, but dies on any failure. // Loads the named timezone, but dies on any failure.
absl::TimeZone LoadTimeZone(const std::string& name); absl::TimeZone LoadTimeZone(const std::string& name);

View file

@ -71,7 +71,7 @@ inline absl::Time::Breakdown InfiniteFutureBreakdown() {
bd.yearday = 365; bd.yearday = 365;
bd.offset = 0; bd.offset = 0;
bd.is_dst = false; bd.is_dst = false;
bd.zone_abbr = "-0000"; bd.zone_abbr = "-00";
return bd; return bd;
} }
@ -88,7 +88,7 @@ inline Time::Breakdown InfinitePastBreakdown() {
bd.yearday = 1; bd.yearday = 1;
bd.offset = 0; bd.offset = 0;
bd.is_dst = false; bd.is_dst = false;
bd.zone_abbr = "-0000"; bd.zone_abbr = "-00";
return bd; return bd;
} }

View file

@ -18,6 +18,7 @@
#include <cstdint> #include <cstdint>
#include <limits> #include <limits>
#include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "absl/time/internal/test_util.h" #include "absl/time/internal/test_util.h"
#include "absl/time/time.h" #include "absl/time/time.h"
@ -32,31 +33,31 @@ TEST(TimeNormCase, SimpleOverflow) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
absl::Time::Breakdown bd = tc.pre.In(utc); absl::Time::Breakdown bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 16, 33, 0, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 16, 33, 0, 0, false);
tc = absl::ConvertDateTime(2013, 11, 15, 16, 59 + 1, 14, utc); tc = absl::ConvertDateTime(2013, 11, 15, 16, 59 + 1, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 17, 0, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 17, 0, 14, 0, false);
tc = absl::ConvertDateTime(2013, 11, 15, 23 + 1, 32, 14, utc); tc = absl::ConvertDateTime(2013, 11, 15, 23 + 1, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 16, 0, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 16, 0, 32, 14, 0, false);
tc = absl::ConvertDateTime(2013, 11, 30 + 1, 16, 32, 14, utc); tc = absl::ConvertDateTime(2013, 11, 30 + 1, 16, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 12, 1, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 12, 1, 16, 32, 14, 0, false);
tc = absl::ConvertDateTime(2013, 12 + 1, 15, 16, 32, 14, utc); tc = absl::ConvertDateTime(2013, 12 + 1, 15, 16, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2014, 1, 15, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2014, 1, 15, 16, 32, 14, 0, false);
} }
TEST(TimeNormCase, SimpleUnderflow) { TEST(TimeNormCase, SimpleUnderflow) {
@ -66,31 +67,31 @@ TEST(TimeNormCase, SimpleUnderflow) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
absl::Time::Breakdown bd = tc.pre.In(utc); absl::Time::Breakdown bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 16, 31, 59, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 16, 31, 59, 0, false);
tc = ConvertDateTime(2013, 11, 15, 16, 0 - 1, 14, utc); tc = ConvertDateTime(2013, 11, 15, 16, 0 - 1, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 15, 59, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 15, 59, 14, 0, false);
tc = ConvertDateTime(2013, 11, 15, 0 - 1, 32, 14, utc); tc = ConvertDateTime(2013, 11, 15, 0 - 1, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 14, 23, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 14, 23, 32, 14, 0, false);
tc = ConvertDateTime(2013, 11, 1 - 1, 16, 32, 14, utc); tc = ConvertDateTime(2013, 11, 1 - 1, 16, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 10, 31, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 10, 31, 16, 32, 14, 0, false);
tc = ConvertDateTime(2013, 1 - 1, 15, 16, 32, 14, utc); tc = ConvertDateTime(2013, 1 - 1, 15, 16, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2012, 12, 15, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2012, 12, 15, 16, 32, 14, 0, false);
} }
TEST(TimeNormCase, MultipleOverflow) { TEST(TimeNormCase, MultipleOverflow) {
@ -99,7 +100,7 @@ TEST(TimeNormCase, MultipleOverflow) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
absl::Time::Breakdown bd = tc.pre.In(utc); absl::Time::Breakdown bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2014, 1, 1, 0, 0, 0, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2014, 1, 1, 0, 0, 0, 0, false);
} }
TEST(TimeNormCase, MultipleUnderflow) { TEST(TimeNormCase, MultipleUnderflow) {
@ -108,7 +109,7 @@ TEST(TimeNormCase, MultipleUnderflow) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
absl::Time::Breakdown bd = tc.pre.In(utc); absl::Time::Breakdown bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 12, 31, 23, 59, 59, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 12, 31, 23, 59, 59, 0, false);
} }
TEST(TimeNormCase, OverflowLimits) { TEST(TimeNormCase, OverflowLimits) {
@ -122,7 +123,7 @@ TEST(TimeNormCase, OverflowLimits) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 185085715, 11, 27, 12, 21, 7, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 185085715, 11, 27, 12, 21, 7, 0, false);
const int kintmin = std::numeric_limits<int>::min(); const int kintmin = std::numeric_limits<int>::min();
tc = absl::ConvertDateTime(0, kintmin, kintmin, kintmin, kintmin, kintmin, tc = absl::ConvertDateTime(0, kintmin, kintmin, kintmin, kintmin, kintmin,
@ -130,8 +131,7 @@ TEST(TimeNormCase, OverflowLimits) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, -185085717, 10, 31, 10, 37, 52, 0, false, ABSL_INTERNAL_EXPECT_TIME(bd, -185085717, 10, 31, 10, 37, 52, 0, false);
"UTC");
const int64_t max_year = std::numeric_limits<int64_t>::max(); const int64_t max_year = std::numeric_limits<int64_t>::max();
tc = absl::ConvertDateTime(max_year, 12, 31, 23, 59, 59, utc); tc = absl::ConvertDateTime(max_year, 12, 31, 23, 59, 59, utc);
@ -154,31 +154,31 @@ TEST(TimeNormCase, ComplexOverflow) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
absl::Time::Breakdown bd = tc.pre.In(utc); absl::Time::Breakdown bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2017, 10, 14, 14, 5, 23, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2017, 10, 14, 14, 5, 23, 0, false);
tc = absl::ConvertDateTime(2013, 11, 15, 16, 32 + 1234567, 14, utc); tc = absl::ConvertDateTime(2013, 11, 15, 16, 32 + 1234567, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2016, 3, 22, 0, 39, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2016, 3, 22, 0, 39, 14, 0, false);
tc = absl::ConvertDateTime(2013, 11, 15, 16 + 123456, 32, 14, utc); tc = absl::ConvertDateTime(2013, 11, 15, 16 + 123456, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2027, 12, 16, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2027, 12, 16, 16, 32, 14, 0, false);
tc = absl::ConvertDateTime(2013, 11, 15 + 1234, 16, 32, 14, utc); tc = absl::ConvertDateTime(2013, 11, 15 + 1234, 16, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2017, 4, 2, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2017, 4, 2, 16, 32, 14, 0, false);
tc = absl::ConvertDateTime(2013, 11 + 123, 15, 16, 32, 14, utc); tc = absl::ConvertDateTime(2013, 11 + 123, 15, 16, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2024, 2, 15, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2024, 2, 15, 16, 32, 14, 0, false);
} }
TEST(TimeNormCase, ComplexUnderflow) { TEST(TimeNormCase, ComplexUnderflow) {
@ -189,37 +189,37 @@ TEST(TimeNormCase, ComplexUnderflow) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
absl::Time::Breakdown bd = tc.pre.In(utc); absl::Time::Breakdown bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 1999, 2, 28, 0, 0, 0, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 1999, 2, 28, 0, 0, 0, 0, false);
tc = absl::ConvertDateTime(2013, 11, 15, 16, 32, 14 - 123456789, utc); tc = absl::ConvertDateTime(2013, 11, 15, 16, 32, 14 - 123456789, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2009, 12, 17, 18, 59, 5, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2009, 12, 17, 18, 59, 5, 0, false);
tc = absl::ConvertDateTime(2013, 11, 15, 16, 32 - 1234567, 14, utc); tc = absl::ConvertDateTime(2013, 11, 15, 16, 32 - 1234567, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2011, 7, 12, 8, 25, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2011, 7, 12, 8, 25, 14, 0, false);
tc = absl::ConvertDateTime(2013, 11, 15, 16 - 123456, 32, 14, utc); tc = absl::ConvertDateTime(2013, 11, 15, 16 - 123456, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 1999, 10, 16, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 1999, 10, 16, 16, 32, 14, 0, false);
tc = absl::ConvertDateTime(2013, 11, 15 - 1234, 16, 32, 14, utc); tc = absl::ConvertDateTime(2013, 11, 15 - 1234, 16, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2010, 6, 30, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2010, 6, 30, 16, 32, 14, 0, false);
tc = absl::ConvertDateTime(2013, 11 - 123, 15, 16, 32, 14, utc); tc = absl::ConvertDateTime(2013, 11 - 123, 15, 16, 32, 14, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2003, 8, 15, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2003, 8, 15, 16, 32, 14, 0, false);
} }
TEST(TimeNormCase, Mishmash) { TEST(TimeNormCase, Mishmash) {
@ -231,14 +231,14 @@ TEST(TimeNormCase, Mishmash) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
absl::Time::Breakdown bd = tc.pre.In(utc); absl::Time::Breakdown bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 1991, 5, 9, 3, 6, 5, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 1991, 5, 9, 3, 6, 5, 0, false);
tc = absl::ConvertDateTime(2013, 11 + 123, 15 - 1234, 16 + 123456, tc = absl::ConvertDateTime(2013, 11 + 123, 15 - 1234, 16 + 123456,
32 - 1234567, 14 + 123456789, utc); 32 - 1234567, 14 + 123456789, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2036, 5, 24, 5, 58, 23, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2036, 5, 24, 5, 58, 23, 0, false);
// Here is a normalization case we got wrong for a while. Because the // Here is a normalization case we got wrong for a while. Because the
// day is converted to "1" within a 400-year (146097-day) period, we // day is converted to "1" within a 400-year (146097-day) period, we
@ -247,7 +247,7 @@ TEST(TimeNormCase, Mishmash) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 1613, 11, 1, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 1613, 11, 1, 16, 32, 14, 0, false);
// Even though the month overflow compensates for the day underflow, // Even though the month overflow compensates for the day underflow,
// this should still be marked as normalized. // this should still be marked as normalized.
@ -255,7 +255,7 @@ TEST(TimeNormCase, Mishmash) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 1, 16, 32, 14, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 1, 16, 32, 14, 0, false);
} }
TEST(TimeNormCase, LeapYears) { TEST(TimeNormCase, LeapYears) {
@ -266,25 +266,25 @@ TEST(TimeNormCase, LeapYears) {
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
absl::Time::Breakdown bd = tc.pre.In(utc); absl::Time::Breakdown bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 3, 1, 0, 0, 0, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 3, 1, 0, 0, 0, 0, false);
tc = absl::ConvertDateTime(2012, 2, 28 + 1, 0, 0, 0, utc); tc = absl::ConvertDateTime(2012, 2, 28 + 1, 0, 0, 0, utc);
EXPECT_FALSE(tc.normalized); EXPECT_FALSE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2012, 2, 29, 0, 0, 0, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2012, 2, 29, 0, 0, 0, 0, false);
tc = absl::ConvertDateTime(2000, 2, 28 + 1, 0, 0, 0, utc); tc = absl::ConvertDateTime(2000, 2, 28 + 1, 0, 0, 0, utc);
EXPECT_FALSE(tc.normalized); EXPECT_FALSE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 2000, 2, 29, 0, 0, 0, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 2000, 2, 29, 0, 0, 0, 0, false);
tc = absl::ConvertDateTime(1900, 2, 28 + 1, 0, 0, 0, utc); tc = absl::ConvertDateTime(1900, 2, 28 + 1, 0, 0, 0, utc);
EXPECT_TRUE(tc.normalized); EXPECT_TRUE(tc.normalized);
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind); EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
bd = tc.pre.In(utc); bd = tc.pre.In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, 1900, 3, 1, 0, 0, 0, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 1900, 3, 1, 0, 0, 0, 0, false);
} }
// Convert all the days from 1970-1-1 to 1970-1-146097 (aka 2369-12-31) // Convert all the days from 1970-1-1 to 1970-1-146097 (aka 2369-12-31)

View file

@ -85,7 +85,7 @@ TEST(Time, ValueSemantics) {
TEST(Time, UnixEpoch) { TEST(Time, UnixEpoch) {
absl::Time::Breakdown bd = absl::UnixEpoch().In(absl::UTCTimeZone()); absl::Time::Breakdown bd = absl::UnixEpoch().In(absl::UTCTimeZone());
ABSL_INTERNAL_EXPECT_TIME(bd, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); ABSL_INTERNAL_EXPECT_TIME(bd, 1970, 1, 1, 0, 0, 0, 0, false);
EXPECT_EQ(absl::ZeroDuration(), bd.subsecond); EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
EXPECT_EQ(4, bd.weekday); // Thursday EXPECT_EQ(4, bd.weekday); // Thursday
} }
@ -96,14 +96,14 @@ TEST(Time, Breakdown) {
// The Unix epoch as seen in NYC. // The Unix epoch as seen in NYC.
absl::Time::Breakdown bd = t.In(tz); absl::Time::Breakdown bd = t.In(tz);
ABSL_INTERNAL_EXPECT_TIME(bd, 1969, 12, 31, 19, 0, 0, -18000, false, "EST"); ABSL_INTERNAL_EXPECT_TIME(bd, 1969, 12, 31, 19, 0, 0, -18000, false);
EXPECT_EQ(absl::ZeroDuration(), bd.subsecond); EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
EXPECT_EQ(3, bd.weekday); // Wednesday EXPECT_EQ(3, bd.weekday); // Wednesday
// Just before the epoch. // Just before the epoch.
t -= absl::Nanoseconds(1); t -= absl::Nanoseconds(1);
bd = t.In(tz); bd = t.In(tz);
ABSL_INTERNAL_EXPECT_TIME(bd, 1969, 12, 31, 18, 59, 59, -18000, false, "EST"); ABSL_INTERNAL_EXPECT_TIME(bd, 1969, 12, 31, 18, 59, 59, -18000, false);
EXPECT_EQ(absl::Nanoseconds(999999999), bd.subsecond); EXPECT_EQ(absl::Nanoseconds(999999999), bd.subsecond);
EXPECT_EQ(3, bd.weekday); // Wednesday EXPECT_EQ(3, bd.weekday); // Wednesday
@ -112,7 +112,7 @@ TEST(Time, Breakdown) {
t += absl::Hours(18) + absl::Minutes(30) + absl::Seconds(15) + t += absl::Hours(18) + absl::Minutes(30) + absl::Seconds(15) +
absl::Nanoseconds(9); absl::Nanoseconds(9);
bd = t.In(tz); bd = t.In(tz);
ABSL_INTERNAL_EXPECT_TIME(bd, 1977, 6, 28, 14, 30, 15, -14400, true, "EDT"); ABSL_INTERNAL_EXPECT_TIME(bd, 1977, 6, 28, 14, 30, 15, -14400, true);
EXPECT_EQ(8, bd.subsecond / absl::Nanoseconds(1)); EXPECT_EQ(8, bd.subsecond / absl::Nanoseconds(1));
EXPECT_EQ(2, bd.weekday); // Tuesday EXPECT_EQ(2, bd.weekday); // Tuesday
} }
@ -983,16 +983,18 @@ TEST(Time, ConversionSaturation) {
// Checks how Time::In() saturates on infinities. // Checks how Time::In() saturates on infinities.
absl::Time::Breakdown bd = absl::InfiniteFuture().In(utc); absl::Time::Breakdown bd = absl::InfiniteFuture().In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, std::numeric_limits<int64_t>::max(), 12, 31, 23, ABSL_INTERNAL_EXPECT_TIME(bd, std::numeric_limits<int64_t>::max(), 12, 31, 23,
59, 59, 0, false, "-0000"); 59, 59, 0, false);
EXPECT_EQ(absl::InfiniteDuration(), bd.subsecond); EXPECT_EQ(absl::InfiniteDuration(), bd.subsecond);
EXPECT_EQ(4, bd.weekday); // Thursday EXPECT_EQ(4, bd.weekday); // Thursday
EXPECT_EQ(365, bd.yearday); EXPECT_EQ(365, bd.yearday);
EXPECT_STREQ("-00", bd.zone_abbr); // artifact of absl::Time::In()
bd = absl::InfinitePast().In(utc); bd = absl::InfinitePast().In(utc);
ABSL_INTERNAL_EXPECT_TIME(bd, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0, ABSL_INTERNAL_EXPECT_TIME(bd, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0,
0, 0, false, "-0000"); 0, 0, false);
EXPECT_EQ(-absl::InfiniteDuration(), bd.subsecond); EXPECT_EQ(-absl::InfiniteDuration(), bd.subsecond);
EXPECT_EQ(7, bd.weekday); // Sunday EXPECT_EQ(7, bd.weekday); // Sunday
EXPECT_EQ(1, bd.yearday); EXPECT_EQ(1, bd.yearday);
EXPECT_STREQ("-00", bd.zone_abbr); // artifact of absl::Time::In()
// Approach the maximal Time value from below. // Approach the maximal Time value from below.
t = absl::FromDateTime(292277026596, 12, 4, 15, 30, 6, utc); t = absl::FromDateTime(292277026596, 12, 4, 15, 30, 6, utc);
@ -1054,13 +1056,11 @@ TEST(Time, ExtendedConversionSaturation) {
// The maximal time converted in each zone. // The maximal time converted in each zone.
bd = max.In(syd); bd = max.In(syd);
ABSL_INTERNAL_EXPECT_TIME(bd, 292277026596, 12, 5, 2, 30, 7, 39600, true, ABSL_INTERNAL_EXPECT_TIME(bd, 292277026596, 12, 5, 2, 30, 7, 39600, true);
"AEDT");
t = absl::FromDateTime(292277026596, 12, 5, 2, 30, 7, syd); t = absl::FromDateTime(292277026596, 12, 5, 2, 30, 7, syd);
EXPECT_EQ(max, t); EXPECT_EQ(max, t);
bd = max.In(nyc); bd = max.In(nyc);
ABSL_INTERNAL_EXPECT_TIME(bd, 292277026596, 12, 4, 10, 30, 7, -18000, false, ABSL_INTERNAL_EXPECT_TIME(bd, 292277026596, 12, 4, 10, 30, 7, -18000, false);
"EST");
t = absl::FromDateTime(292277026596, 12, 4, 10, 30, 7, nyc); t = absl::FromDateTime(292277026596, 12, 4, 10, 30, 7, nyc);
EXPECT_EQ(max, t); EXPECT_EQ(max, t);

View file

@ -20,12 +20,12 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "absl/base/internal/exception_safety_testing.h" #include "absl/base/internal/exception_safety_testing.h"
using Thrower = absl::ThrowingValue<>; using Thrower = testing::ThrowingValue<>;
using NoThrowMoveThrower = using NoThrowMoveThrower =
absl::ThrowingValue<absl::NoThrow::kMoveCtor | absl::NoThrow::kMoveAssign>; testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
using ThrowerList = std::initializer_list<Thrower>; using ThrowerList = std::initializer_list<Thrower>;
using ThrowerVec = std::vector<Thrower>; using ThrowerVec = std::vector<Thrower>;
using ThrowingAlloc = absl::ThrowingAllocator<Thrower>; using ThrowingAlloc = testing::ThrowingAllocator<Thrower>;
using ThrowingThrowerVec = std::vector<Thrower, ThrowingAlloc>; using ThrowingThrowerVec = std::vector<Thrower, ThrowingAlloc>;
namespace { namespace {
@ -81,30 +81,31 @@ testing::AssertionResult AnyIsEmpty(absl::any* a) {
TEST(AnyExceptionSafety, Ctors) { TEST(AnyExceptionSafety, Ctors) {
Thrower val(1); Thrower val(1);
absl::TestThrowingCtor<absl::any>(val); testing::TestThrowingCtor<absl::any>(val);
Thrower copy(val); Thrower copy(val);
absl::TestThrowingCtor<absl::any>(copy); testing::TestThrowingCtor<absl::any>(copy);
absl::TestThrowingCtor<absl::any>(absl::in_place_type_t<Thrower>(), 1); testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<Thrower>(), 1);
absl::TestThrowingCtor<absl::any>(absl::in_place_type_t<ThrowerVec>(), testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<ThrowerVec>(),
ThrowerList{val}); ThrowerList{val});
absl::TestThrowingCtor<absl::any, absl::in_place_type_t<ThrowingThrowerVec>, testing::TestThrowingCtor<absl::any,
ThrowerList, ThrowingAlloc>( absl::in_place_type_t<ThrowingThrowerVec>,
ThrowerList, ThrowingAlloc>(
absl::in_place_type_t<ThrowingThrowerVec>(), {val}, ThrowingAlloc()); absl::in_place_type_t<ThrowingThrowerVec>(), {val}, ThrowingAlloc());
} }
TEST(AnyExceptionSafety, Assignment) { TEST(AnyExceptionSafety, Assignment) {
auto original = auto original =
absl::any(absl::in_place_type_t<Thrower>(), 1, absl::no_throw_ctor); absl::any(absl::in_place_type_t<Thrower>(), 1, testing::no_throw_ctor);
auto any_is_strong = [original](absl::any* ap) { auto any_is_strong = [original](absl::any* ap) {
return testing::AssertionResult(ap->has_value() && return testing::AssertionResult(ap->has_value() &&
absl::any_cast<Thrower>(original) == absl::any_cast<Thrower>(original) ==
absl::any_cast<Thrower>(*ap)); absl::any_cast<Thrower>(*ap));
}; };
auto any_strong_tester = absl::MakeExceptionSafetyTester() auto any_strong_tester = testing::MakeExceptionSafetyTester()
.WithInitialValue(original) .WithInitialValue(original)
.WithInvariants(AnyInvariants, any_is_strong); .WithInvariants(AnyInvariants, any_is_strong);
@ -126,7 +127,7 @@ TEST(AnyExceptionSafety, Assignment) {
return testing::AssertionResult{!ap->has_value()}; return testing::AssertionResult{!ap->has_value()};
}; };
auto strong_empty_any_tester = auto strong_empty_any_tester =
absl::MakeExceptionSafetyTester() testing::MakeExceptionSafetyTester()
.WithInitialValue(absl::any{}) .WithInitialValue(absl::any{})
.WithInvariants(AnyInvariants, empty_any_is_strong); .WithInvariants(AnyInvariants, empty_any_is_strong);
@ -138,14 +139,14 @@ TEST(AnyExceptionSafety, Assignment) {
#if !defined(ABSL_HAVE_STD_ANY) #if !defined(ABSL_HAVE_STD_ANY)
TEST(AnyExceptionSafety, Emplace) { TEST(AnyExceptionSafety, Emplace) {
auto initial_val = auto initial_val =
absl::any{absl::in_place_type_t<Thrower>(), 1, absl::no_throw_ctor}; absl::any{absl::in_place_type_t<Thrower>(), 1, testing::no_throw_ctor};
auto one_tester = absl::MakeExceptionSafetyTester() auto one_tester = testing::MakeExceptionSafetyTester()
.WithInitialValue(initial_val) .WithInitialValue(initial_val)
.WithInvariants(AnyInvariants, AnyIsEmpty); .WithInvariants(AnyInvariants, AnyIsEmpty);
auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); }; auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); };
auto emp_throwervec = [](absl::any* ap) { auto emp_throwervec = [](absl::any* ap) {
std::initializer_list<Thrower> il{Thrower(2, absl::no_throw_ctor)}; std::initializer_list<Thrower> il{Thrower(2, testing::no_throw_ctor)};
ap->emplace<ThrowerVec>(il); ap->emplace<ThrowerVec>(il);
}; };
auto emp_movethrower = [](absl::any* ap) { auto emp_movethrower = [](absl::any* ap) {