OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 <sstream> | |
6 #include <utility> | |
7 | |
8 #include "testing/gtest/include/gtest/gtest.h" | |
9 #include "macros.h" | |
10 #include "nonstd_unique_ptr.h" | |
11 | |
12 using nonstd::unique_ptr; | |
13 | |
14 namespace { | |
15 | |
16 // Used to test depth subtyping. | |
17 class CtorDtorLoggerParent { | |
18 public: | |
19 virtual ~CtorDtorLoggerParent() {} | |
20 | |
21 virtual void SetPtr(int* ptr) = 0; | |
22 | |
23 virtual int SomeMeth(int x) const = 0; | |
24 }; | |
25 | |
26 class CtorDtorLogger : public CtorDtorLoggerParent { | |
27 public: | |
28 CtorDtorLogger() : ptr_(nullptr) {} | |
29 explicit CtorDtorLogger(int* ptr) { SetPtr(ptr); } | |
30 ~CtorDtorLogger() override { --*ptr_; } | |
31 | |
32 void SetPtr(int* ptr) override { | |
33 ptr_ = ptr; | |
34 ++*ptr_; | |
35 } | |
36 | |
37 int SomeMeth(int x) const override { return x; } | |
38 | |
39 private: | |
40 int* ptr_; | |
41 | |
42 // Disallow evil constructors. | |
43 CtorDtorLogger(const CtorDtorLogger&) = delete; | |
44 void operator=(const CtorDtorLogger&) = delete; | |
45 }; | |
46 | |
47 struct CountingDeleter { | |
48 explicit CountingDeleter(int* count) : count_(count) {} | |
49 inline void operator()(double* ptr) const { (*count_)++; } | |
50 int* count_; | |
51 }; | |
52 | |
53 // Do not delete this function! It's existence is to test that you can | |
54 // return a temporarily constructed version of the scoper. | |
55 unique_ptr<CtorDtorLogger> TestReturnOfType(int* constructed) { | |
56 return unique_ptr<CtorDtorLogger>(new CtorDtorLogger(constructed)); | |
57 } | |
58 | |
59 } // namespace | |
60 | |
61 TEST(UniquePtrTest, MoveTest) { | |
62 int constructed = 0; | |
63 int constructed4 = 0; | |
64 { | |
65 unique_ptr<CtorDtorLogger> ptr1(new CtorDtorLogger(&constructed)); | |
66 EXPECT_EQ(1, constructed); | |
67 EXPECT_TRUE(ptr1); | |
68 | |
69 unique_ptr<CtorDtorLogger> ptr2(std::move(ptr1)); | |
70 EXPECT_EQ(1, constructed); | |
71 EXPECT_FALSE(ptr1); | |
72 EXPECT_TRUE(ptr2); | |
73 | |
74 unique_ptr<CtorDtorLogger> ptr3; | |
75 ptr3 = std::move(ptr2); | |
76 EXPECT_EQ(1, constructed); | |
77 EXPECT_FALSE(ptr2); | |
78 EXPECT_TRUE(ptr3); | |
79 | |
80 unique_ptr<CtorDtorLogger> ptr4(new CtorDtorLogger(&constructed4)); | |
81 EXPECT_EQ(1, constructed4); | |
82 ptr4 = std::move(ptr3); | |
83 EXPECT_EQ(0, constructed4); | |
84 EXPECT_FALSE(ptr3); | |
85 EXPECT_TRUE(ptr4); | |
86 } | |
87 EXPECT_EQ(0, constructed); | |
88 } | |
89 | |
90 TEST(UniquePtrTest, UniquePtr) { | |
91 int constructed = 0; | |
92 | |
93 // Ensure size of unique_ptr<> doesn't increase unexpectedly. | |
94 static_assert(sizeof(int*) >= sizeof(unique_ptr<int>), | |
95 "unique_ptr_larger_than_raw_ptr"); | |
96 | |
97 { | |
98 unique_ptr<CtorDtorLogger> scoper(new CtorDtorLogger(&constructed)); | |
99 EXPECT_EQ(1, constructed); | |
100 EXPECT_TRUE(scoper.get()); | |
101 | |
102 EXPECT_EQ(10, scoper->SomeMeth(10)); | |
103 EXPECT_EQ(10, scoper.get()->SomeMeth(10)); | |
104 EXPECT_EQ(10, (*scoper).SomeMeth(10)); | |
105 } | |
106 EXPECT_EQ(0, constructed); | |
107 | |
108 // Test reset() and release() | |
109 { | |
110 unique_ptr<CtorDtorLogger> scoper(new CtorDtorLogger(&constructed)); | |
111 EXPECT_EQ(1, constructed); | |
112 EXPECT_TRUE(scoper.get()); | |
113 | |
114 scoper.reset(new CtorDtorLogger(&constructed)); | |
115 EXPECT_EQ(1, constructed); | |
116 EXPECT_TRUE(scoper.get()); | |
117 | |
118 scoper.reset(); | |
119 EXPECT_EQ(0, constructed); | |
120 EXPECT_FALSE(scoper.get()); | |
121 | |
122 scoper.reset(new CtorDtorLogger(&constructed)); | |
123 EXPECT_EQ(1, constructed); | |
124 EXPECT_TRUE(scoper.get()); | |
125 | |
126 CtorDtorLogger* take = scoper.release(); | |
127 EXPECT_EQ(1, constructed); | |
128 EXPECT_FALSE(scoper.get()); | |
129 delete take; | |
130 EXPECT_EQ(0, constructed); | |
131 | |
132 scoper.reset(new CtorDtorLogger(&constructed)); | |
133 EXPECT_EQ(1, constructed); | |
134 EXPECT_TRUE(scoper.get()); | |
135 } | |
136 EXPECT_EQ(0, constructed); | |
137 | |
138 // Test swap(), == and != | |
139 { | |
140 unique_ptr<CtorDtorLogger> scoper1; | |
141 unique_ptr<CtorDtorLogger> scoper2; | |
142 EXPECT_TRUE(scoper1 == scoper2.get()); | |
143 EXPECT_FALSE(scoper1 != scoper2.get()); | |
144 | |
145 CtorDtorLogger* logger = new CtorDtorLogger(&constructed); | |
146 scoper1.reset(logger); | |
147 EXPECT_EQ(logger, scoper1.get()); | |
148 EXPECT_FALSE(scoper2.get()); | |
149 EXPECT_FALSE(scoper1 == scoper2.get()); | |
150 EXPECT_TRUE(scoper1 != scoper2.get()); | |
151 | |
152 scoper2.swap(scoper1); | |
153 EXPECT_EQ(logger, scoper2.get()); | |
154 EXPECT_FALSE(scoper1.get()); | |
155 EXPECT_FALSE(scoper1 == scoper2.get()); | |
156 EXPECT_TRUE(scoper1 != scoper2.get()); | |
157 } | |
158 EXPECT_EQ(0, constructed); | |
159 } | |
160 | |
161 TEST(UniquePtrTest, UniquePtrWithArray) { | |
162 static const int kNumLoggers = 12; | |
163 | |
164 int constructed = 0; | |
165 | |
166 { | |
167 unique_ptr<CtorDtorLogger[]> scoper(new CtorDtorLogger[kNumLoggers]); | |
168 EXPECT_TRUE(scoper); | |
169 EXPECT_EQ(&scoper[0], scoper.get()); | |
170 for (int i = 0; i < kNumLoggers; ++i) { | |
171 scoper[i].SetPtr(&constructed); | |
172 } | |
173 EXPECT_EQ(12, constructed); | |
174 | |
175 EXPECT_EQ(10, scoper.get()->SomeMeth(10)); | |
176 EXPECT_EQ(10, scoper[2].SomeMeth(10)); | |
177 } | |
178 EXPECT_EQ(0, constructed); | |
179 | |
180 // Test reset() and release() | |
181 { | |
182 unique_ptr<CtorDtorLogger[]> scoper; | |
183 EXPECT_FALSE(scoper.get()); | |
184 EXPECT_FALSE(scoper.release()); | |
185 EXPECT_FALSE(scoper.get()); | |
186 scoper.reset(); | |
187 EXPECT_FALSE(scoper.get()); | |
188 | |
189 scoper.reset(new CtorDtorLogger[kNumLoggers]); | |
190 for (int i = 0; i < kNumLoggers; ++i) { | |
191 scoper[i].SetPtr(&constructed); | |
192 } | |
193 EXPECT_EQ(12, constructed); | |
194 scoper.reset(); | |
195 EXPECT_EQ(0, constructed); | |
196 | |
197 scoper.reset(new CtorDtorLogger[kNumLoggers]); | |
198 for (int i = 0; i < kNumLoggers; ++i) { | |
199 scoper[i].SetPtr(&constructed); | |
200 } | |
201 EXPECT_EQ(12, constructed); | |
202 CtorDtorLogger* ptr = scoper.release(); | |
203 EXPECT_EQ(12, constructed); | |
204 delete[] ptr; | |
205 EXPECT_EQ(0, constructed); | |
206 } | |
207 EXPECT_EQ(0, constructed); | |
208 | |
209 // Test swap(), ==, !=, and type-safe Boolean. | |
210 { | |
211 unique_ptr<CtorDtorLogger[]> scoper1; | |
212 unique_ptr<CtorDtorLogger[]> scoper2; | |
213 EXPECT_TRUE(scoper1 == scoper2.get()); | |
214 EXPECT_FALSE(scoper1 != scoper2.get()); | |
215 | |
216 CtorDtorLogger* loggers = new CtorDtorLogger[kNumLoggers]; | |
217 for (int i = 0; i < kNumLoggers; ++i) { | |
218 loggers[i].SetPtr(&constructed); | |
219 } | |
220 scoper1.reset(loggers); | |
221 EXPECT_TRUE(scoper1); | |
222 EXPECT_EQ(loggers, scoper1.get()); | |
223 EXPECT_FALSE(scoper2); | |
224 EXPECT_FALSE(scoper2.get()); | |
225 EXPECT_FALSE(scoper1 == scoper2.get()); | |
226 EXPECT_TRUE(scoper1 != scoper2.get()); | |
227 | |
228 scoper2.swap(scoper1); | |
229 EXPECT_EQ(loggers, scoper2.get()); | |
230 EXPECT_FALSE(scoper1.get()); | |
231 EXPECT_FALSE(scoper1 == scoper2.get()); | |
232 EXPECT_TRUE(scoper1 != scoper2.get()); | |
233 } | |
234 EXPECT_EQ(0, constructed); | |
235 } | |
236 | |
237 TEST(UniquePtrTest, ReturnTypeBehavior) { | |
238 int constructed = 0; | |
239 | |
240 // Test that we can return a unique_ptr. | |
241 { | |
242 CtorDtorLogger* logger = new CtorDtorLogger(&constructed); | |
243 unique_ptr<CtorDtorLogger> scoper(logger); | |
244 EXPECT_EQ(1, constructed); | |
245 } | |
246 EXPECT_EQ(0, constructed); | |
247 | |
248 // Test uncaught return type not leak. | |
249 { | |
250 CtorDtorLogger* logger = new CtorDtorLogger(&constructed); | |
251 unique_ptr<CtorDtorLogger> scoper(logger); | |
252 EXPECT_EQ(1, constructed); | |
253 } | |
254 EXPECT_EQ(0, constructed); | |
255 | |
256 // Call TestReturnOfType() so the compiler doesn't warn for an unused | |
257 // function. | |
258 { TestReturnOfType(&constructed); } | |
259 EXPECT_EQ(0, constructed); | |
260 } | |
261 | |
262 TEST(UniquePtrTest, CustomDeleter) { | |
263 double dummy_value; // Custom deleter never touches this value. | |
264 int deletes = 0; | |
265 int alternate_deletes = 0; | |
266 | |
267 // Normal delete support. | |
268 { | |
269 deletes = 0; | |
270 unique_ptr<double, CountingDeleter> scoper(&dummy_value, | |
271 CountingDeleter(&deletes)); | |
272 EXPECT_EQ(0, deletes); | |
273 EXPECT_TRUE(scoper.get()); | |
274 } | |
275 EXPECT_EQ(1, deletes); | |
276 | |
277 // Test reset() and release(). | |
278 deletes = 0; | |
279 { | |
280 unique_ptr<double, CountingDeleter> scoper(nullptr, | |
281 CountingDeleter(&deletes)); | |
282 EXPECT_FALSE(scoper.get()); | |
283 EXPECT_FALSE(scoper.release()); | |
284 EXPECT_FALSE(scoper.get()); | |
285 scoper.reset(); | |
286 EXPECT_FALSE(scoper.get()); | |
287 EXPECT_EQ(0, deletes); | |
288 | |
289 scoper.reset(&dummy_value); | |
290 scoper.reset(); | |
291 EXPECT_EQ(1, deletes); | |
292 | |
293 scoper.reset(&dummy_value); | |
294 EXPECT_EQ(&dummy_value, scoper.release()); | |
295 } | |
296 EXPECT_EQ(1, deletes); | |
297 | |
298 // Test get_deleter(). | |
299 deletes = 0; | |
300 alternate_deletes = 0; | |
301 { | |
302 unique_ptr<double, CountingDeleter> scoper(&dummy_value, | |
303 CountingDeleter(&deletes)); | |
304 // Call deleter manually. | |
305 EXPECT_EQ(0, deletes); | |
306 scoper.get_deleter()(&dummy_value); | |
307 EXPECT_EQ(1, deletes); | |
308 | |
309 // Deleter is still there after reset. | |
310 scoper.reset(); | |
311 EXPECT_EQ(2, deletes); | |
312 scoper.get_deleter()(&dummy_value); | |
313 EXPECT_EQ(3, deletes); | |
314 | |
315 // Deleter can be assigned into (matches C++11 unique_ptr<> spec). | |
316 scoper.get_deleter() = CountingDeleter(&alternate_deletes); | |
317 scoper.reset(&dummy_value); | |
318 EXPECT_EQ(0, alternate_deletes); | |
319 } | |
320 EXPECT_EQ(3, deletes); | |
321 EXPECT_EQ(1, alternate_deletes); | |
322 | |
323 // Test swap(), ==, !=, and type-safe Boolean. | |
324 { | |
325 unique_ptr<double, CountingDeleter> scoper1(nullptr, | |
326 CountingDeleter(&deletes)); | |
327 unique_ptr<double, CountingDeleter> scoper2(nullptr, | |
328 CountingDeleter(&deletes)); | |
329 EXPECT_TRUE(scoper1 == scoper2.get()); | |
330 EXPECT_FALSE(scoper1 != scoper2.get()); | |
331 | |
332 scoper1.reset(&dummy_value); | |
333 EXPECT_TRUE(scoper1); | |
334 EXPECT_EQ(&dummy_value, scoper1.get()); | |
335 EXPECT_FALSE(scoper2); | |
336 EXPECT_FALSE(scoper2.get()); | |
337 EXPECT_FALSE(scoper1 == scoper2.get()); | |
338 EXPECT_TRUE(scoper1 != scoper2.get()); | |
339 | |
340 scoper2.swap(scoper1); | |
341 EXPECT_EQ(&dummy_value, scoper2.get()); | |
342 EXPECT_FALSE(scoper1.get()); | |
343 EXPECT_FALSE(scoper1 == scoper2.get()); | |
344 EXPECT_TRUE(scoper1 != scoper2.get()); | |
345 } | |
346 } | |
347 | |
348 unique_ptr<int> NullIntReturn() { | |
349 return nullptr; | |
350 } | |
351 | |
352 TEST(UniquePtrTest, Nullptr) { | |
353 unique_ptr<int> scoper1(nullptr); | |
354 unique_ptr<int> scoper2(new int); | |
355 scoper2 = nullptr; | |
356 unique_ptr<int> scoper3(NullIntReturn()); | |
357 unique_ptr<int> scoper4 = NullIntReturn(); | |
358 EXPECT_EQ(nullptr, scoper1.get()); | |
359 EXPECT_EQ(nullptr, scoper2.get()); | |
360 EXPECT_EQ(nullptr, scoper3.get()); | |
361 EXPECT_EQ(nullptr, scoper4.get()); | |
362 } | |
363 | |
364 unique_ptr<int[]> NullIntArrayReturn() { | |
365 return nullptr; | |
366 } | |
367 | |
368 TEST(UniquePtrTest, NullptrArray) { | |
369 unique_ptr<int[]> scoper1(nullptr); | |
370 unique_ptr<int[]> scoper2(new int[3]); | |
371 scoper2 = nullptr; | |
372 unique_ptr<int[]> scoper3(NullIntArrayReturn()); | |
373 unique_ptr<int[]> scoper4 = NullIntArrayReturn(); | |
374 EXPECT_EQ(nullptr, scoper1.get()); | |
375 EXPECT_EQ(nullptr, scoper2.get()); | |
376 EXPECT_EQ(nullptr, scoper3.get()); | |
377 EXPECT_EQ(nullptr, scoper4.get()); | |
378 } | |
379 | |
380 // Logging a unique_ptr<T> to an ostream shouldn't convert it to a boolean | |
381 // value first. | |
382 TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) { | |
383 unique_ptr<int> x(new int); | |
384 std::stringstream s1; | |
385 s1 << x; | |
386 | |
387 std::stringstream s2; | |
388 s2 << x.get(); | |
389 | |
390 EXPECT_EQ(s2.str(), s1.str()); | |
391 } | |
OLD | NEW |