any_exception_safety_test.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "absl/types/any.h"
00016 
00017 #include <typeinfo>
00018 #include <vector>
00019 
00020 #include "gtest/gtest.h"
00021 #include "absl/base/internal/exception_safety_testing.h"
00022 
00023 using Thrower = testing::ThrowingValue<>;
00024 using NoThrowMoveThrower =
00025     testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
00026 using ThrowerList = std::initializer_list<Thrower>;
00027 using ThrowerVec = std::vector<Thrower>;
00028 using ThrowingAlloc = testing::ThrowingAllocator<Thrower>;
00029 using ThrowingThrowerVec = std::vector<Thrower, ThrowingAlloc>;
00030 
00031 namespace {
00032 
00033 testing::AssertionResult AnyInvariants(absl::any* a) {
00034   using testing::AssertionFailure;
00035   using testing::AssertionSuccess;
00036 
00037   if (a->has_value()) {
00038     if (a->type() == typeid(void)) {
00039       return AssertionFailure()
00040              << "A non-empty any should not have type `void`";
00041     }
00042   } else {
00043     if (a->type() != typeid(void)) {
00044       return AssertionFailure()
00045              << "An empty any should have type void, but has type "
00046              << a->type().name();
00047     }
00048   }
00049 
00050   //  Make sure that reset() changes any to a valid state.
00051   a->reset();
00052   if (a->has_value()) {
00053     return AssertionFailure() << "A reset `any` should be valueless";
00054   }
00055   if (a->type() != typeid(void)) {
00056     return AssertionFailure() << "A reset `any` should have type() of `void`, "
00057                                  "but instead has type "
00058                               << a->type().name();
00059   }
00060   try {
00061     auto unused = absl::any_cast<Thrower>(*a);
00062     static_cast<void>(unused);
00063     return AssertionFailure()
00064            << "A reset `any` should not be able to be any_cast";
00065   } catch (const absl::bad_any_cast&) {
00066   } catch (...) {
00067     return AssertionFailure()
00068            << "Unexpected exception thrown from absl::any_cast";
00069   }
00070   return AssertionSuccess();
00071 }
00072 
00073 testing::AssertionResult AnyIsEmpty(absl::any* a) {
00074   if (!a->has_value()) {
00075     return testing::AssertionSuccess();
00076   }
00077   return testing::AssertionFailure()
00078          << "a should be empty, but instead has value "
00079          << absl::any_cast<Thrower>(*a).Get();
00080 }
00081 
00082 TEST(AnyExceptionSafety, Ctors) {
00083   Thrower val(1);
00084   testing::TestThrowingCtor<absl::any>(val);
00085 
00086   Thrower copy(val);
00087   testing::TestThrowingCtor<absl::any>(copy);
00088 
00089   testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<Thrower>(), 1);
00090 
00091   testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<ThrowerVec>(),
00092                                        ThrowerList{val});
00093 
00094   testing::TestThrowingCtor<absl::any,
00095                             absl::in_place_type_t<ThrowingThrowerVec>,
00096                             ThrowerList, ThrowingAlloc>(
00097       absl::in_place_type_t<ThrowingThrowerVec>(), {val}, ThrowingAlloc());
00098 }
00099 
00100 TEST(AnyExceptionSafety, Assignment) {
00101   auto original =
00102       absl::any(absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor);
00103   auto any_is_strong = [original](absl::any* ap) {
00104     return testing::AssertionResult(ap->has_value() &&
00105                                     absl::any_cast<Thrower>(original) ==
00106                                         absl::any_cast<Thrower>(*ap));
00107   };
00108   auto any_strong_tester = testing::MakeExceptionSafetyTester()
00109                                .WithInitialValue(original)
00110                                .WithContracts(AnyInvariants, any_is_strong);
00111 
00112   Thrower val(2);
00113   absl::any any_val(val);
00114   NoThrowMoveThrower mv_val(2);
00115 
00116   auto assign_any = [&any_val](absl::any* ap) { *ap = any_val; };
00117   auto assign_val = [&val](absl::any* ap) { *ap = val; };
00118   auto move = [&val](absl::any* ap) { *ap = std::move(val); };
00119   auto move_movable = [&mv_val](absl::any* ap) { *ap = std::move(mv_val); };
00120 
00121   EXPECT_TRUE(any_strong_tester.Test(assign_any));
00122   EXPECT_TRUE(any_strong_tester.Test(assign_val));
00123   EXPECT_TRUE(any_strong_tester.Test(move));
00124   EXPECT_TRUE(any_strong_tester.Test(move_movable));
00125 
00126   auto empty_any_is_strong = [](absl::any* ap) {
00127     return testing::AssertionResult{!ap->has_value()};
00128   };
00129   auto strong_empty_any_tester =
00130       testing::MakeExceptionSafetyTester()
00131           .WithInitialValue(absl::any{})
00132           .WithContracts(AnyInvariants, empty_any_is_strong);
00133 
00134   EXPECT_TRUE(strong_empty_any_tester.Test(assign_any));
00135   EXPECT_TRUE(strong_empty_any_tester.Test(assign_val));
00136   EXPECT_TRUE(strong_empty_any_tester.Test(move));
00137 }
00138 
00139 // libstdc++ std::any fails this test
00140 #if !defined(ABSL_HAVE_STD_ANY)
00141 TEST(AnyExceptionSafety, Emplace) {
00142   auto initial_val =
00143       absl::any{absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor};
00144   auto one_tester = testing::MakeExceptionSafetyTester()
00145                         .WithInitialValue(initial_val)
00146                         .WithContracts(AnyInvariants, AnyIsEmpty);
00147 
00148   auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); };
00149   auto emp_throwervec = [](absl::any* ap) {
00150     std::initializer_list<Thrower> il{Thrower(2, testing::nothrow_ctor)};
00151     ap->emplace<ThrowerVec>(il);
00152   };
00153   auto emp_movethrower = [](absl::any* ap) {
00154     ap->emplace<NoThrowMoveThrower>(2);
00155   };
00156 
00157   EXPECT_TRUE(one_tester.Test(emp_thrower));
00158   EXPECT_TRUE(one_tester.Test(emp_throwervec));
00159   EXPECT_TRUE(one_tester.Test(emp_movethrower));
00160 
00161   auto empty_tester = one_tester.WithInitialValue(absl::any{});
00162 
00163   EXPECT_TRUE(empty_tester.Test(emp_thrower));
00164   EXPECT_TRUE(empty_tester.Test(emp_throwervec));
00165 }
00166 #endif  // ABSL_HAVE_STD_ANY
00167 
00168 }  // namespace


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14