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