- add sources.
[platform/framework/web/crosswalk.git] / src / base / mac / objc_property_releaser_unittest.mm
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.
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
14 namespace {
15
16 // The number of CountVonCounts outstanding.
17 int ah_ah_ah;
18
19 // NumberHolder exists to exercise the property attribute string parser by
20 // providing a named struct and an anonymous union.
21 struct 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
238 namespace {
239
240 TEST(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