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