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/retain_ptr.h"
6
7 #include <utility>
8 #include <vector>
9
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "testing/pseudo_retainable.h"
12
13 namespace fxcrt {
14
TEST(RetainPtr,Null)15 TEST(RetainPtr, Null) {
16 RetainPtr<PseudoRetainable> ptr;
17 EXPECT_EQ(nullptr, ptr.Get());
18 }
19
TEST(RetainPtr,Normal)20 TEST(RetainPtr, Normal) {
21 PseudoRetainable obj;
22 {
23 RetainPtr<PseudoRetainable> ptr(&obj);
24 EXPECT_EQ(&obj, ptr.Get());
25 EXPECT_EQ(1, obj.retain_count());
26 EXPECT_EQ(0, obj.release_count());
27 }
28 EXPECT_EQ(1, obj.retain_count());
29 EXPECT_EQ(1, obj.release_count());
30 }
31
TEST(RetainPtr,CopyCtor)32 TEST(RetainPtr, CopyCtor) {
33 PseudoRetainable obj;
34 {
35 RetainPtr<PseudoRetainable> ptr1(&obj);
36 {
37 RetainPtr<PseudoRetainable> ptr2(ptr1);
38 EXPECT_EQ(2, obj.retain_count());
39 EXPECT_EQ(0, obj.release_count());
40 }
41 EXPECT_EQ(2, obj.retain_count());
42 EXPECT_EQ(1, obj.release_count());
43 }
44 EXPECT_EQ(2, obj.retain_count());
45 EXPECT_EQ(2, obj.release_count());
46 }
47
TEST(RetainPtr,MoveCtor)48 TEST(RetainPtr, MoveCtor) {
49 PseudoRetainable obj;
50 {
51 RetainPtr<PseudoRetainable> ptr1(&obj);
52 {
53 RetainPtr<PseudoRetainable> ptr2(std::move(ptr1));
54 EXPECT_EQ(nullptr, ptr1.Get());
55 EXPECT_EQ(&obj, ptr2.Get());
56 EXPECT_EQ(1, obj.retain_count());
57 EXPECT_EQ(0, obj.release_count());
58 }
59 EXPECT_EQ(1, obj.retain_count());
60 EXPECT_EQ(1, obj.release_count());
61 }
62 EXPECT_EQ(1, obj.retain_count());
63 EXPECT_EQ(1, obj.release_count());
64 }
65
TEST(RetainPtr,ResetNull)66 TEST(RetainPtr, ResetNull) {
67 PseudoRetainable obj;
68 {
69 RetainPtr<PseudoRetainable> ptr(&obj);
70 ptr.Reset();
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(RetainPtr,Reset)78 TEST(RetainPtr, Reset) {
79 PseudoRetainable obj1;
80 PseudoRetainable obj2;
81 {
82 RetainPtr<PseudoRetainable> ptr(&obj1);
83 ptr.Reset(&obj2);
84 EXPECT_EQ(1, obj1.retain_count());
85 EXPECT_EQ(1, obj1.release_count());
86 EXPECT_EQ(1, obj2.retain_count());
87 EXPECT_EQ(0, obj2.release_count());
88 }
89 EXPECT_EQ(1, obj1.retain_count());
90 EXPECT_EQ(1, obj1.release_count());
91 EXPECT_EQ(1, obj2.retain_count());
92 EXPECT_EQ(1, obj2.release_count());
93 }
94
TEST(RetainPtr,Swap)95 TEST(RetainPtr, Swap) {
96 PseudoRetainable obj1;
97 PseudoRetainable obj2;
98 {
99 RetainPtr<PseudoRetainable> ptr1(&obj1);
100 {
101 RetainPtr<PseudoRetainable> ptr2(&obj2);
102 ptr1.Swap(ptr2);
103 EXPECT_EQ(1, obj1.retain_count());
104 EXPECT_EQ(0, obj1.release_count());
105 EXPECT_EQ(1, obj2.retain_count());
106 EXPECT_EQ(0, obj2.release_count());
107 }
108 EXPECT_EQ(1, obj1.retain_count());
109 EXPECT_EQ(1, obj1.release_count());
110 EXPECT_EQ(1, obj2.retain_count());
111 EXPECT_EQ(0, obj2.release_count());
112 }
113 EXPECT_EQ(1, obj1.retain_count());
114 EXPECT_EQ(1, obj1.release_count());
115 EXPECT_EQ(1, obj2.retain_count());
116 EXPECT_EQ(1, obj2.release_count());
117 }
118
TEST(RetainPtr,Leak)119 TEST(RetainPtr, Leak) {
120 PseudoRetainable obj;
121 PseudoRetainable* leak;
122 {
123 RetainPtr<PseudoRetainable> ptr(&obj);
124 leak = ptr.Leak();
125 EXPECT_EQ(1, obj.retain_count());
126 EXPECT_EQ(0, obj.release_count());
127 }
128 EXPECT_EQ(1, obj.retain_count());
129 EXPECT_EQ(0, obj.release_count());
130 {
131 RetainPtr<PseudoRetainable> ptr;
132 ptr.Unleak(leak);
133 EXPECT_EQ(1, obj.retain_count());
134 EXPECT_EQ(0, obj.release_count());
135 }
136 EXPECT_EQ(1, obj.retain_count());
137 EXPECT_EQ(1, obj.release_count());
138 }
139
TEST(RetainPtr,SwapNull)140 TEST(RetainPtr, SwapNull) {
141 PseudoRetainable obj1;
142 {
143 RetainPtr<PseudoRetainable> ptr1(&obj1);
144 {
145 RetainPtr<PseudoRetainable> ptr2;
146 ptr1.Swap(ptr2);
147 EXPECT_FALSE(ptr1);
148 EXPECT_TRUE(ptr2);
149 EXPECT_EQ(1, obj1.retain_count());
150 EXPECT_EQ(0, obj1.release_count());
151 }
152 EXPECT_EQ(1, obj1.retain_count());
153 EXPECT_EQ(1, obj1.release_count());
154 }
155 EXPECT_EQ(1, obj1.retain_count());
156 EXPECT_EQ(1, obj1.release_count());
157 }
158
TEST(RetainPtr,Assign)159 TEST(RetainPtr, Assign) {
160 PseudoRetainable obj;
161 {
162 RetainPtr<PseudoRetainable> ptr(&obj);
163 {
164 RetainPtr<PseudoRetainable> ptr2;
165 ptr2 = ptr;
166 EXPECT_EQ(2, obj.retain_count());
167 EXPECT_EQ(0, obj.release_count());
168 }
169 EXPECT_EQ(2, obj.retain_count());
170 EXPECT_EQ(1, obj.release_count());
171 }
172 EXPECT_EQ(2, obj.retain_count());
173 EXPECT_EQ(2, obj.release_count());
174 }
175
TEST(RetainPtr,MoveAssign)176 TEST(RetainPtr, MoveAssign) {
177 PseudoRetainable obj;
178 {
179 RetainPtr<PseudoRetainable> ptr1(&obj);
180 {
181 RetainPtr<PseudoRetainable> ptr2;
182 EXPECT_EQ(&obj, ptr1.Get());
183 EXPECT_EQ(nullptr, ptr2.Get());
184 ptr2 = std::move(ptr1);
185 EXPECT_EQ(nullptr, ptr1.Get());
186 EXPECT_EQ(&obj, ptr2.Get());
187 EXPECT_EQ(1, obj.retain_count());
188 EXPECT_EQ(0, obj.release_count());
189 }
190 EXPECT_EQ(1, obj.retain_count());
191 EXPECT_EQ(1, obj.release_count());
192 }
193 EXPECT_EQ(1, obj.retain_count());
194 EXPECT_EQ(1, obj.release_count());
195 }
196
TEST(RetainPtr,Equals)197 TEST(RetainPtr, Equals) {
198 PseudoRetainable obj1;
199 PseudoRetainable obj2;
200 RetainPtr<PseudoRetainable> null_ptr1;
201 RetainPtr<PseudoRetainable> obj1_ptr1(&obj1);
202 RetainPtr<PseudoRetainable> obj2_ptr1(&obj2);
203 {
204 RetainPtr<PseudoRetainable> null_ptr2;
205 EXPECT_TRUE(null_ptr1 == null_ptr2);
206 EXPECT_TRUE(null_ptr1 == nullptr);
207
208 RetainPtr<PseudoRetainable> obj1_ptr2(&obj1);
209 EXPECT_TRUE(obj1_ptr1 == obj1_ptr2);
210 EXPECT_TRUE(obj1_ptr2 == &obj1);
211
212 RetainPtr<PseudoRetainable> obj2_ptr2(&obj2);
213 EXPECT_TRUE(obj2_ptr1 == obj2_ptr2);
214 }
215 EXPECT_FALSE(null_ptr1 == obj1_ptr1);
216 EXPECT_FALSE(null_ptr1 == obj2_ptr1);
217 EXPECT_FALSE(obj1_ptr1 == obj2_ptr1);
218 }
219
TEST(RetainPtr,EqualsReflexive)220 TEST(RetainPtr, EqualsReflexive) {
221 PseudoRetainable obj1;
222 PseudoRetainable obj2;
223 RetainPtr<PseudoRetainable> obj1_ptr(&obj1);
224 RetainPtr<PseudoRetainable> obj2_ptr(&obj2);
225 EXPECT_TRUE(&obj1 == obj1_ptr);
226 EXPECT_FALSE(&obj1 == obj2_ptr);
227 EXPECT_FALSE(&obj2 == obj1_ptr);
228 EXPECT_TRUE(&obj2 == obj2_ptr);
229 }
230
TEST(RetainPtr,NotEquals)231 TEST(RetainPtr, NotEquals) {
232 PseudoRetainable obj1;
233 PseudoRetainable obj2;
234 RetainPtr<PseudoRetainable> null_ptr1;
235 RetainPtr<PseudoRetainable> obj1_ptr1(&obj1);
236 RetainPtr<PseudoRetainable> obj2_ptr1(&obj2);
237 {
238 RetainPtr<PseudoRetainable> null_ptr2;
239 RetainPtr<PseudoRetainable> obj1_ptr2(&obj1);
240 RetainPtr<PseudoRetainable> obj2_ptr2(&obj2);
241 EXPECT_FALSE(null_ptr1 != null_ptr2);
242 EXPECT_FALSE(obj1_ptr1 != obj1_ptr2);
243 EXPECT_FALSE(obj2_ptr1 != obj2_ptr2);
244 }
245 EXPECT_TRUE(null_ptr1 != obj1_ptr1);
246 EXPECT_TRUE(null_ptr1 != obj2_ptr1);
247 EXPECT_TRUE(obj1_ptr1 != obj2_ptr1);
248 }
249
TEST(RetainPtr,NotEqualsReflexive)250 TEST(RetainPtr, NotEqualsReflexive) {
251 PseudoRetainable obj1;
252 PseudoRetainable obj2;
253 RetainPtr<PseudoRetainable> obj1_ptr(&obj1);
254 RetainPtr<PseudoRetainable> obj2_ptr(&obj2);
255 EXPECT_FALSE(&obj1 != obj1_ptr);
256 EXPECT_TRUE(&obj1 != obj2_ptr);
257 EXPECT_TRUE(&obj2 != obj1_ptr);
258 EXPECT_FALSE(&obj2 != obj2_ptr);
259 }
260
TEST(RetainPtr,LessThan)261 TEST(RetainPtr, LessThan) {
262 PseudoRetainable objs[2];
263 RetainPtr<PseudoRetainable> obj1_ptr(&objs[0]);
264 RetainPtr<PseudoRetainable> obj2_ptr(&objs[1]);
265 EXPECT_TRUE(obj1_ptr < obj2_ptr);
266 EXPECT_FALSE(obj2_ptr < obj1_ptr);
267 }
268
TEST(RetainPtr,Bool)269 TEST(RetainPtr, Bool) {
270 PseudoRetainable obj1;
271 RetainPtr<PseudoRetainable> null_ptr;
272 RetainPtr<PseudoRetainable> obj1_ptr(&obj1);
273 bool null_bool = !!null_ptr;
274 bool obj1_bool = !!obj1_ptr;
275 EXPECT_FALSE(null_bool);
276 EXPECT_TRUE(obj1_bool);
277 }
278
TEST(RetainPtr,MakeRetained)279 TEST(RetainPtr, MakeRetained) {
280 auto ptr = pdfium::MakeRetain<Retainable>();
281 EXPECT_TRUE(ptr->HasOneRef());
282 {
283 RetainPtr<Retainable> other = ptr;
284 EXPECT_FALSE(ptr->HasOneRef());
285 }
286 EXPECT_TRUE(ptr->HasOneRef());
287 }
288
TEST(RetainPtr,VectorMove)289 TEST(RetainPtr, VectorMove) {
290 // Proves move ctor is selected by std::vector over copy/delete, this
291 // may require the ctor to be marked "noexcept".
292 PseudoRetainable obj;
293 {
294 RetainPtr<PseudoRetainable> ptr(&obj);
295 std::vector<RetainPtr<PseudoRetainable>> vec1;
296 vec1.push_back(std::move(ptr));
297 EXPECT_EQ(1, obj.retain_count());
298 EXPECT_EQ(0, obj.release_count());
299
300 std::vector<RetainPtr<PseudoRetainable>> vec2 = std::move(vec1);
301 EXPECT_EQ(1, obj.retain_count());
302 EXPECT_EQ(0, obj.release_count());
303
304 vec2.resize(4096);
305 EXPECT_EQ(1, obj.retain_count());
306 EXPECT_EQ(0, obj.release_count());
307 }
308 EXPECT_EQ(1, obj.retain_count());
309 EXPECT_EQ(1, obj.release_count());
310 }
311
312 } // namespace fxcrt
313