351 lines
11 KiB
Plaintext
351 lines
11 KiB
Plaintext
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
#import "base/mac/objc_property_releaser.h"
|
|
#import "base/mac/scoped_nsautorelease_pool.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
// "When I'm alone, I count myself."
|
|
// --Count von Count, http://www.youtube.com/watch?v=FKzszqa9WA4
|
|
|
|
namespace {
|
|
|
|
// The number of CountVonCounts outstanding.
|
|
int ah_ah_ah;
|
|
|
|
// NumberHolder exists to exercise the property attribute string parser by
|
|
// providing a named struct and an anonymous union.
|
|
struct NumberHolder {
|
|
union {
|
|
long long sixty_four;
|
|
int thirty_two;
|
|
short sixteen;
|
|
char eight;
|
|
} what;
|
|
enum {
|
|
SIXTY_FOUR,
|
|
THIRTY_TWO,
|
|
SIXTEEN,
|
|
EIGHT
|
|
} how;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
@interface CountVonCount : NSObject<NSCopying>
|
|
|
|
+ (CountVonCount*)countVonCount;
|
|
|
|
@end // @interface CountVonCount
|
|
|
|
@implementation CountVonCount
|
|
|
|
+ (CountVonCount*)countVonCount {
|
|
return [[[CountVonCount alloc] init] autorelease];
|
|
}
|
|
|
|
- (id)init {
|
|
++ah_ah_ah;
|
|
return [super init];
|
|
}
|
|
|
|
- (void)dealloc {
|
|
--ah_ah_ah;
|
|
[super dealloc];
|
|
}
|
|
|
|
- (id)copyWithZone:(NSZone*)zone {
|
|
return [[CountVonCount allocWithZone:zone] init];
|
|
}
|
|
|
|
@end // @implementation CountVonCount
|
|
|
|
@interface ObjCPropertyTestBase : NSObject {
|
|
@private
|
|
CountVonCount* baseCvcRetain_;
|
|
CountVonCount* baseCvcCopy_;
|
|
CountVonCount* baseCvcAssign_;
|
|
CountVonCount* baseCvcNotProperty_;
|
|
CountVonCount* baseCvcNil_;
|
|
CountVonCount* baseCvcCustom_;
|
|
int baseInt_;
|
|
double baseDouble_;
|
|
void* basePointer_;
|
|
NumberHolder baseStruct_;
|
|
|
|
base::mac::ObjCPropertyReleaser propertyReleaser_ObjCPropertyTestBase_;
|
|
}
|
|
|
|
@property(retain, nonatomic) CountVonCount* baseCvcRetain;
|
|
@property(copy, nonatomic) CountVonCount* baseCvcCopy;
|
|
@property(assign, nonatomic) CountVonCount* baseCvcAssign;
|
|
@property(retain, nonatomic) CountVonCount* baseCvcNil;
|
|
@property(retain, nonatomic, getter=baseCustom, setter=setBaseCustom:)
|
|
CountVonCount* baseCvcCustom;
|
|
@property(retain, nonatomic) CountVonCount* baseCvcDynamic;
|
|
@property(assign, nonatomic) int baseInt;
|
|
@property(assign, nonatomic) double baseDouble;
|
|
@property(assign, nonatomic) void* basePointer;
|
|
@property(assign, nonatomic) NumberHolder baseStruct;
|
|
|
|
- (void)setBaseCvcNotProperty:(CountVonCount*)cvc;
|
|
|
|
@end // @interface ObjCPropertyTestBase
|
|
|
|
@implementation ObjCPropertyTestBase
|
|
|
|
@synthesize baseCvcRetain = baseCvcRetain_;
|
|
@synthesize baseCvcCopy = baseCvcCopy_;
|
|
@synthesize baseCvcAssign = baseCvcAssign_;
|
|
@synthesize baseCvcNil = baseCvcNil_;
|
|
@synthesize baseCvcCustom = baseCvcCustom_;
|
|
@dynamic baseCvcDynamic;
|
|
@synthesize baseInt = baseInt_;
|
|
@synthesize baseDouble = baseDouble_;
|
|
@synthesize basePointer = basePointer_;
|
|
@synthesize baseStruct = baseStruct_;
|
|
|
|
- (id)init {
|
|
if ((self = [super init])) {
|
|
propertyReleaser_ObjCPropertyTestBase_.Init(
|
|
self, [ObjCPropertyTestBase class]);
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[baseCvcNotProperty_ release];
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void)setBaseCvcNotProperty:(CountVonCount*)cvc {
|
|
if (cvc != baseCvcNotProperty_) {
|
|
[baseCvcNotProperty_ release];
|
|
baseCvcNotProperty_ = [cvc retain];
|
|
}
|
|
}
|
|
|
|
@end // @implementation ObjCPropertyTestBase
|
|
|
|
@protocol ObjCPropertyTestProtocol
|
|
|
|
@property(retain, nonatomic) CountVonCount* protoCvcRetain;
|
|
@property(copy, nonatomic) CountVonCount* protoCvcCopy;
|
|
@property(assign, nonatomic) CountVonCount* protoCvcAssign;
|
|
@property(retain, nonatomic) CountVonCount* protoCvcNil;
|
|
@property(retain, nonatomic, getter=protoCustom, setter=setProtoCustom:)
|
|
CountVonCount* protoCvcCustom;
|
|
@property(retain, nonatomic) CountVonCount* protoCvcDynamic;
|
|
@property(assign, nonatomic) int protoInt;
|
|
@property(assign, nonatomic) double protoDouble;
|
|
@property(assign, nonatomic) void* protoPointer;
|
|
@property(assign, nonatomic) NumberHolder protoStruct;
|
|
|
|
@end // @protocol ObjCPropertyTestProtocol
|
|
|
|
@interface ObjCPropertyTestDerived
|
|
: ObjCPropertyTestBase<ObjCPropertyTestProtocol> {
|
|
@private
|
|
CountVonCount* derivedCvcRetain_;
|
|
CountVonCount* derivedCvcCopy_;
|
|
CountVonCount* derivedCvcAssign_;
|
|
CountVonCount* derivedCvcNotProperty_;
|
|
CountVonCount* derivedCvcNil_;
|
|
CountVonCount* derivedCvcCustom_;
|
|
int derivedInt_;
|
|
double derivedDouble_;
|
|
void* derivedPointer_;
|
|
NumberHolder derivedStruct_;
|
|
|
|
CountVonCount* protoCvcRetain_;
|
|
CountVonCount* protoCvcCopy_;
|
|
CountVonCount* protoCvcAssign_;
|
|
CountVonCount* protoCvcNil_;
|
|
CountVonCount* protoCvcCustom_;
|
|
int protoInt_;
|
|
double protoDouble_;
|
|
void* protoPointer_;
|
|
NumberHolder protoStruct_;
|
|
|
|
base::mac::ObjCPropertyReleaser propertyReleaser_ObjCPropertyTestDerived_;
|
|
}
|
|
|
|
@property(retain, nonatomic) CountVonCount* derivedCvcRetain;
|
|
@property(copy, nonatomic) CountVonCount* derivedCvcCopy;
|
|
@property(assign, nonatomic) CountVonCount* derivedCvcAssign;
|
|
@property(retain, nonatomic) CountVonCount* derivedCvcNil;
|
|
@property(retain, nonatomic, getter=derivedCustom, setter=setDerivedCustom:)
|
|
CountVonCount* derivedCvcCustom;
|
|
@property(retain, nonatomic) CountVonCount* derivedCvcDynamic;
|
|
@property(assign, nonatomic) int derivedInt;
|
|
@property(assign, nonatomic) double derivedDouble;
|
|
@property(assign, nonatomic) void* derivedPointer;
|
|
@property(assign, nonatomic) NumberHolder derivedStruct;
|
|
|
|
- (void)setDerivedCvcNotProperty:(CountVonCount*)cvc;
|
|
|
|
@end // @interface ObjCPropertyTestDerived
|
|
|
|
@implementation ObjCPropertyTestDerived
|
|
|
|
@synthesize derivedCvcRetain = derivedCvcRetain_;
|
|
@synthesize derivedCvcCopy = derivedCvcCopy_;
|
|
@synthesize derivedCvcAssign = derivedCvcAssign_;
|
|
@synthesize derivedCvcNil = derivedCvcNil_;
|
|
@synthesize derivedCvcCustom = derivedCvcCustom_;
|
|
@dynamic derivedCvcDynamic;
|
|
@synthesize derivedInt = derivedInt_;
|
|
@synthesize derivedDouble = derivedDouble_;
|
|
@synthesize derivedPointer = derivedPointer_;
|
|
@synthesize derivedStruct = derivedStruct_;
|
|
|
|
@synthesize protoCvcRetain = protoCvcRetain_;
|
|
@synthesize protoCvcCopy = protoCvcCopy_;
|
|
@synthesize protoCvcAssign = protoCvcAssign_;
|
|
@synthesize protoCvcNil = protoCvcNil_;
|
|
@synthesize protoCvcCustom = protoCvcCustom_;
|
|
@dynamic protoCvcDynamic;
|
|
@synthesize protoInt = protoInt_;
|
|
@synthesize protoDouble = protoDouble_;
|
|
@synthesize protoPointer = protoPointer_;
|
|
@synthesize protoStruct = protoStruct_;
|
|
|
|
- (id)init {
|
|
if ((self = [super init])) {
|
|
propertyReleaser_ObjCPropertyTestDerived_.Init(
|
|
self, [ObjCPropertyTestDerived class]);
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[derivedCvcNotProperty_ release];
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void)setDerivedCvcNotProperty:(CountVonCount*)cvc {
|
|
if (cvc != derivedCvcNotProperty_) {
|
|
[derivedCvcNotProperty_ release];
|
|
derivedCvcNotProperty_ = [cvc retain];
|
|
}
|
|
}
|
|
|
|
@end // @implementation ObjCPropertyTestDerived
|
|
|
|
namespace {
|
|
|
|
TEST(ObjCPropertyReleaserTest, SesameStreet) {
|
|
ObjCPropertyTestDerived* test_object = [[ObjCPropertyTestDerived alloc] init];
|
|
|
|
// Assure a clean slate.
|
|
EXPECT_EQ(0, ah_ah_ah);
|
|
EXPECT_EQ(1U, [test_object retainCount]);
|
|
|
|
CountVonCount* baseAssign = [[CountVonCount alloc] init];
|
|
CountVonCount* derivedAssign = [[CountVonCount alloc] init];
|
|
CountVonCount* protoAssign = [[CountVonCount alloc] init];
|
|
|
|
// Make sure that worked before things get more involved.
|
|
EXPECT_EQ(3, ah_ah_ah);
|
|
|
|
{
|
|
base::mac::ScopedNSAutoreleasePool pool;
|
|
|
|
test_object.baseCvcRetain = [CountVonCount countVonCount];
|
|
test_object.baseCvcCopy = [CountVonCount countVonCount];
|
|
test_object.baseCvcAssign = baseAssign;
|
|
test_object.baseCvcCustom = [CountVonCount countVonCount];
|
|
[test_object setBaseCvcNotProperty:[CountVonCount countVonCount]];
|
|
|
|
// That added 4 objects, plus 1 more that was copied.
|
|
EXPECT_EQ(8, ah_ah_ah);
|
|
|
|
test_object.derivedCvcRetain = [CountVonCount countVonCount];
|
|
test_object.derivedCvcCopy = [CountVonCount countVonCount];
|
|
test_object.derivedCvcAssign = derivedAssign;
|
|
test_object.derivedCvcCustom = [CountVonCount countVonCount];
|
|
[test_object setDerivedCvcNotProperty:[CountVonCount countVonCount]];
|
|
|
|
// That added 4 objects, plus 1 more that was copied.
|
|
EXPECT_EQ(13, ah_ah_ah);
|
|
|
|
test_object.protoCvcRetain = [CountVonCount countVonCount];
|
|
test_object.protoCvcCopy = [CountVonCount countVonCount];
|
|
test_object.protoCvcAssign = protoAssign;
|
|
test_object.protoCvcCustom = [CountVonCount countVonCount];
|
|
|
|
// That added 3 objects, plus 1 more that was copied.
|
|
EXPECT_EQ(17, ah_ah_ah);
|
|
}
|
|
|
|
// Now that the autorelease pool has been popped, the 3 objects that were
|
|
// copied when placed into the test object will have been deallocated.
|
|
EXPECT_EQ(14, ah_ah_ah);
|
|
|
|
// Make sure that the setters work and have the expected semantics.
|
|
test_object.baseCvcRetain = nil;
|
|
test_object.baseCvcCopy = nil;
|
|
test_object.baseCvcAssign = nil;
|
|
test_object.baseCvcCustom = nil;
|
|
test_object.derivedCvcRetain = nil;
|
|
test_object.derivedCvcCopy = nil;
|
|
test_object.derivedCvcAssign = nil;
|
|
test_object.derivedCvcCustom = nil;
|
|
test_object.protoCvcRetain = nil;
|
|
test_object.protoCvcCopy = nil;
|
|
test_object.protoCvcAssign = nil;
|
|
test_object.protoCvcCustom = nil;
|
|
|
|
// The CountVonCounts marked "retain" and "copy" should have been
|
|
// deallocated. Those marked assign should not have been. The only ones that
|
|
// should exist now are the ones marked "assign" and the ones held in
|
|
// non-property instance variables.
|
|
EXPECT_EQ(5, ah_ah_ah);
|
|
|
|
{
|
|
base::mac::ScopedNSAutoreleasePool pool;
|
|
|
|
// Put things back to how they were.
|
|
test_object.baseCvcRetain = [CountVonCount countVonCount];
|
|
test_object.baseCvcCopy = [CountVonCount countVonCount];
|
|
test_object.baseCvcAssign = baseAssign;
|
|
test_object.baseCvcCustom = [CountVonCount countVonCount];
|
|
test_object.derivedCvcRetain = [CountVonCount countVonCount];
|
|
test_object.derivedCvcCopy = [CountVonCount countVonCount];
|
|
test_object.derivedCvcAssign = derivedAssign;
|
|
test_object.derivedCvcCustom = [CountVonCount countVonCount];
|
|
test_object.protoCvcRetain = [CountVonCount countVonCount];
|
|
test_object.protoCvcCopy = [CountVonCount countVonCount];
|
|
test_object.protoCvcAssign = protoAssign;
|
|
test_object.protoCvcCustom = [CountVonCount countVonCount];
|
|
|
|
// 9 more CountVonCounts, 3 of which were copied.
|
|
EXPECT_EQ(17, ah_ah_ah);
|
|
}
|
|
|
|
// Now that the autorelease pool has been popped, the 3 copies are gone.
|
|
EXPECT_EQ(14, ah_ah_ah);
|
|
|
|
// Releasing the test object should get rid of everything that it owns.
|
|
[test_object release];
|
|
|
|
// The property releaser should have released all of the CountVonCounts
|
|
// associated with properties marked "retain" or "copy". The -dealloc
|
|
// methods in each should have released the single non-property objects in
|
|
// each. Only the CountVonCounts assigned to the properties marked "assign"
|
|
// should remain.
|
|
EXPECT_EQ(3, ah_ah_ah);
|
|
|
|
[baseAssign release];
|
|
[derivedAssign release];
|
|
[protoAssign release];
|
|
|
|
// Zero! Zero counts! Ah, ah, ah.
|
|
EXPECT_EQ(0, ah_ah_ah);
|
|
}
|
|
|
|
} // namespace
|