any_exception_safety_test.cc
Go to the documentation of this file.
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 <typeinfo>
18 #include <vector>
19 
20 #include "gtest/gtest.h"
22 
24 using NoThrowMoveThrower =
26 using ThrowerList = std::initializer_list<Thrower>;
27 using ThrowerVec = std::vector<Thrower>;
29 using ThrowingThrowerVec = std::vector<Thrower, ThrowingAlloc>;
30 
31 namespace {
32 
33 testing::AssertionResult AnyInvariants(absl::any* a) {
34  using testing::AssertionFailure;
35  using testing::AssertionSuccess;
36 
37  if (a->has_value()) {
38  if (a->type() == typeid(void)) {
39  return AssertionFailure()
40  << "A non-empty any should not have type `void`";
41  }
42  } else {
43  if (a->type() != typeid(void)) {
44  return AssertionFailure()
45  << "An empty any should have type void, but has type "
46  << a->type().name();
47  }
48  }
49 
50  // Make sure that reset() changes any to a valid state.
51  a->reset();
52  if (a->has_value()) {
53  return AssertionFailure() << "A reset `any` should be valueless";
54  }
55  if (a->type() != typeid(void)) {
56  return AssertionFailure() << "A reset `any` should have type() of `void`, "
57  "but instead has type "
58  << a->type().name();
59  }
60  try {
61  auto unused = absl::any_cast<Thrower>(*a);
62  static_cast<void>(unused);
63  return AssertionFailure()
64  << "A reset `any` should not be able to be any_cast";
65  } catch (const absl::bad_any_cast&) {
66  } catch (...) {
67  return AssertionFailure()
68  << "Unexpected exception thrown from absl::any_cast";
69  }
70  return AssertionSuccess();
71 }
72 
73 testing::AssertionResult AnyIsEmpty(absl::any* a) {
74  if (!a->has_value()) {
75  return testing::AssertionSuccess();
76  }
77  return testing::AssertionFailure()
78  << "a should be empty, but instead has value "
79  << absl::any_cast<Thrower>(*a).Get();
80 }
81 
82 TEST(AnyExceptionSafety, Ctors) {
83  Thrower val(1);
84  testing::TestThrowingCtor<absl::any>(val);
85 
86  Thrower copy(val);
87  testing::TestThrowingCtor<absl::any>(copy);
88 
89  testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<Thrower>(), 1);
90 
91  testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<ThrowerVec>(),
92  ThrowerList{val});
93 
97  absl::in_place_type_t<ThrowingThrowerVec>(), {val}, ThrowingAlloc());
98 }
99 
100 TEST(AnyExceptionSafety, Assignment) {
101  auto original =
103  auto any_is_strong = [original](absl::any* ap) {
104  return testing::AssertionResult(ap->has_value() &&
105  absl::any_cast<Thrower>(original) ==
106  absl::any_cast<Thrower>(*ap));
107  };
108  auto any_strong_tester = testing::MakeExceptionSafetyTester()
109  .WithInitialValue(original)
110  .WithContracts(AnyInvariants, any_is_strong);
111 
112  Thrower val(2);
113  absl::any any_val(val);
114  NoThrowMoveThrower mv_val(2);
115 
116  auto assign_any = [&any_val](absl::any* ap) { *ap = any_val; };
117  auto assign_val = [&val](absl::any* ap) { *ap = val; };
118  auto move = [&val](absl::any* ap) { *ap = std::move(val); };
119  auto move_movable = [&mv_val](absl::any* ap) { *ap = std::move(mv_val); };
120 
121  EXPECT_TRUE(any_strong_tester.Test(assign_any));
122  EXPECT_TRUE(any_strong_tester.Test(assign_val));
123  EXPECT_TRUE(any_strong_tester.Test(move));
124  EXPECT_TRUE(any_strong_tester.Test(move_movable));
125 
126  auto empty_any_is_strong = [](absl::any* ap) {
127  return testing::AssertionResult{!ap->has_value()};
128  };
129  auto strong_empty_any_tester =
132  .WithContracts(AnyInvariants, empty_any_is_strong);
133 
134  EXPECT_TRUE(strong_empty_any_tester.Test(assign_any));
135  EXPECT_TRUE(strong_empty_any_tester.Test(assign_val));
136  EXPECT_TRUE(strong_empty_any_tester.Test(move));
137 }
138 
139 // libstdc++ std::any fails this test
140 #if !defined(ABSL_HAVE_STD_ANY)
141 TEST(AnyExceptionSafety, Emplace) {
142  auto initial_val =
144  auto one_tester = testing::MakeExceptionSafetyTester()
145  .WithInitialValue(initial_val)
146  .WithContracts(AnyInvariants, AnyIsEmpty);
147 
148  auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); };
149  auto emp_throwervec = [](absl::any* ap) {
150  std::initializer_list<Thrower> il{Thrower(2, testing::nothrow_ctor)};
151  ap->emplace<ThrowerVec>(il);
152  };
153  auto emp_movethrower = [](absl::any* ap) {
154  ap->emplace<NoThrowMoveThrower>(2);
155  };
156 
157  EXPECT_TRUE(one_tester.Test(emp_thrower));
158  EXPECT_TRUE(one_tester.Test(emp_throwervec));
159  EXPECT_TRUE(one_tester.Test(emp_movethrower));
160 
161  auto empty_tester = one_tester.WithInitialValue(absl::any{});
162 
163  EXPECT_TRUE(empty_tester.Test(emp_thrower));
164  EXPECT_TRUE(empty_tester.Test(emp_throwervec));
165 }
166 #endif // ABSL_HAVE_STD_ANY
167 
168 } // namespace
void reset() noexcept
Definition: any.h:352
std::vector< Thrower, ThrowingAlloc > ThrowingThrowerVec
bool has_value() const noexcept
Definition: any.h:365
void TestThrowingCtor(Args &&... args)
exceptions_internal::ExceptionSafetyTestBuilder MakeExceptionSafetyTester()
testing::ThrowingValue<> Thrower
void(*)(utility_internal::InPlaceTypeTag< T >) in_place_type_t
Definition: utility.h:189
testing::ThrowingAllocator< Thrower > ThrowingAlloc
Definition: any.h:214
ValueType any_cast(const any &operand)
Definition: any.h:479
const std::type_info & type() const noexcept
Definition: any.h:370
exceptions_internal::NoThrowTag nothrow_ctor
TEST(Symbolize, Unimplemented)
ExceptionSafetyTestBuilder< DefaultFactory< T >, Operation, Contracts... > WithInitialValue(const T &t) const
std::initializer_list< Thrower > ThrowerList
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: utility.h:219
std::vector< Thrower > ThrowerVec


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:17