• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gtest/gtest.h>
18 
19 #include <utils/StrongPointer.h>
20 #include <utils/RefBase.h>
21 
22 using namespace android;
23 
24 class SPFoo : virtual public RefBase {
25   public:
SPFoo(bool * deleted_check)26     explicit SPFoo(bool* deleted_check) : mDeleted(deleted_check) {
27         *mDeleted = false;
28     }
29 
~SPFoo()30     ~SPFoo() {
31         *mDeleted = true;
32     }
33 
34   private:
35     bool* mDeleted;
36 };
37 
38 class SPLightFoo : virtual public VirtualLightRefBase {
39   public:
SPLightFoo(bool * deleted_check)40     explicit SPLightFoo(bool* deleted_check) : mDeleted(deleted_check) { *mDeleted = false; }
41 
~SPLightFoo()42     ~SPLightFoo() { *mDeleted = true; }
43 
44   private:
45     bool* mDeleted;
46 };
47 
48 template <typename T>
49 class StrongPointer : public ::testing::Test {};
50 
51 using RefBaseTypes = ::testing::Types<SPFoo, SPLightFoo>;
52 TYPED_TEST_CASE(StrongPointer, RefBaseTypes);
53 
TYPED_TEST(StrongPointer,move)54 TYPED_TEST(StrongPointer, move) {
55     bool isDeleted;
56     sp<TypeParam> sp1 = sp<TypeParam>::make(&isDeleted);
57     TypeParam* foo = sp1.get();
58     ASSERT_EQ(1, foo->getStrongCount());
59     {
60         sp<TypeParam> sp2 = std::move(sp1);
61         ASSERT_EQ(1, foo->getStrongCount()) << "std::move failed, incremented refcnt";
62         ASSERT_EQ(nullptr, sp1.get()) << "std::move failed, sp1 is still valid";
63         // The strong count isn't increasing, let's double check the old object
64         // is properly reset and doesn't early delete
65         sp1 = std::move(sp2);
66     }
67     ASSERT_FALSE(isDeleted) << "deleted too early! still has a reference!";
68     {
69         // Now let's double check it deletes on time
70         sp<TypeParam> sp2 = std::move(sp1);
71     }
72     ASSERT_TRUE(isDeleted) << "foo was leaked!";
73 }
74 
TYPED_TEST(StrongPointer,NullptrComparison)75 TYPED_TEST(StrongPointer, NullptrComparison) {
76     sp<TypeParam> foo;
77     ASSERT_EQ(foo, nullptr);
78     ASSERT_EQ(nullptr, foo);
79 }
80 
TYPED_TEST(StrongPointer,PointerComparison)81 TYPED_TEST(StrongPointer, PointerComparison) {
82     bool isDeleted;
83     sp<TypeParam> foo = sp<TypeParam>::make(&isDeleted);
84     ASSERT_EQ(foo.get(), foo);
85     ASSERT_EQ(foo, foo.get());
86     ASSERT_NE(nullptr, foo);
87     ASSERT_NE(foo, nullptr);
88 }
89 
TYPED_TEST(StrongPointer,Deleted)90 TYPED_TEST(StrongPointer, Deleted) {
91     bool isDeleted;
92     sp<TypeParam> foo = sp<TypeParam>::make(&isDeleted);
93 
94     auto foo2 = sp<TypeParam>::fromExisting(foo.get());
95 
96     EXPECT_FALSE(isDeleted);
97     foo = nullptr;
98     EXPECT_FALSE(isDeleted);
99     foo2 = nullptr;
100     EXPECT_TRUE(isDeleted);
101 }
102 
TYPED_TEST(StrongPointer,AssertStrongRefExists)103 TYPED_TEST(StrongPointer, AssertStrongRefExists) {
104     bool isDeleted;
105     TypeParam* foo = new TypeParam(&isDeleted);
106     EXPECT_DEATH(sp<TypeParam>::fromExisting(foo), "");
107     delete foo;
108 }
109 
TYPED_TEST(StrongPointer,release)110 TYPED_TEST(StrongPointer, release) {
111     bool isDeleted = false;
112     TypeParam* foo = nullptr;
113     {
114         sp<TypeParam> sp1 = sp<TypeParam>::make(&isDeleted);
115         ASSERT_EQ(1, sp1->getStrongCount());
116         foo = sp1.release();
117     }
118     ASSERT_FALSE(isDeleted) << "release failed, deleted anyway when sp left scope";
119     ASSERT_EQ(1, foo->getStrongCount()) << "release mismanaged refcount";
120     foo->decStrong(nullptr);
121     ASSERT_TRUE(isDeleted) << "foo was leaked!";
122 }
123