FBRetainCycleDetectorTests/FBObjectiveCBlockTests.m (94 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 <XCTest/XCTest.h>
#import <FBRetainCycleDetector/FBObjectiveCBlock.h>
#import <FBRetainCycleDetector/FBObjectiveCGraphElement+Internal.h>
#import <FBRetainCycleDetector/FBObjectiveCObject.h>
#import <FBRetainCycleDetector/FBRetainCycleDetector.h>
typedef void (^_RCDTestBlockType)();
@interface FBObjectiveCBlockTests : XCTestCase
@end
@implementation FBObjectiveCBlockTests
#if _INTERNAL_RCD_ENABLED
- (void)testLayoutForBlockRetainingObjectWillFetchTheObject
{
NSObject *someObject = [NSObject new];
__block NSObject *unretainedObject;
_RCDTestBlockType block = ^{
// Keep strong reference to someObject
unretainedObject = someObject;
};
FBObjectiveCObject *wrappedObject = [[FBObjectiveCObject alloc] initWithObject:someObject];
FBObjectiveCBlock *wrappedBlock = [[FBObjectiveCBlock alloc] initWithObject:block];
NSSet *retainedObjects = [wrappedBlock allRetainedObjects];
XCTAssertTrue([retainedObjects containsObject:wrappedObject]);
}
- (void)testLayoutForBlockRetainingOtherBlockWillFetchTheBlock
{
_RCDTestBlockType block1 = ^{};
_RCDTestBlockType block2 = ^{
block1();
};
FBObjectiveCBlock *wrappedBlock1 = [[FBObjectiveCBlock alloc] initWithObject:block1];
FBObjectiveCBlock *wrappedBlock2 = [[FBObjectiveCBlock alloc] initWithObject:block2];
NSSet *retainedObjects = [wrappedBlock2 allRetainedObjects];
XCTAssertTrue([retainedObjects containsObject:wrappedBlock1]);
}
- (void)testLayoutForBlockRetainingFewObjectsWillFetchAllOfThem
{
NSObject *someObject1 = [NSObject new];
NSObject *someObject2 = [NSObject new];
NSObject *someObject3 = [NSObject new];
__block NSObject *unretainedObject;
_RCDTestBlockType block = ^{
// Keep strong reference to someObject
unretainedObject = someObject1;
unretainedObject = someObject2;
unretainedObject = someObject3;
};
FBObjectiveCObject *wrappedObject1 = [[FBObjectiveCObject alloc] initWithObject:someObject1];
FBObjectiveCObject *wrappedObject2 = [[FBObjectiveCObject alloc] initWithObject:someObject2];
FBObjectiveCObject *wrappedObject3 = [[FBObjectiveCObject alloc] initWithObject:someObject3];
FBObjectiveCBlock *wrappedBlock = [[FBObjectiveCBlock alloc] initWithObject:block];
NSSet *retainedObjects = [wrappedBlock allRetainedObjects];
XCTAssertTrue([retainedObjects containsObject:wrappedObject1]);
XCTAssertTrue([retainedObjects containsObject:wrappedObject2]);
XCTAssertTrue([retainedObjects containsObject:wrappedObject3]);
}
- (void)testLayoutForBlockKeepingObjectBlockMixin
{
NSObject *someObject1 = [NSObject new];
NSObject *someObject2 = [NSObject new];
NSObject *someObject3 = [NSObject new];
_RCDTestBlockType someBlock1 = ^{};
_RCDTestBlockType someBlock2 = ^{};
_RCDTestBlockType someBlock3 = ^{};
__block NSObject *unretainedObject;
_RCDTestBlockType block = ^{
// Keep strong reference to someObject
someBlock1();
unretainedObject = someObject1;
unretainedObject = someObject2;
someBlock2();
someBlock3();
unretainedObject = someObject3;
};
FBObjectiveCObject *wrappedObject1 = [[FBObjectiveCObject alloc] initWithObject:someObject1];
FBObjectiveCObject *wrappedObject2 = [[FBObjectiveCObject alloc] initWithObject:someObject2];
FBObjectiveCObject *wrappedObject3 = [[FBObjectiveCObject alloc] initWithObject:someObject3];
FBObjectiveCBlock *wrappedBlock1 = [[FBObjectiveCBlock alloc] initWithObject:someBlock1];
FBObjectiveCBlock *wrappedBlock2 = [[FBObjectiveCBlock alloc] initWithObject:someBlock2];
FBObjectiveCBlock *wrappedBlock3 = [[FBObjectiveCBlock alloc] initWithObject:someBlock3];
FBObjectiveCBlock *wrappedBlock = [[FBObjectiveCBlock alloc] initWithObject:block];
NSSet *retainedObjects = [wrappedBlock allRetainedObjects];
XCTAssertTrue([retainedObjects containsObject:wrappedObject1]);
XCTAssertTrue([retainedObjects containsObject:wrappedObject2]);
XCTAssertTrue([retainedObjects containsObject:wrappedObject3]);
XCTAssertTrue([retainedObjects containsObject:wrappedBlock1]);
XCTAssertTrue([retainedObjects containsObject:wrappedBlock2]);
XCTAssertTrue([retainedObjects containsObject:wrappedBlock3]);
}
- (void)testLayoutForEmptyBlockWillBeEmpty
{
_RCDTestBlockType block = ^{};
FBObjectiveCBlock *wrappedBlock = [[FBObjectiveCBlock alloc] initWithObject:block];
NSSet *retainedObjects = [wrappedBlock allRetainedObjects];
XCTAssertEqual([retainedObjects count], 0);
}
#endif //_INTERNAL_RCD_ENABLED
@end