exception_safety_testing_test.cc 27 KB

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