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