noarc_block_unittest.mm 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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
  3. // found in the LICENSE file.
  4. #import <Foundation/Foundation.h>
  5. #include <vector>
  6. #include "base/memory/ref_counted.h"
  7. #include "testing/platform_test.h"
  8. #if defined(__has_feature) && __has_feature(objc_arc)
  9. #error "This file must not be compiled with ARC."
  10. #endif
  11. // This test verifies assumptions about the murky world of interaction between
  12. // C++ objects and blocks. Just to make sure.
  13. namespace {
  14. using NoArcBlockTest = PlatformTest;
  15. class RefCountedObject : public base::RefCounted<RefCountedObject> {
  16. public:
  17. RefCountedObject() {}
  18. // Refcount is private in the superclass, fake it by counting how many times
  19. // release can be called until there is one count left, then retain the count
  20. // back.
  21. int refcount() {
  22. int count = 1;
  23. while (!HasOneRef()) {
  24. bool check = base::subtle::RefCountedBase::Release();
  25. EXPECT_FALSE(check);
  26. ++count;
  27. }
  28. for (int ii = 1; ii < count; ii++)
  29. base::subtle::RefCountedBase::AddRef();
  30. return count;
  31. }
  32. protected:
  33. friend base::RefCounted<RefCountedObject>;
  34. virtual ~RefCountedObject() {}
  35. };
  36. TEST_F(NoArcBlockTest, BlockAndCPlusPlus) {
  37. RefCountedObject* object = new RefCountedObject();
  38. object->AddRef();
  39. EXPECT_TRUE(object->HasOneRef());
  40. EXPECT_EQ(1, object->refcount());
  41. {
  42. scoped_refptr<RefCountedObject> object_test_ptr(object);
  43. EXPECT_EQ(2, object->refcount());
  44. }
  45. EXPECT_TRUE(object->HasOneRef());
  46. void (^heap_block)(int) = nil;
  47. {
  48. scoped_refptr<RefCountedObject> object_ptr(object);
  49. EXPECT_EQ(2, object->refcount());
  50. void* object_void_ptr = (void*)object;
  51. void (^stack_block)(int) = ^(int expected) {
  52. EXPECT_EQ(object_void_ptr, object_ptr.get());
  53. EXPECT_EQ(expected, object_ptr.get()->refcount());
  54. };
  55. stack_block(3);
  56. heap_block = [stack_block copy];
  57. stack_block(4);
  58. }
  59. heap_block(2);
  60. [heap_block release];
  61. EXPECT_TRUE(object->HasOneRef());
  62. {
  63. scoped_refptr<RefCountedObject> object_test2_ptr(object);
  64. EXPECT_EQ(2, object->refcount());
  65. }
  66. EXPECT_TRUE(object->HasOneRef());
  67. object->Release();
  68. }
  69. TEST_F(NoArcBlockTest, BlockAndVectors) {
  70. void (^heap_block)(void) = nil;
  71. {
  72. std::vector<int> vector;
  73. vector.push_back(0);
  74. vector.push_back(1);
  75. vector.push_back(2);
  76. void (^stack_block)(void) = ^{
  77. EXPECT_EQ(3ul, vector.size());
  78. EXPECT_EQ(2, vector[2]);
  79. };
  80. stack_block();
  81. vector[2] = 42;
  82. vector.push_back(22);
  83. stack_block();
  84. heap_block = [stack_block copy];
  85. stack_block();
  86. }
  87. heap_block();
  88. [heap_block release];
  89. }
  90. } // namespace