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