Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit 3e53d26

Browse files
author
Adlai Holler
authored
Ensure that all nodes are deallocated inside the thrash testing method to avoid polluting other tests (#2800)
1 parent 498e5a9 commit 3e53d26

2 files changed

Lines changed: 40 additions & 13 deletions

File tree

AsyncDisplayKit/ASDisplayNode.mm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2382,6 +2382,7 @@ - (void)__enterHierarchy
23822382
ASDisplayNodeAssertMainThread();
23832383
ASDisplayNodeAssert(!_flags.isEnteringHierarchy, @"Should not cause recursive __enterHierarchy");
23842384
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
2385+
ASDisplayNodeLogEvent(self, @"enterHierarchy");
23852386

23862387
// Profiling has shown that locking this method is beneficial, so each of the property accesses don't have to lock and unlock.
23872388
__instanceLock__.lock();
@@ -2428,6 +2429,7 @@ - (void)__exitHierarchy
24282429
ASDisplayNodeAssertMainThread();
24292430
ASDisplayNodeAssert(!_flags.isExitingHierarchy, @"Should not cause recursive __exitHierarchy");
24302431
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
2432+
ASDisplayNodeLogEvent(self, @"exitHierarchy");
24312433

24322434
// Profiling has shown that locking this method is beneficial, so each of the property accesses don't have to lock and unlock.
24332435
__instanceLock__.lock();

AsyncDisplayKitTests/ASTableViewThrashTests.m

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ @interface ASThrashTestNode: ASCellNode
175175

176176
@implementation ASThrashTestNode
177177

178+
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
179+
{
180+
ASDisplayNodeAssertFalse(isinf(constrainedSize.width));
181+
return CGSizeMake(constrainedSize.width, 44);
182+
}
183+
178184
@end
179185
#endif
180186

@@ -188,6 +194,8 @@ @interface ASThrashDataSource: NSObject
188194
@property (nonatomic, strong, readonly) UIWindow *window;
189195
@property (nonatomic, strong, readonly) TableView *tableView;
190196
@property (nonatomic, strong) NSArray <ASThrashTestSection *> *data;
197+
// Only access on main
198+
@property (nonatomic, strong) ASWeakSet *allNodes;
191199
@end
192200

193201

@@ -199,6 +207,7 @@ - (instancetype)initWithData:(NSArray <ASThrashTestSection *> *)data {
199207
_data = [[NSArray alloc] initWithArray:data copyItems:YES];
200208
_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
201209
_tableView = [[TableView alloc] initWithFrame:_window.bounds style:UITableViewStylePlain];
210+
_allNodes = [[ASWeakSet alloc] init];
202211
[_window addSubview:_tableView];
203212
#if USE_UIKIT_REFERENCE
204213
_tableView.dataSource = self;
@@ -227,6 +236,17 @@ - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSIntege
227236
return self.data[section].headerHeight;
228237
}
229238

239+
/// Object passed into predicate is ignored.
240+
- (NSPredicate *)predicateForDeallocatedHierarchy
241+
{
242+
ASWeakSet *allNodes = self.allNodes;
243+
__weak UIWindow *window = _window;
244+
__weak ASTableView *view = _tableView;
245+
return [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
246+
return window == nil && view == nil && allNodes.isEmpty;
247+
}];
248+
}
249+
230250
#if USE_UIKIT_REFERENCE
231251

232252
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@@ -240,13 +260,12 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa
240260

241261
#else
242262

243-
- (ASCellNodeBlock)tableView:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath {
244-
ASThrashTestItem *item = self.data[indexPath.section].items[indexPath.item];
245-
return ^{
246-
ASThrashTestNode *node = [[ASThrashTestNode alloc] init];
247-
node.item = item;
248-
return node;
249-
};
263+
- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath
264+
{
265+
ASThrashTestNode *node = [[ASThrashTestNode alloc] init];
266+
node.item = self.data[indexPath.section].items[indexPath.item];;
267+
[self.allNodes addObject:node];
268+
return node;
250269
}
251270

252271
#endif
@@ -495,11 +514,17 @@ - (void)DISABLED_testRecordedThrashCase {
495514
- (void)DISABLED_testThrashingWildly {
496515
for (NSInteger i = 0; i < kThrashingIterationCount; i++) {
497516
[self setUp];
498-
ASThrashDataSource *ds = [[ASThrashDataSource alloc] initWithData:[ASThrashTestSection sectionsWithCount:kInitialSectionCount]];
499-
_update = [[ASThrashUpdate alloc] initWithData:ds.data];
500-
501-
[self applyUpdate:_update toDataSource:ds];
502-
[self verifyDataSource:ds];
517+
@autoreleasepool {
518+
NSArray *sections = [ASThrashTestSection sectionsWithCount:kInitialSectionCount];
519+
_update = [[ASThrashUpdate alloc] initWithData:sections];
520+
ASThrashDataSource *ds = [[ASThrashDataSource alloc] initWithData:sections];
521+
522+
[self applyUpdate:_update toDataSource:ds];
523+
[self verifyDataSource:ds];
524+
[self expectationForPredicate:[ds predicateForDeallocatedHierarchy] evaluatedWithObject:(id)kCFNull handler:nil];
525+
}
526+
[self waitForExpectationsWithTimeout:3 handler:nil];
527+
503528
[self tearDown];
504529
}
505530
}
@@ -533,7 +558,7 @@ - (void)applyUpdate:(ASThrashUpdate *)update toDataSource:(ASThrashDataSource *)
533558
[tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
534559
}];
535560
@try {
536-
[tableView endUpdates];
561+
[tableView endUpdatesAnimated:NO completion:nil];
537562
#if !USE_UIKIT_REFERENCE
538563
[tableView waitUntilAllUpdatesAreCommitted];
539564
#endif

0 commit comments

Comments
 (0)