| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <objc/runtime.h> | 6 #include <objc/runtime.h> |
| 7 | 7 |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #import "base/memory/scoped_nsobject.h" | 9 #import "base/mac/scoped_nsobject.h" |
| 10 #import "chrome/common/mac/objc_zombie.h" | 10 #import "chrome/common/mac/objc_zombie.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 #include "testing/platform_test.h" | 12 #include "testing/platform_test.h" |
| 13 | 13 |
| 14 @interface ZombieCxxDestructTest : NSObject | 14 @interface ZombieCxxDestructTest : NSObject |
| 15 { | 15 { |
| 16 scoped_nsobject<id> aRef_; | 16 base::scoped_nsobject<id> aRef_; |
| 17 } | 17 } |
| 18 - (id)initWith:(id)anObject; | 18 - (id)initWith:(id)anObject; |
| 19 @end | 19 @end |
| 20 | 20 |
| 21 @implementation ZombieCxxDestructTest | 21 @implementation ZombieCxxDestructTest |
| 22 - (id)initWith:(id)anObject { | 22 - (id)initWith:(id)anObject { |
| 23 self = [super init]; | 23 self = [super init]; |
| 24 if (self) { | 24 if (self) { |
| 25 aRef_.reset([anObject retain]); | 25 aRef_.reset([anObject retain]); |
| 26 } | 26 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 47 | 47 |
| 48 @end | 48 @end |
| 49 | 49 |
| 50 namespace { | 50 namespace { |
| 51 | 51 |
| 52 // Verify that the C++ destructors run when the last reference to the | 52 // Verify that the C++ destructors run when the last reference to the |
| 53 // object is released. | 53 // object is released. |
| 54 // NOTE(shess): To test the negative, comment out the |g_objectDestruct()| | 54 // NOTE(shess): To test the negative, comment out the |g_objectDestruct()| |
| 55 // call in |ZombieDealloc()|. | 55 // call in |ZombieDealloc()|. |
| 56 TEST(ObjcZombieTest, CxxDestructors) { | 56 TEST(ObjcZombieTest, CxxDestructors) { |
| 57 scoped_nsobject<id> anObject([[NSObject alloc] init]); | 57 base::scoped_nsobject<id> anObject([[NSObject alloc] init]); |
| 58 EXPECT_EQ(1u, [anObject retainCount]); | 58 EXPECT_EQ(1u, [anObject retainCount]); |
| 59 | 59 |
| 60 ASSERT_TRUE(ObjcEvilDoers::ZombieEnable(YES, 100)); | 60 ASSERT_TRUE(ObjcEvilDoers::ZombieEnable(YES, 100)); |
| 61 | 61 |
| 62 scoped_nsobject<ZombieCxxDestructTest> soonInfected( | 62 base::scoped_nsobject<ZombieCxxDestructTest> soonInfected( |
| 63 [[ZombieCxxDestructTest alloc] initWith:anObject]); | 63 [[ZombieCxxDestructTest alloc] initWith:anObject]); |
| 64 EXPECT_EQ(2u, [anObject retainCount]); | 64 EXPECT_EQ(2u, [anObject retainCount]); |
| 65 | 65 |
| 66 // When |soonInfected| becomes a zombie, the C++ destructors should | 66 // When |soonInfected| becomes a zombie, the C++ destructors should |
| 67 // run and release a reference to |anObject|. | 67 // run and release a reference to |anObject|. |
| 68 soonInfected.reset(); | 68 soonInfected.reset(); |
| 69 EXPECT_EQ(1u, [anObject retainCount]); | 69 EXPECT_EQ(1u, [anObject retainCount]); |
| 70 | 70 |
| 71 // The local reference should remain (C++ destructors aren't re-run). | 71 // The local reference should remain (C++ destructors aren't re-run). |
| 72 ObjcEvilDoers::ZombieDisable(); | 72 ObjcEvilDoers::ZombieDisable(); |
| 73 EXPECT_EQ(1u, [anObject retainCount]); | 73 EXPECT_EQ(1u, [anObject retainCount]); |
| 74 } | 74 } |
| 75 | 75 |
| 76 // Verify that the associated objects are released when the object is | 76 // Verify that the associated objects are released when the object is |
| 77 // released. | 77 // released. |
| 78 TEST(ObjcZombieTest, AssociatedObjectsReleased) { | 78 TEST(ObjcZombieTest, AssociatedObjectsReleased) { |
| 79 scoped_nsobject<id> anObject([[NSObject alloc] init]); | 79 base::scoped_nsobject<id> anObject([[NSObject alloc] init]); |
| 80 EXPECT_EQ(1u, [anObject retainCount]); | 80 EXPECT_EQ(1u, [anObject retainCount]); |
| 81 | 81 |
| 82 ASSERT_TRUE(ObjcEvilDoers::ZombieEnable(YES, 100)); | 82 ASSERT_TRUE(ObjcEvilDoers::ZombieEnable(YES, 100)); |
| 83 | 83 |
| 84 scoped_nsobject<ZombieAssociatedObjectTest> soonInfected( | 84 base::scoped_nsobject<ZombieAssociatedObjectTest> soonInfected( |
| 85 [[ZombieAssociatedObjectTest alloc] initWithAssociatedObject:anObject]); | 85 [[ZombieAssociatedObjectTest alloc] initWithAssociatedObject:anObject]); |
| 86 EXPECT_EQ(2u, [anObject retainCount]); | 86 EXPECT_EQ(2u, [anObject retainCount]); |
| 87 | 87 |
| 88 // When |soonInfected| becomes a zombie, the associated object | 88 // When |soonInfected| becomes a zombie, the associated object |
| 89 // should be released. | 89 // should be released. |
| 90 soonInfected.reset(); | 90 soonInfected.reset(); |
| 91 EXPECT_EQ(1u, [anObject retainCount]); | 91 EXPECT_EQ(1u, [anObject retainCount]); |
| 92 | 92 |
| 93 // The local reference should remain (associated objects not re-released). | 93 // The local reference should remain (associated objects not re-released). |
| 94 ObjcEvilDoers::ZombieDisable(); | 94 ObjcEvilDoers::ZombieDisable(); |
| 95 EXPECT_EQ(1u, [anObject retainCount]); | 95 EXPECT_EQ(1u, [anObject retainCount]); |
| 96 } | 96 } |
| 97 | 97 |
| 98 } // namespace | 98 } // namespace |
| OLD | NEW |