| 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 |