tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

exception_safety_testing.h (38348B)


      1 // Copyright 2017 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 // Utilities for testing exception-safety
     16 
     17 #ifndef ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
     18 #define ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
     19 
     20 #include "absl/base/config.h"
     21 
     22 #ifdef ABSL_HAVE_EXCEPTIONS
     23 
     24 #include <cstddef>
     25 #include <cstdint>
     26 #include <functional>
     27 #include <initializer_list>
     28 #include <iosfwd>
     29 #include <string>
     30 #include <tuple>
     31 #include <unordered_map>
     32 
     33 #include "gtest/gtest.h"
     34 #include "absl/base/internal/pretty_function.h"
     35 #include "absl/memory/memory.h"
     36 #include "absl/meta/type_traits.h"
     37 #include "absl/strings/string_view.h"
     38 #include "absl/strings/substitute.h"
     39 #include "absl/utility/utility.h"
     40 
     41 namespace testing {
     42 
     43 enum class TypeSpec;
     44 enum class AllocSpec;
     45 
     46 constexpr TypeSpec operator|(TypeSpec a, TypeSpec b) {
     47  using T = absl::underlying_type_t<TypeSpec>;
     48  return static_cast<TypeSpec>(static_cast<T>(a) | static_cast<T>(b));
     49 }
     50 
     51 constexpr TypeSpec operator&(TypeSpec a, TypeSpec b) {
     52  using T = absl::underlying_type_t<TypeSpec>;
     53  return static_cast<TypeSpec>(static_cast<T>(a) & static_cast<T>(b));
     54 }
     55 
     56 constexpr AllocSpec operator|(AllocSpec a, AllocSpec b) {
     57  using T = absl::underlying_type_t<AllocSpec>;
     58  return static_cast<AllocSpec>(static_cast<T>(a) | static_cast<T>(b));
     59 }
     60 
     61 constexpr AllocSpec operator&(AllocSpec a, AllocSpec b) {
     62  using T = absl::underlying_type_t<AllocSpec>;
     63  return static_cast<AllocSpec>(static_cast<T>(a) & static_cast<T>(b));
     64 }
     65 
     66 namespace exceptions_internal {
     67 
     68 std::string GetSpecString(TypeSpec);
     69 std::string GetSpecString(AllocSpec);
     70 
     71 struct NoThrowTag {};
     72 struct StrongGuaranteeTagType {};
     73 
     74 // A simple exception class.  We throw this so that test code can catch
     75 // exceptions specifically thrown by ThrowingValue.
     76 class TestException {
     77 public:
     78  explicit TestException(absl::string_view msg) : msg_(msg) {}
     79  virtual ~TestException() {}
     80  virtual const char* what() const noexcept { return msg_.c_str(); }
     81 
     82 private:
     83  std::string msg_;
     84 };
     85 
     86 // TestBadAllocException exists because allocation functions must throw an
     87 // exception which can be caught by a handler of std::bad_alloc.  We use a child
     88 // class of std::bad_alloc so we can customise the error message, and also
     89 // derive from TestException so we don't accidentally end up catching an actual
     90 // bad_alloc exception in TestExceptionSafety.
     91 class TestBadAllocException : public std::bad_alloc, public TestException {
     92 public:
     93  explicit TestBadAllocException(absl::string_view msg) : TestException(msg) {}
     94  using TestException::what;
     95 };
     96 
     97 extern int countdown;
     98 
     99 // Allows the countdown variable to be set manually (defaulting to the initial
    100 // value of 0)
    101 inline void SetCountdown(int i = 0) { countdown = i; }
    102 // Sets the countdown to the terminal value -1
    103 inline void UnsetCountdown() { SetCountdown(-1); }
    104 
    105 void MaybeThrow(absl::string_view msg, bool throw_bad_alloc = false);
    106 
    107 testing::AssertionResult FailureMessage(const TestException& e,
    108                                        int countdown) noexcept;
    109 
    110 struct TrackedAddress {
    111  bool is_alive;
    112  std::string description;
    113 };
    114 
    115 // Inspects the constructions and destructions of anything inheriting from
    116 // TrackedObject. This allows us to safely "leak" TrackedObjects, as
    117 // ConstructorTracker will destroy everything left over in its destructor.
    118 class ConstructorTracker {
    119 public:
    120  explicit ConstructorTracker(int count) : countdown_(count) {
    121    assert(current_tracker_instance_ == nullptr);
    122    current_tracker_instance_ = this;
    123  }
    124 
    125  ~ConstructorTracker() {
    126    assert(current_tracker_instance_ == this);
    127    current_tracker_instance_ = nullptr;
    128 
    129    for (auto& it : address_map_) {
    130      void* address = it.first;
    131      TrackedAddress& tracked_address = it.second;
    132      if (tracked_address.is_alive) {
    133        ADD_FAILURE() << ErrorMessage(address, tracked_address.description,
    134                                      countdown_, "Object was not destroyed.");
    135      }
    136    }
    137  }
    138 
    139  static void ObjectConstructed(void* address, std::string description) {
    140    if (!CurrentlyTracking()) return;
    141 
    142    TrackedAddress& tracked_address =
    143        current_tracker_instance_->address_map_[address];
    144    if (tracked_address.is_alive) {
    145      ADD_FAILURE() << ErrorMessage(
    146          address, tracked_address.description,
    147          current_tracker_instance_->countdown_,
    148          "Object was re-constructed. Current object was constructed by " +
    149              description);
    150    }
    151    tracked_address = {true, std::move(description)};
    152  }
    153 
    154  static void ObjectDestructed(void* address) {
    155    if (!CurrentlyTracking()) return;
    156 
    157    auto it = current_tracker_instance_->address_map_.find(address);
    158    // Not tracked. Ignore.
    159    if (it == current_tracker_instance_->address_map_.end()) return;
    160 
    161    TrackedAddress& tracked_address = it->second;
    162    if (!tracked_address.is_alive) {
    163      ADD_FAILURE() << ErrorMessage(address, tracked_address.description,
    164                                    current_tracker_instance_->countdown_,
    165                                    "Object was re-destroyed.");
    166    }
    167    tracked_address.is_alive = false;
    168  }
    169 
    170 private:
    171  static bool CurrentlyTracking() {
    172    return current_tracker_instance_ != nullptr;
    173  }
    174 
    175  static std::string ErrorMessage(void* address,
    176                                  const std::string& address_description,
    177                                  int countdown,
    178                                  const std::string& error_description) {
    179    return absl::Substitute(
    180        "With coundtown at $0:\n"
    181        "  $1\n"
    182        "  Object originally constructed by $2\n"
    183        "  Object address: $3\n",
    184        countdown, error_description, address_description, address);
    185  }
    186 
    187  std::unordered_map<void*, TrackedAddress> address_map_;
    188  int countdown_;
    189 
    190  static ConstructorTracker* current_tracker_instance_;
    191 };
    192 
    193 class TrackedObject {
    194 public:
    195  TrackedObject(const TrackedObject&) = delete;
    196  TrackedObject(TrackedObject&&) = delete;
    197 
    198 protected:
    199  explicit TrackedObject(std::string description) {
    200    ConstructorTracker::ObjectConstructed(this, std::move(description));
    201  }
    202 
    203  ~TrackedObject() noexcept { ConstructorTracker::ObjectDestructed(this); }
    204 };
    205 }  // namespace exceptions_internal
    206 
    207 extern exceptions_internal::NoThrowTag nothrow_ctor;
    208 
    209 extern exceptions_internal::StrongGuaranteeTagType strong_guarantee;
    210 
    211 // A test class which is convertible to bool.  The conversion can be
    212 // instrumented to throw at a controlled time.
    213 class ThrowingBool {
    214 public:
    215  ThrowingBool(bool b) noexcept : b_(b) {}  // NOLINT(runtime/explicit)
    216  operator bool() const {                   // NOLINT
    217    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    218    return b_;
    219  }
    220 
    221 private:
    222  bool b_;
    223 };
    224 
    225 /*
    226 * Configuration enum for the ThrowingValue type that defines behavior for the
    227 * lifetime of the instance. Use testing::nothrow_ctor to prevent the integer
    228 * constructor from throwing.
    229 *
    230 * kEverythingThrows: Every operation can throw an exception
    231 * kNoThrowCopy: Copy construction and copy assignment will not throw
    232 * kNoThrowMove: Move construction and move assignment will not throw
    233 * kNoThrowNew: Overloaded operators new and new[] will not throw
    234 */
    235 enum class TypeSpec {
    236  kEverythingThrows = 0,
    237  kNoThrowCopy = 1,
    238  kNoThrowMove = 1 << 1,
    239  kNoThrowNew = 1 << 2,
    240 };
    241 
    242 /*
    243 * A testing class instrumented to throw an exception at a controlled time.
    244 *
    245 * ThrowingValue implements a slightly relaxed version of the Regular concept --
    246 * that is it's a value type with the expected semantics.  It also implements
    247 * arithmetic operations.  It doesn't implement member and pointer operators
    248 * like operator-> or operator[].
    249 *
    250 * ThrowingValue can be instrumented to have certain operations be noexcept by
    251 * using compile-time bitfield template arguments.  That is, to make an
    252 * ThrowingValue which has noexcept move construction/assignment and noexcept
    253 * copy construction/assignment, use the following:
    254 *   ThrowingValue<testing::kNoThrowMove | testing::kNoThrowCopy> my_thrwr{val};
    255 */
    256 template <TypeSpec Spec = TypeSpec::kEverythingThrows>
    257 class ThrowingValue : private exceptions_internal::TrackedObject {
    258  static constexpr bool IsSpecified(TypeSpec spec) {
    259    return static_cast<bool>(Spec & spec);
    260  }
    261 
    262  static constexpr int kDefaultValue = 0;
    263  static constexpr int kBadValue = 938550620;
    264 
    265 public:
    266  ThrowingValue() : TrackedObject(GetInstanceString(kDefaultValue)) {
    267    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    268    dummy_ = kDefaultValue;
    269  }
    270 
    271  ThrowingValue(const ThrowingValue& other) noexcept(
    272      IsSpecified(TypeSpec::kNoThrowCopy))
    273      : TrackedObject(GetInstanceString(other.dummy_)) {
    274    if (!IsSpecified(TypeSpec::kNoThrowCopy)) {
    275      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    276    }
    277    dummy_ = other.dummy_;
    278  }
    279 
    280  ThrowingValue(ThrowingValue&& other) noexcept(
    281      IsSpecified(TypeSpec::kNoThrowMove))
    282      : TrackedObject(GetInstanceString(other.dummy_)) {
    283    if (!IsSpecified(TypeSpec::kNoThrowMove)) {
    284      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    285    }
    286    dummy_ = other.dummy_;
    287  }
    288 
    289  explicit ThrowingValue(int i) : TrackedObject(GetInstanceString(i)) {
    290    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    291    dummy_ = i;
    292  }
    293 
    294  ThrowingValue(int i, exceptions_internal::NoThrowTag) noexcept
    295      : TrackedObject(GetInstanceString(i)), dummy_(i) {}
    296 
    297  // absl expects nothrow destructors
    298  ~ThrowingValue() noexcept = default;
    299 
    300  ThrowingValue& operator=(const ThrowingValue& other) noexcept(
    301      IsSpecified(TypeSpec::kNoThrowCopy)) {
    302    dummy_ = kBadValue;
    303    if (!IsSpecified(TypeSpec::kNoThrowCopy)) {
    304      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    305    }
    306    dummy_ = other.dummy_;
    307    return *this;
    308  }
    309 
    310  ThrowingValue& operator=(ThrowingValue&& other) noexcept(
    311      IsSpecified(TypeSpec::kNoThrowMove)) {
    312    dummy_ = kBadValue;
    313    if (!IsSpecified(TypeSpec::kNoThrowMove)) {
    314      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    315    }
    316    dummy_ = other.dummy_;
    317    return *this;
    318  }
    319 
    320  // Arithmetic Operators
    321  ThrowingValue operator+(const ThrowingValue& other) const {
    322    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    323    return ThrowingValue(dummy_ + other.dummy_, nothrow_ctor);
    324  }
    325 
    326  ThrowingValue operator+() const {
    327    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    328    return ThrowingValue(dummy_, nothrow_ctor);
    329  }
    330 
    331  ThrowingValue operator-(const ThrowingValue& other) const {
    332    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    333    return ThrowingValue(dummy_ - other.dummy_, nothrow_ctor);
    334  }
    335 
    336  ThrowingValue operator-() const {
    337    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    338    return ThrowingValue(-dummy_, nothrow_ctor);
    339  }
    340 
    341  ThrowingValue& operator++() {
    342    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    343    ++dummy_;
    344    return *this;
    345  }
    346 
    347  ThrowingValue operator++(int) {
    348    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    349    auto out = ThrowingValue(dummy_, nothrow_ctor);
    350    ++dummy_;
    351    return out;
    352  }
    353 
    354  ThrowingValue& operator--() {
    355    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    356    --dummy_;
    357    return *this;
    358  }
    359 
    360  ThrowingValue operator--(int) {
    361    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    362    auto out = ThrowingValue(dummy_, nothrow_ctor);
    363    --dummy_;
    364    return out;
    365  }
    366 
    367  ThrowingValue operator*(const ThrowingValue& other) const {
    368    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    369    return ThrowingValue(dummy_ * other.dummy_, nothrow_ctor);
    370  }
    371 
    372  ThrowingValue operator/(const ThrowingValue& other) const {
    373    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    374    return ThrowingValue(dummy_ / other.dummy_, nothrow_ctor);
    375  }
    376 
    377  ThrowingValue operator%(const ThrowingValue& other) const {
    378    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    379    return ThrowingValue(dummy_ % other.dummy_, nothrow_ctor);
    380  }
    381 
    382  ThrowingValue operator<<(int shift) const {
    383    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    384    return ThrowingValue(dummy_ << shift, nothrow_ctor);
    385  }
    386 
    387  ThrowingValue operator>>(int shift) const {
    388    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    389    return ThrowingValue(dummy_ >> shift, nothrow_ctor);
    390  }
    391 
    392  // Comparison Operators
    393  // NOTE: We use `ThrowingBool` instead of `bool` because most STL
    394  // types/containers requires T to be convertible to bool.
    395  friend ThrowingBool operator==(const ThrowingValue& a,
    396                                 const ThrowingValue& b) {
    397    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    398    return a.dummy_ == b.dummy_;
    399  }
    400  friend ThrowingBool operator!=(const ThrowingValue& a,
    401                                 const ThrowingValue& b) {
    402    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    403    return a.dummy_ != b.dummy_;
    404  }
    405  friend ThrowingBool operator<(const ThrowingValue& a,
    406                                const ThrowingValue& b) {
    407    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    408    return a.dummy_ < b.dummy_;
    409  }
    410  friend ThrowingBool operator<=(const ThrowingValue& a,
    411                                 const ThrowingValue& b) {
    412    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    413    return a.dummy_ <= b.dummy_;
    414  }
    415  friend ThrowingBool operator>(const ThrowingValue& a,
    416                                const ThrowingValue& b) {
    417    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    418    return a.dummy_ > b.dummy_;
    419  }
    420  friend ThrowingBool operator>=(const ThrowingValue& a,
    421                                 const ThrowingValue& b) {
    422    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    423    return a.dummy_ >= b.dummy_;
    424  }
    425 
    426  // Logical Operators
    427  ThrowingBool operator!() const {
    428    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    429    return !dummy_;
    430  }
    431 
    432  ThrowingBool operator&&(const ThrowingValue& other) const {
    433    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    434    return dummy_ && other.dummy_;
    435  }
    436 
    437  ThrowingBool operator||(const ThrowingValue& other) const {
    438    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    439    return dummy_ || other.dummy_;
    440  }
    441 
    442  // Bitwise Logical Operators
    443  ThrowingValue operator~() const {
    444    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    445    return ThrowingValue(~dummy_, nothrow_ctor);
    446  }
    447 
    448  ThrowingValue operator&(const ThrowingValue& other) const {
    449    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    450    return ThrowingValue(dummy_ & other.dummy_, nothrow_ctor);
    451  }
    452 
    453  ThrowingValue operator|(const ThrowingValue& other) const {
    454    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    455    return ThrowingValue(dummy_ | other.dummy_, nothrow_ctor);
    456  }
    457 
    458  ThrowingValue operator^(const ThrowingValue& other) const {
    459    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    460    return ThrowingValue(dummy_ ^ other.dummy_, nothrow_ctor);
    461  }
    462 
    463  // Compound Assignment operators
    464  ThrowingValue& operator+=(const ThrowingValue& other) {
    465    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    466    dummy_ += other.dummy_;
    467    return *this;
    468  }
    469 
    470  ThrowingValue& operator-=(const ThrowingValue& other) {
    471    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    472    dummy_ -= other.dummy_;
    473    return *this;
    474  }
    475 
    476  ThrowingValue& operator*=(const ThrowingValue& other) {
    477    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    478    dummy_ *= other.dummy_;
    479    return *this;
    480  }
    481 
    482  ThrowingValue& operator/=(const ThrowingValue& other) {
    483    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    484    dummy_ /= other.dummy_;
    485    return *this;
    486  }
    487 
    488  ThrowingValue& operator%=(const ThrowingValue& other) {
    489    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    490    dummy_ %= other.dummy_;
    491    return *this;
    492  }
    493 
    494  ThrowingValue& operator&=(const ThrowingValue& other) {
    495    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    496    dummy_ &= other.dummy_;
    497    return *this;
    498  }
    499 
    500  ThrowingValue& operator|=(const ThrowingValue& other) {
    501    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    502    dummy_ |= other.dummy_;
    503    return *this;
    504  }
    505 
    506  ThrowingValue& operator^=(const ThrowingValue& other) {
    507    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    508    dummy_ ^= other.dummy_;
    509    return *this;
    510  }
    511 
    512  ThrowingValue& operator<<=(int shift) {
    513    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    514    dummy_ <<= shift;
    515    return *this;
    516  }
    517 
    518  ThrowingValue& operator>>=(int shift) {
    519    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    520    dummy_ >>= shift;
    521    return *this;
    522  }
    523 
    524  // Pointer operators
    525  void operator&() const = delete;  // NOLINT(runtime/operator)
    526 
    527  // Stream operators
    528  friend std::ostream& operator<<(std::ostream& os, const ThrowingValue& tv) {
    529    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    530    return os << GetInstanceString(tv.dummy_);
    531  }
    532 
    533  friend std::istream& operator>>(std::istream& is, const ThrowingValue&) {
    534    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    535    return is;
    536  }
    537 
    538  // Memory management operators
    539  static void* operator new(size_t s) noexcept(
    540      IsSpecified(TypeSpec::kNoThrowNew)) {
    541    if (!IsSpecified(TypeSpec::kNoThrowNew)) {
    542      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
    543    }
    544    return ::operator new(s);
    545  }
    546 
    547  static void* operator new[](size_t s) noexcept(
    548      IsSpecified(TypeSpec::kNoThrowNew)) {
    549    if (!IsSpecified(TypeSpec::kNoThrowNew)) {
    550      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
    551    }
    552    return ::operator new[](s);
    553  }
    554 
    555  template <typename... Args>
    556  static void* operator new(size_t s, Args&&... args) noexcept(
    557      IsSpecified(TypeSpec::kNoThrowNew)) {
    558    if (!IsSpecified(TypeSpec::kNoThrowNew)) {
    559      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
    560    }
    561    return ::operator new(s, std::forward<Args>(args)...);
    562  }
    563 
    564  template <typename... Args>
    565  static void* operator new[](size_t s, Args&&... args) noexcept(
    566      IsSpecified(TypeSpec::kNoThrowNew)) {
    567    if (!IsSpecified(TypeSpec::kNoThrowNew)) {
    568      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
    569    }
    570    return ::operator new[](s, std::forward<Args>(args)...);
    571  }
    572 
    573  // Abseil doesn't support throwing overloaded operator delete.  These are
    574  // provided so a throwing operator-new can clean up after itself.
    575  void operator delete(void* p) noexcept { ::operator delete(p); }
    576 
    577  template <typename... Args>
    578  void operator delete(void* p, Args&&... args) noexcept {
    579    ::operator delete(p, std::forward<Args>(args)...);
    580  }
    581 
    582  void operator delete[](void* p) noexcept { return ::operator delete[](p); }
    583 
    584  template <typename... Args>
    585  void operator delete[](void* p, Args&&... args) noexcept {
    586    return ::operator delete[](p, std::forward<Args>(args)...);
    587  }
    588 
    589  // Non-standard access to the actual contained value.  No need for this to
    590  // throw.
    591  int& Get() noexcept { return dummy_; }
    592  const int& Get() const noexcept { return dummy_; }
    593 
    594 private:
    595  static std::string GetInstanceString(int dummy) {
    596    return absl::StrCat("ThrowingValue<",
    597                        exceptions_internal::GetSpecString(Spec), ">(", dummy,
    598                        ")");
    599  }
    600 
    601  int dummy_;
    602 };
    603 // While not having to do with exceptions, explicitly delete comma operator, to
    604 // make sure we don't use it on user-supplied types.
    605 template <TypeSpec Spec, typename T>
    606 void operator,(const ThrowingValue<Spec>&, T&&) = delete;
    607 template <TypeSpec Spec, typename T>
    608 void operator,(T&&, const ThrowingValue<Spec>&) = delete;
    609 
    610 /*
    611 * Configuration enum for the ThrowingAllocator type that defines behavior for
    612 * the lifetime of the instance.
    613 *
    614 * kEverythingThrows: Calls to the member functions may throw
    615 * kNoThrowAllocate: Calls to the member functions will not throw
    616 */
    617 enum class AllocSpec {
    618  kEverythingThrows = 0,
    619  kNoThrowAllocate = 1,
    620 };
    621 
    622 /*
    623 * An allocator type which is instrumented to throw at a controlled time, or not
    624 * to throw, using AllocSpec. The supported settings are the default of every
    625 * function which is allowed to throw in a conforming allocator possibly
    626 * throwing, or nothing throws, in line with the ABSL_ALLOCATOR_THROWS
    627 * configuration macro.
    628 */
    629 template <typename T, AllocSpec Spec = AllocSpec::kEverythingThrows>
    630 class ThrowingAllocator : private exceptions_internal::TrackedObject {
    631  static constexpr bool IsSpecified(AllocSpec spec) {
    632    return static_cast<bool>(Spec & spec);
    633  }
    634 
    635 public:
    636  using pointer = T*;
    637  using const_pointer = const T*;
    638  using reference = T&;
    639  using const_reference = const T&;
    640  using void_pointer = void*;
    641  using const_void_pointer = const void*;
    642  using value_type = T;
    643  using size_type = size_t;
    644  using difference_type = ptrdiff_t;
    645 
    646  using is_nothrow =
    647      std::integral_constant<bool, Spec == AllocSpec::kNoThrowAllocate>;
    648  using propagate_on_container_copy_assignment = std::true_type;
    649  using propagate_on_container_move_assignment = std::true_type;
    650  using propagate_on_container_swap = std::true_type;
    651  using is_always_equal = std::false_type;
    652 
    653  ThrowingAllocator() : TrackedObject(GetInstanceString(next_id_)) {
    654    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
    655    dummy_ = std::make_shared<const int>(next_id_++);
    656  }
    657 
    658  template <typename U>
    659  ThrowingAllocator(const ThrowingAllocator<U, Spec>& other) noexcept  // NOLINT
    660      : TrackedObject(GetInstanceString(*other.State())),
    661        dummy_(other.State()) {}
    662 
    663  // According to C++11 standard [17.6.3.5], Table 28, the move/copy ctors of
    664  // allocator shall not exit via an exception, thus they are marked noexcept.
    665  ThrowingAllocator(const ThrowingAllocator& other) noexcept
    666      : TrackedObject(GetInstanceString(*other.State())),
    667        dummy_(other.State()) {}
    668 
    669  template <typename U>
    670  ThrowingAllocator(ThrowingAllocator<U, Spec>&& other) noexcept  // NOLINT
    671      : TrackedObject(GetInstanceString(*other.State())),
    672        dummy_(std::move(other.State())) {}
    673 
    674  ThrowingAllocator(ThrowingAllocator&& other) noexcept
    675      : TrackedObject(GetInstanceString(*other.State())),
    676        dummy_(std::move(other.State())) {}
    677 
    678  ~ThrowingAllocator() noexcept = default;
    679 
    680  ThrowingAllocator& operator=(const ThrowingAllocator& other) noexcept {
    681    dummy_ = other.State();
    682    return *this;
    683  }
    684 
    685  template <typename U>
    686  ThrowingAllocator& operator=(
    687      const ThrowingAllocator<U, Spec>& other) noexcept {
    688    dummy_ = other.State();
    689    return *this;
    690  }
    691 
    692  template <typename U>
    693  ThrowingAllocator& operator=(ThrowingAllocator<U, Spec>&& other) noexcept {
    694    dummy_ = std::move(other.State());
    695    return *this;
    696  }
    697 
    698  template <typename U>
    699  struct rebind {
    700    using other = ThrowingAllocator<U, Spec>;
    701  };
    702 
    703  pointer allocate(size_type n) noexcept(
    704      IsSpecified(AllocSpec::kNoThrowAllocate)) {
    705    ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
    706    return static_cast<pointer>(::operator new(n * sizeof(T)));
    707  }
    708 
    709  pointer allocate(size_type n, const_void_pointer) noexcept(
    710      IsSpecified(AllocSpec::kNoThrowAllocate)) {
    711    return allocate(n);
    712  }
    713 
    714  void deallocate(pointer ptr, size_type) noexcept {
    715    ReadState();
    716    ::operator delete(static_cast<void*>(ptr));
    717  }
    718 
    719  template <typename U, typename... Args>
    720  void construct(U* ptr, Args&&... args) noexcept(
    721      IsSpecified(AllocSpec::kNoThrowAllocate)) {
    722    ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
    723    ::new (static_cast<void*>(ptr)) U(std::forward<Args>(args)...);
    724  }
    725 
    726  template <typename U>
    727  void destroy(U* p) noexcept {
    728    ReadState();
    729    p->~U();
    730  }
    731 
    732  size_type max_size() const noexcept {
    733    return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
    734  }
    735 
    736  ThrowingAllocator select_on_container_copy_construction() noexcept(
    737      IsSpecified(AllocSpec::kNoThrowAllocate)) {
    738    ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
    739    return *this;
    740  }
    741 
    742  template <typename U>
    743  bool operator==(const ThrowingAllocator<U, Spec>& other) const noexcept {
    744    return dummy_ == other.dummy_;
    745  }
    746 
    747  template <typename U>
    748  bool operator!=(const ThrowingAllocator<U, Spec>& other) const noexcept {
    749    return dummy_ != other.dummy_;
    750  }
    751 
    752  template <typename, AllocSpec>
    753  friend class ThrowingAllocator;
    754 
    755 private:
    756  static std::string GetInstanceString(int dummy) {
    757    return absl::StrCat("ThrowingAllocator<",
    758                        exceptions_internal::GetSpecString(Spec), ">(", dummy,
    759                        ")");
    760  }
    761 
    762  const std::shared_ptr<const int>& State() const { return dummy_; }
    763  std::shared_ptr<const int>& State() { return dummy_; }
    764 
    765  void ReadState() {
    766    // we know that this will never be true, but the compiler doesn't, so this
    767    // should safely force a read of the value.
    768    if (*dummy_ < 0) std::abort();
    769  }
    770 
    771  void ReadStateAndMaybeThrow(absl::string_view msg) const {
    772    if (!IsSpecified(AllocSpec::kNoThrowAllocate)) {
    773      exceptions_internal::MaybeThrow(
    774          absl::Substitute("Allocator id $0 threw from $1", *dummy_, msg));
    775    }
    776  }
    777 
    778  static int next_id_;
    779  std::shared_ptr<const int> dummy_;
    780 };
    781 
    782 template <typename T, AllocSpec Spec>
    783 int ThrowingAllocator<T, Spec>::next_id_ = 0;
    784 
    785 // Tests for resource leaks by attempting to construct a T using args repeatedly
    786 // until successful, using the countdown method.  Side effects can then be
    787 // tested for resource leaks.
    788 template <typename T, typename... Args>
    789 void TestThrowingCtor(Args&&... args) {
    790  struct Cleanup {
    791    ~Cleanup() { exceptions_internal::UnsetCountdown(); }
    792  } c;
    793  for (int count = 0;; ++count) {
    794    exceptions_internal::ConstructorTracker ct(count);
    795    exceptions_internal::SetCountdown(count);
    796    try {
    797      T temp(std::forward<Args>(args)...);
    798      static_cast<void>(temp);
    799      break;
    800    } catch (const exceptions_internal::TestException&) {
    801    }
    802  }
    803 }
    804 
    805 // Tests the nothrow guarantee of the provided nullary operation. If the an
    806 // exception is thrown, the result will be AssertionFailure(). Otherwise, it
    807 // will be AssertionSuccess().
    808 template <typename Operation>
    809 testing::AssertionResult TestNothrowOp(const Operation& operation) {
    810  struct Cleanup {
    811    Cleanup() { exceptions_internal::SetCountdown(); }
    812    ~Cleanup() { exceptions_internal::UnsetCountdown(); }
    813  } c;
    814  try {
    815    operation();
    816    return testing::AssertionSuccess();
    817  } catch (const exceptions_internal::TestException&) {
    818    return testing::AssertionFailure()
    819           << "TestException thrown during call to operation() when nothrow "
    820              "guarantee was expected.";
    821  } catch (...) {
    822    return testing::AssertionFailure()
    823           << "Unknown exception thrown during call to operation() when "
    824              "nothrow guarantee was expected.";
    825  }
    826 }
    827 
    828 namespace exceptions_internal {
    829 
    830 // Dummy struct for ExceptionSafetyTestBuilder<> partial state.
    831 struct UninitializedT {};
    832 
    833 template <typename T>
    834 class DefaultFactory {
    835 public:
    836  explicit DefaultFactory(const T& t) : t_(t) {}
    837  std::unique_ptr<T> operator()() const { return absl::make_unique<T>(t_); }
    838 
    839 private:
    840  T t_;
    841 };
    842 
    843 template <size_t LazyContractsCount, typename LazyFactory,
    844          typename LazyOperation>
    845 using EnableIfTestable = typename absl::enable_if_t<
    846    LazyContractsCount != 0 &&
    847    !std::is_same<LazyFactory, UninitializedT>::value &&
    848    !std::is_same<LazyOperation, UninitializedT>::value>;
    849 
    850 template <typename Factory = UninitializedT,
    851          typename Operation = UninitializedT, typename... Contracts>
    852 class ExceptionSafetyTestBuilder;
    853 
    854 }  // namespace exceptions_internal
    855 
    856 /*
    857 * Constructs an empty ExceptionSafetyTestBuilder. All
    858 * ExceptionSafetyTestBuilder objects are immutable and all With[thing] mutation
    859 * methods return new instances of ExceptionSafetyTestBuilder.
    860 *
    861 * In order to test a T for exception safety, a factory for that T, a testable
    862 * operation, and at least one contract callback returning an assertion
    863 * result must be applied using the respective methods.
    864 */
    865 exceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester();
    866 
    867 namespace exceptions_internal {
    868 template <typename T>
    869 struct IsUniquePtr : std::false_type {};
    870 
    871 template <typename T, typename D>
    872 struct IsUniquePtr<std::unique_ptr<T, D>> : std::true_type {};
    873 
    874 template <typename Factory>
    875 struct FactoryPtrTypeHelper {
    876  using type = decltype(std::declval<const Factory&>()());
    877 
    878  static_assert(IsUniquePtr<type>::value, "Factories must return a unique_ptr");
    879 };
    880 
    881 template <typename Factory>
    882 using FactoryPtrType = typename FactoryPtrTypeHelper<Factory>::type;
    883 
    884 template <typename Factory>
    885 using FactoryElementType = typename FactoryPtrType<Factory>::element_type;
    886 
    887 template <typename T>
    888 class ExceptionSafetyTest {
    889  using Factory = std::function<std::unique_ptr<T>()>;
    890  using Operation = std::function<void(T*)>;
    891  using Contract = std::function<AssertionResult(T*)>;
    892 
    893 public:
    894  template <typename... Contracts>
    895  explicit ExceptionSafetyTest(const Factory& f, const Operation& op,
    896                               const Contracts&... contracts)
    897      : factory_(f), operation_(op), contracts_{WrapContract(contracts)...} {}
    898 
    899  AssertionResult Test() const {
    900    for (int count = 0;; ++count) {
    901      exceptions_internal::ConstructorTracker ct(count);
    902 
    903      for (const auto& contract : contracts_) {
    904        auto t_ptr = factory_();
    905        try {
    906          SetCountdown(count);
    907          operation_(t_ptr.get());
    908          // Unset for the case that the operation throws no exceptions, which
    909          // would leave the countdown set and break the *next* exception safety
    910          // test after this one.
    911          UnsetCountdown();
    912          return AssertionSuccess();
    913        } catch (const exceptions_internal::TestException& e) {
    914          if (!contract(t_ptr.get())) {
    915            return AssertionFailure() << e.what() << " failed contract check";
    916          }
    917        }
    918      }
    919    }
    920  }
    921 
    922 private:
    923  template <typename ContractFn>
    924  Contract WrapContract(const ContractFn& contract) {
    925    return [contract](T* t_ptr) { return AssertionResult(contract(t_ptr)); };
    926  }
    927 
    928  Contract WrapContract(StrongGuaranteeTagType) {
    929    return [this](T* t_ptr) { return AssertionResult(*factory_() == *t_ptr); };
    930  }
    931 
    932  Factory factory_;
    933  Operation operation_;
    934  std::vector<Contract> contracts_;
    935 };
    936 
    937 /*
    938 * Builds a tester object that tests if performing a operation on a T follows
    939 * exception safety guarantees. Verification is done via contract assertion
    940 * callbacks applied to T instances post-throw.
    941 *
    942 * Template parameters for ExceptionSafetyTestBuilder:
    943 *
    944 * - Factory: The factory object (passed in via tester.WithFactory(...) or
    945 *   tester.WithInitialValue(...)) must be invocable with the signature
    946 *   `std::unique_ptr<T> operator()() const` where T is the type being tested.
    947 *   It is used for reliably creating identical T instances to test on.
    948 *
    949 * - Operation: The operation object (passed in via tester.WithOperation(...)
    950 *   or tester.Test(...)) must be invocable with the signature
    951 *   `void operator()(T*) const` where T is the type being tested. It is used
    952 *   for performing steps on a T instance that may throw and that need to be
    953 *   checked for exception safety. Each call to the operation will receive a
    954 *   fresh T instance so it's free to modify and destroy the T instances as it
    955 *   pleases.
    956 *
    957 * - Contracts...: The contract assertion callback objects (passed in via
    958 *   tester.WithContracts(...)) must be invocable with the signature
    959 *   `testing::AssertionResult operator()(T*) const` where T is the type being
    960 *   tested. Contract assertion callbacks are provided T instances post-throw.
    961 *   They must return testing::AssertionSuccess when the type contracts of the
    962 *   provided T instance hold. If the type contracts of the T instance do not
    963 *   hold, they must return testing::AssertionFailure. Execution order of
    964 *   Contracts... is unspecified. They will each individually get a fresh T
    965 *   instance so they are free to modify and destroy the T instances as they
    966 *   please.
    967 */
    968 template <typename Factory, typename Operation, typename... Contracts>
    969 class ExceptionSafetyTestBuilder {
    970 public:
    971  /*
    972   * Returns a new ExceptionSafetyTestBuilder with an included T factory based
    973   * on the provided T instance. The existing factory will not be included in
    974   * the newly created tester instance. The created factory returns a new T
    975   * instance by copy-constructing the provided const T& t.
    976   *
    977   * Preconditions for tester.WithInitialValue(const T& t):
    978   *
    979   * - The const T& t object must be copy-constructible where T is the type
    980   *   being tested. For non-copy-constructible objects, use the method
    981   *   tester.WithFactory(...).
    982   */
    983  template <typename T>
    984  ExceptionSafetyTestBuilder<DefaultFactory<T>, Operation, Contracts...>
    985  WithInitialValue(const T& t) const {
    986    return WithFactory(DefaultFactory<T>(t));
    987  }
    988 
    989  /*
    990   * Returns a new ExceptionSafetyTestBuilder with the provided T factory
    991   * included. The existing factory will not be included in the newly-created
    992   * tester instance. This method is intended for use with types lacking a copy
    993   * constructor. Types that can be copy-constructed should instead use the
    994   * method tester.WithInitialValue(...).
    995   */
    996  template <typename NewFactory>
    997  ExceptionSafetyTestBuilder<absl::decay_t<NewFactory>, Operation, Contracts...>
    998  WithFactory(const NewFactory& new_factory) const {
    999    return {new_factory, operation_, contracts_};
   1000  }
   1001 
   1002  /*
   1003   * Returns a new ExceptionSafetyTestBuilder with the provided testable
   1004   * operation included. The existing operation will not be included in the
   1005   * newly created tester.
   1006   */
   1007  template <typename NewOperation>
   1008  ExceptionSafetyTestBuilder<Factory, absl::decay_t<NewOperation>, Contracts...>
   1009  WithOperation(const NewOperation& new_operation) const {
   1010    return {factory_, new_operation, contracts_};
   1011  }
   1012 
   1013  /*
   1014   * Returns a new ExceptionSafetyTestBuilder with the provided MoreContracts...
   1015   * combined with the Contracts... that were already included in the instance
   1016   * on which the method was called. Contracts... cannot be removed or replaced
   1017   * once added to an ExceptionSafetyTestBuilder instance. A fresh object must
   1018   * be created in order to get an empty Contracts... list.
   1019   *
   1020   * In addition to passing in custom contract assertion callbacks, this method
   1021   * accepts `testing::strong_guarantee` as an argument which checks T instances
   1022   * post-throw against freshly created T instances via operator== to verify
   1023   * that any state changes made during the execution of the operation were
   1024   * properly rolled back.
   1025   */
   1026  template <typename... MoreContracts>
   1027  ExceptionSafetyTestBuilder<Factory, Operation, Contracts...,
   1028                             absl::decay_t<MoreContracts>...>
   1029  WithContracts(const MoreContracts&... more_contracts) const {
   1030    return {
   1031        factory_, operation_,
   1032        std::tuple_cat(contracts_, std::tuple<absl::decay_t<MoreContracts>...>(
   1033                                       more_contracts...))};
   1034  }
   1035 
   1036  /*
   1037   * Returns a testing::AssertionResult that is the reduced result of the
   1038   * exception safety algorithm. The algorithm short circuits and returns
   1039   * AssertionFailure after the first contract callback returns an
   1040   * AssertionFailure. Otherwise, if all contract callbacks return an
   1041   * AssertionSuccess, the reduced result is AssertionSuccess.
   1042   *
   1043   * The passed-in testable operation will not be saved in a new tester instance
   1044   * nor will it modify/replace the existing tester instance. This is useful
   1045   * when each operation being tested is unique and does not need to be reused.
   1046   *
   1047   * Preconditions for tester.Test(const NewOperation& new_operation):
   1048   *
   1049   * - May only be called after at least one contract assertion callback and a
   1050   *   factory or initial value have been provided.
   1051   */
   1052  template <
   1053      typename NewOperation,
   1054      typename = EnableIfTestable<sizeof...(Contracts), Factory, NewOperation>>
   1055  testing::AssertionResult Test(const NewOperation& new_operation) const {
   1056    return TestImpl(new_operation, absl::index_sequence_for<Contracts...>());
   1057  }
   1058 
   1059  /*
   1060   * Returns a testing::AssertionResult that is the reduced result of the
   1061   * exception safety algorithm. The algorithm short circuits and returns
   1062   * AssertionFailure after the first contract callback returns an
   1063   * AssertionFailure. Otherwise, if all contract callbacks return an
   1064   * AssertionSuccess, the reduced result is AssertionSuccess.
   1065   *
   1066   * Preconditions for tester.Test():
   1067   *
   1068   * - May only be called after at least one contract assertion callback, a
   1069   *   factory or initial value and a testable operation have been provided.
   1070   */
   1071  template <
   1072      typename LazyOperation = Operation,
   1073      typename = EnableIfTestable<sizeof...(Contracts), Factory, LazyOperation>>
   1074  testing::AssertionResult Test() const {
   1075    return Test(operation_);
   1076  }
   1077 
   1078 private:
   1079  template <typename, typename, typename...>
   1080  friend class ExceptionSafetyTestBuilder;
   1081 
   1082  friend ExceptionSafetyTestBuilder<> testing::MakeExceptionSafetyTester();
   1083 
   1084  ExceptionSafetyTestBuilder() {}
   1085 
   1086  ExceptionSafetyTestBuilder(const Factory& f, const Operation& o,
   1087                             const std::tuple<Contracts...>& i)
   1088      : factory_(f), operation_(o), contracts_(i) {}
   1089 
   1090  template <typename SelectedOperation, size_t... Indices>
   1091  testing::AssertionResult TestImpl(SelectedOperation selected_operation,
   1092                                    absl::index_sequence<Indices...>) const {
   1093    return ExceptionSafetyTest<FactoryElementType<Factory>>(
   1094               factory_, selected_operation, std::get<Indices>(contracts_)...)
   1095        .Test();
   1096  }
   1097 
   1098  Factory factory_;
   1099  Operation operation_;
   1100  std::tuple<Contracts...> contracts_;
   1101 };
   1102 
   1103 }  // namespace exceptions_internal
   1104 
   1105 }  // namespace testing
   1106 
   1107 #endif  // ABSL_HAVE_EXCEPTIONS
   1108 
   1109 #endif  // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_