"Fossies" - the Fresh Open Source Software Archive

Member "abseil-cpp-20230802.1/absl/types/any_exception_safety_test.cc" (18 Sep 2023, 6070 Bytes) of package /linux/misc/abseil-cpp-20230802.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "any_exception_safety_test.cc" see the Fossies "Dox" file reference documentation.

    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 #include "absl/types/any.h"
   16 
   17 #include "absl/base/config.h"
   18 
   19 // This test is a no-op when absl::any is an alias for std::any and when
   20 // exceptions are not enabled.
   21 #if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
   22 
   23 #include <typeinfo>
   24 #include <vector>
   25 
   26 #include "gtest/gtest.h"
   27 #include "absl/base/internal/exception_safety_testing.h"
   28 
   29 using Thrower = testing::ThrowingValue<>;
   30 using NoThrowMoveThrower =
   31     testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
   32 using ThrowerList = std::initializer_list<Thrower>;
   33 using ThrowerVec = std::vector<Thrower>;
   34 using ThrowingAlloc = testing::ThrowingAllocator<Thrower>;
   35 using ThrowingThrowerVec = std::vector<Thrower, ThrowingAlloc>;
   36 
   37 namespace {
   38 
   39 testing::AssertionResult AnyInvariants(absl::any* a) {
   40   using testing::AssertionFailure;
   41   using testing::AssertionSuccess;
   42 
   43   if (a->has_value()) {
   44     if (a->type() == typeid(void)) {
   45       return AssertionFailure()
   46              << "A non-empty any should not have type `void`";
   47     }
   48   } else {
   49     if (a->type() != typeid(void)) {
   50       return AssertionFailure()
   51              << "An empty any should have type void, but has type "
   52              << a->type().name();
   53     }
   54   }
   55 
   56   //  Make sure that reset() changes any to a valid state.
   57   a->reset();
   58   if (a->has_value()) {
   59     return AssertionFailure() << "A reset `any` should be valueless";
   60   }
   61   if (a->type() != typeid(void)) {
   62     return AssertionFailure() << "A reset `any` should have type() of `void`, "
   63                                  "but instead has type "
   64                               << a->type().name();
   65   }
   66   try {
   67     auto unused = absl::any_cast<Thrower>(*a);
   68     static_cast<void>(unused);
   69     return AssertionFailure()
   70            << "A reset `any` should not be able to be any_cast";
   71   } catch (const absl::bad_any_cast&) {
   72   } catch (...) {
   73     return AssertionFailure()
   74            << "Unexpected exception thrown from absl::any_cast";
   75   }
   76   return AssertionSuccess();
   77 }
   78 
   79 testing::AssertionResult AnyIsEmpty(absl::any* a) {
   80   if (!a->has_value()) {
   81     return testing::AssertionSuccess();
   82   }
   83   return testing::AssertionFailure()
   84          << "a should be empty, but instead has value "
   85          << absl::any_cast<Thrower>(*a).Get();
   86 }
   87 
   88 TEST(AnyExceptionSafety, Ctors) {
   89   Thrower val(1);
   90   testing::TestThrowingCtor<absl::any>(val);
   91 
   92   Thrower copy(val);
   93   testing::TestThrowingCtor<absl::any>(copy);
   94 
   95   testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<Thrower>(), 1);
   96 
   97   testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<ThrowerVec>(),
   98                                        ThrowerList{val});
   99 
  100   testing::TestThrowingCtor<absl::any,
  101                             absl::in_place_type_t<ThrowingThrowerVec>,
  102                             ThrowerList, ThrowingAlloc>(
  103       absl::in_place_type_t<ThrowingThrowerVec>(), {val}, ThrowingAlloc());
  104 }
  105 
  106 TEST(AnyExceptionSafety, Assignment) {
  107   auto original =
  108       absl::any(absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor);
  109   auto any_is_strong = [original](absl::any* ap) {
  110     return testing::AssertionResult(ap->has_value() &&
  111                                     absl::any_cast<Thrower>(original) ==
  112                                         absl::any_cast<Thrower>(*ap));
  113   };
  114   auto any_strong_tester = testing::MakeExceptionSafetyTester()
  115                                .WithInitialValue(original)
  116                                .WithContracts(AnyInvariants, any_is_strong);
  117 
  118   Thrower val(2);
  119   absl::any any_val(val);
  120   NoThrowMoveThrower mv_val(2);
  121 
  122   auto assign_any = [&any_val](absl::any* ap) { *ap = any_val; };
  123   auto assign_val = [&val](absl::any* ap) { *ap = val; };
  124   auto move = [&val](absl::any* ap) { *ap = std::move(val); };
  125   auto move_movable = [&mv_val](absl::any* ap) { *ap = std::move(mv_val); };
  126 
  127   EXPECT_TRUE(any_strong_tester.Test(assign_any));
  128   EXPECT_TRUE(any_strong_tester.Test(assign_val));
  129   EXPECT_TRUE(any_strong_tester.Test(move));
  130   EXPECT_TRUE(any_strong_tester.Test(move_movable));
  131 
  132   auto empty_any_is_strong = [](absl::any* ap) {
  133     return testing::AssertionResult{!ap->has_value()};
  134   };
  135   auto strong_empty_any_tester =
  136       testing::MakeExceptionSafetyTester()
  137           .WithInitialValue(absl::any{})
  138           .WithContracts(AnyInvariants, empty_any_is_strong);
  139 
  140   EXPECT_TRUE(strong_empty_any_tester.Test(assign_any));
  141   EXPECT_TRUE(strong_empty_any_tester.Test(assign_val));
  142   EXPECT_TRUE(strong_empty_any_tester.Test(move));
  143 }
  144 
  145 TEST(AnyExceptionSafety, Emplace) {
  146   auto initial_val =
  147       absl::any{absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor};
  148   auto one_tester = testing::MakeExceptionSafetyTester()
  149                         .WithInitialValue(initial_val)
  150                         .WithContracts(AnyInvariants, AnyIsEmpty);
  151 
  152   auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); };
  153   auto emp_throwervec = [](absl::any* ap) {
  154     std::initializer_list<Thrower> il{Thrower(2, testing::nothrow_ctor)};
  155     ap->emplace<ThrowerVec>(il);
  156   };
  157   auto emp_movethrower = [](absl::any* ap) {
  158     ap->emplace<NoThrowMoveThrower>(2);
  159   };
  160 
  161   EXPECT_TRUE(one_tester.Test(emp_thrower));
  162   EXPECT_TRUE(one_tester.Test(emp_throwervec));
  163   EXPECT_TRUE(one_tester.Test(emp_movethrower));
  164 
  165   auto empty_tester = one_tester.WithInitialValue(absl::any{});
  166 
  167   EXPECT_TRUE(empty_tester.Test(emp_thrower));
  168   EXPECT_TRUE(empty_tester.Test(emp_throwervec));
  169 }
  170 
  171 }  // namespace
  172 
  173 #endif  // #if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)