blob: 2ed386065f0a71429d48b351bb0eca3c2d21f6ef [file] [log] [blame]
Abseil Teamff704562017-12-20 12:34:46 -08001// 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//
nik727338b70432019-03-08 10:27:53 -05007// https://www.apache.org/licenses/LICENSE-2.0
Abseil Teamff704562017-12-20 12:34:46 -08008//
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
Abseil Team8db6cfd2017-10-30 15:55:37 -070015#include "absl/base/internal/exception_safety_testing.h"
16
17#include <cstddef>
18#include <exception>
19#include <iostream>
20#include <list>
Abseil Teameed36bf2018-03-15 13:48:55 -070021#include <type_traits>
Abseil Team8db6cfd2017-10-30 15:55:37 -070022#include <vector>
23
24#include "gtest/gtest-spi.h"
25#include "gtest/gtest.h"
26#include "absl/memory/memory.h"
27
Abseil Team96136782018-04-30 11:44:26 -070028namespace testing {
29
Abseil Team8db6cfd2017-10-30 15:55:37 -070030namespace {
Abseil Team96136782018-04-30 11:44:26 -070031
32using ::testing::exceptions_internal::SetCountdown;
33using ::testing::exceptions_internal::TestException;
34using ::testing::exceptions_internal::UnsetCountdown;
Abseil Team8db6cfd2017-10-30 15:55:37 -070035
Abseil Team8db6cfd2017-10-30 15:55:37 -070036// EXPECT_NO_THROW can't inspect the thrown inspection in general.
37template <typename F>
38void ExpectNoThrow(const F& f) {
39 try {
40 f();
Abseil Team02451912018-09-11 11:22:56 -070041 } catch (const TestException& e) {
Abseil Team8db6cfd2017-10-30 15:55:37 -070042 ADD_FAILURE() << "Unexpected exception thrown from " << e.what();
43 }
44}
45
Abseil Team28f5b892018-04-26 06:47:58 -070046TEST(ThrowingValueTest, Throws) {
Abseil Team8db6cfd2017-10-30 15:55:37 -070047 SetCountdown();
48 EXPECT_THROW(ThrowingValue<> bomb, TestException);
49
50 // It's not guaranteed that every operator only throws *once*. The default
51 // ctor only throws once, though, so use it to make sure we only throw when
52 // the countdown hits 0
Abseil Teamfaf0a1b2018-04-20 09:16:52 -070053 SetCountdown(2);
Abseil Team8db6cfd2017-10-30 15:55:37 -070054 ExpectNoThrow([]() { ThrowingValue<> bomb; });
55 ExpectNoThrow([]() { ThrowingValue<> bomb; });
56 EXPECT_THROW(ThrowingValue<> bomb, TestException);
Abseil Team28f5b892018-04-26 06:47:58 -070057
58 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -070059}
60
61// Tests that an operation throws when the countdown is at 0, doesn't throw when
62// the countdown doesn't hit 0, and doesn't modify the state of the
63// ThrowingValue if it throws
64template <typename F>
Abseil Team4132ce22018-01-05 07:54:33 -080065void TestOp(const F& f) {
Abseil Team8db6cfd2017-10-30 15:55:37 -070066 ExpectNoThrow(f);
67
68 SetCountdown();
69 EXPECT_THROW(f(), TestException);
70 UnsetCountdown();
71}
72
Abseil Team28f5b892018-04-26 06:47:58 -070073TEST(ThrowingValueTest, ThrowingCtors) {
Abseil Team8db6cfd2017-10-30 15:55:37 -070074 ThrowingValue<> bomb;
75
76 TestOp([]() { ThrowingValue<> bomb(1); });
77 TestOp([&]() { ThrowingValue<> bomb1 = bomb; });
78 TestOp([&]() { ThrowingValue<> bomb1 = std::move(bomb); });
79}
80
Abseil Team28f5b892018-04-26 06:47:58 -070081TEST(ThrowingValueTest, ThrowingAssignment) {
Abseil Team8db6cfd2017-10-30 15:55:37 -070082 ThrowingValue<> bomb, bomb1;
83
84 TestOp([&]() { bomb = bomb1; });
85 TestOp([&]() { bomb = std::move(bomb1); });
Abseil Team26b789f2018-05-04 09:58:56 -070086
87 // Test that when assignment throws, the assignment should fail (lhs != rhs)
88 // and strong guarantee fails (lhs != lhs_copy).
89 {
90 ThrowingValue<> lhs(39), rhs(42);
91 ThrowingValue<> lhs_copy(lhs);
92 SetCountdown();
93 EXPECT_THROW(lhs = rhs, TestException);
94 UnsetCountdown();
95 EXPECT_NE(lhs, rhs);
96 EXPECT_NE(lhs_copy, lhs);
97 }
98 {
99 ThrowingValue<> lhs(39), rhs(42);
100 ThrowingValue<> lhs_copy(lhs), rhs_copy(rhs);
101 SetCountdown();
102 EXPECT_THROW(lhs = std::move(rhs), TestException);
103 UnsetCountdown();
104 EXPECT_NE(lhs, rhs_copy);
105 EXPECT_NE(lhs_copy, lhs);
106 }
Abseil Team8db6cfd2017-10-30 15:55:37 -0700107}
108
Abseil Team28f5b892018-04-26 06:47:58 -0700109TEST(ThrowingValueTest, ThrowingComparisons) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700110 ThrowingValue<> bomb1, bomb2;
111 TestOp([&]() { return bomb1 == bomb2; });
112 TestOp([&]() { return bomb1 != bomb2; });
113 TestOp([&]() { return bomb1 < bomb2; });
114 TestOp([&]() { return bomb1 <= bomb2; });
115 TestOp([&]() { return bomb1 > bomb2; });
116 TestOp([&]() { return bomb1 >= bomb2; });
117}
118
Abseil Team28f5b892018-04-26 06:47:58 -0700119TEST(ThrowingValueTest, ThrowingArithmeticOps) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700120 ThrowingValue<> bomb1(1), bomb2(2);
121
122 TestOp([&bomb1]() { +bomb1; });
123 TestOp([&bomb1]() { -bomb1; });
124 TestOp([&bomb1]() { ++bomb1; });
125 TestOp([&bomb1]() { bomb1++; });
126 TestOp([&bomb1]() { --bomb1; });
127 TestOp([&bomb1]() { bomb1--; });
128
129 TestOp([&]() { bomb1 + bomb2; });
130 TestOp([&]() { bomb1 - bomb2; });
131 TestOp([&]() { bomb1* bomb2; });
132 TestOp([&]() { bomb1 / bomb2; });
133 TestOp([&]() { bomb1 << 1; });
134 TestOp([&]() { bomb1 >> 1; });
135}
136
Abseil Team28f5b892018-04-26 06:47:58 -0700137TEST(ThrowingValueTest, ThrowingLogicalOps) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700138 ThrowingValue<> bomb1, bomb2;
139
140 TestOp([&bomb1]() { !bomb1; });
141 TestOp([&]() { bomb1&& bomb2; });
142 TestOp([&]() { bomb1 || bomb2; });
143}
144
Abseil Team28f5b892018-04-26 06:47:58 -0700145TEST(ThrowingValueTest, ThrowingBitwiseOps) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700146 ThrowingValue<> bomb1, bomb2;
147
148 TestOp([&bomb1]() { ~bomb1; });
149 TestOp([&]() { bomb1& bomb2; });
150 TestOp([&]() { bomb1 | bomb2; });
151 TestOp([&]() { bomb1 ^ bomb2; });
152}
153
Abseil Team28f5b892018-04-26 06:47:58 -0700154TEST(ThrowingValueTest, ThrowingCompoundAssignmentOps) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700155 ThrowingValue<> bomb1(1), bomb2(2);
156
157 TestOp([&]() { bomb1 += bomb2; });
158 TestOp([&]() { bomb1 -= bomb2; });
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}
167
Abseil Team28f5b892018-04-26 06:47:58 -0700168TEST(ThrowingValueTest, ThrowingStreamOps) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700169 ThrowingValue<> bomb;
170
Abseil Team92020a02018-06-08 08:14:48 -0700171 TestOp([&]() {
172 std::istringstream stream;
173 stream >> bomb;
174 });
175 TestOp([&]() {
176 std::stringstream stream;
177 stream << bomb;
178 });
179}
180
181// Tests the operator<< of ThrowingValue by forcing ConstructorTracker to emit
Abseil Teambed5bd62018-08-21 11:31:02 -0700182// a nonfatal failure that contains the string representation of the Thrower
Abseil Team92020a02018-06-08 08:14:48 -0700183TEST(ThrowingValueTest, StreamOpsOutput) {
184 using ::testing::TypeSpec;
185 exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
186
187 // Test default spec list (kEverythingThrows)
188 EXPECT_NONFATAL_FAILURE(
189 {
190 using Thrower = ThrowingValue<TypeSpec{}>;
191 auto thrower = Thrower(123);
192 thrower.~Thrower();
193 },
194 "ThrowingValue<>(123)");
195
196 // Test with one item in spec list (kNoThrowCopy)
197 EXPECT_NONFATAL_FAILURE(
198 {
199 using Thrower = ThrowingValue<TypeSpec::kNoThrowCopy>;
200 auto thrower = Thrower(234);
201 thrower.~Thrower();
202 },
203 "ThrowingValue<kNoThrowCopy>(234)");
204
205 // Test with multiple items in spec list (kNoThrowMove, kNoThrowNew)
206 EXPECT_NONFATAL_FAILURE(
207 {
208 using Thrower =
209 ThrowingValue<TypeSpec::kNoThrowMove | TypeSpec::kNoThrowNew>;
210 auto thrower = Thrower(345);
211 thrower.~Thrower();
212 },
213 "ThrowingValue<kNoThrowMove | kNoThrowNew>(345)");
214
215 // Test with all items in spec list (kNoThrowCopy, kNoThrowMove, kNoThrowNew)
216 EXPECT_NONFATAL_FAILURE(
217 {
218 using Thrower = ThrowingValue<static_cast<TypeSpec>(-1)>;
219 auto thrower = Thrower(456);
220 thrower.~Thrower();
221 },
222 "ThrowingValue<kNoThrowCopy | kNoThrowMove | kNoThrowNew>(456)");
Abseil Team8db6cfd2017-10-30 15:55:37 -0700223}
224
Abseil Team4132ce22018-01-05 07:54:33 -0800225template <typename F>
226void TestAllocatingOp(const F& f) {
Abseil Team4132ce22018-01-05 07:54:33 -0800227 ExpectNoThrow(f);
228
229 SetCountdown();
230 EXPECT_THROW(f(), exceptions_internal::TestBadAllocException);
231 UnsetCountdown();
232}
233
Abseil Team28f5b892018-04-26 06:47:58 -0700234TEST(ThrowingValueTest, ThrowingAllocatingOps) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700235 // make_unique calls unqualified operator new, so these exercise the
236 // ThrowingValue overloads.
Abseil Team4132ce22018-01-05 07:54:33 -0800237 TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>>(1); });
238 TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>[]>(2); });
Abseil Team8db6cfd2017-10-30 15:55:37 -0700239}
240
Abseil Team28f5b892018-04-26 06:47:58 -0700241TEST(ThrowingValueTest, NonThrowingMoveCtor) {
Abseil Team96136782018-04-30 11:44:26 -0700242 ThrowingValue<TypeSpec::kNoThrowMove> nothrow_ctor;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700243
244 SetCountdown();
245 ExpectNoThrow([&nothrow_ctor]() {
Abseil Team96136782018-04-30 11:44:26 -0700246 ThrowingValue<TypeSpec::kNoThrowMove> nothrow1 = std::move(nothrow_ctor);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700247 });
Abseil Team28f5b892018-04-26 06:47:58 -0700248 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700249}
250
Abseil Team28f5b892018-04-26 06:47:58 -0700251TEST(ThrowingValueTest, NonThrowingMoveAssign) {
Abseil Team96136782018-04-30 11:44:26 -0700252 ThrowingValue<TypeSpec::kNoThrowMove> nothrow_assign1, nothrow_assign2;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700253
254 SetCountdown();
255 ExpectNoThrow([&nothrow_assign1, &nothrow_assign2]() {
256 nothrow_assign1 = std::move(nothrow_assign2);
257 });
Abseil Team28f5b892018-04-26 06:47:58 -0700258 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700259}
260
Abseil Team96136782018-04-30 11:44:26 -0700261TEST(ThrowingValueTest, ThrowingCopyCtor) {
262 ThrowingValue<> tv;
263
264 TestOp([&]() { ThrowingValue<> tv_copy(tv); });
265}
266
267TEST(ThrowingValueTest, ThrowingCopyAssign) {
268 ThrowingValue<> tv1, tv2;
269
270 TestOp([&]() { tv1 = tv2; });
271}
272
273TEST(ThrowingValueTest, NonThrowingCopyCtor) {
274 ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_ctor;
275
276 SetCountdown();
277 ExpectNoThrow([&nothrow_ctor]() {
278 ThrowingValue<TypeSpec::kNoThrowCopy> nothrow1(nothrow_ctor);
279 });
280 UnsetCountdown();
281}
282
283TEST(ThrowingValueTest, NonThrowingCopyAssign) {
284 ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_assign1, nothrow_assign2;
285
286 SetCountdown();
287 ExpectNoThrow([&nothrow_assign1, &nothrow_assign2]() {
288 nothrow_assign1 = nothrow_assign2;
289 });
290 UnsetCountdown();
291}
292
Abseil Team28f5b892018-04-26 06:47:58 -0700293TEST(ThrowingValueTest, ThrowingSwap) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700294 ThrowingValue<> bomb1, bomb2;
295 TestOp([&]() { std::swap(bomb1, bomb2); });
Abseil Team8db6cfd2017-10-30 15:55:37 -0700296}
297
Abseil Team28f5b892018-04-26 06:47:58 -0700298TEST(ThrowingValueTest, NonThrowingSwap) {
Abseil Team96136782018-04-30 11:44:26 -0700299 ThrowingValue<TypeSpec::kNoThrowMove> bomb1, bomb2;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700300 ExpectNoThrow([&]() { std::swap(bomb1, bomb2); });
301}
302
Abseil Team28f5b892018-04-26 06:47:58 -0700303TEST(ThrowingValueTest, NonThrowingAllocation) {
Abseil Team96136782018-04-30 11:44:26 -0700304 ThrowingValue<TypeSpec::kNoThrowNew>* allocated;
305 ThrowingValue<TypeSpec::kNoThrowNew>* array;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700306
307 ExpectNoThrow([&allocated]() {
Abseil Team96136782018-04-30 11:44:26 -0700308 allocated = new ThrowingValue<TypeSpec::kNoThrowNew>(1);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700309 delete allocated;
310 });
311 ExpectNoThrow([&array]() {
Abseil Team96136782018-04-30 11:44:26 -0700312 array = new ThrowingValue<TypeSpec::kNoThrowNew>[2];
Abseil Team8db6cfd2017-10-30 15:55:37 -0700313 delete[] array;
314 });
315}
316
Abseil Team28f5b892018-04-26 06:47:58 -0700317TEST(ThrowingValueTest, NonThrowingDelete) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700318 auto* allocated = new ThrowingValue<>(1);
319 auto* array = new ThrowingValue<>[2];
320
321 SetCountdown();
322 ExpectNoThrow([allocated]() { delete allocated; });
323 SetCountdown();
324 ExpectNoThrow([array]() { delete[] array; });
Abseil Team28f5b892018-04-26 06:47:58 -0700325
326 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700327}
328
329using Storage =
330 absl::aligned_storage_t<sizeof(ThrowingValue<>), alignof(ThrowingValue<>)>;
331
Abseil Team28f5b892018-04-26 06:47:58 -0700332TEST(ThrowingValueTest, NonThrowingPlacementDelete) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700333 constexpr int kArrayLen = 2;
334 // We intentionally create extra space to store the tag allocated by placement
335 // new[].
336 constexpr int kStorageLen = 4;
337
338 Storage buf;
339 Storage array_buf[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 });
Abseil Team28f5b892018-04-26 06:47:58 -0700354
355 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700356}
357
Abseil Team28f5b892018-04-26 06:47:58 -0700358TEST(ThrowingValueTest, NonThrowingDestructor) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700359 auto* allocated = new ThrowingValue<>();
Abseil Team28f5b892018-04-26 06:47:58 -0700360
Abseil Team8db6cfd2017-10-30 15:55:37 -0700361 SetCountdown();
362 ExpectNoThrow([allocated]() { delete allocated; });
Abseil Team28f5b892018-04-26 06:47:58 -0700363 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700364}
365
366TEST(ThrowingBoolTest, ThrowingBool) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700367 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
Abseil Team28f5b892018-04-26 06:47:58 -0700377TEST(ThrowingAllocatorTest, MemoryManagement) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700378 // 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
Abseil Team96136782018-04-30 11:44:26 -0700386 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);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700391}
392
Abseil Team28f5b892018-04-26 06:47:58 -0700393TEST(ThrowingAllocatorTest, CallsGlobalNew) {
Abseil Team96136782018-04-30 11:44:26 -0700394 ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate> nothrow_alloc;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700395 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);
Abseil Team28f5b892018-04-26 06:47:58 -0700401
402 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700403}
404
Abseil Team28f5b892018-04-26 06:47:58 -0700405TEST(ThrowingAllocatorTest, ThrowingConstructors) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700406 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);
Abseil Team28f5b892018-04-26 06:47:58 -0700418
419 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700420}
421
Abseil Team28f5b892018-04-26 06:47:58 -0700422TEST(ThrowingAllocatorTest, NonThrowingConstruction) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700423 {
Abseil Team96136782018-04-30 11:44:26 -0700424 ThrowingAllocator<int, AllocSpec::kNoThrowAllocate> int_alloc;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700425 int* ip = nullptr;
426
427 SetCountdown();
428 ExpectNoThrow([&]() { ip = int_alloc.allocate(1); });
Abseil Team28f5b892018-04-26 06:47:58 -0700429
Abseil Team8db6cfd2017-10-30 15:55:37 -0700430 SetCountdown();
431 ExpectNoThrow([&]() { int_alloc.construct(ip, 2); });
Abseil Team28f5b892018-04-26 06:47:58 -0700432
Abseil Team8db6cfd2017-10-30 15:55:37 -0700433 EXPECT_EQ(*ip, 2);
434 int_alloc.deallocate(ip, 1);
Abseil Team28f5b892018-04-26 06:47:58 -0700435
436 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700437 }
438
Abseil Team8db6cfd2017-10-30 15:55:37 -0700439 {
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
Abseil Team8db6cfd2017-10-30 15:55:37 -0700448 {
Abseil Team96136782018-04-30 11:44:26 -0700449 ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate>
450 nothrow_alloc;
451 ThrowingValue<>* ptr;
Abseil Team28f5b892018-04-26 06:47:58 -0700452
Abseil Team8db6cfd2017-10-30 15:55:37 -0700453 SetCountdown();
Abseil Team96136782018-04-30 11:44:26 -0700454 ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); });
Abseil Team28f5b892018-04-26 06:47:58 -0700455
Abseil Team8db6cfd2017-10-30 15:55:37 -0700456 SetCountdown();
Abseil Team96136782018-04-30 11:44:26 -0700457 ExpectNoThrow(
Abseil Team04dd99d2018-05-14 13:41:38 -0700458 [&]() { nothrow_alloc.construct(ptr, 2, testing::nothrow_ctor); });
Abseil Team28f5b892018-04-26 06:47:58 -0700459
Abseil Team96136782018-04-30 11:44:26 -0700460 EXPECT_EQ(ptr->Get(), 2);
461 nothrow_alloc.destroy(ptr);
462 nothrow_alloc.deallocate(ptr, 1);
Abseil Team28f5b892018-04-26 06:47:58 -0700463
464 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700465 }
466
Abseil Team8db6cfd2017-10-30 15:55:37 -0700467 {
468 ThrowingAllocator<int> a;
Abseil Team28f5b892018-04-26 06:47:58 -0700469
Abseil Team8db6cfd2017-10-30 15:55:37 -0700470 SetCountdown();
471 ExpectNoThrow([&]() { ThrowingAllocator<double> a1 = a; });
Abseil Team28f5b892018-04-26 06:47:58 -0700472
Abseil Team8db6cfd2017-10-30 15:55:37 -0700473 SetCountdown();
474 ExpectNoThrow([&]() { ThrowingAllocator<double> a1 = std::move(a); });
Abseil Team28f5b892018-04-26 06:47:58 -0700475
476 UnsetCountdown();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700477 }
478}
479
Abseil Team28f5b892018-04-26 06:47:58 -0700480TEST(ThrowingAllocatorTest, ThrowingAllocatorConstruction) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700481 ThrowingAllocator<int> a;
482 TestOp([]() { ThrowingAllocator<int> a; });
483 TestOp([&]() { a.select_on_container_copy_construction(); });
484}
485
Abseil Team28f5b892018-04-26 06:47:58 -0700486TEST(ThrowingAllocatorTest, State) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700487 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
Abseil Team28f5b892018-04-26 06:47:58 -0700498TEST(ThrowingAllocatorTest, InVector) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700499 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
Abseil Team28f5b892018-04-26 06:47:58 -0700504TEST(ThrowingAllocatorTest, InList) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700505 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
Abseil Team5b535402018-04-18 05:56:39 -0700512template <typename TesterInstance, typename = void>
513struct NullaryTestValidator : public std::false_type {};
514
515template <typename TesterInstance>
516struct NullaryTestValidator<
517 TesterInstance,
518 absl::void_t<decltype(std::declval<TesterInstance>().Test())>>
519 : public std::true_type {};
520
521template <typename TesterInstance>
522bool HasNullaryTest(const TesterInstance&) {
523 return NullaryTestValidator<TesterInstance>::value;
524}
525
526void DummyOp(void*) {}
527
528template <typename TesterInstance, typename = void>
529struct UnaryTestValidator : public std::false_type {};
530
531template <typename TesterInstance>
532struct UnaryTestValidator<
533 TesterInstance,
534 absl::void_t<decltype(std::declval<TesterInstance>().Test(DummyOp))>>
535 : public std::true_type {};
536
537template <typename TesterInstance>
538bool HasUnaryTest(const TesterInstance&) {
539 return UnaryTestValidator<TesterInstance>::value;
540}
541
542TEST(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 =
Abseil Teame01d9552018-09-24 11:57:52 -0700551 testing::MakeExceptionSafetyTester().WithOperation(op).WithContracts(
Abseil Team96136782018-04-30 11:44:26 -0700552 inv, testing::strong_guarantee);
Abseil Team5b535402018-04-18 05:56:39 -0700553 EXPECT_FALSE(HasNullaryTest(without_fac));
554 EXPECT_FALSE(HasUnaryTest(without_fac));
555
Abseil Teame01d9552018-09-24 11:57:52 -0700556 // Test that providing contracts and factory allows the invocation of
Abseil Team5b535402018-04-18 05:56:39 -0700557 // .Test(op) but does not allow for .Test() because it lacks an operation
Abseil Team96136782018-04-30 11:44:26 -0700558 auto without_op = testing::MakeExceptionSafetyTester()
Abseil Teame01d9552018-09-24 11:57:52 -0700559 .WithContracts(inv, testing::strong_guarantee)
Abseil Team5b535402018-04-18 05:56:39 -0700560 .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
Abseil Teame01d9552018-09-24 11:57:52 -0700565 // the invocation of .Test() and .Test(op) because it lacks contracts
Abseil Team5b535402018-04-18 05:56:39 -0700566 auto without_inv =
Abseil Team96136782018-04-30 11:44:26 -0700567 testing::MakeExceptionSafetyTester().WithOperation(op).WithFactory(fac);
Abseil Team5b535402018-04-18 05:56:39 -0700568 EXPECT_FALSE(HasNullaryTest(without_inv));
569 EXPECT_FALSE(HasUnaryTest(without_inv));
570}
571
572struct ExampleStruct {};
573
574std::unique_ptr<ExampleStruct> ExampleFunctionFactory() {
575 return absl::make_unique<ExampleStruct>();
576}
577
578void ExampleFunctionOperation(ExampleStruct*) {}
579
Abseil Teame01d9552018-09-24 11:57:52 -0700580testing::AssertionResult ExampleFunctionContract(ExampleStruct*) {
Abseil Team5b535402018-04-18 05:56:39 -0700581 return testing::AssertionSuccess();
582}
583
584struct {
585 std::unique_ptr<ExampleStruct> operator()() const {
586 return ExampleFunctionFactory();
587 }
588} example_struct_factory;
589
590struct {
591 void operator()(ExampleStruct*) const {}
592} example_struct_operation;
593
594struct {
595 testing::AssertionResult operator()(ExampleStruct* example_struct) const {
Abseil Teame01d9552018-09-24 11:57:52 -0700596 return ExampleFunctionContract(example_struct);
Abseil Team5b535402018-04-18 05:56:39 -0700597 }
Abseil Teame01d9552018-09-24 11:57:52 -0700598} example_struct_contract;
Abseil Team5b535402018-04-18 05:56:39 -0700599
600auto example_lambda_factory = []() { return ExampleFunctionFactory(); };
601
602auto example_lambda_operation = [](ExampleStruct*) {};
603
Abseil Teame01d9552018-09-24 11:57:52 -0700604auto example_lambda_contract = [](ExampleStruct* example_struct) {
605 return ExampleFunctionContract(example_struct);
Abseil Team5b535402018-04-18 05:56:39 -0700606};
607
608// Testing that function references, pointers, structs with operator() and
609// lambdas can all be used with ExceptionSafetyTester
610TEST(ExceptionSafetyTesterTest, MixedFunctionTypes) {
611 // function reference
Abseil Team96136782018-04-30 11:44:26 -0700612 EXPECT_TRUE(testing::MakeExceptionSafetyTester()
Abseil Team5b535402018-04-18 05:56:39 -0700613 .WithFactory(ExampleFunctionFactory)
614 .WithOperation(ExampleFunctionOperation)
Abseil Teame01d9552018-09-24 11:57:52 -0700615 .WithContracts(ExampleFunctionContract)
Abseil Team5b535402018-04-18 05:56:39 -0700616 .Test());
617
618 // function pointer
Abseil Team96136782018-04-30 11:44:26 -0700619 EXPECT_TRUE(testing::MakeExceptionSafetyTester()
Abseil Team5b535402018-04-18 05:56:39 -0700620 .WithFactory(&ExampleFunctionFactory)
621 .WithOperation(&ExampleFunctionOperation)
Abseil Teame01d9552018-09-24 11:57:52 -0700622 .WithContracts(&ExampleFunctionContract)
Abseil Team5b535402018-04-18 05:56:39 -0700623 .Test());
624
625 // struct
Abseil Team96136782018-04-30 11:44:26 -0700626 EXPECT_TRUE(testing::MakeExceptionSafetyTester()
Abseil Team5b535402018-04-18 05:56:39 -0700627 .WithFactory(example_struct_factory)
628 .WithOperation(example_struct_operation)
Abseil Teame01d9552018-09-24 11:57:52 -0700629 .WithContracts(example_struct_contract)
Abseil Team5b535402018-04-18 05:56:39 -0700630 .Test());
631
632 // lambda
Abseil Team96136782018-04-30 11:44:26 -0700633 EXPECT_TRUE(testing::MakeExceptionSafetyTester()
Abseil Team5b535402018-04-18 05:56:39 -0700634 .WithFactory(example_lambda_factory)
635 .WithOperation(example_lambda_operation)
Abseil Teame01d9552018-09-24 11:57:52 -0700636 .WithContracts(example_lambda_contract)
Abseil Team5b535402018-04-18 05:56:39 -0700637 .Test());
638}
639
640struct NonNegative {
641 bool operator==(const NonNegative& other) const { return i == other.i; }
642 int i;
643};
644
645testing::AssertionResult CheckNonNegativeInvariants(NonNegative* g) {
646 if (g->i >= 0) {
647 return testing::AssertionSuccess();
648 }
649 return testing::AssertionFailure()
650 << "i should be non-negative but is " << g->i;
651}
652
653struct {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700654 template <typename T>
655 void operator()(T* t) const {
656 (*t)();
657 }
Abseil Team5b535402018-04-18 05:56:39 -0700658} invoker;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700659
Abseil Team5b535402018-04-18 05:56:39 -0700660auto tester =
Abseil Teame01d9552018-09-24 11:57:52 -0700661 testing::MakeExceptionSafetyTester().WithOperation(invoker).WithContracts(
Abseil Team5b535402018-04-18 05:56:39 -0700662 CheckNonNegativeInvariants);
Abseil Teame01d9552018-09-24 11:57:52 -0700663auto strong_tester = tester.WithContracts(testing::strong_guarantee);
Abseil Team8b727aa2017-12-01 12:15:49 -0800664
665struct FailsBasicGuarantee : public NonNegative {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700666 void operator()() {
667 --i;
668 ThrowingValue<> bomb;
669 ++i;
670 }
Abseil Team8db6cfd2017-10-30 15:55:37 -0700671};
672
673TEST(ExceptionCheckTest, BasicGuaranteeFailure) {
Abseil Team5b535402018-04-18 05:56:39 -0700674 EXPECT_FALSE(tester.WithInitialValue(FailsBasicGuarantee{}).Test());
Abseil Team8db6cfd2017-10-30 15:55:37 -0700675}
676
Abseil Team8b727aa2017-12-01 12:15:49 -0800677struct FollowsBasicGuarantee : public NonNegative {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700678 void operator()() {
679 ++i;
680 ThrowingValue<> bomb;
681 }
Abseil Team8db6cfd2017-10-30 15:55:37 -0700682};
683
684TEST(ExceptionCheckTest, BasicGuarantee) {
Abseil Team5b535402018-04-18 05:56:39 -0700685 EXPECT_TRUE(tester.WithInitialValue(FollowsBasicGuarantee{}).Test());
Abseil Team8db6cfd2017-10-30 15:55:37 -0700686}
687
688TEST(ExceptionCheckTest, StrongGuaranteeFailure) {
Abseil Team5b535402018-04-18 05:56:39 -0700689 EXPECT_FALSE(strong_tester.WithInitialValue(FailsBasicGuarantee{}).Test());
690 EXPECT_FALSE(strong_tester.WithInitialValue(FollowsBasicGuarantee{}).Test());
Abseil Teamae0cef32017-11-22 07:42:54 -0800691}
692
Abseil Teame01d9552018-09-24 11:57:52 -0700693struct BasicGuaranteeWithExtraContracts : public NonNegative {
Abseil Teamae0cef32017-11-22 07:42:54 -0800694 // 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
Abseil Teamae0cef32017-11-22 07:42:54 -0800702 static constexpr int kExceptionSentinel = 9999;
703};
Abseil Teame01d9552018-09-24 11:57:52 -0700704constexpr int BasicGuaranteeWithExtraContracts::kExceptionSentinel;
Abseil Teamae0cef32017-11-22 07:42:54 -0800705
Abseil Teame01d9552018-09-24 11:57:52 -0700706TEST(ExceptionCheckTest, BasicGuaranteeWithExtraContracts) {
Abseil Team5b535402018-04-18 05:56:39 -0700707 auto tester_with_val =
Abseil Teame01d9552018-09-24 11:57:52 -0700708 tester.WithInitialValue(BasicGuaranteeWithExtraContracts{});
Abseil Team5b535402018-04-18 05:56:39 -0700709 EXPECT_TRUE(tester_with_val.Test());
710 EXPECT_TRUE(
711 tester_with_val
Abseil Teame01d9552018-09-24 11:57:52 -0700712 .WithContracts([](BasicGuaranteeWithExtraContracts* o) {
713 if (o->i == BasicGuaranteeWithExtraContracts::kExceptionSentinel) {
Abseil Team5b535402018-04-18 05:56:39 -0700714 return testing::AssertionSuccess();
715 }
716 return testing::AssertionFailure()
717 << "i should be "
Abseil Teame01d9552018-09-24 11:57:52 -0700718 << BasicGuaranteeWithExtraContracts::kExceptionSentinel
Abseil Team92020a02018-06-08 08:14:48 -0700719 << ", but is " << o->i;
Abseil Team5b535402018-04-18 05:56:39 -0700720 })
721 .Test());
Abseil Team8db6cfd2017-10-30 15:55:37 -0700722}
723
Abseil Team8b727aa2017-12-01 12:15:49 -0800724struct FollowsStrongGuarantee : public NonNegative {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700725 void operator()() { ThrowingValue<> bomb; }
Abseil Team8db6cfd2017-10-30 15:55:37 -0700726};
727
728TEST(ExceptionCheckTest, StrongGuarantee) {
Abseil Team5b535402018-04-18 05:56:39 -0700729 EXPECT_TRUE(tester.WithInitialValue(FollowsStrongGuarantee{}).Test());
730 EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{}).Test());
Abseil Teamae0cef32017-11-22 07:42:54 -0800731}
732
Abseil Team8b727aa2017-12-01 12:15:49 -0800733struct HasReset : public NonNegative {
734 void operator()() {
735 i = -1;
736 ThrowingValue<> bomb;
737 i = 1;
Abseil Teamae0cef32017-11-22 07:42:54 -0800738 }
739
Abseil Team8b727aa2017-12-01 12:15:49 -0800740 void reset() { i = 0; }
Abseil Team8b727aa2017-12-01 12:15:49 -0800741};
742
Abseil Teame01d9552018-09-24 11:57:52 -0700743testing::AssertionResult CheckHasResetContracts(HasReset* h) {
Abseil Team5b535402018-04-18 05:56:39 -0700744 h->reset();
745 return testing::AssertionResult(h->i == 0);
746}
747
Abseil Team8b727aa2017-12-01 12:15:49 -0800748TEST(ExceptionCheckTest, ModifyingChecker) {
Abseil Team5b535402018-04-18 05:56:39 -0700749 auto set_to_1000 = [](FollowsBasicGuarantee* g) {
750 g->i = 1000;
751 return testing::AssertionSuccess();
752 };
753 auto is_1000 = [](FollowsBasicGuarantee* g) {
754 return testing::AssertionResult(g->i == 1000);
755 };
756 auto increment = [](FollowsStrongGuarantee* g) {
757 ++g->i;
758 return testing::AssertionSuccess();
759 };
760
761 EXPECT_FALSE(tester.WithInitialValue(FollowsBasicGuarantee{})
Abseil Teame01d9552018-09-24 11:57:52 -0700762 .WithContracts(set_to_1000, is_1000)
Abseil Team5b535402018-04-18 05:56:39 -0700763 .Test());
764 EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{})
Abseil Teame01d9552018-09-24 11:57:52 -0700765 .WithContracts(increment)
Abseil Team5b535402018-04-18 05:56:39 -0700766 .Test());
Abseil Team96136782018-04-30 11:44:26 -0700767 EXPECT_TRUE(testing::MakeExceptionSafetyTester()
Abseil Team5b535402018-04-18 05:56:39 -0700768 .WithInitialValue(HasReset{})
Abseil Teame01d9552018-09-24 11:57:52 -0700769 .WithContracts(CheckHasResetContracts)
Abseil Team5b535402018-04-18 05:56:39 -0700770 .Test(invoker));
Abseil Team8b727aa2017-12-01 12:15:49 -0800771}
772
Abseil Team94c298e2018-10-23 18:09:41 -0700773TEST(ExceptionSafetyTesterTest, ResetsCountdown) {
774 auto test =
775 testing::MakeExceptionSafetyTester()
776 .WithInitialValue(ThrowingValue<>())
777 .WithContracts([](ThrowingValue<>*) { return AssertionSuccess(); })
778 .WithOperation([](ThrowingValue<>*) {});
779 ASSERT_TRUE(test.Test());
780 // If the countdown isn't reset because there were no exceptions thrown, then
781 // this will fail with a termination from an unhandled exception
782 EXPECT_TRUE(test.Test());
783}
784
Abseil Team8b727aa2017-12-01 12:15:49 -0800785struct NonCopyable : public NonNegative {
786 NonCopyable(const NonCopyable&) = delete;
787 NonCopyable() : NonNegative{0} {}
788
789 void operator()() { ThrowingValue<> bomb; }
Abseil Teamae0cef32017-11-22 07:42:54 -0800790};
791
792TEST(ExceptionCheckTest, NonCopyable) {
Abseil Team5b535402018-04-18 05:56:39 -0700793 auto factory = []() { return absl::make_unique<NonCopyable>(); };
794 EXPECT_TRUE(tester.WithFactory(factory).Test());
795 EXPECT_TRUE(strong_tester.WithFactory(factory).Test());
Abseil Teamae0cef32017-11-22 07:42:54 -0800796}
797
Abseil Team8b727aa2017-12-01 12:15:49 -0800798struct NonEqualityComparable : public NonNegative {
Abseil Teamae0cef32017-11-22 07:42:54 -0800799 void operator()() { ThrowingValue<> bomb; }
800
801 void ModifyOnThrow() {
802 ++i;
803 ThrowingValue<> bomb;
804 static_cast<void>(bomb);
805 --i;
806 }
Abseil Teamae0cef32017-11-22 07:42:54 -0800807};
808
809TEST(ExceptionCheckTest, NonEqualityComparable) {
Abseil Team5b535402018-04-18 05:56:39 -0700810 auto nec_is_strong = [](NonEqualityComparable* nec) {
811 return testing::AssertionResult(nec->i == NonEqualityComparable().i);
812 };
813 auto strong_nec_tester = tester.WithInitialValue(NonEqualityComparable{})
Abseil Teame01d9552018-09-24 11:57:52 -0700814 .WithContracts(nec_is_strong);
Abseil Team5b535402018-04-18 05:56:39 -0700815
816 EXPECT_TRUE(strong_nec_tester.Test());
817 EXPECT_FALSE(strong_nec_tester.Test(
818 [](NonEqualityComparable* n) { n->ModifyOnThrow(); }));
Abseil Team8db6cfd2017-10-30 15:55:37 -0700819}
820
821template <typename T>
Abseil Team8b727aa2017-12-01 12:15:49 -0800822struct ExhaustivenessTester {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700823 void operator()() {
Abseil Team8b727aa2017-12-01 12:15:49 -0800824 successes |= 1;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700825 T b1;
826 static_cast<void>(b1);
Abseil Team8b727aa2017-12-01 12:15:49 -0800827 successes |= (1 << 1);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700828 T b2;
829 static_cast<void>(b2);
Abseil Team8b727aa2017-12-01 12:15:49 -0800830 successes |= (1 << 2);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700831 T b3;
832 static_cast<void>(b3);
Abseil Team8b727aa2017-12-01 12:15:49 -0800833 successes |= (1 << 3);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700834 }
835
Abseil Team8b727aa2017-12-01 12:15:49 -0800836 bool operator==(const ExhaustivenessTester<ThrowingValue<>>&) const {
Abseil Teamae0cef32017-11-22 07:42:54 -0800837 return true;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700838 }
839
Abseil Team8b727aa2017-12-01 12:15:49 -0800840 static unsigned char successes;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700841};
Abseil Team5b535402018-04-18 05:56:39 -0700842
843struct {
844 template <typename T>
845 testing::AssertionResult operator()(ExhaustivenessTester<T>*) const {
846 return testing::AssertionSuccess();
847 }
Abseil Teame01d9552018-09-24 11:57:52 -0700848} CheckExhaustivenessTesterContracts;
Abseil Team5b535402018-04-18 05:56:39 -0700849
Abseil Team8db6cfd2017-10-30 15:55:37 -0700850template <typename T>
Abseil Team8b727aa2017-12-01 12:15:49 -0800851unsigned char ExhaustivenessTester<T>::successes = 0;
Abseil Team8db6cfd2017-10-30 15:55:37 -0700852
853TEST(ExceptionCheckTest, Exhaustiveness) {
Abseil Team96136782018-04-30 11:44:26 -0700854 auto exhaust_tester = testing::MakeExceptionSafetyTester()
Abseil Teame01d9552018-09-24 11:57:52 -0700855 .WithContracts(CheckExhaustivenessTesterContracts)
Abseil Team5b535402018-04-18 05:56:39 -0700856 .WithOperation(invoker);
857
858 EXPECT_TRUE(
859 exhaust_tester.WithInitialValue(ExhaustivenessTester<int>{}).Test());
Abseil Team8b727aa2017-12-01 12:15:49 -0800860 EXPECT_EQ(ExhaustivenessTester<int>::successes, 0xF);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700861
Abseil Team5b535402018-04-18 05:56:39 -0700862 EXPECT_TRUE(
863 exhaust_tester.WithInitialValue(ExhaustivenessTester<ThrowingValue<>>{})
Abseil Teame01d9552018-09-24 11:57:52 -0700864 .WithContracts(testing::strong_guarantee)
Abseil Team5b535402018-04-18 05:56:39 -0700865 .Test());
Abseil Team8b727aa2017-12-01 12:15:49 -0800866 EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::successes, 0xF);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700867}
868
Abseil Teamae0cef32017-11-22 07:42:54 -0800869struct LeaksIfCtorThrows : private exceptions_internal::TrackedObject {
870 LeaksIfCtorThrows() : TrackedObject(ABSL_PRETTY_FUNCTION) {
871 ++counter;
872 ThrowingValue<> v;
873 static_cast<void>(v);
874 --counter;
875 }
876 LeaksIfCtorThrows(const LeaksIfCtorThrows&) noexcept
877 : TrackedObject(ABSL_PRETTY_FUNCTION) {}
878 static int counter;
879};
880int LeaksIfCtorThrows::counter = 0;
881
882TEST(ExceptionCheckTest, TestLeakyCtor) {
Abseil Team96136782018-04-30 11:44:26 -0700883 testing::TestThrowingCtor<LeaksIfCtorThrows>();
Abseil Teamae0cef32017-11-22 07:42:54 -0800884 EXPECT_EQ(LeaksIfCtorThrows::counter, 1);
885 LeaksIfCtorThrows::counter = 0;
886}
887
Abseil Team8db6cfd2017-10-30 15:55:37 -0700888struct Tracked : private exceptions_internal::TrackedObject {
889 Tracked() : TrackedObject(ABSL_PRETTY_FUNCTION) {}
890};
891
Abseil Team28f5b892018-04-26 06:47:58 -0700892TEST(ConstructorTrackerTest, CreatedBefore) {
893 Tracked a, b, c;
894 exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700895}
896
Abseil Team28f5b892018-04-26 06:47:58 -0700897TEST(ConstructorTrackerTest, CreatedAfter) {
898 exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
899 Tracked a, b, c;
900}
901
902TEST(ConstructorTrackerTest, NotDestroyedAfter) {
Abseil Team8db6cfd2017-10-30 15:55:37 -0700903 absl::aligned_storage_t<sizeof(Tracked), alignof(Tracked)> storage;
904 EXPECT_NONFATAL_FAILURE(
905 {
Abseil Team28f5b892018-04-26 06:47:58 -0700906 exceptions_internal::ConstructorTracker ct(
907 exceptions_internal::countdown);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700908 new (&storage) Tracked;
909 },
910 "not destroyed");
911}
912
Abseil Team70b5fa92018-03-26 15:15:40 -0700913TEST(ConstructorTrackerTest, DestroyedTwice) {
Abseil Team92020a02018-06-08 08:14:48 -0700914 exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700915 EXPECT_NONFATAL_FAILURE(
916 {
917 Tracked t;
918 t.~Tracked();
919 },
Abseil Team92020a02018-06-08 08:14:48 -0700920 "re-destroyed");
Abseil Team8db6cfd2017-10-30 15:55:37 -0700921}
922
Abseil Team70b5fa92018-03-26 15:15:40 -0700923TEST(ConstructorTrackerTest, ConstructedTwice) {
Abseil Team92020a02018-06-08 08:14:48 -0700924 exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
Abseil Team8db6cfd2017-10-30 15:55:37 -0700925 absl::aligned_storage_t<sizeof(Tracked), alignof(Tracked)> storage;
926 EXPECT_NONFATAL_FAILURE(
927 {
928 new (&storage) Tracked;
929 new (&storage) Tracked;
Abseil Team92020a02018-06-08 08:14:48 -0700930 reinterpret_cast<Tracked*>(&storage)->~Tracked();
Abseil Team8db6cfd2017-10-30 15:55:37 -0700931 },
932 "re-constructed");
933}
Abseil Teameed36bf2018-03-15 13:48:55 -0700934
935TEST(ThrowingValueTraitsTest, RelationalOperators) {
936 ThrowingValue<> a, b;
937 EXPECT_TRUE((std::is_convertible<decltype(a == b), bool>::value));
938 EXPECT_TRUE((std::is_convertible<decltype(a != b), bool>::value));
939 EXPECT_TRUE((std::is_convertible<decltype(a < b), bool>::value));
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}
944
Abseil Team70b5fa92018-03-26 15:15:40 -0700945TEST(ThrowingAllocatorTraitsTest, Assignablility) {
Abseil Team083d04d2018-08-07 11:43:34 -0700946 EXPECT_TRUE(absl::is_move_assignable<ThrowingAllocator<int>>::value);
947 EXPECT_TRUE(absl::is_copy_assignable<ThrowingAllocator<int>>::value);
Abseil Team70b5fa92018-03-26 15:15:40 -0700948 EXPECT_TRUE(std::is_nothrow_move_assignable<ThrowingAllocator<int>>::value);
949 EXPECT_TRUE(std::is_nothrow_copy_assignable<ThrowingAllocator<int>>::value);
950}
951
Abseil Team8db6cfd2017-10-30 15:55:37 -0700952} // namespace
Abseil Team96136782018-04-30 11:44:26 -0700953
954} // namespace testing