Roll src/third_party/WebKit 6f84130:7353389 (svn 184386:184391)
[chromium-blink-merge.git] / chrome / common / mac / objc_zombie_unittest.mm
blob9e438d2901950d194c7e4635b789f8ed37b9b3fb
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
3 // found in the LICENSE file.
5 #import <Foundation/Foundation.h>
6 #include <objc/runtime.h>
8 #include "base/logging.h"
9 #import "base/mac/scoped_nsobject.h"
10 #import "chrome/common/mac/objc_zombie.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "testing/platform_test.h"
14 @interface ZombieCxxDestructTest : NSObject
16   base::scoped_nsobject<id> aRef_;
18 - (id)initWith:(id)anObject;
19 @end
21 @implementation ZombieCxxDestructTest
22 - (id)initWith:(id)anObject {
23   self = [super init];
24   if (self) {
25     aRef_.reset([anObject retain]);
26   }
27   return self;
29 @end
31 @interface ZombieAssociatedObjectTest : NSObject
32 - (id)initWithAssociatedObject:(id)anObject;
33 @end
35 @implementation ZombieAssociatedObjectTest
37 - (id)initWithAssociatedObject:(id)anObject {
38   if ((self = [super init])) {
39     // The address of the variable itself is the unique key, the
40     // contents don't matter.
41     static char kAssociatedObjectKey = 'x';
42     objc_setAssociatedObject(
43         self, &kAssociatedObjectKey, anObject, OBJC_ASSOCIATION_RETAIN);
44   }
45   return self;
48 @end
50 namespace {
52 // Verify that the C++ destructors run when the last reference to the
53 // object is released.
54 // NOTE(shess): To test the negative, comment out the |g_objectDestruct()|
55 // call in |ZombieDealloc()|.
56 TEST(ObjcZombieTest, CxxDestructors) {
57   base::scoped_nsobject<id> anObject([[NSObject alloc] init]);
58   EXPECT_EQ(1u, [anObject retainCount]);
60   ASSERT_TRUE(ObjcEvilDoers::ZombieEnable(YES, 100));
62   base::scoped_nsobject<ZombieCxxDestructTest> soonInfected(
63       [[ZombieCxxDestructTest alloc] initWith:anObject]);
64   EXPECT_EQ(2u, [anObject retainCount]);
66   // When |soonInfected| becomes a zombie, the C++ destructors should
67   // run and release a reference to |anObject|.
68   soonInfected.reset();
69   EXPECT_EQ(1u, [anObject retainCount]);
71   // The local reference should remain (C++ destructors aren't re-run).
72   ObjcEvilDoers::ZombieDisable();
73   EXPECT_EQ(1u, [anObject retainCount]);
76 // Verify that the associated objects are released when the object is
77 // released.
78 TEST(ObjcZombieTest, AssociatedObjectsReleased) {
79   base::scoped_nsobject<id> anObject([[NSObject alloc] init]);
80   EXPECT_EQ(1u, [anObject retainCount]);
82   ASSERT_TRUE(ObjcEvilDoers::ZombieEnable(YES, 100));
84   base::scoped_nsobject<ZombieAssociatedObjectTest> soonInfected(
85       [[ZombieAssociatedObjectTest alloc] initWithAssociatedObject:anObject]);
86   EXPECT_EQ(2u, [anObject retainCount]);
88   // When |soonInfected| becomes a zombie, the associated object
89   // should be released.
90   soonInfected.reset();
91   EXPECT_EQ(1u, [anObject retainCount]);
93   // The local reference should remain (associated objects not re-released).
94   ObjcEvilDoers::ZombieDisable();
95   EXPECT_EQ(1u, [anObject retainCount]);
98 }  // namespace