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