1 // Copyright 2017 The Fuchsia 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 #include <fbl/alloc_checker.h>
6 #include <fbl/ref_counted.h>
7 #include <fbl/ref_ptr.h>
8 #include <fbl/unique_ptr.h>
9 #include <unittest/unittest.h>
10
11 namespace {
12
13 template <typename T> struct PtrTraits;
14
15 template <typename T>
16 struct PtrTraits<fbl::unique_ptr<T>> {
17 using ObjType = typename fbl::remove_cv<T>::type;
MakePointer__anon4134c3020111::PtrTraits18 static fbl::unique_ptr<T> MakePointer(T* raw) { return fbl::unique_ptr<T>(raw); }
19 };
20
21 template <typename T>
22 struct PtrTraits<fbl::RefPtr<T>> {
23 using ObjType = typename fbl::remove_cv<T>::type;
MakePointer__anon4134c3020111::PtrTraits24 static fbl::RefPtr<T> MakePointer(T* raw) { return fbl::AdoptRef<T>(raw); }
25 };
26
27
28 class TestBase {
29 public:
TestBase()30 TestBase() { recycle_was_called_ = false; }
recycle_was_called()31 static bool recycle_was_called() { return recycle_was_called_; }
32 protected:
33 static bool recycle_was_called_;
34 };
35
36 bool TestBase::recycle_was_called_;
37
38 class TestPublicRecycle : public TestBase,
39 public fbl::Recyclable<TestPublicRecycle> {
40 public:
fbl_recycle()41 void fbl_recycle() {
42 recycle_was_called_ = true;
43 delete this;
44 }
45 };
46
47 class RefedTestPublicRecycle : public TestBase,
48 public fbl::RefCounted<RefedTestPublicRecycle>,
49 public fbl::Recyclable<RefedTestPublicRecycle> {
50 public:
fbl_recycle()51 void fbl_recycle() {
52 recycle_was_called_ = true;
53 delete this;
54 }
55 };
56
57 class TestPrivateRecycle : public TestBase,
58 public fbl::Recyclable<TestPrivateRecycle> {
59 private:
60 friend class fbl::Recyclable<TestPrivateRecycle>;
fbl_recycle()61 void fbl_recycle() {
62 recycle_was_called_ = true;
63 delete this;
64 }
65 };
66
67 class RefedTestPrivateRecycle : public TestBase,
68 public fbl::RefCounted<RefedTestPrivateRecycle>,
69 public fbl::Recyclable<RefedTestPrivateRecycle> {
70 private:
71 friend class fbl::Recyclable<RefedTestPrivateRecycle>;
fbl_recycle()72 void fbl_recycle() {
73 recycle_was_called_ = true;
74 delete this;
75 }
76 };
77
78 struct FailNoMethod : public fbl::Recyclable<FailNoMethod> { };
fbl_recycle__anon4134c3020111::FailBadRet79 struct FailBadRet : public fbl::Recyclable<FailBadRet> { int fbl_recycle() { return 1; } };
fbl_recycle__anon4134c3020111::FailBadArg80 struct FailBadArg : public fbl::Recyclable<FailBadArg> { void fbl_recycle(int a = 1) {} };
fbl_recycle()81 class FailNotVis : public fbl::Recyclable<FailNotVis> { void fbl_recycle() {} };
82
83 #if TEST_WILL_NOT_COMPILE || 0
fbl_recycle__anon4134c3020111::FailCVBase184 struct FailCVBase1 : public fbl::Recyclable<const FailCVBase1> { void fbl_recycle() {} };
85 #endif
86 #if TEST_WILL_NOT_COMPILE || 0
fbl_recycle__anon4134c3020111::FailCVBase287 struct FailCVBase2 : public fbl::Recyclable<volatile FailCVBase2> { void fbl_recycle() {} };
88 #endif
89 #if TEST_WILL_NOT_COMPILE || 0
fbl_recycle__anon4134c3020111::FailCVBase390 struct FailCVBase3 : public fbl::Recyclable<const volatile FailCVBase3> { void fbl_recycle() {} };
91 #endif
92
93 template <typename T>
do_test()94 static bool do_test() {
95 BEGIN_TEST;
96
97 fbl::AllocChecker ac;
98 auto ptr = PtrTraits<T>::MakePointer(new (&ac) typename PtrTraits<T>::ObjType);
99
100 ASSERT_TRUE(ac.check());
101 EXPECT_FALSE(TestBase::recycle_was_called());
102
103 ptr = nullptr;
104 EXPECT_TRUE(TestBase::recycle_was_called());
105
106 END_TEST;
107 }
108
109 } // anon namespace
110
111 BEGIN_TEST_CASE(fbl_recycle)
112 RUN_NAMED_TEST("public unique_ptr fbl_recycle()",
113 do_test<fbl::unique_ptr<TestPublicRecycle>>)
114 RUN_NAMED_TEST("public const unique_ptr fbl_recycle()",
115 do_test<fbl::unique_ptr<const TestPublicRecycle>>)
116 RUN_NAMED_TEST("public volatile unique_ptr fbl_recycle()",
117 do_test<fbl::unique_ptr<volatile TestPublicRecycle>>)
118 RUN_NAMED_TEST("public const volatile unique_ptr fbl_recycle()",
119 do_test<fbl::unique_ptr<const volatile TestPublicRecycle>>)
120 RUN_NAMED_TEST("private unique_ptr fbl_recycle()",
121 do_test<fbl::unique_ptr<TestPrivateRecycle>>)
122 RUN_NAMED_TEST("private const unique_ptr fbl_recycle()",
123 do_test<fbl::unique_ptr<const TestPrivateRecycle>>)
124 RUN_NAMED_TEST("private volatile unique_ptr fbl_recycle()",
125 do_test<fbl::unique_ptr<volatile TestPrivateRecycle>>)
126 RUN_NAMED_TEST("private const volatile unique_ptr fbl_recycle()",
127 do_test<fbl::unique_ptr<const volatile TestPrivateRecycle>>)
128 RUN_NAMED_TEST("public RefPtr fbl_recycle()",
129 do_test<fbl::RefPtr<RefedTestPublicRecycle>>)
130 RUN_NAMED_TEST("private RefPtr fbl_recycle()",
131 do_test<fbl::RefPtr<RefedTestPrivateRecycle>>)
132 #if TEST_WILL_NOT_COMPILE || 0
133 // TODO(johngro) : If we ever support RefPtr<>s to const/volatile objects,
134 // instantiate tests for them here.
135 RUN_NAMED_TEST("public const RefPtr fbl_recycle()",
136 do_test<fbl::RefPtr<const RefedTestPublicRecycle>>)
137 RUN_NAMED_TEST("public volatile RefPtr fbl_recycle()",
138 do_test<fbl::RefPtr<volatile RefedTestPublicRecycle>>)
139 RUN_NAMED_TEST("public const volatile RefPtr fbl_recycle()",
140 do_test<fbl::RefPtr<const volatile RefedTestPublicRecycle>>)
141 RUN_NAMED_TEST("private const RefPtr fbl_recycle()",
142 do_test<fbl::RefPtr<const RefedTestPrivateRecycle>>)
143 RUN_NAMED_TEST("private volatile RefPtr fbl_recycle()",
144 do_test<fbl::RefPtr<volatile RefedTestPrivateRecycle>>)
145 RUN_NAMED_TEST("private const volatile RefPtr fbl_recycle()",
146 do_test<fbl::RefPtr<const volatile RefedTestPrivateRecycle>>)
147 #endif
148 #if TEST_WILL_NOT_COMPILE || 0
149 RUN_NAMED_TEST("FailNoMethod", do_test<fbl::unique_ptr<FailNoMethod>>);
150 #endif
151 #if TEST_WILL_NOT_COMPILE || 0
152 RUN_NAMED_TEST("FailBadRet", do_test<fbl::unique_ptr<FailBadRet>>);
153 #endif
154 #if TEST_WILL_NOT_COMPILE || 0
155 RUN_NAMED_TEST("FailBadArg", do_test<fbl::unique_ptr<FailBadArg>>);
156 #endif
157 #if TEST_WILL_NOT_COMPILE || 0
158 RUN_NAMED_TEST("FailNotVis", do_test<fbl::unique_ptr<FailBadArg>>);
159 #endif
160 END_TEST_CASE(fbl_recycle);
161