OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
| 5 #include "base/memory/scoped_ptr.h" |
| 6 |
5 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
6 #include "base/memory/scoped_ptr.h" | 8 #include "base/bind.h" |
| 9 #include "base/callback.h" |
7 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
8 | 11 |
9 namespace { | 12 namespace { |
10 | 13 |
11 // Used to test depth subtyping. | 14 // Used to test depth subtyping. |
12 class ConDecLoggerParent { | 15 class ConDecLoggerParent { |
13 public: | 16 public: |
14 virtual ~ConDecLoggerParent() {} | 17 virtual ~ConDecLoggerParent() {} |
15 | 18 |
16 virtual void SetPtr(int* ptr) = 0; | 19 virtual void SetPtr(int* ptr) = 0; |
(...skipping 10 matching lines...) Expand all Loading... |
27 virtual void SetPtr(int* ptr) OVERRIDE { ptr_ = ptr; ++*ptr_; } | 30 virtual void SetPtr(int* ptr) OVERRIDE { ptr_ = ptr; ++*ptr_; } |
28 | 31 |
29 virtual int SomeMeth(int x) const OVERRIDE { return x; } | 32 virtual int SomeMeth(int x) const OVERRIDE { return x; } |
30 | 33 |
31 private: | 34 private: |
32 int* ptr_; | 35 int* ptr_; |
33 | 36 |
34 DISALLOW_COPY_AND_ASSIGN(ConDecLogger); | 37 DISALLOW_COPY_AND_ASSIGN(ConDecLogger); |
35 }; | 38 }; |
36 | 39 |
| 40 struct CountingDeleter { |
| 41 explicit CountingDeleter(int* count) : count_(count) {} |
| 42 inline void operator()(double* ptr) const { |
| 43 (*count_)++; |
| 44 } |
| 45 int* count_; |
| 46 }; |
| 47 |
| 48 // Used to test assignment of convertible deleters. |
| 49 struct CountingDeleterChild : public CountingDeleter { |
| 50 explicit CountingDeleterChild(int* count) : CountingDeleter(count) {} |
| 51 }; |
| 52 |
| 53 class OverloadedNewAndDelete { |
| 54 public: |
| 55 void* operator new(size_t size) { |
| 56 g_new_count++; |
| 57 return malloc(size); |
| 58 } |
| 59 |
| 60 void operator delete(void* ptr) { |
| 61 g_delete_count++; |
| 62 free(ptr); |
| 63 } |
| 64 |
| 65 static void ResetCounters() { |
| 66 g_new_count = 0; |
| 67 g_delete_count = 0; |
| 68 } |
| 69 |
| 70 static int new_count() { return g_new_count; } |
| 71 static int delete_count() { return g_delete_count; } |
| 72 |
| 73 private: |
| 74 static int g_new_count; |
| 75 static int g_delete_count; |
| 76 }; |
| 77 |
| 78 int OverloadedNewAndDelete::g_new_count = 0; |
| 79 int OverloadedNewAndDelete::g_delete_count = 0; |
| 80 |
37 scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) { | 81 scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) { |
38 return logger.Pass(); | 82 return logger.Pass(); |
39 } | 83 } |
40 | 84 |
41 void GrabAndDrop(scoped_ptr<ConDecLogger> logger) { | 85 void GrabAndDrop(scoped_ptr<ConDecLogger> logger) { |
42 } | 86 } |
43 | 87 |
44 // Do not delete this function! It's existence is to test that you can | 88 // Do not delete this function! It's existence is to test that you can |
45 // return a temporarily constructed version of the scoper. | 89 // return a temporarily constructed version of the scoper. |
46 scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) { | 90 scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 EXPECT_EQ(1, constructed); | 222 EXPECT_EQ(1, constructed); |
179 EXPECT_TRUE(scoper.get()); | 223 EXPECT_TRUE(scoper.get()); |
180 | 224 |
181 scoped_ptr<const ConDecLogger> scoper_const; | 225 scoped_ptr<const ConDecLogger> scoper_const; |
182 scoper_const = scoper.Pass(); | 226 scoper_const = scoper.Pass(); |
183 EXPECT_EQ(1, constructed); | 227 EXPECT_EQ(1, constructed); |
184 EXPECT_TRUE(scoper_const.get()); | 228 EXPECT_TRUE(scoper_const.get()); |
185 EXPECT_FALSE(scoper.get()); | 229 EXPECT_FALSE(scoper.get()); |
186 } | 230 } |
187 EXPECT_EQ(0, constructed); | 231 EXPECT_EQ(0, constructed); |
| 232 |
| 233 // Test assignment to a scoped_ptr deleter of parent type. |
| 234 { |
| 235 // Custom deleters never touch these value. |
| 236 double dummy_value, dummy_value2; |
| 237 int deletes = 0; |
| 238 int alternate_deletes = 0; |
| 239 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, |
| 240 CountingDeleter(&deletes)); |
| 241 scoped_ptr<double, CountingDeleterChild> scoper_child( |
| 242 &dummy_value2, CountingDeleterChild(&alternate_deletes)); |
| 243 |
| 244 EXPECT_TRUE(scoper); |
| 245 EXPECT_TRUE(scoper_child); |
| 246 EXPECT_EQ(0, deletes); |
| 247 EXPECT_EQ(0, alternate_deletes); |
| 248 |
| 249 // Test this compiles and correctly overwrites the deleter state. |
| 250 scoper = scoper_child.Pass(); |
| 251 EXPECT_TRUE(scoper); |
| 252 EXPECT_FALSE(scoper_child); |
| 253 EXPECT_EQ(1, deletes); |
| 254 EXPECT_EQ(0, alternate_deletes); |
| 255 |
| 256 scoper.reset(); |
| 257 EXPECT_FALSE(scoper); |
| 258 EXPECT_FALSE(scoper_child); |
| 259 EXPECT_EQ(1, deletes); |
| 260 EXPECT_EQ(1, alternate_deletes); |
| 261 |
| 262 scoper_child.reset(&dummy_value); |
| 263 EXPECT_TRUE(scoper_child); |
| 264 EXPECT_EQ(1, deletes); |
| 265 EXPECT_EQ(1, alternate_deletes); |
| 266 scoped_ptr<double, CountingDeleter> scoper_construct(scoper_child.Pass()); |
| 267 EXPECT_TRUE(scoper_construct); |
| 268 EXPECT_FALSE(scoper_child); |
| 269 EXPECT_EQ(1, deletes); |
| 270 EXPECT_EQ(1, alternate_deletes); |
| 271 |
| 272 scoper_construct.reset(); |
| 273 EXPECT_EQ(1, deletes); |
| 274 EXPECT_EQ(2, alternate_deletes); |
| 275 } |
| 276 } |
| 277 |
| 278 TEST(ScopedPtrTest, ScopedPtrWithArray) { |
| 279 static const int kNumLoggers = 12; |
| 280 |
| 281 int constructed = 0; |
| 282 |
| 283 { |
| 284 scoped_ptr<ConDecLogger[]> scoper(new ConDecLogger[kNumLoggers]); |
| 285 EXPECT_TRUE(scoper); |
| 286 EXPECT_EQ(&scoper[0], scoper.get()); |
| 287 for (int i = 0; i < kNumLoggers; ++i) { |
| 288 scoper[i].SetPtr(&constructed); |
| 289 } |
| 290 EXPECT_EQ(12, constructed); |
| 291 |
| 292 EXPECT_EQ(10, scoper.get()->SomeMeth(10)); |
| 293 EXPECT_EQ(10, scoper[2].SomeMeth(10)); |
| 294 } |
| 295 EXPECT_EQ(0, constructed); |
| 296 |
| 297 // Test reset() and release() |
| 298 { |
| 299 scoped_ptr<ConDecLogger[]> scoper; |
| 300 EXPECT_FALSE(scoper.get()); |
| 301 EXPECT_FALSE(scoper.release()); |
| 302 EXPECT_FALSE(scoper.get()); |
| 303 scoper.reset(); |
| 304 EXPECT_FALSE(scoper.get()); |
| 305 |
| 306 scoper.reset(new ConDecLogger[kNumLoggers]); |
| 307 for (int i = 0; i < kNumLoggers; ++i) { |
| 308 scoper[i].SetPtr(&constructed); |
| 309 } |
| 310 EXPECT_EQ(12, constructed); |
| 311 scoper.reset(); |
| 312 EXPECT_EQ(0, constructed); |
| 313 |
| 314 scoper.reset(new ConDecLogger[kNumLoggers]); |
| 315 for (int i = 0; i < kNumLoggers; ++i) { |
| 316 scoper[i].SetPtr(&constructed); |
| 317 } |
| 318 EXPECT_EQ(12, constructed); |
| 319 ConDecLogger* ptr = scoper.release(); |
| 320 EXPECT_EQ(12, constructed); |
| 321 delete[] ptr; |
| 322 EXPECT_EQ(0, constructed); |
| 323 } |
| 324 EXPECT_EQ(0, constructed); |
| 325 |
| 326 // Test swap(), ==, !=, and type-safe Boolean. |
| 327 { |
| 328 scoped_ptr<ConDecLogger[]> scoper1; |
| 329 scoped_ptr<ConDecLogger[]> scoper2; |
| 330 EXPECT_TRUE(scoper1 == scoper2.get()); |
| 331 EXPECT_FALSE(scoper1 != scoper2.get()); |
| 332 |
| 333 ConDecLogger* loggers = new ConDecLogger[kNumLoggers]; |
| 334 for (int i = 0; i < kNumLoggers; ++i) { |
| 335 loggers[i].SetPtr(&constructed); |
| 336 } |
| 337 scoper1.reset(loggers); |
| 338 EXPECT_TRUE(scoper1); |
| 339 EXPECT_EQ(loggers, scoper1.get()); |
| 340 EXPECT_FALSE(scoper2); |
| 341 EXPECT_FALSE(scoper2.get()); |
| 342 EXPECT_FALSE(scoper1 == scoper2.get()); |
| 343 EXPECT_TRUE(scoper1 != scoper2.get()); |
| 344 |
| 345 scoper2.swap(scoper1); |
| 346 EXPECT_EQ(loggers, scoper2.get()); |
| 347 EXPECT_FALSE(scoper1.get()); |
| 348 EXPECT_FALSE(scoper1 == scoper2.get()); |
| 349 EXPECT_TRUE(scoper1 != scoper2.get()); |
| 350 } |
| 351 EXPECT_EQ(0, constructed); |
| 352 |
| 353 { |
| 354 ConDecLogger* loggers = new ConDecLogger[kNumLoggers]; |
| 355 scoped_ptr<ConDecLogger[]> scoper(loggers); |
| 356 EXPECT_TRUE(scoper); |
| 357 for (int i = 0; i < kNumLoggers; ++i) { |
| 358 scoper[i].SetPtr(&constructed); |
| 359 } |
| 360 EXPECT_EQ(kNumLoggers, constructed); |
| 361 |
| 362 // Test Pass() with constructor; |
| 363 scoped_ptr<ConDecLogger[]> scoper2(scoper.Pass()); |
| 364 EXPECT_EQ(kNumLoggers, constructed); |
| 365 |
| 366 // Test Pass() with assignment; |
| 367 scoped_ptr<ConDecLogger[]> scoper3; |
| 368 scoper3 = scoper2.Pass(); |
| 369 EXPECT_EQ(kNumLoggers, constructed); |
| 370 EXPECT_FALSE(scoper); |
| 371 EXPECT_FALSE(scoper2); |
| 372 EXPECT_TRUE(scoper3); |
| 373 } |
| 374 EXPECT_EQ(0, constructed); |
188 } | 375 } |
189 | 376 |
190 TEST(ScopedPtrTest, ScopedArray) { | 377 TEST(ScopedPtrTest, ScopedArray) { |
191 static const int kNumLoggers = 12; | 378 static const int kNumLoggers = 12; |
192 | 379 |
193 int constructed = 0; | 380 int constructed = 0; |
194 | 381 |
195 { | 382 { |
196 scoped_array<ConDecLogger> scoper(new ConDecLogger[kNumLoggers]); | 383 scoped_array<ConDecLogger> scoper(new ConDecLogger[kNumLoggers]); |
197 EXPECT_TRUE(scoper.get()); | 384 EXPECT_TRUE(scoper.get()); |
(...skipping 30 matching lines...) Expand all Loading... |
228 scoper[i].SetPtr(&constructed); | 415 scoper[i].SetPtr(&constructed); |
229 } | 416 } |
230 EXPECT_EQ(12, constructed); | 417 EXPECT_EQ(12, constructed); |
231 ConDecLogger* ptr = scoper.release(); | 418 ConDecLogger* ptr = scoper.release(); |
232 EXPECT_EQ(12, constructed); | 419 EXPECT_EQ(12, constructed); |
233 delete[] ptr; | 420 delete[] ptr; |
234 EXPECT_EQ(0, constructed); | 421 EXPECT_EQ(0, constructed); |
235 } | 422 } |
236 EXPECT_EQ(0, constructed); | 423 EXPECT_EQ(0, constructed); |
237 | 424 |
238 // Test swap(), == and != | 425 // Test swap(), ==, !=, and type-safe Boolean. |
239 { | 426 { |
240 scoped_array<ConDecLogger> scoper1; | 427 scoped_array<ConDecLogger> scoper1; |
241 scoped_array<ConDecLogger> scoper2; | 428 scoped_array<ConDecLogger> scoper2; |
242 EXPECT_TRUE(scoper1 == scoper2.get()); | 429 EXPECT_TRUE(scoper1 == scoper2.get()); |
243 EXPECT_FALSE(scoper1 != scoper2.get()); | 430 EXPECT_FALSE(scoper1 != scoper2.get()); |
244 | 431 |
245 ConDecLogger* loggers = new ConDecLogger[kNumLoggers]; | 432 ConDecLogger* loggers = new ConDecLogger[kNumLoggers]; |
246 for (int i = 0; i < kNumLoggers; ++i) { | 433 for (int i = 0; i < kNumLoggers; ++i) { |
247 loggers[i].SetPtr(&constructed); | 434 loggers[i].SetPtr(&constructed); |
248 } | 435 } |
249 scoper1.reset(loggers); | 436 scoper1.reset(loggers); |
| 437 EXPECT_TRUE(scoper1); |
250 EXPECT_EQ(loggers, scoper1.get()); | 438 EXPECT_EQ(loggers, scoper1.get()); |
| 439 EXPECT_FALSE(scoper2); |
251 EXPECT_FALSE(scoper2.get()); | 440 EXPECT_FALSE(scoper2.get()); |
252 EXPECT_FALSE(scoper1 == scoper2.get()); | 441 EXPECT_FALSE(scoper1 == scoper2.get()); |
253 EXPECT_TRUE(scoper1 != scoper2.get()); | 442 EXPECT_TRUE(scoper1 != scoper2.get()); |
254 | 443 |
255 scoper2.swap(scoper1); | 444 scoper2.swap(scoper1); |
256 EXPECT_EQ(loggers, scoper2.get()); | 445 EXPECT_EQ(loggers, scoper2.get()); |
257 EXPECT_FALSE(scoper1.get()); | 446 EXPECT_FALSE(scoper1.get()); |
258 EXPECT_FALSE(scoper1 == scoper2.get()); | 447 EXPECT_FALSE(scoper1 == scoper2.get()); |
259 EXPECT_TRUE(scoper1 != scoper2.get()); | 448 EXPECT_TRUE(scoper1 != scoper2.get()); |
260 } | 449 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 | 538 |
350 scoped_ptr<ConDecLoggerParent> scoper_parent; | 539 scoped_ptr<ConDecLoggerParent> scoper_parent; |
351 scoper_parent = UpcastUsingPassAs(scoper.Pass()); | 540 scoper_parent = UpcastUsingPassAs(scoper.Pass()); |
352 EXPECT_EQ(1, constructed); | 541 EXPECT_EQ(1, constructed); |
353 EXPECT_TRUE(scoper_parent.get()); | 542 EXPECT_TRUE(scoper_parent.get()); |
354 EXPECT_FALSE(scoper.get()); | 543 EXPECT_FALSE(scoper.get()); |
355 } | 544 } |
356 EXPECT_EQ(0, constructed); | 545 EXPECT_EQ(0, constructed); |
357 } | 546 } |
358 | 547 |
| 548 TEST(ScopedPtrTest, CustomDeleter) { |
| 549 double dummy_value; // Custom deleter never touches this value. |
| 550 int deletes = 0; |
| 551 int alternate_deletes = 0; |
| 552 |
| 553 // Normal delete support. |
| 554 { |
| 555 deletes = 0; |
| 556 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, |
| 557 CountingDeleter(&deletes)); |
| 558 EXPECT_EQ(0, deletes); |
| 559 EXPECT_TRUE(scoper.get()); |
| 560 } |
| 561 EXPECT_EQ(1, deletes); |
| 562 |
| 563 // Test reset() and release(). |
| 564 deletes = 0; |
| 565 { |
| 566 scoped_ptr<double, CountingDeleter> scoper(NULL, |
| 567 CountingDeleter(&deletes)); |
| 568 EXPECT_FALSE(scoper.get()); |
| 569 EXPECT_FALSE(scoper.release()); |
| 570 EXPECT_FALSE(scoper.get()); |
| 571 scoper.reset(); |
| 572 EXPECT_FALSE(scoper.get()); |
| 573 EXPECT_EQ(0, deletes); |
| 574 |
| 575 scoper.reset(&dummy_value); |
| 576 scoper.reset(); |
| 577 EXPECT_EQ(1, deletes); |
| 578 |
| 579 scoper.reset(&dummy_value); |
| 580 EXPECT_EQ(&dummy_value, scoper.release()); |
| 581 } |
| 582 EXPECT_EQ(1, deletes); |
| 583 |
| 584 // Test get_deleter(). |
| 585 deletes = 0; |
| 586 alternate_deletes = 0; |
| 587 { |
| 588 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, |
| 589 CountingDeleter(&deletes)); |
| 590 // Call deleter manually. |
| 591 EXPECT_EQ(0, deletes); |
| 592 scoper.get_deleter()(&dummy_value); |
| 593 EXPECT_EQ(1, deletes); |
| 594 |
| 595 // Deleter is still there after reset. |
| 596 scoper.reset(); |
| 597 EXPECT_EQ(2, deletes); |
| 598 scoper.get_deleter()(&dummy_value); |
| 599 EXPECT_EQ(3, deletes); |
| 600 |
| 601 // Deleter can be assigned into (matches C++11 unique_ptr<> spec). |
| 602 scoper.get_deleter() = CountingDeleter(&alternate_deletes); |
| 603 scoper.reset(&dummy_value); |
| 604 EXPECT_EQ(0, alternate_deletes); |
| 605 |
| 606 } |
| 607 EXPECT_EQ(3, deletes); |
| 608 EXPECT_EQ(1, alternate_deletes); |
| 609 |
| 610 // Test operator= deleter support. |
| 611 deletes = 0; |
| 612 alternate_deletes = 0; |
| 613 { |
| 614 double dummy_value2; |
| 615 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, |
| 616 CountingDeleter(&deletes)); |
| 617 scoped_ptr<double, CountingDeleter> scoper2( |
| 618 &dummy_value2, |
| 619 CountingDeleter(&alternate_deletes)); |
| 620 EXPECT_EQ(0, deletes); |
| 621 EXPECT_EQ(0, alternate_deletes); |
| 622 |
| 623 // Pass the second deleter through a constructor and an operator=. Then |
| 624 // reinitialize the empty scopers to ensure that each one is deleting |
| 625 // properly. |
| 626 scoped_ptr<double, CountingDeleter> scoper3(scoper2.Pass()); |
| 627 scoper = scoper3.Pass(); |
| 628 EXPECT_EQ(1, deletes); |
| 629 |
| 630 scoper2.reset(&dummy_value2); |
| 631 scoper3.reset(&dummy_value2); |
| 632 EXPECT_EQ(0, alternate_deletes); |
| 633 |
| 634 } |
| 635 EXPECT_EQ(1, deletes); |
| 636 EXPECT_EQ(3, alternate_deletes); |
| 637 |
| 638 // Test swap(), ==, !=, and type-safe Boolean. |
| 639 { |
| 640 scoped_ptr<double, CountingDeleter> scoper1(NULL, |
| 641 CountingDeleter(&deletes)); |
| 642 scoped_ptr<double, CountingDeleter> scoper2(NULL, |
| 643 CountingDeleter(&deletes)); |
| 644 EXPECT_TRUE(scoper1 == scoper2.get()); |
| 645 EXPECT_FALSE(scoper1 != scoper2.get()); |
| 646 |
| 647 scoper1.reset(&dummy_value); |
| 648 EXPECT_TRUE(scoper1); |
| 649 EXPECT_EQ(&dummy_value, scoper1.get()); |
| 650 EXPECT_FALSE(scoper2); |
| 651 EXPECT_FALSE(scoper2.get()); |
| 652 EXPECT_FALSE(scoper1 == scoper2.get()); |
| 653 EXPECT_TRUE(scoper1 != scoper2.get()); |
| 654 |
| 655 scoper2.swap(scoper1); |
| 656 EXPECT_EQ(&dummy_value, scoper2.get()); |
| 657 EXPECT_FALSE(scoper1.get()); |
| 658 EXPECT_FALSE(scoper1 == scoper2.get()); |
| 659 EXPECT_TRUE(scoper1 != scoper2.get()); |
| 660 } |
| 661 } |
| 662 |
| 663 // Sanity check test for overloaded new and delete operators. Does not do full |
| 664 // coverage of reset/release/Pass() operations as that is redundant with the |
| 665 // above. |
| 666 TEST(ScopedPtrTest, OverloadedNewAndDelete) { |
| 667 { |
| 668 OverloadedNewAndDelete::ResetCounters(); |
| 669 scoped_ptr<OverloadedNewAndDelete> scoper(new OverloadedNewAndDelete()); |
| 670 EXPECT_TRUE(scoper.get()); |
| 671 |
| 672 scoped_ptr<OverloadedNewAndDelete> scoper2(scoper.Pass()); |
| 673 } |
| 674 EXPECT_EQ(1, OverloadedNewAndDelete::delete_count()); |
| 675 EXPECT_EQ(1, OverloadedNewAndDelete::new_count()); |
| 676 } |
| 677 |
359 // TODO scoped_ptr_malloc | 678 // TODO scoped_ptr_malloc |
OLD | NEW |