Skip to content

Commit

Permalink
Fix retain cycle with transaction operations (TextureGroup#1429)
Browse files Browse the repository at this point in the history
Add unit tests that help find cycles. `-testWeakWithSingleOperation` fails without the code fix applied.
  • Loading branch information
bolsinga authored and hebertialmeida committed May 10, 2019
1 parent a631803 commit 6b81f5a
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
4 changes: 4 additions & 0 deletions AsyncDisplayKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@
CCEDDDD9200C518800FFCD0A /* ASConfigurationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDD8200C518800FFCD0A /* ASConfigurationTests.mm */; };
CCF18FF41D2575E300DF5895 /* NSIndexSet+ASHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
CCF1FF5E20C4785000AAD8FC /* ASLocking.h in Headers */ = {isa = PBXBuildFile; fileRef = CCF1FF5D20C4785000AAD8FC /* ASLocking.h */; settings = {ATTRIBUTES = (Public, ); }; };
D933F041224AD17F00FF495E /* ASTransactionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = D933F040224AD17F00FF495E /* ASTransactionTests.mm */; };
DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; };
DB78412E1C6BCE1600A9E2B4 /* _ASTransitionContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.mm */; };
Expand Down Expand Up @@ -1000,6 +1001,7 @@
D3779BCFF841AD3EB56537ED /* Pods-AsyncDisplayKitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.release.xcconfig"; sourceTree = "<group>"; };
D785F6601A74327E00291744 /* ASScrollNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASScrollNode.h; sourceTree = "<group>"; };
D785F6611A74327E00291744 /* ASScrollNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASScrollNode.mm; sourceTree = "<group>"; };
D933F040224AD17F00FF495E /* ASTransactionTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTransactionTests.mm; sourceTree = "<group>"; };
DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = _ASTransitionContext.h; path = ../_ASTransitionContext.h; sourceTree = "<group>"; };
DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = _ASTransitionContext.mm; path = ../_ASTransitionContext.mm; sourceTree = "<group>"; };
DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASContextTransitioning.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1389,6 +1391,7 @@
83A7D95D1D446A6E00BF333E /* ASWeakMapTests.mm */,
CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.mm */,
695BE2541DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm */,
D933F040224AD17F00FF495E /* ASTransactionTests.mm */,
057D02C01AC0A66700C7AC3C /* AsyncDisplayKitTestHost */,
CC583ABF1EF9BAB400134156 /* Common */,
058D09C6195D04C000B7D73C /* Supporting Files */,
Expand Down Expand Up @@ -2292,6 +2295,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D933F041224AD17F00FF495E /* ASTransactionTests.mm in Sources */,
CCEDDDD9200C518800FFCD0A /* ASConfigurationTests.mm in Sources */,
AE440175210FB7CF00B36DA2 /* ASTextKitFontSizeAdjusterTests.mm in Sources */,
E51B78BF1F028ABF00E32604 /* ASLayoutFlatteningTests.mm in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ - (_ASAsyncTransaction *)asyncdisplaykit_asyncTransaction
if (self == nil) {
return;
}
[transactions removeObject:completedTransaction];
[self.asyncdisplaykit_asyncLayerTransactions removeObject:completedTransaction];
[self asyncdisplaykit_asyncTransactionContainerDidCompleteTransaction:completedTransaction];
}];
[transactions addObject:transaction];
Expand Down
84 changes: 84 additions & 0 deletions Tests/ASTransactionTests.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//
// ASTransactionTests.m
// AsyncDisplayKitTests
//
// Created by Greg Bolsinga on 3/26/19.
// Copyright © 2019 Pinterest. All rights reserved.
//

#import "ASTestCase.h"
#import <AsyncDisplayKit/AsyncDisplayKit.h>

@interface ASTransactionTests : ASTestCase

@end

@implementation ASTransactionTests

- (void)testWeak
{
__weak _ASAsyncTransaction* weakTransaction = nil;
@autoreleasepool {
CALayer *layer = [[CALayer alloc] init];
_ASAsyncTransaction *transaction = layer.asyncdisplaykit_asyncTransaction;

weakTransaction = transaction;
layer = nil;
}

// held by main transaction group
XCTAssertNotNil(weakTransaction);

// run so that transaction group drains.
static NSTimeInterval delay = 0.1;
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:delay]];

XCTAssertNil(weakTransaction);
}

- (void)testWeakWhenCancelled
{
__weak _ASAsyncTransaction* weakTransaction = nil;
@autoreleasepool {
CALayer *layer = [[CALayer alloc] init];
_ASAsyncTransaction *transaction = layer.asyncdisplaykit_asyncTransaction;

weakTransaction = transaction;

[layer asyncdisplaykit_cancelAsyncTransactions];
layer = nil;
}

XCTAssertNil(weakTransaction);
}

- (void)testWeakWithSingleOperation
{
__weak _ASAsyncTransaction* weakTransaction = nil;
@autoreleasepool {
CALayer *layer = [[CALayer alloc] init];
_ASAsyncTransaction *transaction = layer.asyncdisplaykit_asyncTransaction;

[transaction addOperationWithBlock:^id<NSObject> _Nullable{
return nil;
} priority:1
queue:dispatch_get_main_queue()
completion:^(id _Nullable value, BOOL canceled) {
;
}];

weakTransaction = transaction;
layer = nil;
}

// held by main transaction group
XCTAssertNotNil(weakTransaction);

// run so that transaction group drains.
static NSTimeInterval delay = 0.1;
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:delay]];

XCTAssertNil(weakTransaction);
}

@end

0 comments on commit 6b81f5a

Please sign in to comment.