FBRetainCycleDetectorTests/FBClassStrongLayoutTests.mm (202 lines of code) (raw):
/**
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <memory>
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import <FBRetainCycleDetector/FBClassStrongLayout.h>
#import <FBRetainCycleDetector/FBRetainCycleDetector.h>
@interface _RCDTestEmptyClass : NSObject
@end
@implementation _RCDTestEmptyClass
@end
@interface _RCDTestClassWithWeakProperty : NSObject
@property (nonatomic, weak) NSObject *object;
@end
@implementation _RCDTestClassWithWeakProperty
@end
@interface _RCDTestClassWithStrongProperty : NSObject
@property (nonatomic, strong) NSObject *object;
@end
@implementation _RCDTestClassWithStrongProperty
@end
@interface _RCDTestClassWithMixedWeakAndStrongProperties : NSObject
@property (nonatomic, strong) NSObject *object1;
@property (nonatomic, strong) NSObject *object2;
@property (nonatomic, strong) NSObject *object3;
@property (nonatomic, weak) NSObject *object4;
@property (nonatomic, strong) NSObject *object5;
@property (nonatomic, weak) NSObject *object6;
@end
@implementation _RCDTestClassWithMixedWeakAndStrongProperties
@end
@interface _RCDTestClassWithSimpleInheritance : _RCDTestEmptyClass
@property (nonatomic, strong) NSObject *object1;
@property (nonatomic, weak) NSObject *object2;
@end
@implementation _RCDTestClassWithSimpleInheritance
@end
@interface _RCDTestClassSubclassingClassWithStrongProperties : _RCDTestClassWithMixedWeakAndStrongProperties
@property (nonatomic, weak) NSObject *object7;
@end
@implementation _RCDTestClassSubclassingClassWithStrongProperties
@end
typedef struct {
int someInt;
char someCharacter;
unsigned long long someUnsignedLongLong;
} _RCDTestStructWithPrimitives;
@interface _RCDTestClassWithSimpleStruct : NSObject
@property (nonatomic, assign) _RCDTestStructWithPrimitives structure;
@end
@implementation _RCDTestClassWithSimpleStruct
@end
typedef struct {
NSObject *retainedObject;
int number;
NSObject *anotherRetainedObject;
} _RCDTestStructWithObjects;
@interface _RCDTestClassWithStructContainingObjects : NSObject
@property (nonatomic, assign) _RCDTestStructWithObjects structure;
@end
@implementation _RCDTestClassWithStructContainingObjects
@end
typedef struct {
__weak NSObject *object;
} _RCDTestStructWithWeakObject;
@interface _RCDTestClassWithStructContainingWeakObject : NSObject
@property (nonatomic, assign) _RCDTestStructWithWeakObject structure;
@end
@implementation _RCDTestClassWithStructContainingWeakObject
@end
typedef struct {
int a;
_RCDTestStructWithObjects someStruct;
char b;
int c;
int d;
__weak NSObject *object;
float *e;
void *f;
NSObject *g;
_RCDTestStructWithObjects someStruct2;
} _RCDTestStructWithComplicatedLayout;
@interface _RCDTestClassWithComplicatedStruct : NSObject
@property (nonatomic, assign) _RCDTestStructWithComplicatedLayout testStruct;
@end
@implementation _RCDTestClassWithComplicatedStruct
@end
typedef struct {
unsigned somebit1: 1;
unsigned somebit2: 1;
unsigned somebit3: 1;
unsigned somebit4: 1;
unsigned somebit5: 6;
} _RCDTestStructWithBitfields;
@interface _RCDTestClassWithBitfieldStructAndStrongProperties : NSObject
@property (nonatomic, strong) NSObject *object1;
@property (nonatomic, assign) _RCDTestStructWithBitfields someStruct;
@property (nonatomic, strong) NSObject *object2;
@end
@implementation _RCDTestClassWithBitfieldStructAndStrongProperties
@end
@interface _RCDTestClassWithEnumValue : NSObject
@end
@implementation _RCDTestClassWithEnumValue
{
UIRectEdge rectEdge;
}
@end
@interface _RCDTestClassWithSharedPointer : NSObject
@end
@implementation _RCDTestClassWithSharedPointer
{
std::shared_ptr<_RCDTestStructWithObjects> _sharedPointer;
}
- (instancetype)init
{
if (self = [super init]) {
_sharedPointer = std::shared_ptr<_RCDTestStructWithObjects> (new _RCDTestStructWithObjects);
}
return self;
}
@end
@interface _RCDTestClassWithCppStructAndStrongProperty : NSObject
@end
@implementation _RCDTestClassWithCppStructAndStrongProperty
{
std::atomic<bool> _someAtomicValue;
NSObject *_object;
}
@end
@interface FBClassStrongLayoutTests : XCTestCase
@end
@implementation FBClassStrongLayoutTests
- (void)testLayoutForEmptyClassWillBeEmpty
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestEmptyClass new], nil);
XCTAssertEqual([ivars count], 0);
}
- (void)testLayoutForClassWithWeakPropertyWillBeEmpty
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithWeakProperty new], nil);
XCTAssertEqual([ivars count], 0);
}
- (void)testLayoutForClassWithStrongPropertyWillHaveOneReference
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithStrongProperty new], nil);
XCTAssertEqual([ivars count], 1);
}
- (void)testLayoutForClassWithMixedStrongAndWeakWillFetchOnlyStrong
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithMixedWeakAndStrongProperties new], nil);
XCTAssertEqual([ivars count], 4);
}
- (void)testLayoutForClassSubclassingEmptyClassWillFetchPropertiesProperly
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithSimpleInheritance new], nil);
XCTAssertEqual([ivars count], 1);
}
- (void)testLayoutForClassSubclassingClassWithStrongPropertiesWillFetchParentsClassProperties
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassSubclassingClassWithStrongProperties new], nil);
XCTAssertEqual([ivars count], 4);
}
- (void)testLayoutForClassWithStructAsIvarWillNotCrash
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithSimpleStruct new], nil);
XCTAssertEqual([ivars count], 0);
}
- (void)testLayoutForClassWithStructContainingObjectsWillFetchThoseObjects
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithStructContainingObjects new], nil);
XCTAssertEqual([ivars count], 2);
}
- (void)testLayoutForClassWithStructContainingWeakObjectWillBeEmpty
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithStructContainingWeakObject new], nil);
XCTAssertEqual([ivars count], 0);
}
- (void)testLayoutForClassWithComplicatedStructWillWorkProperly
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithComplicatedStruct new], nil);
XCTAssertEqual([ivars count], 5);
}
- (void)testLayoutForClassWithBitfieldsWillNotCrash
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithBitfieldStructAndStrongProperties new], nil);
XCTAssertEqual([ivars count], 2);
}
- (void)testLayoutForClassWithEnumValueWillNotCrash
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithEnumValue new], nil);
XCTAssertEqual([ivars count], 0);
}
- (void)testLayoutForClassWithSharedPointerWillNotCrash
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithSharedPointer new], nil);
XCTAssertEqual([ivars count], 0);
}
- (void)testLayoutForClassWithCppStructAndStrongPropertyWillNotCrashAndFetchStrongProperty
{
NSArray *ivars = FBGetObjectStrongReferences([_RCDTestClassWithCppStructAndStrongProperty new], nil);
XCTAssertEqual([ivars count], 1);
}
@end