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>
7 #import "base/mac/objc_property_releaser.h"
8 #import "base/mac/scoped_nsautorelease_pool.h"
9 #include "testing/gtest/include/gtest/gtest.h"
11 // "When I'm alone, I count myself."
12 // --Count von Count, http://www.youtube.com/watch?v=FKzszqa9WA4
16 // The number of CountVonCounts outstanding.
19 // NumberHolder exists to exercise the property attribute string parser by
20 // providing a named struct and an anonymous union.
38 @interface CountVonCount : NSObject<NSCopying>
40 + (CountVonCount*)countVonCount;
42 @end // @interface CountVonCount
44 @implementation CountVonCount
46 + (CountVonCount*)countVonCount {
47 return [[[CountVonCount alloc] init] autorelease];
60 - (id)copyWithZone:(NSZone*)zone {
61 return [[CountVonCount allocWithZone:zone] init];
64 @end // @implementation CountVonCount
66 @interface ObjCPropertyTestBase : NSObject {
68 CountVonCount* baseCvcRetain_;
69 CountVonCount* baseCvcCopy_;
70 CountVonCount* baseCvcAssign_;
71 CountVonCount* baseCvcNotProperty_;
72 CountVonCount* baseCvcNil_;
73 CountVonCount* baseCvcCustom_;
77 NumberHolder baseStruct_;
79 base::mac::ObjCPropertyReleaser propertyReleaser_ObjCPropertyTestBase_;
82 @property(retain, nonatomic) CountVonCount* baseCvcRetain;
83 @property(copy, nonatomic) CountVonCount* baseCvcCopy;
84 @property(assign, nonatomic) CountVonCount* baseCvcAssign;
85 @property(retain, nonatomic) CountVonCount* baseCvcNil;
86 @property(retain, nonatomic, getter=baseCustom, setter=setBaseCustom:)
87 CountVonCount* baseCvcCustom;
88 @property(retain, nonatomic) CountVonCount* baseCvcDynamic;
89 @property(assign, nonatomic) int baseInt;
90 @property(assign, nonatomic) double baseDouble;
91 @property(assign, nonatomic) void* basePointer;
92 @property(assign, nonatomic) NumberHolder baseStruct;
94 - (void)setBaseCvcNotProperty:(CountVonCount*)cvc;
96 @end // @interface ObjCPropertyTestBase
98 @implementation ObjCPropertyTestBase
100 @synthesize baseCvcRetain = baseCvcRetain_;
101 @synthesize baseCvcCopy = baseCvcCopy_;
102 @synthesize baseCvcAssign = baseCvcAssign_;
103 @synthesize baseCvcNil = baseCvcNil_;
104 @synthesize baseCvcCustom = baseCvcCustom_;
105 @dynamic baseCvcDynamic;
106 @synthesize baseInt = baseInt_;
107 @synthesize baseDouble = baseDouble_;
108 @synthesize basePointer = basePointer_;
109 @synthesize baseStruct = baseStruct_;
112 if ((self = [super init])) {
113 propertyReleaser_ObjCPropertyTestBase_.Init(
114 self, [ObjCPropertyTestBase class]);
120 [baseCvcNotProperty_ release];
124 - (void)setBaseCvcNotProperty:(CountVonCount*)cvc {
125 if (cvc != baseCvcNotProperty_) {
126 [baseCvcNotProperty_ release];
127 baseCvcNotProperty_ = [cvc retain];
131 @end // @implementation ObjCPropertyTestBase
133 @protocol ObjCPropertyTestProtocol
135 @property(retain, nonatomic) CountVonCount* protoCvcRetain;
136 @property(copy, nonatomic) CountVonCount* protoCvcCopy;
137 @property(assign, nonatomic) CountVonCount* protoCvcAssign;
138 @property(retain, nonatomic) CountVonCount* protoCvcNil;
139 @property(retain, nonatomic, getter=protoCustom, setter=setProtoCustom:)
140 CountVonCount* protoCvcCustom;
141 @property(retain, nonatomic) CountVonCount* protoCvcDynamic;
142 @property(assign, nonatomic) int protoInt;
143 @property(assign, nonatomic) double protoDouble;
144 @property(assign, nonatomic) void* protoPointer;
145 @property(assign, nonatomic) NumberHolder protoStruct;
147 @end // @protocol ObjCPropertyTestProtocol
149 @interface ObjCPropertyTestDerived
150 : ObjCPropertyTestBase<ObjCPropertyTestProtocol> {
152 CountVonCount* derivedCvcRetain_;
153 CountVonCount* derivedCvcCopy_;
154 CountVonCount* derivedCvcAssign_;
155 CountVonCount* derivedCvcNotProperty_;
156 CountVonCount* derivedCvcNil_;
157 CountVonCount* derivedCvcCustom_;
159 double derivedDouble_;
160 void* derivedPointer_;
161 NumberHolder derivedStruct_;
163 CountVonCount* protoCvcRetain_;
164 CountVonCount* protoCvcCopy_;
165 CountVonCount* protoCvcAssign_;
166 CountVonCount* protoCvcNil_;
167 CountVonCount* protoCvcCustom_;
171 NumberHolder protoStruct_;
173 base::mac::ObjCPropertyReleaser propertyReleaser_ObjCPropertyTestDerived_;
176 @property(retain, nonatomic) CountVonCount* derivedCvcRetain;
177 @property(copy, nonatomic) CountVonCount* derivedCvcCopy;
178 @property(assign, nonatomic) CountVonCount* derivedCvcAssign;
179 @property(retain, nonatomic) CountVonCount* derivedCvcNil;
180 @property(retain, nonatomic, getter=derivedCustom, setter=setDerivedCustom:)
181 CountVonCount* derivedCvcCustom;
182 @property(retain, nonatomic) CountVonCount* derivedCvcDynamic;
183 @property(assign, nonatomic) int derivedInt;
184 @property(assign, nonatomic) double derivedDouble;
185 @property(assign, nonatomic) void* derivedPointer;
186 @property(assign, nonatomic) NumberHolder derivedStruct;
188 - (void)setDerivedCvcNotProperty:(CountVonCount*)cvc;
190 @end // @interface ObjCPropertyTestDerived
192 @implementation ObjCPropertyTestDerived
194 @synthesize derivedCvcRetain = derivedCvcRetain_;
195 @synthesize derivedCvcCopy = derivedCvcCopy_;
196 @synthesize derivedCvcAssign = derivedCvcAssign_;
197 @synthesize derivedCvcNil = derivedCvcNil_;
198 @synthesize derivedCvcCustom = derivedCvcCustom_;
199 @dynamic derivedCvcDynamic;
200 @synthesize derivedInt = derivedInt_;
201 @synthesize derivedDouble = derivedDouble_;
202 @synthesize derivedPointer = derivedPointer_;
203 @synthesize derivedStruct = derivedStruct_;
205 @synthesize protoCvcRetain = protoCvcRetain_;
206 @synthesize protoCvcCopy = protoCvcCopy_;
207 @synthesize protoCvcAssign = protoCvcAssign_;
208 @synthesize protoCvcNil = protoCvcNil_;
209 @synthesize protoCvcCustom = protoCvcCustom_;
210 @dynamic protoCvcDynamic;
211 @synthesize protoInt = protoInt_;
212 @synthesize protoDouble = protoDouble_;
213 @synthesize protoPointer = protoPointer_;
214 @synthesize protoStruct = protoStruct_;
217 if ((self = [super init])) {
218 propertyReleaser_ObjCPropertyTestDerived_.Init(
219 self, [ObjCPropertyTestDerived class]);
225 [derivedCvcNotProperty_ release];
229 - (void)setDerivedCvcNotProperty:(CountVonCount*)cvc {
230 if (cvc != derivedCvcNotProperty_) {
231 [derivedCvcNotProperty_ release];
232 derivedCvcNotProperty_ = [cvc retain];
236 @end // @implementation ObjCPropertyTestDerived
240 TEST(ObjCPropertyReleaserTest, SesameStreet) {
241 ObjCPropertyTestDerived* test_object = [[ObjCPropertyTestDerived alloc] init];
243 // Assure a clean slate.
244 EXPECT_EQ(0, ah_ah_ah);
245 EXPECT_EQ(1U, [test_object retainCount]);
247 CountVonCount* baseAssign = [[CountVonCount alloc] init];
248 CountVonCount* derivedAssign = [[CountVonCount alloc] init];
249 CountVonCount* protoAssign = [[CountVonCount alloc] init];
251 // Make sure that worked before things get more involved.
252 EXPECT_EQ(3, ah_ah_ah);
255 base::mac::ScopedNSAutoreleasePool pool;
257 test_object.baseCvcRetain = [CountVonCount countVonCount];
258 test_object.baseCvcCopy = [CountVonCount countVonCount];
259 test_object.baseCvcAssign = baseAssign;
260 test_object.baseCvcCustom = [CountVonCount countVonCount];
261 [test_object setBaseCvcNotProperty:[CountVonCount countVonCount]];
263 // That added 4 objects, plus 1 more that was copied.
264 EXPECT_EQ(8, ah_ah_ah);
266 test_object.derivedCvcRetain = [CountVonCount countVonCount];
267 test_object.derivedCvcCopy = [CountVonCount countVonCount];
268 test_object.derivedCvcAssign = derivedAssign;
269 test_object.derivedCvcCustom = [CountVonCount countVonCount];
270 [test_object setDerivedCvcNotProperty:[CountVonCount countVonCount]];
272 // That added 4 objects, plus 1 more that was copied.
273 EXPECT_EQ(13, ah_ah_ah);
275 test_object.protoCvcRetain = [CountVonCount countVonCount];
276 test_object.protoCvcCopy = [CountVonCount countVonCount];
277 test_object.protoCvcAssign = protoAssign;
278 test_object.protoCvcCustom = [CountVonCount countVonCount];
280 // That added 3 objects, plus 1 more that was copied.
281 EXPECT_EQ(17, ah_ah_ah);
284 // Now that the autorelease pool has been popped, the 3 objects that were
285 // copied when placed into the test object will have been deallocated.
286 EXPECT_EQ(14, ah_ah_ah);
288 // Make sure that the setters work and have the expected semantics.
289 test_object.baseCvcRetain = nil;
290 test_object.baseCvcCopy = nil;
291 test_object.baseCvcAssign = nil;
292 test_object.baseCvcCustom = nil;
293 test_object.derivedCvcRetain = nil;
294 test_object.derivedCvcCopy = nil;
295 test_object.derivedCvcAssign = nil;
296 test_object.derivedCvcCustom = nil;
297 test_object.protoCvcRetain = nil;
298 test_object.protoCvcCopy = nil;
299 test_object.protoCvcAssign = nil;
300 test_object.protoCvcCustom = nil;
302 // The CountVonCounts marked "retain" and "copy" should have been
303 // deallocated. Those marked assign should not have been. The only ones that
304 // should exist now are the ones marked "assign" and the ones held in
305 // non-property instance variables.
306 EXPECT_EQ(5, ah_ah_ah);
309 base::mac::ScopedNSAutoreleasePool pool;
311 // Put things back to how they were.
312 test_object.baseCvcRetain = [CountVonCount countVonCount];
313 test_object.baseCvcCopy = [CountVonCount countVonCount];
314 test_object.baseCvcAssign = baseAssign;
315 test_object.baseCvcCustom = [CountVonCount countVonCount];
316 test_object.derivedCvcRetain = [CountVonCount countVonCount];
317 test_object.derivedCvcCopy = [CountVonCount countVonCount];
318 test_object.derivedCvcAssign = derivedAssign;
319 test_object.derivedCvcCustom = [CountVonCount countVonCount];
320 test_object.protoCvcRetain = [CountVonCount countVonCount];
321 test_object.protoCvcCopy = [CountVonCount countVonCount];
322 test_object.protoCvcAssign = protoAssign;
323 test_object.protoCvcCustom = [CountVonCount countVonCount];
325 // 9 more CountVonCounts, 3 of which were copied.
326 EXPECT_EQ(17, ah_ah_ah);
329 // Now that the autorelease pool has been popped, the 3 copies are gone.
330 EXPECT_EQ(14, ah_ah_ah);
332 // Releasing the test object should get rid of everything that it owns.
333 [test_object release];
335 // The property releaser should have released all of the CountVonCounts
336 // associated with properties marked "retain" or "copy". The -dealloc
337 // methods in each should have released the single non-property objects in
338 // each. Only the CountVonCounts assigned to the properties marked "assign"
340 EXPECT_EQ(3, ah_ah_ah);
342 [baseAssign release];
343 [derivedAssign release];
344 [protoAssign release];
346 // Zero! Zero counts! Ah, ah, ah.
347 EXPECT_EQ(0, ah_ah_ah);