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