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