Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(943)

Side by Side Diff: chrome/browser/ui/cocoa/objc_zombie_unittest.mm

Issue 7084017: [Mac] Use object_destructInstance() if available. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Per-runtime initialization, unit test, misc. Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <Cocoa/Cocoa.h> 5 #import <Cocoa/Cocoa.h>
6 #include <dlfcn.h>
6 7
8 #include "base/logging.h"
7 #import "base/memory/scoped_nsobject.h" 9 #import "base/memory/scoped_nsobject.h"
8 #import "chrome/browser/ui/cocoa/objc_zombie.h" 10 #import "chrome/browser/ui/cocoa/objc_zombie.h"
9 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
10 #include "testing/platform_test.h" 12 #include "testing/platform_test.h"
11 13
14 namespace {
15
16 // Dynamically lookup |objc_setAssociatedObject()|, which isn't
Mark Mentovai 2011/06/07 21:42:57 look up
Scott Hess - ex-Googler 2011/06/07 23:48:21 Done.
17 // available until the 10.6 SDK.
18
19 typedef void objc_setAssociatedObjectFn(id object, void *key, id value,
20 int policy);
21 objc_setAssociatedObjectFn* LookupSetAssociatedObjectFn() {
22 return reinterpret_cast<objc_setAssociatedObjectFn*>(
23 dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
24 }
25
26 } // namespace
27
12 @interface ZombieCxxDestructTest : NSObject 28 @interface ZombieCxxDestructTest : NSObject
13 { 29 {
14 scoped_nsobject<id> aRef_; 30 scoped_nsobject<id> aRef_;
15 } 31 }
16 - (id)initWith:(id)anObject; 32 - (id)initWith:(id)anObject;
17 @end 33 @end
18 34
19 @implementation ZombieCxxDestructTest 35 @implementation ZombieCxxDestructTest
20 - (id)initWith:(id)anObject { 36 - (id)initWith:(id)anObject {
21 self = [super init]; 37 self = [super init];
22 if (self) { 38 if (self) {
23 aRef_.reset([anObject retain]); 39 aRef_.reset([anObject retain]);
24 } 40 }
25 return self; 41 return self;
26 } 42 }
27 @end 43 @end
28 44
45 @interface ZombieAssociatedObjectTest : NSObject
46 {
Mark Mentovai 2011/06/07 21:42:57 You don’t need the { } for an instance variable-fr
Scott Hess - ex-Googler 2011/06/07 23:48:21 Done.
47 }
48 + (BOOL)supportsAssociatedObjects;
49
50 - (id)initWithAssociatedObject:(id)anObject;
51 @end
52
53 @implementation ZombieAssociatedObjectTest
54
55 + (BOOL)supportsAssociatedObjects {
56 if (LookupSetAssociatedObjectFn())
57 return YES;
58 return NO;
59 }
60
61 - (id)initWithAssociatedObject:(id)anObject {
62 self = [super init];
63 if (self) {
64 objc_setAssociatedObjectFn* fn = LookupSetAssociatedObjectFn();
65 if (fn) {
66 // Cribbed from 10.6 <objc/runtime.h>.
67 static const int kObjcAssociationRetain = 01401;
68
69 // The address of the variable itself is the unique key, the
70 // contents don't matter.
71 static char kAssociatedObjectKey = 'x';
72
73 (*fn)(self, &kAssociatedObjectKey, anObject, kObjcAssociationRetain);
74 }
75 }
76 return self;
77 }
78
79 @end
80
29 namespace { 81 namespace {
30 82
31 // Verify that the C++ destructors run when the last reference to the 83 // Verify that the C++ destructors run when the last reference to the
32 // object is released. Unfortunately, testing the negative requires 84 // object is released.
33 // commenting out the |object_cxxDestruct()| call in 85 // NOTE(shess): To test the negative, comment out the |g_objectDestruct()|
34 // |ZombieDealloc()|. 86 // call in |ZombieDealloc()|.
35
36 TEST(ObjcZombieTest, CxxDestructors) { 87 TEST(ObjcZombieTest, CxxDestructors) {
37 scoped_nsobject<id> anObject([[NSObject alloc] init]); 88 scoped_nsobject<id> anObject([[NSObject alloc] init]);
38 EXPECT_EQ(1u, [anObject retainCount]); 89 EXPECT_EQ(1u, [anObject retainCount]);
39 90
40 ASSERT_TRUE(ObjcEvilDoers::ZombieEnable(YES, 100)); 91 ASSERT_TRUE(
92 ObjcEvilDoers::ZombieEnable(ObjcEvilDoers::RUNTIME_GUESS, YES, 100));
41 93
42 scoped_nsobject<ZombieCxxDestructTest> soonInfected( 94 scoped_nsobject<ZombieCxxDestructTest> soonInfected(
43 [[ZombieCxxDestructTest alloc] initWith:anObject]); 95 [[ZombieCxxDestructTest alloc] initWith:anObject]);
44 EXPECT_EQ(2u, [anObject retainCount]); 96 EXPECT_EQ(2u, [anObject retainCount]);
45 97
46 // When |soonInfected| becomes a zombie, the C++ destructors should 98 // When |soonInfected| becomes a zombie, the C++ destructors should
47 // run and release a reference to |anObject|. 99 // run and release a reference to |anObject|.
48 soonInfected.reset(); 100 soonInfected.reset();
49 EXPECT_EQ(1u, [anObject retainCount]); 101 EXPECT_EQ(1u, [anObject retainCount]);
50 102
51 // The local reference should remain (C++ destructors aren't re-run). 103 // The local reference should remain (C++ destructors aren't re-run).
52 ObjcEvilDoers::ZombieDisable(); 104 ObjcEvilDoers::ZombieDisable();
53 EXPECT_EQ(1u, [anObject retainCount]); 105 EXPECT_EQ(1u, [anObject retainCount]);
54 } 106 }
55 107
108 // Verify that the associated objects are released when the object is
109 // released.
110 // NOTE(shess): To test the negative, enable zombies with
111 // |RUNTIME_10_5|, and run this test in isolation on 10.6.
112 TEST(ObjcZombieTest, AssociatedObjectsReleased) {
113 if (![ZombieAssociatedObjectTest supportsAssociatedObjects]) {
114 LOG(ERROR)
115 << "ObjcZombieTest.AssociatedObjectsReleased not supported on 10.5";
116 return;
117 }
118
119 scoped_nsobject<id> anObject([[NSObject alloc] init]);
120 EXPECT_EQ(1u, [anObject retainCount]);
121
122 ASSERT_TRUE(
123 ObjcEvilDoers::ZombieEnable(ObjcEvilDoers::RUNTIME_GUESS, YES, 100));
124
125 scoped_nsobject<ZombieAssociatedObjectTest> soonInfected(
126 [[ZombieAssociatedObjectTest alloc] initWithAssociatedObject:anObject]);
127 EXPECT_EQ(2u, [anObject retainCount]);
128
129 // When |soonInfected| becomes a zombie, the associated object
Mark Mentovai 2011/06/07 21:42:57 Good test.
130 // should be released.
131 soonInfected.reset();
132 EXPECT_EQ(1u, [anObject retainCount]);
133
134 // The local reference should remain (associated objects not re-released).
135 ObjcEvilDoers::ZombieDisable();
136 EXPECT_EQ(1u, [anObject retainCount]);
137 }
138
56 } // namespace 139 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698