Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
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
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 }