abseil-cpp/absl/cleanup/cleanup_test.cc
Go to the documentation of this file.
1 // Copyright 2021 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/cleanup/cleanup.h"
16 
17 #include <functional>
18 #include <type_traits>
19 #include <utility>
20 
21 #include "gtest/gtest.h"
22 #include "absl/base/config.h"
23 #include "absl/utility/utility.h"
24 
25 namespace {
26 
28 
29 template <typename Type1, typename Type2>
30 constexpr bool IsSame() {
32 }
33 
34 struct IdentityFactory {
35  template <typename Callback>
36  static Callback AsCallback(Callback callback) {
37  return Callback(std::move(callback));
38  }
39 };
40 
41 // `FunctorClass` is a type used for testing `absl::Cleanup`. It is intended to
42 // represent users that make their own move-only callback types outside of
43 // `std::function` and lambda literals.
44 class FunctorClass {
45  using Callback = std::function<void()>;
46 
47  public:
48  explicit FunctorClass(Callback callback) : callback_(std::move(callback)) {}
49 
50  FunctorClass(FunctorClass&& other)
51  : callback_(absl::exchange(other.callback_, Callback())) {}
52 
53  FunctorClass(const FunctorClass&) = delete;
54 
55  FunctorClass& operator=(const FunctorClass&) = delete;
56 
57  FunctorClass& operator=(FunctorClass&&) = delete;
58 
59  void operator()() const& = delete;
60 
61  void operator()() && {
62  ASSERT_TRUE(callback_);
63  callback_();
64  callback_ = nullptr;
65  }
66 
67  private:
68  Callback callback_;
69 };
70 
71 struct FunctorClassFactory {
72  template <typename Callback>
73  static FunctorClass AsCallback(Callback callback) {
74  return FunctorClass(std::move(callback));
75  }
76 };
77 
78 struct StdFunctionFactory {
79  template <typename Callback>
80  static std::function<void()> AsCallback(Callback callback) {
81  return std::function<void()>(std::move(callback));
82  }
83 };
84 
85 using CleanupTestParams =
87 template <typename>
88 struct CleanupTest : public ::testing::Test {};
89 TYPED_TEST_SUITE(CleanupTest, CleanupTestParams);
90 
91 bool fn_ptr_called = false;
92 void FnPtrFunction() { fn_ptr_called = true; }
93 
94 TYPED_TEST(CleanupTest, FactoryProducesCorrectType) {
95  {
96  auto callback = TypeParam::AsCallback([] {});
98 
99  static_assert(
100  IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),
101  "");
102  }
103 
104  {
105  auto cleanup = absl::MakeCleanup(&FnPtrFunction);
106 
107  static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
108  "");
109  }
110 
111  {
112  auto cleanup = absl::MakeCleanup(FnPtrFunction);
113 
114  static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
115  "");
116  }
117 }
118 
119 #if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
120 TYPED_TEST(CleanupTest, CTADProducesCorrectType) {
121  {
122  auto callback = TypeParam::AsCallback([] {});
124 
125  static_assert(
126  IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),
127  "");
128  }
129 
130  {
131  absl::Cleanup cleanup = &FnPtrFunction;
132 
133  static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
134  "");
135  }
136 
137  {
138  absl::Cleanup cleanup = FnPtrFunction;
139 
140  static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
141  "");
142  }
143 }
144 
145 TYPED_TEST(CleanupTest, FactoryAndCTADProduceSameType) {
146  {
147  auto callback = IdentityFactory::AsCallback([] {});
148  auto factory_cleanup = absl::MakeCleanup(callback);
149  absl::Cleanup deduction_cleanup = callback;
150 
151  static_assert(
152  IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
153  }
154 
155  {
156  auto factory_cleanup =
157  absl::MakeCleanup(FunctorClassFactory::AsCallback([] {}));
158  absl::Cleanup deduction_cleanup = FunctorClassFactory::AsCallback([] {});
159 
160  static_assert(
161  IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
162  }
163 
164  {
165  auto factory_cleanup =
166  absl::MakeCleanup(StdFunctionFactory::AsCallback([] {}));
167  absl::Cleanup deduction_cleanup = StdFunctionFactory::AsCallback([] {});
168 
169  static_assert(
170  IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
171  }
172 
173  {
174  auto factory_cleanup = absl::MakeCleanup(&FnPtrFunction);
175  absl::Cleanup deduction_cleanup = &FnPtrFunction;
176 
177  static_assert(
178  IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
179  }
180 
181  {
182  auto factory_cleanup = absl::MakeCleanup(FnPtrFunction);
183  absl::Cleanup deduction_cleanup = FnPtrFunction;
184 
185  static_assert(
186  IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
187  }
188 }
189 #endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
190 
191 TYPED_TEST(CleanupTest, BasicUsage) {
192  bool called = false;
193 
194  {
195  auto cleanup =
196  absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
197  EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
198  }
199 
200  EXPECT_TRUE(called); // Destructor should invoke the callback
201 }
202 
203 TYPED_TEST(CleanupTest, BasicUsageWithFunctionPointer) {
204  fn_ptr_called = false;
205 
206  {
207  auto cleanup = absl::MakeCleanup(TypeParam::AsCallback(&FnPtrFunction));
208  EXPECT_FALSE(fn_ptr_called); // Constructor shouldn't invoke the callback
209  }
210 
211  EXPECT_TRUE(fn_ptr_called); // Destructor should invoke the callback
212 }
213 
214 TYPED_TEST(CleanupTest, Cancel) {
215  bool called = false;
216 
217  {
218  auto cleanup =
219  absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
220  EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
221 
222  std::move(cleanup).Cancel();
223  EXPECT_FALSE(called); // Cancel shouldn't invoke the callback
224  }
225 
226  EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
227 }
228 
229 TYPED_TEST(CleanupTest, Invoke) {
230  bool called = false;
231 
232  {
233  auto cleanup =
234  absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
235  EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
236 
237  std::move(cleanup).Invoke();
238  EXPECT_TRUE(called); // Invoke should invoke the callback
239 
240  called = false; // Reset tracker before destructor runs
241  }
242 
243  EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
244 }
245 
246 TYPED_TEST(CleanupTest, Move) {
247  bool called = false;
248 
249  {
250  auto moved_from_cleanup =
251  absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
252  EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
253 
254  {
255  auto moved_to_cleanup = std::move(moved_from_cleanup);
256  EXPECT_FALSE(called); // Move shouldn't invoke the callback
257  }
258 
259  EXPECT_TRUE(called); // Destructor should invoke the callback
260 
261  called = false; // Reset tracker before destructor runs
262  }
263 
264  EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
265 }
266 
267 int DestructionCount = 0;
268 
269 struct DestructionCounter {
270  void operator()() {}
271 
272  ~DestructionCounter() { ++DestructionCount; }
273 };
274 
275 TYPED_TEST(CleanupTest, DestructorDestroys) {
276  {
277  auto cleanup =
278  absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
279  DestructionCount = 0;
280  }
281 
282  EXPECT_EQ(DestructionCount, 1); // Engaged cleanup destroys
283 }
284 
285 TYPED_TEST(CleanupTest, CancelDestroys) {
286  {
287  auto cleanup =
288  absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
289  DestructionCount = 0;
290 
291  std::move(cleanup).Cancel();
292  EXPECT_EQ(DestructionCount, 1); // Cancel destroys
293  }
294 
295  EXPECT_EQ(DestructionCount, 1); // Canceled cleanup does not double destroy
296 }
297 
298 TYPED_TEST(CleanupTest, InvokeDestroys) {
299  {
300  auto cleanup =
301  absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
302  DestructionCount = 0;
303 
304  std::move(cleanup).Invoke();
305  EXPECT_EQ(DestructionCount, 1); // Invoke destroys
306  }
307 
308  EXPECT_EQ(DestructionCount, 1); // Invoked cleanup does not double destroy
309 }
310 
311 } // namespace
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
const
#define const
Definition: bloaty/third_party/zlib/zconf.h:230
absl::MakeCleanup
absl::Cleanup< cleanup_internal::Tag, Callback > MakeCleanup(Callback callback)
Definition: abseil-cpp/absl/cleanup/cleanup.h:127
run_xds_tests.delete
delete
Definition: run_xds_tests.py:3329
testing::Test
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:402
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
testing::internal::ProxyTypeList
Definition: googletest/googletest/include/gtest/internal/gtest-type-util.h:155
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
TYPED_TEST
#define TYPED_TEST(CaseName, TestName)
Definition: googletest/googletest/include/gtest/gtest-typed-test.h:197
opencensus.proto.stats.v1.stats_pb2.Tag
Tag
Definition: stats_pb2.py:431
callback
static void callback(void *arg, int status, int timeouts, struct hostent *host)
Definition: acountry.c:224
value
const char * value
Definition: hpack_parser_table.cc:165
TYPED_TEST_SUITE
#define TYPED_TEST_SUITE(CaseName, Types,...)
Definition: googletest/googletest/include/gtest/gtest-typed-test.h:191
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
ASSERT_TRUE
#define ASSERT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1973
testing::Invoke
std::decay< FunctionImpl >::type Invoke(FunctionImpl &&function_impl)
Definition: bloaty/third_party/googletest/googlemock/include/gmock/gmock-actions.h:1084
absl::Cleanup
Definition: abseil-cpp/absl/cleanup/cleanup.h:81
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1967
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
cleanup
Definition: cleanup.py:1
function
std::function< bool(GrpcTool *, int, const char **, const CliCredentials &, GrpcToolOutputCallback)> function
Definition: grpc_tool.cc:250
absl::exchange
T exchange(T &obj, U &&new_value)
Definition: abseil-cpp/absl/utility/utility.h:314


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:54