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