about summary refs log tree commit diff
path: root/absl/base
diff options
context:
space:
mode:
Diffstat (limited to 'absl/base')
-rw-r--r--absl/base/exception_safety_testing_test.cc128
-rw-r--r--absl/base/internal/exception_safety_testing.cc6
-rw-r--r--absl/base/internal/exception_safety_testing.h214
3 files changed, 209 insertions, 139 deletions
diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc
index ab029e1f09d3..9bd8b9dbd040 100644
--- a/absl/base/exception_safety_testing_test.cc
+++ b/absl/base/exception_safety_testing_test.cc
@@ -25,11 +25,13 @@
 #include "gtest/gtest.h"
 #include "absl/memory/memory.h"
 
-namespace absl {
+namespace testing {
+
 namespace {
-using ::absl::exceptions_internal::SetCountdown;
-using ::absl::exceptions_internal::TestException;
-using ::absl::exceptions_internal::UnsetCountdown;
+
+using ::testing::exceptions_internal::SetCountdown;
+using ::testing::exceptions_internal::TestException;
+using ::testing::exceptions_internal::UnsetCountdown;
 
 // EXPECT_NO_THROW can't inspect the thrown inspection in general.
 template <typename F>
@@ -166,17 +168,17 @@ TEST(ThrowingValueTest, ThrowingAllocatingOps) {
 }
 
 TEST(ThrowingValueTest, NonThrowingMoveCtor) {
-  ThrowingValue<NoThrow::kMoveCtor> nothrow_ctor;
+  ThrowingValue<TypeSpec::kNoThrowMove> nothrow_ctor;
 
   SetCountdown();
   ExpectNoThrow([&nothrow_ctor]() {
-    ThrowingValue<NoThrow::kMoveCtor> nothrow1 = std::move(nothrow_ctor);
+    ThrowingValue<TypeSpec::kNoThrowMove> nothrow1 = std::move(nothrow_ctor);
   });
   UnsetCountdown();
 }
 
 TEST(ThrowingValueTest, NonThrowingMoveAssign) {
-  ThrowingValue<NoThrow::kMoveAssign> nothrow_assign1, nothrow_assign2;
+  ThrowingValue<TypeSpec::kNoThrowMove> nothrow_assign1, nothrow_assign2;
 
   SetCountdown();
   ExpectNoThrow([&nothrow_assign1, &nothrow_assign2]() {
@@ -185,32 +187,58 @@ TEST(ThrowingValueTest, NonThrowingMoveAssign) {
   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) {
   ThrowingValue<> 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) {
-  ThrowingValue<NoThrow::kMoveAssign | NoThrow::kMoveCtor> bomb1, bomb2;
+  ThrowingValue<TypeSpec::kNoThrowMove> bomb1, bomb2;
   ExpectNoThrow([&]() { std::swap(bomb1, bomb2); });
 }
 
 TEST(ThrowingValueTest, NonThrowingAllocation) {
-  ThrowingValue<NoThrow::kAllocation>* allocated;
-  ThrowingValue<NoThrow::kAllocation>* array;
+  ThrowingValue<TypeSpec::kNoThrowNew>* allocated;
+  ThrowingValue<TypeSpec::kNoThrowNew>* array;
 
   ExpectNoThrow([&allocated]() {
-    allocated = new ThrowingValue<NoThrow::kAllocation>(1);
+    allocated = new ThrowingValue<TypeSpec::kNoThrowNew>(1);
     delete allocated;
   });
   ExpectNoThrow([&array]() {
-    array = new ThrowingValue<NoThrow::kAllocation>[2];
+    array = new ThrowingValue<TypeSpec::kNoThrowNew>[2];
     delete[] array;
   });
 }
@@ -284,15 +312,15 @@ TEST(ThrowingAllocatorTest, MemoryManagement) {
   int* i_array = int_alloc.allocate(2);
   int_alloc.deallocate(i_array, 2);
 
-  ThrowingAllocator<ThrowingValue<>> ef_alloc;
-  ThrowingValue<>* efp = ef_alloc.allocate(1);
-  ef_alloc.deallocate(efp, 1);
-  ThrowingValue<>* ef_array = ef_alloc.allocate(2);
-  ef_alloc.deallocate(ef_array, 2);
+  ThrowingAllocator<ThrowingValue<>> tv_alloc;
+  ThrowingValue<>* ptr = tv_alloc.allocate(1);
+  tv_alloc.deallocate(ptr, 1);
+  ThrowingValue<>* tv_array = tv_alloc.allocate(2);
+  tv_alloc.deallocate(tv_array, 2);
 }
 
 TEST(ThrowingAllocatorTest, CallsGlobalNew) {
-  ThrowingAllocator<ThrowingValue<>, NoThrow::kNoThrow> nothrow_alloc;
+  ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate> nothrow_alloc;
   ThrowingValue<>* ptr;
 
   SetCountdown();
@@ -322,7 +350,7 @@ TEST(ThrowingAllocatorTest, ThrowingConstructors) {
 
 TEST(ThrowingAllocatorTest, NonThrowingConstruction) {
   {
-    ThrowingAllocator<int, NoThrow::kNoThrow> int_alloc;
+    ThrowingAllocator<int, AllocSpec::kNoThrowAllocate> int_alloc;
     int* ip = nullptr;
 
     SetCountdown();
@@ -347,19 +375,20 @@ TEST(ThrowingAllocatorTest, NonThrowingConstruction) {
   }
 
   {
-    ThrowingAllocator<ThrowingValue<NoThrow::kIntCtor>, NoThrow::kNoThrow>
-        ef_alloc;
-    ThrowingValue<NoThrow::kIntCtor>* efp;
+    ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate>
+        nothrow_alloc;
+    ThrowingValue<>* ptr;
 
     SetCountdown();
-    ExpectNoThrow([&]() { efp = ef_alloc.allocate(1); });
+    ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); });
 
     SetCountdown();
-    ExpectNoThrow([&]() { ef_alloc.construct(efp, 2); });
+    ExpectNoThrow(
+        [&]() { nothrow_alloc.construct(ptr, 2, testing::no_throw_ctor); });
 
-    EXPECT_EQ(efp->Get(), 2);
-    ef_alloc.destroy(efp);
-    ef_alloc.deallocate(efp, 1);
+    EXPECT_EQ(ptr->Get(), 2);
+    nothrow_alloc.destroy(ptr);
+    nothrow_alloc.deallocate(ptr, 1);
 
     UnsetCountdown();
   }
@@ -448,15 +477,15 @@ TEST(ExceptionSafetyTesterTest, IncompleteTypesAreNotTestable) {
   // 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);
+      testing::MakeExceptionSafetyTester().WithOperation(op).WithInvariants(
+          inv, testing::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)
+  auto without_op = testing::MakeExceptionSafetyTester()
+                        .WithInvariants(inv, testing::strong_guarantee)
                         .WithFactory(fac);
   EXPECT_FALSE(HasNullaryTest(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
   // the invocation of .Test() and .Test(op) because it lacks invariants
   auto without_inv =
-      absl::MakeExceptionSafetyTester().WithOperation(op).WithFactory(fac);
+      testing::MakeExceptionSafetyTester().WithOperation(op).WithFactory(fac);
   EXPECT_FALSE(HasNullaryTest(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
 TEST(ExceptionSafetyTesterTest, MixedFunctionTypes) {
   // function reference
-  EXPECT_TRUE(absl::MakeExceptionSafetyTester()
+  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
                   .WithFactory(ExampleFunctionFactory)
                   .WithOperation(ExampleFunctionOperation)
                   .WithInvariants(ExampleFunctionInvariant)
                   .Test());
 
   // function pointer
-  EXPECT_TRUE(absl::MakeExceptionSafetyTester()
+  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
                   .WithFactory(&ExampleFunctionFactory)
                   .WithOperation(&ExampleFunctionOperation)
                   .WithInvariants(&ExampleFunctionInvariant)
                   .Test());
 
   // struct
-  EXPECT_TRUE(absl::MakeExceptionSafetyTester()
+  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
                   .WithFactory(example_struct_factory)
                   .WithOperation(example_struct_operation)
                   .WithInvariants(example_struct_invariant)
                   .Test());
 
   // lambda
-  EXPECT_TRUE(absl::MakeExceptionSafetyTester()
+  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
                   .WithFactory(example_lambda_factory)
                   .WithOperation(example_lambda_operation)
                   .WithInvariants(example_lambda_invariant)
@@ -558,9 +587,9 @@ struct {
 } invoker;
 
 auto tester =
-    absl::MakeExceptionSafetyTester().WithOperation(invoker).WithInvariants(
+    testing::MakeExceptionSafetyTester().WithOperation(invoker).WithInvariants(
         CheckNonNegativeInvariants);
-auto strong_tester = tester.WithInvariants(absl::strong_guarantee);
+auto strong_tester = tester.WithInvariants(testing::strong_guarantee);
 
 struct FailsBasicGuarantee : public NonNegative {
   void operator()() {
@@ -664,7 +693,7 @@ TEST(ExceptionCheckTest, ModifyingChecker) {
   EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{})
                   .WithInvariants(increment)
                   .Test());
-  EXPECT_TRUE(absl::MakeExceptionSafetyTester()
+  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
                   .WithInitialValue(HasReset{})
                   .WithInvariants(CheckHasResetInvariants)
                   .Test(invoker));
@@ -739,7 +768,7 @@ template <typename T>
 unsigned char ExhaustivenessTester<T>::successes = 0;
 
 TEST(ExceptionCheckTest, Exhaustiveness) {
-  auto exhaust_tester = absl::MakeExceptionSafetyTester()
+  auto exhaust_tester = testing::MakeExceptionSafetyTester()
                             .WithInvariants(CheckExhaustivenessTesterInvariants)
                             .WithOperation(invoker);
 
@@ -749,7 +778,7 @@ TEST(ExceptionCheckTest, Exhaustiveness) {
 
   EXPECT_TRUE(
       exhaust_tester.WithInitialValue(ExhaustivenessTester<ThrowingValue<>>{})
-          .WithInvariants(absl::strong_guarantee)
+          .WithInvariants(testing::strong_guarantee)
           .Test());
   EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::successes, 0xF);
 }
@@ -768,7 +797,7 @@ struct LeaksIfCtorThrows : private exceptions_internal::TrackedObject {
 int LeaksIfCtorThrows::counter = 0;
 
 TEST(ExceptionCheckTest, TestLeakyCtor) {
-  absl::TestThrowingCtor<LeaksIfCtorThrows>();
+  testing::TestThrowingCtor<LeaksIfCtorThrows>();
   EXPECT_EQ(LeaksIfCtorThrows::counter, 1);
   LeaksIfCtorThrows::counter = 0;
 }
@@ -839,4 +868,5 @@ TEST(ThrowingAllocatorTraitsTest, Assignablility) {
 }
 
 }  // namespace
-}  // namespace absl
+
+}  // namespace testing
diff --git a/absl/base/internal/exception_safety_testing.cc b/absl/base/internal/exception_safety_testing.cc
index c6f7c7cfff7b..c92d07bcdc5b 100644
--- a/absl/base/internal/exception_safety_testing.cc
+++ b/absl/base/internal/exception_safety_testing.cc
@@ -17,7 +17,7 @@
 #include "gtest/gtest.h"
 #include "absl/meta/type_traits.h"
 
-namespace absl {
+namespace testing {
 
 exceptions_internal::NoThrowTag no_throw_ctor;
 exceptions_internal::StrongGuaranteeTagType strong_guarantee;
@@ -37,5 +37,7 @@ testing::AssertionResult FailureMessage(const TestException& e,
                                         int countdown) noexcept {
   return testing::AssertionFailure() << "Exception thrown from " << e.what();
 }
+
 }  // namespace exceptions_internal
-}  // namespace absl
+
+}  // namespace testing
diff --git a/absl/base/internal/exception_safety_testing.h b/absl/base/internal/exception_safety_testing.h
index c014fb30fc95..32450465a3d1 100644
--- a/absl/base/internal/exception_safety_testing.h
+++ b/absl/base/internal/exception_safety_testing.h
@@ -35,38 +35,36 @@
 #include "absl/strings/substitute.h"
 #include "absl/types/optional.h"
 
-namespace absl {
-
-// A configuration enum for Throwing*.  Operations whose flags are set will
-// throw, everything else won't.  This isn't meant to be exhaustive, more flags
-// 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)
-};
+namespace testing {
+
+enum class TypeSpec;
+enum class AllocSpec;
+
+constexpr TypeSpec operator|(TypeSpec a, TypeSpec b) {
+  using T = absl::underlying_type_t<TypeSpec>;
+  return static_cast<TypeSpec>(static_cast<T>(a) | static_cast<T>(b));
+}
+
+constexpr TypeSpec operator&(TypeSpec a, TypeSpec b) {
+  using T = absl::underlying_type_t<TypeSpec>;
+  return static_cast<TypeSpec>(static_cast<T>(a) & static_cast<T>(b));
+}
 
-constexpr NoThrow operator|(NoThrow a, NoThrow b) {
-  using T = absl::underlying_type_t<NoThrow>;
-  return static_cast<NoThrow>(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 NoThrow operator&(NoThrow a, NoThrow b) {
-  using T = absl::underlying_type_t<NoThrow>;
-  return static_cast<NoThrow>(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 {
+
 struct NoThrowTag {};
 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
 // exceptions specifically thrown by ThrowingValue.
 class TestException {
@@ -246,47 +244,69 @@ class ThrowingBool {
   bool b_;
 };
 
-// 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 flag template arguments.  That is, to make an
-// ThrowingValue which has a noexcept move constructor and noexcept move
-// assignment, use
-// ThrowingValue<absl::NoThrow::kMoveCtor | absl::NoThrow::kMoveAssign>.
-template <NoThrow Flags = NoThrow::kNone>
+/*
+ * Configuration enum for the ThrowingValue type that defines behavior for the
+ * lifetime of the instance. Use testing::no_throw_ctor to prevent the integer
+ * constructor from throwing.
+ *
+ * kEverythingThrows: Every operation can throw an exception
+ * kNoThrowCopy: Copy construction and copy assignment will not throw
+ * kNoThrowMove: Move construction and move assignment will not throw
+ * kNoThrowNew: Overloaded operators new and new[] will not throw
+ */
+enum class TypeSpec {
+  kEverythingThrows = 0,
+  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 {
+  constexpr static bool IsSpecified(TypeSpec spec) {
+    return static_cast<bool>(Spec & spec);
+  }
+
  public:
   ThrowingValue() : TrackedObject(ABSL_PRETTY_FUNCTION) {
     exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
     dummy_ = 0;
   }
 
-  ThrowingValue(const ThrowingValue& other)
+  ThrowingValue(const ThrowingValue& other) noexcept(
+      IsSpecified(TypeSpec::kNoThrowCopy))
       : TrackedObject(ABSL_PRETTY_FUNCTION) {
-    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+    if (!IsSpecified(TypeSpec::kNoThrowCopy)) {
+      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+    }
     dummy_ = other.dummy_;
   }
 
   ThrowingValue(ThrowingValue&& other) noexcept(
-      !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kMoveCtor))
+      IsSpecified(TypeSpec::kNoThrowMove))
       : TrackedObject(ABSL_PRETTY_FUNCTION) {
-    if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kMoveCtor)) {
+    if (!IsSpecified(TypeSpec::kNoThrowMove)) {
       exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
     }
     dummy_ = other.dummy_;
   }
 
-  explicit ThrowingValue(int i) noexcept(
-      !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kIntCtor))
-      : TrackedObject(ABSL_PRETTY_FUNCTION) {
-    if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kIntCtor)) {
-      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
-    }
+  explicit ThrowingValue(int i) : TrackedObject(ABSL_PRETTY_FUNCTION) {
+    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
     dummy_ = i;
   }
 
@@ -296,15 +316,18 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
   // absl expects nothrow destructors
   ~ThrowingValue() noexcept = default;
 
-  ThrowingValue& operator=(const ThrowingValue& other) {
-    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+  ThrowingValue& operator=(const ThrowingValue& other) noexcept(
+      IsSpecified(TypeSpec::kNoThrowCopy)) {
+    if (!IsSpecified(TypeSpec::kNoThrowCopy)) {
+      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+    }
     dummy_ = other.dummy_;
     return *this;
   }
 
   ThrowingValue& operator=(ThrowingValue&& other) noexcept(
-      !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kMoveAssign)) {
-    if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kMoveAssign)) {
+      IsSpecified(TypeSpec::kNoThrowMove)) {
+    if (!IsSpecified(TypeSpec::kNoThrowMove)) {
       exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
     }
     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
   template <typename... Args>
   static void* operator new(size_t s, Args&&... args) noexcept(
-      !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) {
-    if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) {
+      IsSpecified(TypeSpec::kNoThrowNew)) {
+    if (!IsSpecified(TypeSpec::kNoThrowNew)) {
       exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
     }
     return ::operator new(s, std::forward<Args>(args)...);
@@ -542,8 +565,8 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
 
   template <typename... Args>
   static void* operator new[](size_t s, Args&&... args) noexcept(
-      !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) {
-    if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) {
+      IsSpecified(TypeSpec::kNoThrowNew)) {
+    if (!IsSpecified(TypeSpec::kNoThrowNew)) {
       exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
     }
     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
 // make sure we don't use it on user-supplied types.
-template <NoThrow N, typename T>
-void operator,(const ThrowingValue<N>& ef, T&& t) = delete;
-template <NoThrow N, typename T>
-void operator,(T&& t, const ThrowingValue<N>& ef) = 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
-// 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, NoThrow Flags = NoThrow::kNone>
+template <TypeSpec Spec, typename T>
+void operator,(const ThrowingValue<Spec>&, T&&) = delete;
+template <TypeSpec Spec, typename T>
+void operator,(T&&, const ThrowingValue<Spec>&) = delete;
+
+/*
+ * Configuration enum for the ThrowingAllocator type that defines behavior for
+ * the lifetime of the instance.
+ *
+ * kEverythingThrows: Calls to the member functions may throw
+ * 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 {
-  static_assert(Flags == NoThrow::kNone || Flags == NoThrow::kNoThrow,
-                "Invalid flag");
+  constexpr static bool IsSpecified(AllocSpec spec) {
+    return static_cast<bool>(Spec & spec);
+  }
 
  public:
   using pointer = T*;
@@ -607,7 +645,8 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
   using size_type = size_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_move_assignment = std::true_type;
   using propagate_on_container_swap = std::true_type;
@@ -619,8 +658,7 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
   }
 
   template <typename U>
-  ThrowingAllocator(  // NOLINT
-      const ThrowingAllocator<U, Flags>& other) noexcept
+  ThrowingAllocator(const ThrowingAllocator<U, Spec>& other) noexcept  // NOLINT
       : TrackedObject(ABSL_PRETTY_FUNCTION), dummy_(other.State()) {}
 
   // 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()) {}
 
   template <typename U>
-  ThrowingAllocator(  // NOLINT
-      ThrowingAllocator<U, Flags>&& other) noexcept
+  ThrowingAllocator(ThrowingAllocator<U, Spec>&& other) noexcept  // NOLINT
       : TrackedObject(ABSL_PRETTY_FUNCTION), dummy_(std::move(other.State())) {}
 
   ThrowingAllocator(ThrowingAllocator&& other) noexcept
@@ -645,29 +682,30 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
 
   template <typename U>
   ThrowingAllocator& operator=(
-      const ThrowingAllocator<U, Flags>& other) noexcept {
+      const ThrowingAllocator<U, Spec>& other) noexcept {
     dummy_ = other.State();
     return *this;
   }
 
   template <typename U>
-  ThrowingAllocator& operator=(ThrowingAllocator<U, Flags>&& other) noexcept {
+  ThrowingAllocator& operator=(ThrowingAllocator<U, Spec>&& other) noexcept {
     dummy_ = std::move(other.State());
     return *this;
   }
 
   template <typename U>
   struct rebind {
-    using other = ThrowingAllocator<U, Flags>;
+    using other = ThrowingAllocator<U, Spec>;
   };
 
   pointer allocate(size_type n) noexcept(
-      !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kNoThrow)) {
+      IsSpecified(AllocSpec::kNoThrowAllocate)) {
     ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
     return static_cast<pointer>(::operator new(n * sizeof(T)));
   }
+
   pointer allocate(size_type n, const_void_pointer) noexcept(
-      !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kNoThrow)) {
+      IsSpecified(AllocSpec::kNoThrowAllocate)) {
     return allocate(n);
   }
 
@@ -678,7 +716,7 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
 
   template <typename U, typename... Args>
   void construct(U* ptr, Args&&... args) noexcept(
-      !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kNoThrow)) {
+      IsSpecified(AllocSpec::kNoThrowAllocate)) {
     ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
     ::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(
-      !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kNoThrow)) {
+      IsSpecified(AllocSpec::kNoThrowAllocate)) {
     auto& out = *this;
     ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
     return out;
   }
 
   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_;
   }
 
   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_;
   }
 
-  template <typename U, NoThrow B>
+  template <typename, AllocSpec>
   friend class ThrowingAllocator;
 
  private:
@@ -724,7 +762,7 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
   }
 
   void ReadStateAndMaybeThrow(absl::string_view msg) const {
-    if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kNoThrow)) {
+    if (!IsSpecified(AllocSpec::kNoThrowAllocate)) {
       exceptions_internal::MaybeThrow(
           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_;
 };
 
-template <typename T, NoThrow Throws>
-int ThrowingAllocator<T, Throws>::next_id_ = 0;
+template <typename T, AllocSpec Spec>
+int ThrowingAllocator<T, Spec>::next_id_ = 0;
 
 // Tests for resource leaks by attempting to construct a T using args repeatedly
 // 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.
    *
    * 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
    * that any state changes made during the execution of the operation were
    * properly rolled back.
@@ -934,7 +972,7 @@ class ExceptionSafetyTester {
   template <typename, typename, typename...>
   friend class ExceptionSafetyTester;
 
-  friend ExceptionSafetyTester<> absl::MakeExceptionSafetyTester();
+  friend ExceptionSafetyTester<> testing::MakeExceptionSafetyTester();
 
   ExceptionSafetyTester() {}
 
@@ -992,6 +1030,6 @@ MakeExceptionSafetyTester() {
   return {};
 }
 
-}  // namespace absl
+}  // namespace testing
 
 #endif  // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_