abseil-cpp/absl/base/exception_safety_testing_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/base/internal/exception_safety_testing.h"
16 
17 #ifdef ABSL_HAVE_EXCEPTIONS
18 
19 #include <cstddef>
20 #include <exception>
21 #include <iostream>
22 #include <list>
23 #include <type_traits>
24 #include <vector>
25 
26 #include "gtest/gtest-spi.h"
27 #include "gtest/gtest.h"
28 #include "absl/memory/memory.h"
29 
30 namespace testing {
31 
32 namespace {
33 
34 using ::testing::exceptions_internal::SetCountdown;
35 using ::testing::exceptions_internal::TestException;
36 using ::testing::exceptions_internal::UnsetCountdown;
37 
38 // EXPECT_NO_THROW can't inspect the thrown inspection in general.
39 template <typename F>
40 void ExpectNoThrow(const F& f) {
41  try {
42  f();
43  } catch (const TestException& e) {
44  ADD_FAILURE() << "Unexpected exception thrown from " << e.what();
45  }
46 }
47 
48 TEST(ThrowingValueTest, Throws) {
49  SetCountdown();
50  EXPECT_THROW(ThrowingValue<> bomb, TestException);
51 
52  // It's not guaranteed that every operator only throws *once*. The default
53  // ctor only throws once, though, so use it to make sure we only throw when
54  // the countdown hits 0
55  SetCountdown(2);
56  ExpectNoThrow([]() { ThrowingValue<> bomb; });
57  ExpectNoThrow([]() { ThrowingValue<> bomb; });
58  EXPECT_THROW(ThrowingValue<> bomb, TestException);
59 
60  UnsetCountdown();
61 }
62 
63 // Tests that an operation throws when the countdown is at 0, doesn't throw when
64 // the countdown doesn't hit 0, and doesn't modify the state of the
65 // ThrowingValue if it throws
66 template <typename F>
67 void TestOp(const F& f) {
68  ExpectNoThrow(f);
69 
70  SetCountdown();
71  EXPECT_THROW(f(), TestException);
72  UnsetCountdown();
73 }
74 
75 TEST(ThrowingValueTest, ThrowingCtors) {
76  ThrowingValue<> bomb;
77 
78  TestOp([]() { ThrowingValue<> bomb(1); });
79  TestOp([&]() { ThrowingValue<> bomb1 = bomb; });
80  TestOp([&]() { ThrowingValue<> bomb1 = std::move(bomb); });
81 }
82 
83 TEST(ThrowingValueTest, ThrowingAssignment) {
84  ThrowingValue<> bomb, bomb1;
85 
86  TestOp([&]() { bomb = bomb1; });
87  TestOp([&]() { bomb = std::move(bomb1); });
88 
89  // Test that when assignment throws, the assignment should fail (lhs != rhs)
90  // and strong guarantee fails (lhs != lhs_copy).
91  {
92  ThrowingValue<> lhs(39), rhs(42);
93  ThrowingValue<> lhs_copy(lhs);
94  SetCountdown();
95  EXPECT_THROW(lhs = rhs, TestException);
96  UnsetCountdown();
97  EXPECT_NE(lhs, rhs);
98  EXPECT_NE(lhs_copy, lhs);
99  }
100  {
101  ThrowingValue<> lhs(39), rhs(42);
102  ThrowingValue<> lhs_copy(lhs), rhs_copy(rhs);
103  SetCountdown();
104  EXPECT_THROW(lhs = std::move(rhs), TestException);
105  UnsetCountdown();
106  EXPECT_NE(lhs, rhs_copy);
107  EXPECT_NE(lhs_copy, lhs);
108  }
109 }
110 
111 TEST(ThrowingValueTest, ThrowingComparisons) {
112  ThrowingValue<> bomb1, bomb2;
113  TestOp([&]() { return bomb1 == bomb2; });
114  TestOp([&]() { return bomb1 != bomb2; });
115  TestOp([&]() { return bomb1 < bomb2; });
116  TestOp([&]() { return bomb1 <= bomb2; });
117  TestOp([&]() { return bomb1 > bomb2; });
118  TestOp([&]() { return bomb1 >= bomb2; });
119 }
120 
121 TEST(ThrowingValueTest, ThrowingArithmeticOps) {
122  ThrowingValue<> bomb1(1), bomb2(2);
123 
124  TestOp([&bomb1]() { +bomb1; });
125  TestOp([&bomb1]() { -bomb1; });
126  TestOp([&bomb1]() { ++bomb1; });
127  TestOp([&bomb1]() { bomb1++; });
128  TestOp([&bomb1]() { --bomb1; });
129  TestOp([&bomb1]() { bomb1--; });
130 
131  TestOp([&]() { bomb1 + bomb2; });
132  TestOp([&]() { bomb1 - bomb2; });
133  TestOp([&]() { bomb1* bomb2; });
134  TestOp([&]() { bomb1 / bomb2; });
135  TestOp([&]() { bomb1 << 1; });
136  TestOp([&]() { bomb1 >> 1; });
137 }
138 
139 TEST(ThrowingValueTest, ThrowingLogicalOps) {
140  ThrowingValue<> bomb1, bomb2;
141 
142  TestOp([&bomb1]() { !bomb1; });
143  TestOp([&]() { bomb1&& bomb2; });
144  TestOp([&]() { bomb1 || bomb2; });
145 }
146 
147 TEST(ThrowingValueTest, ThrowingBitwiseOps) {
148  ThrowingValue<> bomb1, bomb2;
149 
150  TestOp([&bomb1]() { ~bomb1; });
151  TestOp([&]() { bomb1& bomb2; });
152  TestOp([&]() { bomb1 | bomb2; });
153  TestOp([&]() { bomb1 ^ bomb2; });
154 }
155 
156 TEST(ThrowingValueTest, ThrowingCompoundAssignmentOps) {
157  ThrowingValue<> bomb1(1), bomb2(2);
158 
159  TestOp([&]() { bomb1 += bomb2; });
160  TestOp([&]() { bomb1 -= bomb2; });
161  TestOp([&]() { bomb1 *= bomb2; });
162  TestOp([&]() { bomb1 /= bomb2; });
163  TestOp([&]() { bomb1 %= bomb2; });
164  TestOp([&]() { bomb1 &= bomb2; });
165  TestOp([&]() { bomb1 |= bomb2; });
166  TestOp([&]() { bomb1 ^= bomb2; });
167  TestOp([&]() { bomb1 *= bomb2; });
168 }
169 
170 TEST(ThrowingValueTest, ThrowingStreamOps) {
171  ThrowingValue<> bomb;
172 
173  TestOp([&]() {
174  std::istringstream stream;
175  stream >> bomb;
176  });
177  TestOp([&]() {
178  std::stringstream stream;
179  stream << bomb;
180  });
181 }
182 
183 // Tests the operator<< of ThrowingValue by forcing ConstructorTracker to emit
184 // a nonfatal failure that contains the string representation of the Thrower
185 TEST(ThrowingValueTest, StreamOpsOutput) {
186  using ::testing::TypeSpec;
187  exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
188 
189  // Test default spec list (kEverythingThrows)
191  {
192  using Thrower = ThrowingValue<TypeSpec{}>;
193  auto thrower = Thrower(123);
194  thrower.~Thrower();
195  },
196  "ThrowingValue<>(123)");
197 
198  // Test with one item in spec list (kNoThrowCopy)
200  {
201  using Thrower = ThrowingValue<TypeSpec::kNoThrowCopy>;
202  auto thrower = Thrower(234);
203  thrower.~Thrower();
204  },
205  "ThrowingValue<kNoThrowCopy>(234)");
206 
207  // Test with multiple items in spec list (kNoThrowMove, kNoThrowNew)
209  {
210  using Thrower =
211  ThrowingValue<TypeSpec::kNoThrowMove | TypeSpec::kNoThrowNew>;
212  auto thrower = Thrower(345);
213  thrower.~Thrower();
214  },
215  "ThrowingValue<kNoThrowMove | kNoThrowNew>(345)");
216 
217  // Test with all items in spec list (kNoThrowCopy, kNoThrowMove, kNoThrowNew)
219  {
220  using Thrower = ThrowingValue<static_cast<TypeSpec>(-1)>;
221  auto thrower = Thrower(456);
222  thrower.~Thrower();
223  },
224  "ThrowingValue<kNoThrowCopy | kNoThrowMove | kNoThrowNew>(456)");
225 }
226 
227 template <typename F>
228 void TestAllocatingOp(const F& f) {
229  ExpectNoThrow(f);
230 
231  SetCountdown();
232  EXPECT_THROW(f(), exceptions_internal::TestBadAllocException);
233  UnsetCountdown();
234 }
235 
236 TEST(ThrowingValueTest, ThrowingAllocatingOps) {
237  // make_unique calls unqualified operator new, so these exercise the
238  // ThrowingValue overloads.
239  TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>>(1); });
240  TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>[]>(2); });
241 }
242 
243 TEST(ThrowingValueTest, NonThrowingMoveCtor) {
244  ThrowingValue<TypeSpec::kNoThrowMove> nothrow_ctor;
245 
246  SetCountdown();
247  ExpectNoThrow([&nothrow_ctor]() {
248  ThrowingValue<TypeSpec::kNoThrowMove> nothrow1 = std::move(nothrow_ctor);
249  });
250  UnsetCountdown();
251 }
252 
253 TEST(ThrowingValueTest, NonThrowingMoveAssign) {
254  ThrowingValue<TypeSpec::kNoThrowMove> nothrow_assign1, nothrow_assign2;
255 
256  SetCountdown();
257  ExpectNoThrow([&nothrow_assign1, &nothrow_assign2]() {
258  nothrow_assign1 = std::move(nothrow_assign2);
259  });
260  UnsetCountdown();
261 }
262 
263 TEST(ThrowingValueTest, ThrowingCopyCtor) {
264  ThrowingValue<> tv;
265 
266  TestOp([&]() { ThrowingValue<> tv_copy(tv); });
267 }
268 
269 TEST(ThrowingValueTest, ThrowingCopyAssign) {
270  ThrowingValue<> tv1, tv2;
271 
272  TestOp([&]() { tv1 = tv2; });
273 }
274 
275 TEST(ThrowingValueTest, NonThrowingCopyCtor) {
276  ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_ctor;
277 
278  SetCountdown();
279  ExpectNoThrow([&nothrow_ctor]() {
280  ThrowingValue<TypeSpec::kNoThrowCopy> nothrow1(nothrow_ctor);
281  });
282  UnsetCountdown();
283 }
284 
285 TEST(ThrowingValueTest, NonThrowingCopyAssign) {
286  ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_assign1, nothrow_assign2;
287 
288  SetCountdown();
289  ExpectNoThrow([&nothrow_assign1, &nothrow_assign2]() {
290  nothrow_assign1 = nothrow_assign2;
291  });
292  UnsetCountdown();
293 }
294 
295 TEST(ThrowingValueTest, ThrowingSwap) {
296  ThrowingValue<> bomb1, bomb2;
297  TestOp([&]() { std::swap(bomb1, bomb2); });
298 }
299 
300 TEST(ThrowingValueTest, NonThrowingSwap) {
301  ThrowingValue<TypeSpec::kNoThrowMove> bomb1, bomb2;
302  ExpectNoThrow([&]() { std::swap(bomb1, bomb2); });
303 }
304 
305 TEST(ThrowingValueTest, NonThrowingAllocation) {
306  ThrowingValue<TypeSpec::kNoThrowNew>* allocated;
307  ThrowingValue<TypeSpec::kNoThrowNew>* array;
308 
309  ExpectNoThrow([&allocated]() {
310  allocated = new ThrowingValue<TypeSpec::kNoThrowNew>(1);
311  delete allocated;
312  });
313  ExpectNoThrow([&array]() {
314  array = new ThrowingValue<TypeSpec::kNoThrowNew>[2];
315  delete[] array;
316  });
317 }
318 
319 TEST(ThrowingValueTest, NonThrowingDelete) {
320  auto* allocated = new ThrowingValue<>(1);
321  auto* array = new ThrowingValue<>[2];
322 
323  SetCountdown();
324  ExpectNoThrow([allocated]() { delete allocated; });
325  SetCountdown();
326  ExpectNoThrow([array]() { delete[] array; });
327 
328  UnsetCountdown();
329 }
330 
331 TEST(ThrowingValueTest, NonThrowingPlacementDelete) {
332  constexpr int kArrayLen = 2;
333  // We intentionally create extra space to store the tag allocated by placement
334  // new[].
335  constexpr int kStorageLen = 4;
336 
337  alignas(ThrowingValue<>) unsigned char buf[sizeof(ThrowingValue<>)];
338  alignas(ThrowingValue<>) unsigned char
339  array_buf[sizeof(ThrowingValue<>[kStorageLen])];
340  auto* placed = new (&buf) ThrowingValue<>(1);
341  auto placed_array = new (&array_buf) ThrowingValue<>[kArrayLen];
342 
343  SetCountdown();
344  ExpectNoThrow([placed, &buf]() {
345  placed->~ThrowingValue<>();
346  ThrowingValue<>::operator delete(placed, &buf);
347  });
348 
349  SetCountdown();
350  ExpectNoThrow([&, placed_array]() {
351  for (int i = 0; i < kArrayLen; ++i) placed_array[i].~ThrowingValue<>();
352  ThrowingValue<>::operator delete[](placed_array, &array_buf);
353  });
354 
355  UnsetCountdown();
356 }
357 
358 TEST(ThrowingValueTest, NonThrowingDestructor) {
359  auto* allocated = new ThrowingValue<>();
360 
361  SetCountdown();
362  ExpectNoThrow([allocated]() { delete allocated; });
363  UnsetCountdown();
364 }
365 
366 TEST(ThrowingBoolTest, ThrowingBool) {
367  ThrowingBool t = true;
368 
369  // Test that it's contextually convertible to bool
370  if (t) { // NOLINT(whitespace/empty_if_body)
371  }
372  EXPECT_TRUE(t);
373 
374  TestOp([&]() { (void)!t; });
375 }
376 
377 TEST(ThrowingAllocatorTest, MemoryManagement) {
378  // Just exercise the memory management capabilities under LSan to make sure we
379  // don't leak.
380  ThrowingAllocator<int> int_alloc;
381  int* ip = int_alloc.allocate(1);
382  int_alloc.deallocate(ip, 1);
383  int* i_array = int_alloc.allocate(2);
384  int_alloc.deallocate(i_array, 2);
385 
386  ThrowingAllocator<ThrowingValue<>> tv_alloc;
387  ThrowingValue<>* ptr = tv_alloc.allocate(1);
388  tv_alloc.deallocate(ptr, 1);
389  ThrowingValue<>* tv_array = tv_alloc.allocate(2);
390  tv_alloc.deallocate(tv_array, 2);
391 }
392 
393 TEST(ThrowingAllocatorTest, CallsGlobalNew) {
394  ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate> nothrow_alloc;
395  ThrowingValue<>* ptr;
396 
397  SetCountdown();
398  // This will only throw if ThrowingValue::new is called.
399  ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); });
400  nothrow_alloc.deallocate(ptr, 1);
401 
402  UnsetCountdown();
403 }
404 
405 TEST(ThrowingAllocatorTest, ThrowingConstructors) {
406  ThrowingAllocator<int> int_alloc;
407  int* ip = nullptr;
408 
409  SetCountdown();
410  EXPECT_THROW(ip = int_alloc.allocate(1), TestException);
411  ExpectNoThrow([&]() { ip = int_alloc.allocate(1); });
412 
413  *ip = 1;
414  SetCountdown();
415  EXPECT_THROW(int_alloc.construct(ip, 2), TestException);
416  EXPECT_EQ(*ip, 1);
417  int_alloc.deallocate(ip, 1);
418 
419  UnsetCountdown();
420 }
421 
422 TEST(ThrowingAllocatorTest, NonThrowingConstruction) {
423  {
424  ThrowingAllocator<int, AllocSpec::kNoThrowAllocate> int_alloc;
425  int* ip = nullptr;
426 
427  SetCountdown();
428  ExpectNoThrow([&]() { ip = int_alloc.allocate(1); });
429 
430  SetCountdown();
431  ExpectNoThrow([&]() { int_alloc.construct(ip, 2); });
432 
433  EXPECT_EQ(*ip, 2);
434  int_alloc.deallocate(ip, 1);
435 
436  UnsetCountdown();
437  }
438 
439  {
440  ThrowingAllocator<int> int_alloc;
441  int* ip = nullptr;
442  ExpectNoThrow([&]() { ip = int_alloc.allocate(1); });
443  ExpectNoThrow([&]() { int_alloc.construct(ip, 2); });
444  EXPECT_EQ(*ip, 2);
445  int_alloc.deallocate(ip, 1);
446  }
447 
448  {
449  ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate>
450  nothrow_alloc;
451  ThrowingValue<>* ptr;
452 
453  SetCountdown();
454  ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); });
455 
456  SetCountdown();
457  ExpectNoThrow(
458  [&]() { nothrow_alloc.construct(ptr, 2, testing::nothrow_ctor); });
459 
460  EXPECT_EQ(ptr->Get(), 2);
461  nothrow_alloc.destroy(ptr);
462  nothrow_alloc.deallocate(ptr, 1);
463 
464  UnsetCountdown();
465  }
466 
467  {
468  ThrowingAllocator<int> a;
469 
470  SetCountdown();
471  ExpectNoThrow([&]() { ThrowingAllocator<double> a1 = a; });
472 
473  SetCountdown();
474  ExpectNoThrow([&]() { ThrowingAllocator<double> a1 = std::move(a); });
475 
476  UnsetCountdown();
477  }
478 }
479 
480 TEST(ThrowingAllocatorTest, ThrowingAllocatorConstruction) {
481  ThrowingAllocator<int> a;
482  TestOp([]() { ThrowingAllocator<int> a; });
483  TestOp([&]() { a.select_on_container_copy_construction(); });
484 }
485 
486 TEST(ThrowingAllocatorTest, State) {
487  ThrowingAllocator<int> a1, a2;
488  EXPECT_NE(a1, a2);
489 
490  auto a3 = a1;
491  EXPECT_EQ(a3, a1);
492  int* ip = a1.allocate(1);
493  EXPECT_EQ(a3, a1);
494  a3.deallocate(ip, 1);
495  EXPECT_EQ(a3, a1);
496 }
497 
498 TEST(ThrowingAllocatorTest, InVector) {
499  std::vector<ThrowingValue<>, ThrowingAllocator<ThrowingValue<>>> v;
500  for (int i = 0; i < 20; ++i) v.push_back({});
501  for (int i = 0; i < 20; ++i) v.pop_back();
502 }
503 
504 TEST(ThrowingAllocatorTest, InList) {
505  std::list<ThrowingValue<>, ThrowingAllocator<ThrowingValue<>>> l;
506  for (int i = 0; i < 20; ++i) l.push_back({});
507  for (int i = 0; i < 20; ++i) l.pop_back();
508  for (int i = 0; i < 20; ++i) l.push_front({});
509  for (int i = 0; i < 20; ++i) l.pop_front();
510 }
511 
512 template <typename TesterInstance, typename = void>
513 struct NullaryTestValidator : public std::false_type {};
514 
515 template <typename TesterInstance>
516 struct NullaryTestValidator<
517  TesterInstance,
518  absl::void_t<decltype(std::declval<TesterInstance>().Test())>>
519  : public std::true_type {};
520 
521 template <typename TesterInstance>
522 bool HasNullaryTest(const TesterInstance&) {
524 }
525 
526 void DummyOp(void*) {}
527 
528 template <typename TesterInstance, typename = void>
529 struct UnaryTestValidator : public std::false_type {};
530 
531 template <typename TesterInstance>
532 struct UnaryTestValidator<
533  TesterInstance,
534  absl::void_t<decltype(std::declval<TesterInstance>().Test(DummyOp))>>
535  : public std::true_type {};
536 
537 template <typename TesterInstance>
538 bool HasUnaryTest(const TesterInstance&) {
540 }
541 
542 TEST(ExceptionSafetyTesterTest, IncompleteTypesAreNotTestable) {
543  using T = exceptions_internal::UninitializedT;
544  auto op = [](T* t) {};
545  auto inv = [](T*) { return testing::AssertionSuccess(); };
546  auto fac = []() { return absl::make_unique<T>(); };
547 
548  // Test that providing operation and inveriants still does not allow for the
549  // the invocation of .Test() and .Test(op) because it lacks a factory
550  auto without_fac =
551  testing::MakeExceptionSafetyTester().WithOperation(op).WithContracts(
552  inv, testing::strong_guarantee);
553  EXPECT_FALSE(HasNullaryTest(without_fac));
554  EXPECT_FALSE(HasUnaryTest(without_fac));
555 
556  // Test that providing contracts and factory allows the invocation of
557  // .Test(op) but does not allow for .Test() because it lacks an operation
558  auto without_op = testing::MakeExceptionSafetyTester()
559  .WithContracts(inv, testing::strong_guarantee)
560  .WithFactory(fac);
561  EXPECT_FALSE(HasNullaryTest(without_op));
562  EXPECT_TRUE(HasUnaryTest(without_op));
563 
564  // Test that providing operation and factory still does not allow for the
565  // the invocation of .Test() and .Test(op) because it lacks contracts
566  auto without_inv =
567  testing::MakeExceptionSafetyTester().WithOperation(op).WithFactory(fac);
568  EXPECT_FALSE(HasNullaryTest(without_inv));
569  EXPECT_FALSE(HasUnaryTest(without_inv));
570 }
571 
572 struct ExampleStruct {};
573 
574 std::unique_ptr<ExampleStruct> ExampleFunctionFactory() {
575  return absl::make_unique<ExampleStruct>();
576 }
577 
578 void ExampleFunctionOperation(ExampleStruct*) {}
579 
580 testing::AssertionResult ExampleFunctionContract(ExampleStruct*) {
581  return testing::AssertionSuccess();
582 }
583 
584 struct {
585  std::unique_ptr<ExampleStruct> operator()() const {
586  return ExampleFunctionFactory();
587  }
588 } example_struct_factory;
589 
590 struct {
591  void operator()(ExampleStruct*) const {}
592 } example_struct_operation;
593 
594 struct {
595  testing::AssertionResult operator()(ExampleStruct* example_struct) const {
596  return ExampleFunctionContract(example_struct);
597  }
598 } example_struct_contract;
599 
600 auto example_lambda_factory = []() { return ExampleFunctionFactory(); };
601 
602 auto example_lambda_operation = [](ExampleStruct*) {};
603 
604 auto example_lambda_contract = [](ExampleStruct* example_struct) {
605  return ExampleFunctionContract(example_struct);
606 };
607 
608 // Testing that function references, pointers, structs with operator() and
609 // lambdas can all be used with ExceptionSafetyTester
610 TEST(ExceptionSafetyTesterTest, MixedFunctionTypes) {
611  // function reference
612  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
613  .WithFactory(ExampleFunctionFactory)
614  .WithOperation(ExampleFunctionOperation)
615  .WithContracts(ExampleFunctionContract)
616  .Test());
617 
618  // function pointer
619  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
620  .WithFactory(&ExampleFunctionFactory)
621  .WithOperation(&ExampleFunctionOperation)
622  .WithContracts(&ExampleFunctionContract)
623  .Test());
624 
625  // struct
626  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
627  .WithFactory(example_struct_factory)
628  .WithOperation(example_struct_operation)
629  .WithContracts(example_struct_contract)
630  .Test());
631 
632  // lambda
633  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
634  .WithFactory(example_lambda_factory)
635  .WithOperation(example_lambda_operation)
636  .WithContracts(example_lambda_contract)
637  .Test());
638 }
639 
640 struct NonNegative {
641  bool operator==(const NonNegative& other) const { return i == other.i; }
642  int i;
643 };
644 
645 testing::AssertionResult CheckNonNegativeInvariants(NonNegative* g) {
646  if (g->i >= 0) {
647  return testing::AssertionSuccess();
648  }
650  << "i should be non-negative but is " << g->i;
651 }
652 
653 struct {
654  template <typename T>
655  void operator()(T* t) const {
656  (*t)();
657  }
658 } invoker;
659 
660 auto tester =
661  testing::MakeExceptionSafetyTester().WithOperation(invoker).WithContracts(
662  CheckNonNegativeInvariants);
663 auto strong_tester = tester.WithContracts(testing::strong_guarantee);
664 
665 struct FailsBasicGuarantee : public NonNegative {
666  void operator()() {
667  --i;
668  ThrowingValue<> bomb;
669  ++i;
670  }
671 };
672 
673 TEST(ExceptionCheckTest, BasicGuaranteeFailure) {
674  EXPECT_FALSE(tester.WithInitialValue(FailsBasicGuarantee{}).Test());
675 }
676 
677 struct FollowsBasicGuarantee : public NonNegative {
678  void operator()() {
679  ++i;
680  ThrowingValue<> bomb;
681  }
682 };
683 
684 TEST(ExceptionCheckTest, BasicGuarantee) {
685  EXPECT_TRUE(tester.WithInitialValue(FollowsBasicGuarantee{}).Test());
686 }
687 
688 TEST(ExceptionCheckTest, StrongGuaranteeFailure) {
689  EXPECT_FALSE(strong_tester.WithInitialValue(FailsBasicGuarantee{}).Test());
690  EXPECT_FALSE(strong_tester.WithInitialValue(FollowsBasicGuarantee{}).Test());
691 }
692 
693 struct BasicGuaranteeWithExtraContracts : public NonNegative {
694  // After operator(), i is incremented. If operator() throws, i is set to 9999
695  void operator()() {
696  int old_i = i;
697  i = kExceptionSentinel;
698  ThrowingValue<> bomb;
699  i = ++old_i;
700  }
701 
702  static constexpr int kExceptionSentinel = 9999;
703 };
704 
705 #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
706 constexpr int BasicGuaranteeWithExtraContracts::kExceptionSentinel;
707 #endif
708 
709 TEST(ExceptionCheckTest, BasicGuaranteeWithExtraContracts) {
710  auto tester_with_val =
711  tester.WithInitialValue(BasicGuaranteeWithExtraContracts{});
712  EXPECT_TRUE(tester_with_val.Test());
713  EXPECT_TRUE(
714  tester_with_val
715  .WithContracts([](BasicGuaranteeWithExtraContracts* o) {
716  if (o->i == BasicGuaranteeWithExtraContracts::kExceptionSentinel) {
717  return testing::AssertionSuccess();
718  }
720  << "i should be "
721  << BasicGuaranteeWithExtraContracts::kExceptionSentinel
722  << ", but is " << o->i;
723  })
724  .Test());
725 }
726 
727 struct FollowsStrongGuarantee : public NonNegative {
728  void operator()() { ThrowingValue<> bomb; }
729 };
730 
731 TEST(ExceptionCheckTest, StrongGuarantee) {
732  EXPECT_TRUE(tester.WithInitialValue(FollowsStrongGuarantee{}).Test());
733  EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{}).Test());
734 }
735 
736 struct HasReset : public NonNegative {
737  void operator()() {
738  i = -1;
739  ThrowingValue<> bomb;
740  i = 1;
741  }
742 
743  void reset() { i = 0; }
744 };
745 
746 testing::AssertionResult CheckHasResetContracts(HasReset* h) {
747  h->reset();
748  return testing::AssertionResult(h->i == 0);
749 }
750 
751 TEST(ExceptionCheckTest, ModifyingChecker) {
752  auto set_to_1000 = [](FollowsBasicGuarantee* g) {
753  g->i = 1000;
754  return testing::AssertionSuccess();
755  };
756  auto is_1000 = [](FollowsBasicGuarantee* g) {
757  return testing::AssertionResult(g->i == 1000);
758  };
759  auto increment = [](FollowsStrongGuarantee* g) {
760  ++g->i;
761  return testing::AssertionSuccess();
762  };
763 
764  EXPECT_FALSE(tester.WithInitialValue(FollowsBasicGuarantee{})
765  .WithContracts(set_to_1000, is_1000)
766  .Test());
767  EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{})
768  .WithContracts(increment)
769  .Test());
770  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
771  .WithInitialValue(HasReset{})
772  .WithContracts(CheckHasResetContracts)
773  .Test(invoker));
774 }
775 
776 TEST(ExceptionSafetyTesterTest, ResetsCountdown) {
777  auto test =
778  testing::MakeExceptionSafetyTester()
779  .WithInitialValue(ThrowingValue<>())
780  .WithContracts([](ThrowingValue<>*) { return AssertionSuccess(); })
781  .WithOperation([](ThrowingValue<>*) {});
782  ASSERT_TRUE(test.Test());
783  // If the countdown isn't reset because there were no exceptions thrown, then
784  // this will fail with a termination from an unhandled exception
785  EXPECT_TRUE(test.Test());
786 }
787 
788 struct NonCopyable : public NonNegative {
789  NonCopyable(const NonCopyable&) = delete;
790  NonCopyable() : NonNegative{0} {}
791 
792  void operator()() { ThrowingValue<> bomb; }
793 };
794 
795 TEST(ExceptionCheckTest, NonCopyable) {
796  auto factory = []() { return absl::make_unique<NonCopyable>(); };
797  EXPECT_TRUE(tester.WithFactory(factory).Test());
798  EXPECT_TRUE(strong_tester.WithFactory(factory).Test());
799 }
800 
801 struct NonEqualityComparable : public NonNegative {
802  void operator()() { ThrowingValue<> bomb; }
803 
804  void ModifyOnThrow() {
805  ++i;
806  ThrowingValue<> bomb;
807  static_cast<void>(bomb);
808  --i;
809  }
810 };
811 
812 TEST(ExceptionCheckTest, NonEqualityComparable) {
813  auto nec_is_strong = [](NonEqualityComparable* nec) {
814  return testing::AssertionResult(nec->i == NonEqualityComparable().i);
815  };
816  auto strong_nec_tester = tester.WithInitialValue(NonEqualityComparable{})
817  .WithContracts(nec_is_strong);
818 
819  EXPECT_TRUE(strong_nec_tester.Test());
820  EXPECT_FALSE(strong_nec_tester.Test(
821  [](NonEqualityComparable* n) { n->ModifyOnThrow(); }));
822 }
823 
824 template <typename T>
825 struct ExhaustivenessTester {
826  void operator()() {
827  successes |= 1;
828  T b1;
829  static_cast<void>(b1);
830  successes |= (1 << 1);
831  T b2;
832  static_cast<void>(b2);
833  successes |= (1 << 2);
834  T b3;
835  static_cast<void>(b3);
836  successes |= (1 << 3);
837  }
838 
839  bool operator==(const ExhaustivenessTester<ThrowingValue<>>&) const {
840  return true;
841  }
842 
843  static unsigned char successes;
844 };
845 
846 struct {
847  template <typename T>
848  testing::AssertionResult operator()(ExhaustivenessTester<T>*) const {
849  return testing::AssertionSuccess();
850  }
851 } CheckExhaustivenessTesterContracts;
852 
853 template <typename T>
854 unsigned char ExhaustivenessTester<T>::successes = 0;
855 
856 TEST(ExceptionCheckTest, Exhaustiveness) {
857  auto exhaust_tester = testing::MakeExceptionSafetyTester()
858  .WithContracts(CheckExhaustivenessTesterContracts)
859  .WithOperation(invoker);
860 
861  EXPECT_TRUE(
862  exhaust_tester.WithInitialValue(ExhaustivenessTester<int>{}).Test());
864 
865  EXPECT_TRUE(
866  exhaust_tester.WithInitialValue(ExhaustivenessTester<ThrowingValue<>>{})
867  .WithContracts(testing::strong_guarantee)
868  .Test());
869  EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::successes, 0xF);
870 }
871 
872 struct LeaksIfCtorThrows : private exceptions_internal::TrackedObject {
873  LeaksIfCtorThrows() : TrackedObject(ABSL_PRETTY_FUNCTION) {
874  ++counter;
875  ThrowingValue<> v;
876  static_cast<void>(v);
877  --counter;
878  }
879  LeaksIfCtorThrows(const LeaksIfCtorThrows&) noexcept
880  : TrackedObject(ABSL_PRETTY_FUNCTION) {}
881  static int counter;
882 };
884 
885 TEST(ExceptionCheckTest, TestLeakyCtor) {
886  testing::TestThrowingCtor<LeaksIfCtorThrows>();
889 }
890 
891 struct Tracked : private exceptions_internal::TrackedObject {
892  Tracked() : TrackedObject(ABSL_PRETTY_FUNCTION) {}
893 };
894 
895 TEST(ConstructorTrackerTest, CreatedBefore) {
896  Tracked a, b, c;
897  exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
898 }
899 
900 TEST(ConstructorTrackerTest, CreatedAfter) {
901  exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
902  Tracked a, b, c;
903 }
904 
905 TEST(ConstructorTrackerTest, NotDestroyedAfter) {
906  alignas(Tracked) unsigned char storage[sizeof(Tracked)];
908  {
909  exceptions_internal::ConstructorTracker ct(
910  exceptions_internal::countdown);
911  new (&storage) Tracked();
912  },
913  "not destroyed");
914 }
915 
916 TEST(ConstructorTrackerTest, DestroyedTwice) {
917  exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
919  {
920  Tracked t;
921  t.~Tracked();
922  },
923  "re-destroyed");
924 }
925 
926 TEST(ConstructorTrackerTest, ConstructedTwice) {
927  exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
928  alignas(Tracked) unsigned char storage[sizeof(Tracked)];
930  {
931  new (&storage) Tracked();
932  new (&storage) Tracked();
933  reinterpret_cast<Tracked*>(&storage)->~Tracked();
934  },
935  "re-constructed");
936 }
937 
938 TEST(ThrowingValueTraitsTest, RelationalOperators) {
939  ThrowingValue<> a, b;
940  EXPECT_TRUE((std::is_convertible<decltype(a == b), bool>::value));
941  EXPECT_TRUE((std::is_convertible<decltype(a != b), bool>::value));
942  EXPECT_TRUE((std::is_convertible<decltype(a < b), bool>::value));
943  EXPECT_TRUE((std::is_convertible<decltype(a <= b), bool>::value));
944  EXPECT_TRUE((std::is_convertible<decltype(a > b), bool>::value));
945  EXPECT_TRUE((std::is_convertible<decltype(a >= b), bool>::value));
946 }
947 
948 TEST(ThrowingAllocatorTraitsTest, Assignablility) {
949  EXPECT_TRUE(absl::is_move_assignable<ThrowingAllocator<int>>::value);
950  EXPECT_TRUE(absl::is_copy_assignable<ThrowingAllocator<int>>::value);
951  EXPECT_TRUE(std::is_nothrow_move_assignable<ThrowingAllocator<int>>::value);
952  EXPECT_TRUE(std::is_nothrow_copy_assignable<ThrowingAllocator<int>>::value);
953 }
954 
955 } // namespace
956 
957 } // namespace testing
958 
959 #endif // ABSL_HAVE_EXCEPTIONS
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
testing
Definition: aws_request_signer_test.cc:25
testing::AssertionFailure
AssertionResult AssertionFailure()
Definition: bloaty/third_party/googletest/googletest/src/gtest.cc:1028
Test
void Test(StringPiece pattern, const RE2::Options &options, StringPiece text)
Definition: bloaty/third_party/re2/re2/fuzzing/re2_fuzzer.cc:20
grpc_event_engine::experimental::slice_detail::operator==
bool operator==(const BaseSlice &a, const BaseSlice &b)
Definition: include/grpc/event_engine/slice.h:117
fix_build_deps.c
list c
Definition: fix_build_deps.py:490
test
Definition: spinlock_test.cc:36
google::protobuf.internal::true_type
integral_constant< bool, true > true_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:89
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
google::protobuf.internal::false_type
integral_constant< bool, false > false_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:90
array
PHP_PROTO_OBJECT_FREE_END PHP_PROTO_OBJECT_DTOR_END intern array
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/array.c:111
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
T
#define T(upbtypeconst, upbtype, ctype, default_value)
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
o
UnboundConversion o
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:97
absl::FormatConversionChar::e
@ e
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
EXPECT_THROW
#define EXPECT_THROW(statement, expected_exception)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1951
a2
T::first_type a2
Definition: abseil-cpp/absl/container/internal/hash_function_defaults_test.cc:307
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
array
Definition: undname.c:101
b2
T::second_type b2
Definition: abseil-cpp/absl/container/internal/hash_function_defaults_test.cc:308
EXPECT_NE
#define EXPECT_NE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2028
successes
std::atomic< uint64_t > successes
Definition: outlier_detection.cc:232
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
testing::AssertionResult
Definition: cares/cares/test/gmock-1.8.0/gtest/gtest.h:18855
counter
static int counter
Definition: abseil-cpp/absl/flags/reflection_test.cc:131
std::swap
void swap(Json::Value &a, Json::Value &b)
Specialize std::swap() for Json::Value.
Definition: third_party/bloaty/third_party/protobuf/conformance/third_party/jsoncpp/json.h:1226
testing::AssertionSuccess
AssertionResult AssertionSuccess()
Definition: bloaty/third_party/googletest/googletest/src/gtest.cc:1023
a1
T::first_type a1
Definition: abseil-cpp/absl/container/internal/hash_function_defaults_test.cc:305
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
g
struct @717 g
ADD_FAILURE
#define ADD_FAILURE()
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1911
value
const char * value
Definition: hpack_parser_table.cc:165
b1
T::second_type b1
Definition: abseil-cpp/absl/container/internal/hash_function_defaults_test.cc:306
absl::void_t
typename type_traits_internal::VoidTImpl< Ts... >::type void_t
Definition: abseil-cpp/absl/meta/type_traits.h:218
absl::str_format_internal::LengthMod::t
@ t
testing::TEST
TEST(GrpcAwsRequestSignerTest, AWSOfficialExample)
Definition: aws_request_signer_test.cc:68
ASSERT_TRUE
#define ASSERT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1973
absl::is_copy_assignable
Definition: abseil-cpp/absl/meta/type_traits.h:194
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1967
absl::is_move_assignable
Definition: abseil-cpp/absl/meta/type_traits.h:199
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
EXPECT_NONFATAL_FAILURE
#define EXPECT_NONFATAL_FAILURE(statement, substr)
run_grpclb_interop_tests.l
dictionary l
Definition: run_grpclb_interop_tests.py:410
absl::str_format_internal::LengthMod::h
@ h
op
static grpc_op * op
Definition: test/core/fling/client.cc:47
absl::status_internal::storage
static ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook< StatusPayloadPrinter > storage
Definition: abseil-cpp/absl/status/status_payload_printer.cc:26
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
stream
voidpf stream
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:20