1 // Copyright 2016 PDFium 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 "core/fxcrt/cfx_retain_ptr.h"
6
7 #include <utility>
8
9 #include "testing/fx_string_testhelpers.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace {
13
14 class PseudoRetainable {
15 public:
PseudoRetainable()16 PseudoRetainable() : retain_count_(0), release_count_(0) {}
Retain()17 void Retain() { ++retain_count_; }
Release()18 void Release() { ++release_count_; }
retain_count() const19 int retain_count() const { return retain_count_; }
release_count() const20 int release_count() const { return release_count_; }
21
22 private:
23 int retain_count_;
24 int release_count_;
25 };
26
27 } // namespace
28
TEST(fxcrt,RetainPtrNull)29 TEST(fxcrt, RetainPtrNull) {
30 CFX_RetainPtr<PseudoRetainable> ptr;
31 EXPECT_EQ(nullptr, ptr.Get());
32 }
33
TEST(fxcrt,RetainPtrNormal)34 TEST(fxcrt, RetainPtrNormal) {
35 PseudoRetainable obj;
36 {
37 CFX_RetainPtr<PseudoRetainable> ptr(&obj);
38 EXPECT_EQ(&obj, ptr.Get());
39 EXPECT_EQ(1, obj.retain_count());
40 EXPECT_EQ(0, obj.release_count());
41 }
42 EXPECT_EQ(1, obj.retain_count());
43 EXPECT_EQ(1, obj.release_count());
44 }
45
TEST(fxcrt,RetainPtrCopyCtor)46 TEST(fxcrt, RetainPtrCopyCtor) {
47 PseudoRetainable obj;
48 {
49 CFX_RetainPtr<PseudoRetainable> ptr1(&obj);
50 {
51 CFX_RetainPtr<PseudoRetainable> ptr2(ptr1);
52 EXPECT_EQ(2, obj.retain_count());
53 EXPECT_EQ(0, obj.release_count());
54 }
55 EXPECT_EQ(2, obj.retain_count());
56 EXPECT_EQ(1, obj.release_count());
57 }
58 EXPECT_EQ(2, obj.retain_count());
59 EXPECT_EQ(2, obj.release_count());
60 }
61
TEST(fxcrt,RetainPtrMoveCtor)62 TEST(fxcrt, RetainPtrMoveCtor) {
63 PseudoRetainable obj;
64 {
65 CFX_RetainPtr<PseudoRetainable> ptr1(&obj);
66 {
67 CFX_RetainPtr<PseudoRetainable> ptr2(std::move(ptr1));
68 EXPECT_EQ(1, obj.retain_count());
69 EXPECT_EQ(0, obj.release_count());
70 }
71 EXPECT_EQ(1, obj.retain_count());
72 EXPECT_EQ(1, obj.release_count());
73 }
74 EXPECT_EQ(1, obj.retain_count());
75 EXPECT_EQ(1, obj.release_count());
76 }
77
TEST(fxcrt,RetainPtrResetNull)78 TEST(fxcrt, RetainPtrResetNull) {
79 PseudoRetainable obj;
80 {
81 CFX_RetainPtr<PseudoRetainable> ptr(&obj);
82 ptr.Reset();
83 EXPECT_EQ(1, obj.retain_count());
84 EXPECT_EQ(1, obj.release_count());
85 }
86 EXPECT_EQ(1, obj.retain_count());
87 EXPECT_EQ(1, obj.release_count());
88 }
89
TEST(fxcrt,RetainPtrReset)90 TEST(fxcrt, RetainPtrReset) {
91 PseudoRetainable obj1;
92 PseudoRetainable obj2;
93 {
94 CFX_RetainPtr<PseudoRetainable> ptr(&obj1);
95 ptr.Reset(&obj2);
96 EXPECT_EQ(1, obj1.retain_count());
97 EXPECT_EQ(1, obj1.release_count());
98 EXPECT_EQ(1, obj2.retain_count());
99 EXPECT_EQ(0, obj2.release_count());
100 }
101 EXPECT_EQ(1, obj1.retain_count());
102 EXPECT_EQ(1, obj1.release_count());
103 EXPECT_EQ(1, obj2.retain_count());
104 EXPECT_EQ(1, obj2.release_count());
105 }
106
TEST(fxcrt,RetainPtrSwap)107 TEST(fxcrt, RetainPtrSwap) {
108 PseudoRetainable obj1;
109 PseudoRetainable obj2;
110 {
111 CFX_RetainPtr<PseudoRetainable> ptr1(&obj1);
112 {
113 CFX_RetainPtr<PseudoRetainable> ptr2(&obj2);
114 ptr1.Swap(ptr2);
115 EXPECT_EQ(1, obj1.retain_count());
116 EXPECT_EQ(0, obj1.release_count());
117 EXPECT_EQ(1, obj2.retain_count());
118 EXPECT_EQ(0, obj2.release_count());
119 }
120 EXPECT_EQ(1, obj1.retain_count());
121 EXPECT_EQ(1, obj1.release_count());
122 EXPECT_EQ(1, obj2.retain_count());
123 EXPECT_EQ(0, obj2.release_count());
124 }
125 EXPECT_EQ(1, obj1.retain_count());
126 EXPECT_EQ(1, obj1.release_count());
127 EXPECT_EQ(1, obj2.retain_count());
128 EXPECT_EQ(1, obj2.release_count());
129 }
130
TEST(fxcrt,RetainPtrLeak)131 TEST(fxcrt, RetainPtrLeak) {
132 PseudoRetainable obj;
133 PseudoRetainable* leak;
134 {
135 CFX_RetainPtr<PseudoRetainable> ptr(&obj);
136 leak = ptr.Leak();
137 EXPECT_EQ(1, obj.retain_count());
138 EXPECT_EQ(0, obj.release_count());
139 }
140 EXPECT_EQ(1, obj.retain_count());
141 EXPECT_EQ(0, obj.release_count());
142 {
143 CFX_RetainPtr<PseudoRetainable> ptr;
144 ptr.Unleak(leak);
145 EXPECT_EQ(1, obj.retain_count());
146 EXPECT_EQ(0, obj.release_count());
147 }
148 EXPECT_EQ(1, obj.retain_count());
149 EXPECT_EQ(1, obj.release_count());
150 }
151
TEST(fxcrt,RetainPtrSwapNull)152 TEST(fxcrt, RetainPtrSwapNull) {
153 PseudoRetainable obj1;
154 {
155 CFX_RetainPtr<PseudoRetainable> ptr1(&obj1);
156 {
157 CFX_RetainPtr<PseudoRetainable> ptr2;
158 ptr1.Swap(ptr2);
159 EXPECT_FALSE(ptr1);
160 EXPECT_TRUE(ptr2);
161 EXPECT_EQ(1, obj1.retain_count());
162 EXPECT_EQ(0, obj1.release_count());
163 }
164 EXPECT_EQ(1, obj1.retain_count());
165 EXPECT_EQ(1, obj1.release_count());
166 }
167 EXPECT_EQ(1, obj1.retain_count());
168 EXPECT_EQ(1, obj1.release_count());
169 }
170
TEST(fxcrt,RetainPtrAssign)171 TEST(fxcrt, RetainPtrAssign) {
172 PseudoRetainable obj;
173 {
174 CFX_RetainPtr<PseudoRetainable> ptr(&obj);
175 {
176 CFX_RetainPtr<PseudoRetainable> ptr2;
177 ptr2 = ptr;
178 EXPECT_EQ(2, obj.retain_count());
179 EXPECT_EQ(0, obj.release_count());
180 }
181 EXPECT_EQ(2, obj.retain_count());
182 EXPECT_EQ(1, obj.release_count());
183 }
184 EXPECT_EQ(2, obj.retain_count());
185 EXPECT_EQ(2, obj.release_count());
186 }
187
TEST(fxcrt,RetainPtrEquals)188 TEST(fxcrt, RetainPtrEquals) {
189 PseudoRetainable obj1;
190 PseudoRetainable obj2;
191 CFX_RetainPtr<PseudoRetainable> null_ptr1;
192 CFX_RetainPtr<PseudoRetainable> obj1_ptr1(&obj1);
193 CFX_RetainPtr<PseudoRetainable> obj2_ptr1(&obj2);
194 {
195 CFX_RetainPtr<PseudoRetainable> null_ptr2;
196 EXPECT_TRUE(null_ptr1 == null_ptr2);
197
198 CFX_RetainPtr<PseudoRetainable> obj1_ptr2(&obj1);
199 EXPECT_TRUE(obj1_ptr1 == obj1_ptr2);
200
201 CFX_RetainPtr<PseudoRetainable> obj2_ptr2(&obj2);
202 EXPECT_TRUE(obj2_ptr1 == obj2_ptr2);
203 }
204 EXPECT_FALSE(null_ptr1 == obj1_ptr1);
205 EXPECT_FALSE(null_ptr1 == obj2_ptr1);
206 EXPECT_FALSE(obj1_ptr1 == obj2_ptr1);
207 }
208
TEST(fxcrt,RetainPtrNotEquals)209 TEST(fxcrt, RetainPtrNotEquals) {
210 PseudoRetainable obj1;
211 PseudoRetainable obj2;
212 CFX_RetainPtr<PseudoRetainable> null_ptr1;
213 CFX_RetainPtr<PseudoRetainable> obj1_ptr1(&obj1);
214 CFX_RetainPtr<PseudoRetainable> obj2_ptr1(&obj2);
215 {
216 CFX_RetainPtr<PseudoRetainable> null_ptr2;
217 CFX_RetainPtr<PseudoRetainable> obj1_ptr2(&obj1);
218 CFX_RetainPtr<PseudoRetainable> obj2_ptr2(&obj2);
219 EXPECT_FALSE(null_ptr1 != null_ptr2);
220 EXPECT_FALSE(obj1_ptr1 != obj1_ptr2);
221 EXPECT_FALSE(obj2_ptr1 != obj2_ptr2);
222 }
223 EXPECT_TRUE(null_ptr1 != obj1_ptr1);
224 EXPECT_TRUE(null_ptr1 != obj2_ptr1);
225 EXPECT_TRUE(obj1_ptr1 != obj2_ptr1);
226 }
227
TEST(fxcrt,RetainPtrLessThan)228 TEST(fxcrt, RetainPtrLessThan) {
229 PseudoRetainable objs[2];
230 CFX_RetainPtr<PseudoRetainable> obj1_ptr(&objs[0]);
231 CFX_RetainPtr<PseudoRetainable> obj2_ptr(&objs[1]);
232 EXPECT_TRUE(obj1_ptr < obj2_ptr);
233 EXPECT_FALSE(obj2_ptr < obj1_ptr);
234 }
235
TEST(fxcrt,RetainPtrBool)236 TEST(fxcrt, RetainPtrBool) {
237 PseudoRetainable obj1;
238 CFX_RetainPtr<PseudoRetainable> null_ptr;
239 CFX_RetainPtr<PseudoRetainable> obj1_ptr(&obj1);
240 bool null_bool = !!null_ptr;
241 bool obj1_bool = !!obj1_ptr;
242 EXPECT_FALSE(null_bool);
243 EXPECT_TRUE(obj1_bool);
244 }
245
TEST(fxcrt,RetainPtrMakeRetained)246 TEST(fxcrt, RetainPtrMakeRetained) {
247 auto ptr = pdfium::MakeRetain<CFX_Retainable>();
248 EXPECT_TRUE(ptr->HasOneRef());
249 {
250 CFX_RetainPtr<CFX_Retainable> other = ptr;
251 EXPECT_FALSE(ptr->HasOneRef());
252 }
253 EXPECT_TRUE(ptr->HasOneRef());
254 }
255