Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
ref_counted_unittest.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This file tests both ref_counted.h and ref_ptr.h (which the former includes).
6// TODO(vtl): Possibly we could separate these tests out better, since a lot of
7// it is actually testing |RefPtr|.
8
9#include "flutter/fml/memory/ref_counted.h"
10
11#include "flutter/fml/macros.h"
12#include "gtest/gtest.h"
13
14#if defined(__clang__)
15#define ALLOW_PESSIMIZING_MOVE(code_line) \
16 _Pragma("clang diagnostic push") \
17 _Pragma("clang diagnostic ignored \"-Wpessimizing-move\"") code_line; \
18 _Pragma("clang diagnostic pop")
19#else
20#define ALLOW_PESSIMIZING_MOVE(code_line) code_line;
21#endif
22
23#if defined(__clang__)
24#define ALLOW_SELF_MOVE(code_line) \
25 _Pragma("clang diagnostic push") \
26 _Pragma("clang diagnostic ignored \"-Wself-move\"") code_line; \
27 _Pragma("clang diagnostic pop")
28#else
29#define ALLOW_SELF_MOVE(code_line) code_line;
30#endif
31
32#if defined(__clang__)
33#define ALLOW_SELF_ASSIGN_OVERLOADED(code_line) \
34 _Pragma("clang diagnostic push") \
35 _Pragma("clang diagnostic ignored \"-Wself-assign-overloaded\"") \
36 code_line; \
37 _Pragma("clang diagnostic pop")
38#else
39#define ALLOW_SELF_ASSIGN_OVERLOADED(code_line) code_line;
40#endif
41
42namespace fml {
43namespace {
44
45class MyClass : public RefCountedThreadSafe<MyClass> {
46 protected:
47 MyClass(MyClass** created, bool* was_destroyed)
48 : was_destroyed_(was_destroyed) {
49 if (created) {
50 *created = this;
51 }
52 }
53 virtual ~MyClass() {
54 if (was_destroyed_) {
55 *was_destroyed_ = true;
56 }
57 }
58
59 private:
62
63 bool* was_destroyed_;
64
66};
67
68class MySubclass final : public MyClass {
69 private:
72
73 MySubclass(MySubclass** created, bool* was_destroyed)
74 : MyClass(nullptr, was_destroyed) {
75 if (created) {
76 *created = this;
77 }
78 }
79 ~MySubclass() override {}
80
82};
83
84TEST(RefCountedTest, Constructors) {
85 bool was_destroyed;
86
87 {
88 // Default.
89 RefPtr<MyClass> r;
90 EXPECT_TRUE(r.get() == nullptr);
91 EXPECT_FALSE(r);
92 }
93
94 {
95 // Nullptr.
96 RefPtr<MyClass> r(nullptr);
97 EXPECT_TRUE(r.get() == nullptr);
98 EXPECT_FALSE(r);
99 }
100
101 {
102 MyClass* created = nullptr;
103 was_destroyed = false;
104 // Adopt, then RVO.
105 RefPtr<MyClass> r(MakeRefCounted<MyClass>(&created, &was_destroyed));
106 EXPECT_TRUE(created);
107 EXPECT_EQ(created, r.get());
108 EXPECT_TRUE(r);
109 EXPECT_FALSE(was_destroyed);
110 }
111 EXPECT_TRUE(was_destroyed);
112
113 {
114 MyClass* created = nullptr;
115 was_destroyed = false;
116 // Adopt, then move.
117 ALLOW_PESSIMIZING_MOVE(RefPtr<MyClass> r(
118 std::move(MakeRefCounted<MyClass>(&created, &was_destroyed))))
119 EXPECT_TRUE(created);
120 EXPECT_EQ(created, r.get());
121 EXPECT_TRUE(r);
122 EXPECT_FALSE(was_destroyed);
123 }
124 EXPECT_TRUE(was_destroyed);
125
126 {
127 MyClass* created = nullptr;
128 was_destroyed = false;
129 RefPtr<MyClass> r1(MakeRefCounted<MyClass>(&created, &was_destroyed));
130 // Copy.
131 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
132 RefPtr<MyClass> r2(r1);
133 EXPECT_TRUE(created);
134 EXPECT_EQ(created, r1.get());
135 EXPECT_EQ(created, r2.get());
136 EXPECT_TRUE(r1);
137 EXPECT_TRUE(r2);
138 EXPECT_FALSE(was_destroyed);
139 }
140 EXPECT_TRUE(was_destroyed);
141
142 {
143 MyClass* created = nullptr;
144 was_destroyed = false;
145 RefPtr<MyClass> r1(MakeRefCounted<MyClass>(&created, &was_destroyed));
146 // From raw pointer.
147 RefPtr<MyClass> r2(created);
148 EXPECT_TRUE(created);
149 EXPECT_EQ(created, r1.get());
150 EXPECT_EQ(created, r2.get());
151 EXPECT_TRUE(r1);
152 EXPECT_TRUE(r2);
153 EXPECT_FALSE(was_destroyed);
154 }
155 EXPECT_TRUE(was_destroyed);
156
157 {
158 MySubclass* created = nullptr;
159 was_destroyed = false;
160 // Adopt, then "move".
161 RefPtr<MyClass> r(MakeRefCounted<MySubclass>(&created, &was_destroyed));
162 EXPECT_TRUE(created);
163 EXPECT_EQ(static_cast<MyClass*>(created), r.get());
164 EXPECT_TRUE(r);
165 EXPECT_FALSE(was_destroyed);
166 }
167 EXPECT_TRUE(was_destroyed);
168
169 {
170 MySubclass* created = nullptr;
171 was_destroyed = false;
172 // Adopt, then "move".
173 ALLOW_PESSIMIZING_MOVE(RefPtr<MyClass> r(
174 std::move(MakeRefCounted<MySubclass>(&created, &was_destroyed))))
175 EXPECT_TRUE(created);
176 EXPECT_EQ(static_cast<MyClass*>(created), r.get());
177 EXPECT_TRUE(r);
178 EXPECT_FALSE(was_destroyed);
179 }
180 EXPECT_TRUE(was_destroyed);
181
182 {
183 MySubclass* created = nullptr;
184 was_destroyed = false;
185 RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(&created, &was_destroyed));
186 // "Copy".
187 RefPtr<MyClass> r2(r1);
188 EXPECT_TRUE(created);
189 EXPECT_EQ(static_cast<MyClass*>(created), r1.get());
190 EXPECT_EQ(static_cast<MyClass*>(created), r2.get());
191 EXPECT_TRUE(r1);
192 EXPECT_TRUE(r2);
193 EXPECT_FALSE(was_destroyed);
194 }
195 EXPECT_TRUE(was_destroyed);
196
197 {
198 MySubclass* created = nullptr;
199 was_destroyed = false;
200 RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(&created, &was_destroyed));
201 // From raw pointer.
202 RefPtr<MyClass> r2(created);
203 EXPECT_TRUE(created);
204 EXPECT_EQ(static_cast<MyClass*>(created), r1.get());
205 EXPECT_EQ(static_cast<MyClass*>(created), r2.get());
206 EXPECT_TRUE(r1);
207 EXPECT_TRUE(r2);
208 EXPECT_FALSE(was_destroyed);
209 }
210 EXPECT_TRUE(was_destroyed);
211}
212
213TEST(RefCountedTest, NullAssignmentToNull) {
214 RefPtr<MyClass> r1;
215 // No-op null assignment using |nullptr|.
216 r1 = nullptr;
217 EXPECT_TRUE(r1.get() == nullptr);
218 EXPECT_FALSE(r1);
219
220 RefPtr<MyClass> r2;
221 // No-op null assignment using copy constructor.
222 r1 = r2;
223 EXPECT_TRUE(r1.get() == nullptr);
224 EXPECT_TRUE(r2.get() == nullptr);
225 EXPECT_FALSE(r1);
226 EXPECT_FALSE(r2);
227
228 // No-op null assignment using move constructor.
229 r1 = std::move(r2);
230 EXPECT_TRUE(r1.get() == nullptr);
231 // The clang linter flags the method called on the moved-from reference, but
232 // this is testing the move implementation, so it is marked NOLINT.
233 EXPECT_TRUE(r2.get() == nullptr); // NOLINT(clang-analyzer-cplusplus.Move,
234 // bugprone-use-after-move)
235 EXPECT_FALSE(r1);
236 EXPECT_FALSE(r2);
237
238 RefPtr<MySubclass> r3;
239 // No-op null assignment using "copy" constructor.
240 r1 = r3;
241 EXPECT_TRUE(r1.get() == nullptr);
242 EXPECT_TRUE(r3.get() == nullptr);
243 EXPECT_FALSE(r1);
244 EXPECT_FALSE(r3);
245
246 // No-op null assignment using "move" constructor.
247 r1 = std::move(r3);
248 EXPECT_TRUE(r1.get() == nullptr);
249 EXPECT_TRUE(r3.get() == nullptr); // NOLINT(bugprone-use-after-move)
250 EXPECT_FALSE(r1);
251 EXPECT_FALSE(r3);
252}
253
254TEST(RefCountedTest, NonNullAssignmentToNull) {
255 bool was_destroyed;
256
257 {
258 MyClass* created = nullptr;
259 was_destroyed = false;
260 RefPtr<MyClass> r1(MakeRefCounted<MyClass>(&created, &was_destroyed));
261 RefPtr<MyClass> r2;
262 // Copy assignment (to null ref pointer).
263 r2 = r1;
264 EXPECT_EQ(created, r1.get());
265 EXPECT_EQ(created, r2.get());
266 EXPECT_TRUE(r1);
267 EXPECT_TRUE(r2);
268 EXPECT_FALSE(was_destroyed);
269 }
270 EXPECT_TRUE(was_destroyed);
271
272 {
273 MyClass* created = nullptr;
274 was_destroyed = false;
275 RefPtr<MyClass> r1(MakeRefCounted<MyClass>(&created, &was_destroyed));
276 RefPtr<MyClass> r2;
277 // Move assignment (to null ref pointer).
278 r2 = std::move(r1);
279 // The clang linter flags the method called on the moved-from reference, but
280 // this is testing the move implementation, so it is marked NOLINT.
281 EXPECT_TRUE(r1.get() == nullptr); // NOLINT(clang-analyzer-cplusplus.Move,
282 // bugprone-use-after-move)
283 EXPECT_EQ(created, r2.get());
284 EXPECT_FALSE(r1);
285 EXPECT_TRUE(r2);
286 EXPECT_FALSE(was_destroyed);
287 }
288 EXPECT_TRUE(was_destroyed);
289
290 {
291 MySubclass* created = nullptr;
292 was_destroyed = false;
293 RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(&created, &was_destroyed));
294 RefPtr<MyClass> r2;
295 // "Copy" assignment (to null ref pointer).
296 r2 = r1;
297 EXPECT_EQ(created, r1.get());
298 EXPECT_EQ(static_cast<MyClass*>(created), r2.get());
299 EXPECT_TRUE(r1);
300 EXPECT_TRUE(r2);
301 EXPECT_FALSE(was_destroyed);
302 }
303 EXPECT_TRUE(was_destroyed);
304
305 {
306 MySubclass* created = nullptr;
307 was_destroyed = false;
308 RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(&created, &was_destroyed));
309 RefPtr<MyClass> r2;
310 // "Move" assignment (to null ref pointer).
311 r2 = std::move(r1);
312 EXPECT_TRUE(r1.get() == nullptr); // NOLINT(bugprone-use-after-move)
313 EXPECT_EQ(static_cast<MyClass*>(created), r2.get());
314 EXPECT_FALSE(r1);
315 EXPECT_TRUE(r2);
316 EXPECT_FALSE(was_destroyed);
317 }
318 EXPECT_TRUE(was_destroyed);
319}
320
321TEST(RefCountedTest, NullAssignmentToNonNull) {
322 bool was_destroyed = false;
323 RefPtr<MyClass> r1(MakeRefCounted<MyClass>(nullptr, &was_destroyed));
324 // Null assignment (to non-null ref pointer) using |nullptr|.
325 r1 = nullptr;
326 EXPECT_TRUE(r1.get() == nullptr);
327 EXPECT_FALSE(r1);
328 EXPECT_TRUE(was_destroyed);
329
330 was_destroyed = false;
331 r1 = MakeRefCounted<MyClass>(nullptr, &was_destroyed);
332 RefPtr<MyClass> r2;
333 // Null assignment (to non-null ref pointer) using copy constructor.
334 r1 = r2;
335 EXPECT_TRUE(r1.get() == nullptr);
336 EXPECT_TRUE(r2.get() == nullptr);
337 EXPECT_FALSE(r1);
338 EXPECT_FALSE(r2);
339 EXPECT_TRUE(was_destroyed);
340
341 was_destroyed = false;
342 r1 = MakeRefCounted<MyClass>(nullptr, &was_destroyed);
343 // Null assignment using move constructor.
344 r1 = std::move(r2);
345 EXPECT_TRUE(r1.get() == nullptr);
346 // The clang linter flags the method called on the moved-from reference, but
347 // this is testing the move implementation, so it is marked NOLINT.
348 EXPECT_TRUE(r2.get() == nullptr); // NOLINT(clang-analyzer-cplusplus.Move,
349 // bugprone-use-after-move)
350 EXPECT_FALSE(r1);
351 EXPECT_FALSE(r2);
352 EXPECT_TRUE(was_destroyed);
353
354 was_destroyed = false;
355 r1 = MakeRefCounted<MyClass>(nullptr, &was_destroyed);
356 RefPtr<MySubclass> r3;
357 // Null assignment (to non-null ref pointer) using "copy" constructor.
358 r1 = r3;
359 EXPECT_TRUE(r1.get() == nullptr);
360 EXPECT_TRUE(r3.get() == nullptr);
361 EXPECT_FALSE(r1);
362 EXPECT_FALSE(r3);
363 EXPECT_TRUE(was_destroyed);
364
365 was_destroyed = false;
366 r1 = MakeRefCounted<MyClass>(nullptr, &was_destroyed);
367 // Null assignment (to non-null ref pointer) using "move" constructor.
368 r1 = std::move(r3);
369 EXPECT_TRUE(r1.get() == nullptr);
370 EXPECT_TRUE(r3.get() == nullptr); // NOLINT(bugprone-use-after-move)
371 EXPECT_FALSE(r1);
372 EXPECT_FALSE(r3);
373 EXPECT_TRUE(was_destroyed);
374}
375
376TEST(RefCountedTest, NonNullAssignmentToNonNull) {
377 bool was_destroyed1;
378 bool was_destroyed2;
379
380 {
381 was_destroyed1 = false;
382 was_destroyed2 = false;
383 RefPtr<MyClass> r1(MakeRefCounted<MyClass>(nullptr, &was_destroyed1));
384 RefPtr<MyClass> r2(MakeRefCounted<MyClass>(nullptr, &was_destroyed2));
385 // Copy assignment (to non-null ref pointer).
386 r2 = r1;
387 EXPECT_EQ(r1.get(), r2.get());
388 EXPECT_TRUE(r1);
389 EXPECT_TRUE(r2);
390 EXPECT_FALSE(was_destroyed1);
391 EXPECT_TRUE(was_destroyed2);
392 }
393 EXPECT_TRUE(was_destroyed1);
394
395 {
396 was_destroyed1 = false;
397 was_destroyed2 = false;
398 RefPtr<MyClass> r1(MakeRefCounted<MyClass>(nullptr, &was_destroyed1));
399 RefPtr<MyClass> r2(MakeRefCounted<MyClass>(nullptr, &was_destroyed2));
400 // Move assignment (to non-null ref pointer).
401 r2 = std::move(r1);
402 // The clang linter flags the method called on the moved-from reference, but
403 // this is testing the move implementation, so it is marked NOLINT.
404 EXPECT_TRUE(r1.get() == nullptr); // NOLINT(clang-analyzer-cplusplus.Move,
405 // bugprone-use-after-move)
406 EXPECT_FALSE(r2.get() == nullptr);
407 EXPECT_FALSE(r1);
408 EXPECT_TRUE(r2);
409 EXPECT_FALSE(was_destroyed1);
410 EXPECT_TRUE(was_destroyed2);
411 }
412 EXPECT_TRUE(was_destroyed1);
413
414 {
415 was_destroyed1 = false;
416 was_destroyed2 = false;
417 RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(nullptr, &was_destroyed1));
418 RefPtr<MyClass> r2(MakeRefCounted<MyClass>(nullptr, &was_destroyed2));
419 // "Copy" assignment (to non-null ref pointer).
420 r2 = r1;
421 EXPECT_EQ(r1.get(), r2.get());
422 EXPECT_TRUE(r1);
423 EXPECT_TRUE(r2);
424 EXPECT_FALSE(was_destroyed1);
425 EXPECT_TRUE(was_destroyed2);
426 }
427 EXPECT_TRUE(was_destroyed1);
428
429 {
430 was_destroyed1 = false;
431 was_destroyed2 = false;
432 RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(nullptr, &was_destroyed1));
433 RefPtr<MyClass> r2(MakeRefCounted<MyClass>(nullptr, &was_destroyed2));
434 // Move assignment (to non-null ref pointer).
435 r2 = std::move(r1);
436 EXPECT_TRUE(r1.get() == nullptr); // NOLINT(bugprone-use-after-move)
437 EXPECT_FALSE(r2.get() == nullptr);
438 EXPECT_FALSE(r1);
439 EXPECT_TRUE(r2);
440 EXPECT_FALSE(was_destroyed1);
441 EXPECT_TRUE(was_destroyed2);
442 }
443 EXPECT_TRUE(was_destroyed1);
444}
445
446TEST(RefCountedTest, SelfAssignment) {
447 bool was_destroyed;
448
449 {
450 MyClass* created = nullptr;
451 was_destroyed = false;
452 // This line is marked NOLINT because the clang linter does not reason about
453 // the value of the reference count. In particular, the self-assignment
454 // below is handled in the copy constructor by a refcount increment then
455 // decrement. The linter sees only that the decrement might destroy the
456 // object.
457 RefPtr<MyClass> r(MakeRefCounted<MyClass>( // NOLINT
458 &created, &was_destroyed));
459 // Copy.
461 EXPECT_EQ(created, r.get());
462 EXPECT_FALSE(was_destroyed);
463 }
464 EXPECT_TRUE(was_destroyed);
465
466 {
467 MyClass* created = nullptr;
468 was_destroyed = false;
469 RefPtr<MyClass> r(MakeRefCounted<MyClass>(&created, &was_destroyed));
470 // Move.
471 ALLOW_SELF_MOVE(r = std::move(r))
472 EXPECT_EQ(created, r.get());
473 EXPECT_FALSE(was_destroyed);
474 }
475 EXPECT_TRUE(was_destroyed);
476}
477
478TEST(RefCountedTest, Swap) {
479 MyClass* created1 = nullptr;
480 static bool was_destroyed1;
481 was_destroyed1 = false;
482 RefPtr<MyClass> r1(MakeRefCounted<MyClass>(&created1, &was_destroyed1));
483 EXPECT_TRUE(created1);
484 EXPECT_EQ(created1, r1.get());
485
486 MyClass* created2 = nullptr;
487 static bool was_destroyed2;
488 was_destroyed2 = false;
489 RefPtr<MyClass> r2(MakeRefCounted<MyClass>(&created2, &was_destroyed2));
490 EXPECT_TRUE(created2);
491 EXPECT_EQ(created2, r2.get());
492 EXPECT_NE(created1, created2);
493
494 r1.swap(r2);
495 EXPECT_EQ(created2, r1.get());
496 EXPECT_EQ(created1, r2.get());
497}
498
499TEST(RefCountedTest, GetAndDereferenceOperators) {
500 // Note: We check here that .get(), operator*, and operator-> are const, but
501 // return non-const pointers/refs.
502
503 MyClass* created = nullptr;
504 const RefPtr<MyClass> r(MakeRefCounted<MyClass>(&created, nullptr));
505 MyClass* ptr = r.get(); // Assign to non-const pointer.
506 EXPECT_EQ(created, ptr);
507 ptr = r.operator->(); // Assign to non-const pointer.
508 EXPECT_EQ(created, ptr);
509 MyClass& ref = *r; // "Assign" to non-const reference.
510 EXPECT_EQ(created, &ref);
511}
512
513// You can manually call |AddRef()| and |Release()| if you want.
514TEST(RefCountedTest, AddRefRelease) {
515 MyClass* created = nullptr;
516 bool was_destroyed = false;
517 {
518 RefPtr<MyClass> r(MakeRefCounted<MyClass>(&created, &was_destroyed));
519 EXPECT_EQ(created, r.get());
520 created->AddRef();
521 }
522 EXPECT_FALSE(was_destroyed);
523 created->Release();
524 EXPECT_TRUE(was_destroyed);
525}
526
527TEST(RefCountedTest, Mix) {
528 MySubclass* created = nullptr;
529 bool was_destroyed = false;
530 RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(&created, &was_destroyed));
531 ASSERT_FALSE(was_destroyed);
532 EXPECT_TRUE(created->HasOneRef());
533 created->AssertHasOneRef();
534
535 RefPtr<MySubclass> r2 = r1;
536 ASSERT_FALSE(was_destroyed);
537 EXPECT_FALSE(created->HasOneRef());
538
539 r1 = nullptr;
540 ASSERT_FALSE(was_destroyed);
541 created->AssertHasOneRef();
542
543 {
544 RefPtr<MyClass> r3 = r2;
545 EXPECT_FALSE(created->HasOneRef());
546 {
547 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
548 RefPtr<MyClass> r4(r3);
549 r2 = nullptr;
550 ASSERT_FALSE(was_destroyed);
551 EXPECT_FALSE(created->HasOneRef());
552 }
553 ASSERT_FALSE(was_destroyed);
554 EXPECT_TRUE(created->HasOneRef());
555 created->AssertHasOneRef();
556
557 r1 = RefPtr<MySubclass>(static_cast<MySubclass*>(r3.get()));
558 ASSERT_FALSE(was_destroyed);
559 EXPECT_FALSE(created->HasOneRef());
560 }
561 ASSERT_FALSE(was_destroyed);
562 EXPECT_TRUE(created->HasOneRef());
563 created->AssertHasOneRef();
564
565 EXPECT_EQ(created, r1.get());
566
567 r1 = nullptr;
568 EXPECT_TRUE(was_destroyed);
569}
570
571class MyPublicClass : public RefCountedThreadSafe<MyPublicClass> {
572 public:
573 // Overloaded constructors work with |MakeRefCounted()|.
574 MyPublicClass() : has_num_(false), num_(0) {}
575 explicit MyPublicClass(int num) : has_num_(true), num_(num) {}
576
577 ~MyPublicClass() {}
578
579 bool has_num() const { return has_num_; }
580 int num() const { return num_; }
581
582 private:
583 bool has_num_;
584 int num_;
585
586 FML_DISALLOW_COPY_AND_ASSIGN(MyPublicClass);
587};
588
589// You can also just keep constructors and destructors public. Make sure that
590// works (mostly that it compiles).
591TEST(RefCountedTest, PublicCtorAndDtor) {
592 RefPtr<MyPublicClass> r1 = MakeRefCounted<MyPublicClass>();
593 ASSERT_TRUE(r1);
594 EXPECT_FALSE(r1->has_num());
595
596 RefPtr<MyPublicClass> r2 = MakeRefCounted<MyPublicClass>(123);
597 ASSERT_TRUE(r2);
598 EXPECT_TRUE(r2->has_num());
599 EXPECT_EQ(123, r2->num());
600 EXPECT_NE(r1.get(), r2.get());
601
602 r1 = r2;
603 EXPECT_TRUE(r1->has_num());
604 EXPECT_EQ(123, r1->num());
605 EXPECT_EQ(r1.get(), r2.get());
606
607 r2 = nullptr;
608 EXPECT_FALSE(r2);
609 EXPECT_TRUE(r1->has_num());
610 EXPECT_EQ(123, r1->num());
611
612 r1 = nullptr;
613 EXPECT_FALSE(r1);
614}
615
616// The danger with having a public constructor or destructor is that certain
617// things will compile. You should get some protection by assertions in Debug
618// builds.
619#ifndef NDEBUG
620TEST(RefCountedTest, DebugChecks) {
621 {
622 MyPublicClass* p = new MyPublicClass();
623 EXPECT_DEATH_IF_SUPPORTED( // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
624 delete p, "!adoption_required_");
625 }
626
627 {
628 MyPublicClass* p = new MyPublicClass();
629 EXPECT_DEATH_IF_SUPPORTED( // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
630 RefPtr<MyPublicClass> r(p), "!adoption_required_");
631 }
632
633 {
634 RefPtr<MyPublicClass> r(MakeRefCounted<MyPublicClass>());
635 EXPECT_DEATH_IF_SUPPORTED(delete r.get(), "destruction_started_");
636 }
637}
638#endif
639
640// TODO(vtl): Add (threaded) stress tests.
641
642} // namespace
643} // namespace fml
#define TEST(S, s, D, expected)
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
#define FML_FRIEND_REF_COUNTED_THREAD_SAFE(T)
#define FML_FRIEND_MAKE_REF_COUNTED(T)
#define ALLOW_PESSIMIZING_MOVE(code_line)
#define ALLOW_SELF_ASSIGN_OVERLOADED(code_line)
#define ALLOW_SELF_MOVE(code_line)
#define EXPECT_TRUE(handle)
Definition unit_test.h:685