blob: 50f81a876206472af81c511f09f7d6310a8707a8 [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// 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.
4
5#import <Foundation/Foundation.h>
6
7#import "base/mac/objc_property_releaser.h"
8#import "base/mac/scoped_nsautorelease_pool.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11// "When I'm alone, I count myself."
12// --Count von Count, http://www.youtube.com/watch?v=FKzszqa9WA4
13
14namespace {
15
16// The number of CountVonCounts outstanding.
17int ah_ah_ah;
18
19// NumberHolder exists to exercise the property attribute string parser by
20// providing a named struct and an anonymous union.
21struct NumberHolder {
22 union {
23 long long sixty_four;
24 int thirty_two;
25 short sixteen;
26 char eight;
27 } what;
28 enum {
29 SIXTY_FOUR,
30 THIRTY_TWO,
31 SIXTEEN,
32 EIGHT
33 } how;
34};
35
36} // namespace
37
38@interface CountVonCount : NSObject<NSCopying>
39
40+ (CountVonCount*)countVonCount;
41
42@end // @interface CountVonCount
43
44@implementation CountVonCount
45
46+ (CountVonCount*)countVonCount {
47 return [[[CountVonCount alloc] init] autorelease];
48}
49
50- (id)init {
51 ++ah_ah_ah;
52 return [super init];
53}
54
55- (void)dealloc {
56 --ah_ah_ah;
57 [super dealloc];
58}
59
60- (id)copyWithZone:(NSZone*)zone {
61 return [[CountVonCount allocWithZone:zone] init];
62}
63
64@end // @implementation CountVonCount
65
66@interface ObjCPropertyTestBase : NSObject {
67 @private
68 CountVonCount* baseCvcRetain_;
69 CountVonCount* baseCvcCopy_;
70 CountVonCount* baseCvcAssign_;
71 CountVonCount* baseCvcNotProperty_;
72 CountVonCount* baseCvcNil_;
73 CountVonCount* baseCvcCustom_;
74 int baseInt_;
75 double baseDouble_;
76 void* basePointer_;
77 NumberHolder baseStruct_;
78
79 base::mac::ObjCPropertyReleaser propertyReleaser_ObjCPropertyTestBase_;
80}
81
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;
93
94- (void)setBaseCvcNotProperty:(CountVonCount*)cvc;
95
96@end // @interface ObjCPropertyTestBase
97
98@implementation ObjCPropertyTestBase
99
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_;
110
111- (id)init {
112 if ((self = [super init])) {
113 propertyReleaser_ObjCPropertyTestBase_.Init(
114 self, [ObjCPropertyTestBase class]);
115 }
116 return self;
117}
118
119- (void)dealloc {
120 [baseCvcNotProperty_ release];
121 [super dealloc];
122}
123
124- (void)setBaseCvcNotProperty:(CountVonCount*)cvc {
125 if (cvc != baseCvcNotProperty_) {
126 [baseCvcNotProperty_ release];
127 baseCvcNotProperty_ = [cvc retain];
128 }
129}
130
131@end // @implementation ObjCPropertyTestBase
132
133@protocol ObjCPropertyTestProtocol
134
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;
146
147@end // @protocol ObjCPropertyTestProtocol
148
149@interface ObjCPropertyTestDerived
150 : ObjCPropertyTestBase<ObjCPropertyTestProtocol> {
151 @private
152 CountVonCount* derivedCvcRetain_;
153 CountVonCount* derivedCvcCopy_;
154 CountVonCount* derivedCvcAssign_;
155 CountVonCount* derivedCvcNotProperty_;
156 CountVonCount* derivedCvcNil_;
157 CountVonCount* derivedCvcCustom_;
158 int derivedInt_;
159 double derivedDouble_;
160 void* derivedPointer_;
161 NumberHolder derivedStruct_;
162
163 CountVonCount* protoCvcRetain_;
164 CountVonCount* protoCvcCopy_;
165 CountVonCount* protoCvcAssign_;
166 CountVonCount* protoCvcNil_;
167 CountVonCount* protoCvcCustom_;
168 int protoInt_;
169 double protoDouble_;
170 void* protoPointer_;
171 NumberHolder protoStruct_;
172
173 base::mac::ObjCPropertyReleaser propertyReleaser_ObjCPropertyTestDerived_;
174}
175
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;
187
188- (void)setDerivedCvcNotProperty:(CountVonCount*)cvc;
189
190@end // @interface ObjCPropertyTestDerived
191
192@implementation ObjCPropertyTestDerived
193
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_;
204
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_;
215
216- (id)init {
217 if ((self = [super init])) {
218 propertyReleaser_ObjCPropertyTestDerived_.Init(
219 self, [ObjCPropertyTestDerived class]);
220 }
221 return self;
222}
223
224- (void)dealloc {
225 [derivedCvcNotProperty_ release];
226 [super dealloc];
227}
228
229- (void)setDerivedCvcNotProperty:(CountVonCount*)cvc {
230 if (cvc != derivedCvcNotProperty_) {
231 [derivedCvcNotProperty_ release];
232 derivedCvcNotProperty_ = [cvc retain];
233 }
234}
235
236@end // @implementation ObjCPropertyTestDerived
237
238namespace {
239
240TEST(ObjCPropertyReleaserTest, SesameStreet) {
241 ObjCPropertyTestDerived* test_object = [[ObjCPropertyTestDerived alloc] init];
242
243 // Assure a clean slate.
244 EXPECT_EQ(0, ah_ah_ah);
245 EXPECT_EQ(1U, [test_object retainCount]);
246
247 CountVonCount* baseAssign = [[CountVonCount alloc] init];
248 CountVonCount* derivedAssign = [[CountVonCount alloc] init];
249 CountVonCount* protoAssign = [[CountVonCount alloc] init];
250
251 // Make sure that worked before things get more involved.
252 EXPECT_EQ(3, ah_ah_ah);
253
254 {
255 base::mac::ScopedNSAutoreleasePool pool;
256
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]];
262
263 // That added 4 objects, plus 1 more that was copied.
264 EXPECT_EQ(8, ah_ah_ah);
265
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]];
271
272 // That added 4 objects, plus 1 more that was copied.
273 EXPECT_EQ(13, ah_ah_ah);
274
275 test_object.protoCvcRetain = [CountVonCount countVonCount];
276 test_object.protoCvcCopy = [CountVonCount countVonCount];
277 test_object.protoCvcAssign = protoAssign;
278 test_object.protoCvcCustom = [CountVonCount countVonCount];
279
280 // That added 3 objects, plus 1 more that was copied.
281 EXPECT_EQ(17, ah_ah_ah);
282 }
283
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);
287
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;
301
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);
307
308 {
309 base::mac::ScopedNSAutoreleasePool pool;
310
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];
324
325 // 9 more CountVonCounts, 3 of which were copied.
326 EXPECT_EQ(17, ah_ah_ah);
327 }
328
329 // Now that the autorelease pool has been popped, the 3 copies are gone.
330 EXPECT_EQ(14, ah_ah_ah);
331
332 // Releasing the test object should get rid of everything that it owns.
333 [test_object release];
334
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"
339 // should remain.
340 EXPECT_EQ(3, ah_ah_ah);
341
342 [baseAssign release];
343 [derivedAssign release];
344 [protoAssign release];
345
346 // Zero! Zero counts! Ah, ah, ah.
347 EXPECT_EQ(0, ah_ah_ah);
348}
349
350} // namespace