Flutter Engine
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 
42 namespace fml {
43 namespace {
44 
45 class 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 
68 class MySubclass final : public MyClass {
69  private:
71  FML_FRIEND_MAKE_REF_COUNTED(MySubclass);
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 
81  FML_DISALLOW_COPY_AND_ASSIGN(MySubclass);
82 };
83 
84 TEST(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  RefPtr<MyClass> r2(r1);
132  EXPECT_TRUE(created);
133  EXPECT_EQ(created, r1.get());
134  EXPECT_EQ(created, r2.get());
135  EXPECT_TRUE(r1);
136  EXPECT_TRUE(r2);
137  EXPECT_FALSE(was_destroyed);
138  }
139  EXPECT_TRUE(was_destroyed);
140 
141  {
142  MyClass* created = nullptr;
143  was_destroyed = false;
144  RefPtr<MyClass> r1(MakeRefCounted<MyClass>(&created, &was_destroyed));
145  // From raw pointer.
146  RefPtr<MyClass> r2(created);
147  EXPECT_TRUE(created);
148  EXPECT_EQ(created, r1.get());
149  EXPECT_EQ(created, r2.get());
150  EXPECT_TRUE(r1);
151  EXPECT_TRUE(r2);
152  EXPECT_FALSE(was_destroyed);
153  }
154  EXPECT_TRUE(was_destroyed);
155 
156  {
157  MySubclass* created = nullptr;
158  was_destroyed = false;
159  // Adopt, then "move".
160  RefPtr<MyClass> r(MakeRefCounted<MySubclass>(&created, &was_destroyed));
161  EXPECT_TRUE(created);
162  EXPECT_EQ(static_cast<MyClass*>(created), r.get());
163  EXPECT_TRUE(r);
164  EXPECT_FALSE(was_destroyed);
165  }
166  EXPECT_TRUE(was_destroyed);
167 
168  {
169  MySubclass* created = nullptr;
170  was_destroyed = false;
171  // Adopt, then "move".
172  ALLOW_PESSIMIZING_MOVE(RefPtr<MyClass> r(
173  std::move(MakeRefCounted<MySubclass>(&created, &was_destroyed))))
174  EXPECT_TRUE(created);
175  EXPECT_EQ(static_cast<MyClass*>(created), r.get());
176  EXPECT_TRUE(r);
177  EXPECT_FALSE(was_destroyed);
178  }
179  EXPECT_TRUE(was_destroyed);
180 
181  {
182  MySubclass* created = nullptr;
183  was_destroyed = false;
184  RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(&created, &was_destroyed));
185  // "Copy".
186  RefPtr<MyClass> r2(r1);
187  EXPECT_TRUE(created);
188  EXPECT_EQ(static_cast<MyClass*>(created), r1.get());
189  EXPECT_EQ(static_cast<MyClass*>(created), r2.get());
190  EXPECT_TRUE(r1);
191  EXPECT_TRUE(r2);
192  EXPECT_FALSE(was_destroyed);
193  }
194  EXPECT_TRUE(was_destroyed);
195 
196  {
197  MySubclass* created = nullptr;
198  was_destroyed = false;
199  RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(&created, &was_destroyed));
200  // From raw pointer.
201  RefPtr<MyClass> r2(created);
202  EXPECT_TRUE(created);
203  EXPECT_EQ(static_cast<MyClass*>(created), r1.get());
204  EXPECT_EQ(static_cast<MyClass*>(created), r2.get());
205  EXPECT_TRUE(r1);
206  EXPECT_TRUE(r2);
207  EXPECT_FALSE(was_destroyed);
208  }
209  EXPECT_TRUE(was_destroyed);
210 }
211 
212 TEST(RefCountedTest, NullAssignmentToNull) {
213  RefPtr<MyClass> r1;
214  // No-op null assignment using |nullptr|.
215  r1 = nullptr;
216  EXPECT_TRUE(r1.get() == nullptr);
217  EXPECT_FALSE(r1);
218 
219  RefPtr<MyClass> r2;
220  // No-op null assignment using copy constructor.
221  r1 = r2;
222  EXPECT_TRUE(r1.get() == nullptr);
223  EXPECT_TRUE(r2.get() == nullptr);
224  EXPECT_FALSE(r1);
225  EXPECT_FALSE(r2);
226 
227  // No-op null assignment using move constructor.
228  r1 = std::move(r2);
229  EXPECT_TRUE(r1.get() == nullptr);
230  // The clang linter flags the method called on the moved-from reference, but
231  // this is testing the move implementation, so it is marked NOLINT.
232  EXPECT_TRUE(r2.get() == nullptr); // NOLINT(clang-analyzer-cplusplus.Move)
233  EXPECT_FALSE(r1);
234  EXPECT_FALSE(r2);
235 
236  RefPtr<MySubclass> r3;
237  // No-op null assignment using "copy" constructor.
238  r1 = r3;
239  EXPECT_TRUE(r1.get() == nullptr);
240  EXPECT_TRUE(r3.get() == nullptr);
241  EXPECT_FALSE(r1);
242  EXPECT_FALSE(r3);
243 
244  // No-op null assignment using "move" constructor.
245  r1 = std::move(r3);
246  EXPECT_TRUE(r1.get() == nullptr);
247  EXPECT_TRUE(r3.get() == nullptr);
248  EXPECT_FALSE(r1);
249  EXPECT_FALSE(r3);
250 }
251 
252 TEST(RefCountedTest, NonNullAssignmentToNull) {
253  bool was_destroyed;
254 
255  {
256  MyClass* created = nullptr;
257  was_destroyed = false;
258  RefPtr<MyClass> r1(MakeRefCounted<MyClass>(&created, &was_destroyed));
259  RefPtr<MyClass> r2;
260  // Copy assignment (to null ref pointer).
261  r2 = r1;
262  EXPECT_EQ(created, r1.get());
263  EXPECT_EQ(created, r2.get());
264  EXPECT_TRUE(r1);
265  EXPECT_TRUE(r2);
266  EXPECT_FALSE(was_destroyed);
267  }
268  EXPECT_TRUE(was_destroyed);
269 
270  {
271  MyClass* created = nullptr;
272  was_destroyed = false;
273  RefPtr<MyClass> r1(MakeRefCounted<MyClass>(&created, &was_destroyed));
274  RefPtr<MyClass> r2;
275  // Move assignment (to null ref pointer).
276  r2 = std::move(r1);
277  // The clang linter flags the method called on the moved-from reference, but
278  // this is testing the move implementation, so it is marked NOLINT.
279  EXPECT_TRUE(r1.get() == nullptr); // NOLINT(clang-analyzer-cplusplus.Move)
280  EXPECT_EQ(created, r2.get());
281  EXPECT_FALSE(r1);
282  EXPECT_TRUE(r2);
283  EXPECT_FALSE(was_destroyed);
284  }
285  EXPECT_TRUE(was_destroyed);
286 
287  {
288  MySubclass* created = nullptr;
289  was_destroyed = false;
290  RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(&created, &was_destroyed));
291  RefPtr<MyClass> r2;
292  // "Copy" assignment (to null ref pointer).
293  r2 = r1;
294  EXPECT_EQ(created, r1.get());
295  EXPECT_EQ(static_cast<MyClass*>(created), r2.get());
296  EXPECT_TRUE(r1);
297  EXPECT_TRUE(r2);
298  EXPECT_FALSE(was_destroyed);
299  }
300  EXPECT_TRUE(was_destroyed);
301 
302  {
303  MySubclass* created = nullptr;
304  was_destroyed = false;
305  RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(&created, &was_destroyed));
306  RefPtr<MyClass> r2;
307  // "Move" assignment (to null ref pointer).
308  r2 = std::move(r1);
309  EXPECT_TRUE(r1.get() == nullptr);
310  EXPECT_EQ(static_cast<MyClass*>(created), r2.get());
311  EXPECT_FALSE(r1);
312  EXPECT_TRUE(r2);
313  EXPECT_FALSE(was_destroyed);
314  }
315  EXPECT_TRUE(was_destroyed);
316 }
317 
318 TEST(RefCountedTest, NullAssignmentToNonNull) {
319  bool was_destroyed = false;
320  RefPtr<MyClass> r1(MakeRefCounted<MyClass>(nullptr, &was_destroyed));
321  // Null assignment (to non-null ref pointer) using |nullptr|.
322  r1 = nullptr;
323  EXPECT_TRUE(r1.get() == nullptr);
324  EXPECT_FALSE(r1);
325  EXPECT_TRUE(was_destroyed);
326 
327  was_destroyed = false;
328  r1 = MakeRefCounted<MyClass>(nullptr, &was_destroyed);
329  RefPtr<MyClass> r2;
330  // Null assignment (to non-null ref pointer) using copy constructor.
331  r1 = r2;
332  EXPECT_TRUE(r1.get() == nullptr);
333  EXPECT_TRUE(r2.get() == nullptr);
334  EXPECT_FALSE(r1);
335  EXPECT_FALSE(r2);
336  EXPECT_TRUE(was_destroyed);
337 
338  was_destroyed = false;
339  r1 = MakeRefCounted<MyClass>(nullptr, &was_destroyed);
340  // Null assignment using move constructor.
341  r1 = std::move(r2);
342  EXPECT_TRUE(r1.get() == nullptr);
343  // The clang linter flags the method called on the moved-from reference, but
344  // this is testing the move implementation, so it is marked NOLINT.
345  EXPECT_TRUE(r2.get() == nullptr); // NOLINT(clang-analyzer-cplusplus.Move)
346  EXPECT_FALSE(r1);
347  EXPECT_FALSE(r2);
348  EXPECT_TRUE(was_destroyed);
349 
350  was_destroyed = false;
351  r1 = MakeRefCounted<MyClass>(nullptr, &was_destroyed);
352  RefPtr<MySubclass> r3;
353  // Null assignment (to non-null ref pointer) using "copy" constructor.
354  r1 = r3;
355  EXPECT_TRUE(r1.get() == nullptr);
356  EXPECT_TRUE(r3.get() == nullptr);
357  EXPECT_FALSE(r1);
358  EXPECT_FALSE(r3);
359  EXPECT_TRUE(was_destroyed);
360 
361  was_destroyed = false;
362  r1 = MakeRefCounted<MyClass>(nullptr, &was_destroyed);
363  // Null assignment (to non-null ref pointer) using "move" constructor.
364  r1 = std::move(r3);
365  EXPECT_TRUE(r1.get() == nullptr);
366  EXPECT_TRUE(r3.get() == nullptr);
367  EXPECT_FALSE(r1);
368  EXPECT_FALSE(r3);
369  EXPECT_TRUE(was_destroyed);
370 }
371 
372 TEST(RefCountedTest, NonNullAssignmentToNonNull) {
373  bool was_destroyed1;
374  bool was_destroyed2;
375 
376  {
377  was_destroyed1 = false;
378  was_destroyed2 = false;
379  RefPtr<MyClass> r1(MakeRefCounted<MyClass>(nullptr, &was_destroyed1));
380  RefPtr<MyClass> r2(MakeRefCounted<MyClass>(nullptr, &was_destroyed2));
381  // Copy assignment (to non-null ref pointer).
382  r2 = r1;
383  EXPECT_EQ(r1.get(), r2.get());
384  EXPECT_TRUE(r1);
385  EXPECT_TRUE(r2);
386  EXPECT_FALSE(was_destroyed1);
387  EXPECT_TRUE(was_destroyed2);
388  }
389  EXPECT_TRUE(was_destroyed1);
390 
391  {
392  was_destroyed1 = false;
393  was_destroyed2 = false;
394  RefPtr<MyClass> r1(MakeRefCounted<MyClass>(nullptr, &was_destroyed1));
395  RefPtr<MyClass> r2(MakeRefCounted<MyClass>(nullptr, &was_destroyed2));
396  // Move assignment (to non-null ref pointer).
397  r2 = std::move(r1);
398  // The clang linter flags the method called on the moved-from reference, but
399  // this is testing the move implementation, so it is marked NOLINT.
400  EXPECT_TRUE(r1.get() == nullptr); // NOLINT(clang-analyzer-cplusplus.Move)
401  EXPECT_FALSE(r2.get() == nullptr);
402  EXPECT_FALSE(r1);
403  EXPECT_TRUE(r2);
404  EXPECT_FALSE(was_destroyed1);
405  EXPECT_TRUE(was_destroyed2);
406  }
407  EXPECT_TRUE(was_destroyed1);
408 
409  {
410  was_destroyed1 = false;
411  was_destroyed2 = false;
412  RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(nullptr, &was_destroyed1));
413  RefPtr<MyClass> r2(MakeRefCounted<MyClass>(nullptr, &was_destroyed2));
414  // "Copy" assignment (to non-null ref pointer).
415  r2 = r1;
416  EXPECT_EQ(r1.get(), r2.get());
417  EXPECT_TRUE(r1);
418  EXPECT_TRUE(r2);
419  EXPECT_FALSE(was_destroyed1);
420  EXPECT_TRUE(was_destroyed2);
421  }
422  EXPECT_TRUE(was_destroyed1);
423 
424  {
425  was_destroyed1 = false;
426  was_destroyed2 = false;
427  RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(nullptr, &was_destroyed1));
428  RefPtr<MyClass> r2(MakeRefCounted<MyClass>(nullptr, &was_destroyed2));
429  // Move assignment (to non-null ref pointer).
430  r2 = std::move(r1);
431  EXPECT_TRUE(r1.get() == nullptr);
432  EXPECT_FALSE(r2.get() == nullptr);
433  EXPECT_FALSE(r1);
434  EXPECT_TRUE(r2);
435  EXPECT_FALSE(was_destroyed1);
436  EXPECT_TRUE(was_destroyed2);
437  }
438  EXPECT_TRUE(was_destroyed1);
439 }
440 
441 TEST(RefCountedTest, SelfAssignment) {
442  bool was_destroyed;
443 
444  {
445  MyClass* created = nullptr;
446  was_destroyed = false;
447  // This line is marked NOLINT because the clang linter does not reason about
448  // the value of the reference count. In particular, the self-assignment
449  // below is handled in the copy constructor by a refcount increment then
450  // decrement. The linter sees only that the decrement might destroy the
451  // object.
452  RefPtr<MyClass> r(MakeRefCounted<MyClass>( // NOLINT
453  &created, &was_destroyed));
454  // Copy.
456  EXPECT_EQ(created, r.get());
457  EXPECT_FALSE(was_destroyed);
458  }
459  EXPECT_TRUE(was_destroyed);
460 
461  {
462  MyClass* created = nullptr;
463  was_destroyed = false;
464  RefPtr<MyClass> r(MakeRefCounted<MyClass>(&created, &was_destroyed));
465  // Move.
466  ALLOW_SELF_MOVE(r = std::move(r))
467  EXPECT_EQ(created, r.get());
468  EXPECT_FALSE(was_destroyed);
469  }
470  EXPECT_TRUE(was_destroyed);
471 }
472 
473 TEST(RefCountedTest, Swap) {
474  MyClass* created1 = nullptr;
475  bool was_destroyed1 = false;
476  RefPtr<MyClass> r1(MakeRefCounted<MyClass>(&created1, &was_destroyed1));
477  EXPECT_TRUE(created1);
478  EXPECT_EQ(created1, r1.get());
479 
480  MyClass* created2 = nullptr;
481  bool was_destroyed2 = false;
482  RefPtr<MyClass> r2(MakeRefCounted<MyClass>(&created2, &was_destroyed2));
483  EXPECT_TRUE(created2);
484  EXPECT_EQ(created2, r2.get());
485  EXPECT_NE(created1, created2);
486 
487  r1.swap(r2);
488  EXPECT_EQ(created2, r1.get());
489  EXPECT_EQ(created1, r2.get());
490 }
491 
492 TEST(RefCountedTest, GetAndDereferenceOperators) {
493  // Note: We check here that .get(), operator*, and operator-> are const, but
494  // return non-const pointers/refs.
495 
496  MyClass* created = nullptr;
497  const RefPtr<MyClass> r(MakeRefCounted<MyClass>(&created, nullptr));
498  MyClass* ptr = r.get(); // Assign to non-const pointer.
499  EXPECT_EQ(created, ptr);
500  ptr = r.operator->(); // Assign to non-const pointer.
501  EXPECT_EQ(created, ptr);
502  MyClass& ref = *r; // "Assign" to non-const reference.
503  EXPECT_EQ(created, &ref);
504 }
505 
506 // You can manually call |AddRef()| and |Release()| if you want.
507 TEST(RefCountedTest, AddRefRelease) {
508  MyClass* created = nullptr;
509  bool was_destroyed = false;
510  {
511  RefPtr<MyClass> r(MakeRefCounted<MyClass>(&created, &was_destroyed));
512  EXPECT_EQ(created, r.get());
513  created->AddRef();
514  }
515  EXPECT_FALSE(was_destroyed);
516  created->Release();
517  EXPECT_TRUE(was_destroyed);
518 }
519 
520 TEST(RefCountedTest, Mix) {
521  MySubclass* created = nullptr;
522  bool was_destroyed = false;
523  RefPtr<MySubclass> r1(MakeRefCounted<MySubclass>(&created, &was_destroyed));
524  ASSERT_FALSE(was_destroyed);
525  EXPECT_TRUE(created->HasOneRef());
526  created->AssertHasOneRef();
527 
528  RefPtr<MySubclass> r2 = r1;
529  ASSERT_FALSE(was_destroyed);
530  EXPECT_FALSE(created->HasOneRef());
531 
532  r1 = nullptr;
533  ASSERT_FALSE(was_destroyed);
534  created->AssertHasOneRef();
535 
536  {
537  RefPtr<MyClass> r3 = r2;
538  EXPECT_FALSE(created->HasOneRef());
539  {
540  RefPtr<MyClass> r4(r3);
541  r2 = nullptr;
542  ASSERT_FALSE(was_destroyed);
543  EXPECT_FALSE(created->HasOneRef());
544  }
545  ASSERT_FALSE(was_destroyed);
546  EXPECT_TRUE(created->HasOneRef());
547  created->AssertHasOneRef();
548 
549  r1 = RefPtr<MySubclass>(static_cast<MySubclass*>(r3.get()));
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  EXPECT_EQ(created, r1.get());
558 
559  r1 = nullptr;
560  EXPECT_TRUE(was_destroyed);
561 }
562 
563 class MyPublicClass : public RefCountedThreadSafe<MyPublicClass> {
564  public:
565  // Overloaded constructors work with |MakeRefCounted()|.
566  MyPublicClass() : has_num_(false), num_(0) {}
567  explicit MyPublicClass(int num) : has_num_(true), num_(num) {}
568 
569  ~MyPublicClass() {}
570 
571  bool has_num() const { return has_num_; }
572  int num() const { return num_; }
573 
574  private:
575  bool has_num_;
576  int num_;
577 
578  FML_DISALLOW_COPY_AND_ASSIGN(MyPublicClass);
579 };
580 
581 // You can also just keep constructors and destructors public. Make sure that
582 // works (mostly that it compiles).
583 TEST(RefCountedTest, PublicCtorAndDtor) {
584  RefPtr<MyPublicClass> r1 = MakeRefCounted<MyPublicClass>();
585  ASSERT_TRUE(r1);
586  EXPECT_FALSE(r1->has_num());
587 
588  RefPtr<MyPublicClass> r2 = MakeRefCounted<MyPublicClass>(123);
589  ASSERT_TRUE(r2);
590  EXPECT_TRUE(r2->has_num());
591  EXPECT_EQ(123, r2->num());
592  EXPECT_NE(r1.get(), r2.get());
593 
594  r1 = r2;
595  EXPECT_TRUE(r1->has_num());
596  EXPECT_EQ(123, r1->num());
597  EXPECT_EQ(r1.get(), r2.get());
598 
599  r2 = nullptr;
600  EXPECT_FALSE(r2);
601  EXPECT_TRUE(r1->has_num());
602  EXPECT_EQ(123, r1->num());
603 
604  r1 = nullptr;
605  EXPECT_FALSE(r1);
606 }
607 
608 // The danger with having a public constructor or destructor is that certain
609 // things will compile. You should get some protection by assertions in Debug
610 // builds.
611 #ifndef NDEBUG
612 TEST(RefCountedTest, DebugChecks) {
613  {
614  MyPublicClass* p = new MyPublicClass();
615  EXPECT_DEATH_IF_SUPPORTED( // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
616  delete p, "!adoption_required_");
617  }
618 
619  {
620  MyPublicClass* p = new MyPublicClass();
621  EXPECT_DEATH_IF_SUPPORTED( // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
622  RefPtr<MyPublicClass> r(p), "!adoption_required_");
623  }
624 
625  {
626  RefPtr<MyPublicClass> r(MakeRefCounted<MyPublicClass>());
627  EXPECT_DEATH_IF_SUPPORTED(delete r.get(), "destruction_started_");
628  }
629 }
630 #endif
631 
632 // TODO(vtl): Add (threaded) stress tests.
633 
634 } // namespace
635 } // namespace fml
#define FML_FRIEND_REF_COUNTED_THREAD_SAFE(T)
Definition: ref_counted.h:125
#define ALLOW_PESSIMIZING_MOVE(code_line)
Definition: ascii_trie.cc:9
#define FML_FRIEND_MAKE_REF_COUNTED(T)
Definition: ref_counted.h:131
#define ALLOW_SELF_MOVE(code_line)
TEST(MessageTest, CanEncodeTriviallyCopyableTypes)
#define ALLOW_SELF_ASSIGN_OVERLOADED(code_line)
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27