FBRetainCycleDetectorTests/FBRCDCollectionTests.m (72 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/FBObjectiveCGraphElement+Internal.h>
#import <FBRetainCycleDetector/FBObjectiveCObject.h>
#import <FBRetainCycleDetector/FBRetainCycleDetector.h>
@interface FBRCDTestCollection : NSMutableDictionary
@end
@implementation FBRCDTestCollection
{
NSMutableDictionary *_proxy;
NSUInteger _currentIndex;
}
- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey
{
[_proxy setObject:anObject forKeyedSubscript:aKey];
}
- (void)removeObjectForKey:(id)aKey
{
[_proxy removeObjectForKey:aKey];
}
- (instancetype)initWithObjects:(const id _Nonnull __unsafe_unretained *)objects forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys count:(NSUInteger)cnt
{
return [self init];
}
- (instancetype)init
{
if (self = [super init]) {
_proxy = [NSMutableDictionary new];
}
return self;
}
- (NSUInteger)count
{
return _proxy.count;
}
- (id)objectForKey:(id)aKey
{
_proxy[@"i_am_big_troll"] = @YES;
return [_proxy objectForKey:aKey];
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id _Nonnull *)buffer count:(NSUInteger)len
{
return [_proxy countByEnumeratingWithState:state objects:buffer count:len];
}
@end
@interface FBRCDCollectionTests : XCTestCase
@end
@implementation FBRCDCollectionTests
#if _INTERNAL_RCD_ENABLED
- (void)testThatRetainCycleDetectorSkipsWhenCollectionIsMutatedWhileEnumeration
{
FBRCDTestCollection *testCollection = [FBRCDTestCollection new];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-circular-container"
testCollection[@"a"] = testCollection;
testCollection[@"b"] = testCollection;
#pragma clang diagnostic pop
FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:testCollection];
NSSet *retainCycles = [detector findRetainCycles];
XCTAssertFalse([retainCycles containsObject:[[FBObjectiveCObject alloc] initWithObject:testCollection]]);
}
- (void)testNSMapTableWithOpaqueMemoryOption {
NSMapTable *mapTableWithOpaqueMemory = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsOpaqueMemory | NSPointerFunctionsIntegerPersonality valueOptions:NSPointerFunctionsOpaqueMemory | NSPointerFunctionsIntegerPersonality capacity:0];
NSInteger sample = 1;
[mapTableWithOpaqueMemory setObject:(__bridge id)((void *)sample) forKey:(__bridge id)((void *)sample)];
FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:mapTableWithOpaqueMemory];
NSSet *retainCycles = [detector findRetainCycles];
XCTAssertFalse([retainCycles containsObject:[[FBObjectiveCObject alloc] initWithObject:mapTableWithOpaqueMemory]]);
}
#endif //_INTERNAL_RCD_ENABLED
@end