• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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