mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-02-16 07:41:08 +00:00
* fix SIMULATE_WEB_RESPONSE not imported #449 * Coalesce interface state updates to ASCATransactionQueue before CATransaction commit. This will avoid duplicate interface state delegate calls caused by view repeatly added/removed to/from hierarchy during controller animation transition. * fix tests for new run loop queue * Support for disabling ASCATransactionQueue * Fix didExitHierarchy to use ASCATransactionQueue. * merge range managed and none range managed for didExitHierarchy * Revert "merge range managed and none range managed for didExitHierarchy" This reverts commit f807efaa65ed5dbdb6622d06da542e01a53715fa. * merge range managed and none range managed for didExitHierarchy * remove metadata * abstract queue to impl class methods * Add tests * Fix test fail because of shared object. * guard _pendingInterfaceState access with lock * name refactor * Refactor from comments https://github.com/TextureGroup/Texture/pull/788/\#pullrequestreview-94849919 * Apply InterfaceState immediately after ASCATranactionQueue is processed and before next runloop started. * refactor * no op to start CI build * remove unused var and kick off tests * change lisence * remove code for weak ref * add change log and adjust license
193 lines
6.6 KiB
Objective-C
193 lines
6.6 KiB
Objective-C
//
|
|
// ASRunLoopQueueTests.m
|
|
// Texture
|
|
//
|
|
// Copyright (c) 2017-present,
|
|
// Pinterest, Inc. Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
|
|
#import <XCTest/XCTest.h>
|
|
#import <AsyncDisplayKit/ASRunLoopQueue.h>
|
|
#import "ASDisplayNodeTestsHelper.h"
|
|
|
|
static NSTimeInterval const kRunLoopRunTime = 0.001; // Allow the RunLoop to run for one millisecond each time.
|
|
|
|
@interface QueueObject : NSObject <ASCATransactionQueueObserving>
|
|
@property (nonatomic, assign) BOOL queueObjectProcessed;
|
|
@end
|
|
|
|
@implementation QueueObject
|
|
- (void)prepareForCATransactionCommit
|
|
{
|
|
self.queueObjectProcessed = YES;
|
|
}
|
|
@end
|
|
|
|
@interface ASRunLoopQueueTests : XCTestCase
|
|
|
|
@end
|
|
|
|
@implementation ASRunLoopQueueTests
|
|
|
|
#pragma mark enqueue tests
|
|
|
|
- (void)testEnqueueNilObjectsToQueue
|
|
{
|
|
ASRunLoopQueue *queue = [[ASRunLoopQueue alloc] initWithRunLoop:CFRunLoopGetMain() retainObjects:YES handler:nil];
|
|
id object = nil;
|
|
[queue enqueue:object];
|
|
XCTAssertTrue(queue.isEmpty);
|
|
}
|
|
|
|
- (void)testEnqueueSameObjectTwiceToDefaultQueue
|
|
{
|
|
id object = [[NSObject alloc] init];
|
|
__unsafe_unretained id weakObject = object;
|
|
__block NSUInteger dequeuedCount = 0;
|
|
ASRunLoopQueue *queue = [[ASRunLoopQueue alloc] initWithRunLoop:CFRunLoopGetMain() retainObjects:YES handler:^(id _Nonnull dequeuedItem, BOOL isQueueDrained) {
|
|
if (dequeuedItem == weakObject) {
|
|
dequeuedCount++;
|
|
}
|
|
}];
|
|
[queue enqueue:object];
|
|
[queue enqueue:object];
|
|
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:kRunLoopRunTime]];
|
|
XCTAssert(dequeuedCount == 1);
|
|
}
|
|
|
|
- (void)testEnqueueSameObjectTwiceToNonExclusiveMembershipQueue
|
|
{
|
|
id object = [[NSObject alloc] init];
|
|
__unsafe_unretained id weakObject = object;
|
|
__block NSUInteger dequeuedCount = 0;
|
|
ASRunLoopQueue *queue = [[ASRunLoopQueue alloc] initWithRunLoop:CFRunLoopGetMain() retainObjects:YES handler:^(id _Nonnull dequeuedItem, BOOL isQueueDrained) {
|
|
if (dequeuedItem == weakObject) {
|
|
dequeuedCount++;
|
|
}
|
|
}];
|
|
queue.ensureExclusiveMembership = NO;
|
|
[queue enqueue:object];
|
|
[queue enqueue:object];
|
|
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:kRunLoopRunTime]];
|
|
XCTAssert(dequeuedCount == 2);
|
|
}
|
|
|
|
#pragma mark processQueue tests
|
|
|
|
- (void)testDefaultQueueProcessObjectsOneAtATime
|
|
{
|
|
ASRunLoopQueue *queue = [[ASRunLoopQueue alloc] initWithRunLoop:CFRunLoopGetMain() retainObjects:YES handler:^(id _Nonnull dequeuedItem, BOOL isQueueDrained) {
|
|
[NSThread sleepForTimeInterval:kRunLoopRunTime * 2]; // So each element takes more time than the available
|
|
}];
|
|
[queue enqueue:[[NSObject alloc] init]];
|
|
[queue enqueue:[[NSObject alloc] init]];
|
|
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:kRunLoopRunTime]];
|
|
XCTAssertFalse(queue.isEmpty);
|
|
}
|
|
|
|
- (void)testQueueProcessObjectsInBatchesOfSpecifiedSize
|
|
{
|
|
ASRunLoopQueue *queue = [[ASRunLoopQueue alloc] initWithRunLoop:CFRunLoopGetMain() retainObjects:YES handler:^(id _Nonnull dequeuedItem, BOOL isQueueDrained) {
|
|
[NSThread sleepForTimeInterval:kRunLoopRunTime * 2]; // So each element takes more time than the available
|
|
}];
|
|
queue.batchSize = 2;
|
|
[queue enqueue:[[NSObject alloc] init]];
|
|
[queue enqueue:[[NSObject alloc] init]];
|
|
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:kRunLoopRunTime]];
|
|
XCTAssertTrue(queue.isEmpty);
|
|
}
|
|
|
|
- (void)testQueueOnlySendsIsDrainedForLastObjectInBatch
|
|
{
|
|
id objectA = [[NSObject alloc] init];
|
|
id objectB = [[NSObject alloc] init];
|
|
__unsafe_unretained id weakObjectA = objectA;
|
|
__unsafe_unretained id weakObjectB = objectB;
|
|
__block BOOL isQueueDrainedWhenProcessingA = NO;
|
|
__block BOOL isQueueDrainedWhenProcessingB = NO;
|
|
ASRunLoopQueue *queue = [[ASRunLoopQueue alloc] initWithRunLoop:CFRunLoopGetMain() retainObjects:YES handler:^(id _Nonnull dequeuedItem, BOOL isQueueDrained) {
|
|
if (dequeuedItem == weakObjectA) {
|
|
isQueueDrainedWhenProcessingA = isQueueDrained;
|
|
} else if (dequeuedItem == weakObjectB) {
|
|
isQueueDrainedWhenProcessingB = isQueueDrained;
|
|
}
|
|
}];
|
|
queue.batchSize = 2;
|
|
[queue enqueue:objectA];
|
|
[queue enqueue:objectB];
|
|
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:kRunLoopRunTime]];
|
|
XCTAssertFalse(isQueueDrainedWhenProcessingA);
|
|
XCTAssertTrue(isQueueDrainedWhenProcessingB);
|
|
}
|
|
|
|
#pragma mark strong/weak tests
|
|
|
|
- (void)testStrongQueueRetainsObjects
|
|
{
|
|
id object = [[NSObject alloc] init];
|
|
__unsafe_unretained id weakObject = object;
|
|
__block BOOL didProcessObject = NO;
|
|
ASRunLoopQueue *queue = [[ASRunLoopQueue alloc] initWithRunLoop:CFRunLoopGetMain() retainObjects:YES handler:^(id _Nonnull dequeuedItem, BOOL isQueueDrained) {
|
|
if (dequeuedItem == weakObject) {
|
|
didProcessObject = YES;
|
|
}
|
|
}];
|
|
[queue enqueue:object];
|
|
object = nil;
|
|
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:kRunLoopRunTime]];
|
|
XCTAssertTrue(didProcessObject);
|
|
}
|
|
|
|
- (void)testWeakQueueDoesNotRetainsObjects
|
|
{
|
|
id object = [[NSObject alloc] init];
|
|
__unsafe_unretained id weakObject = object;
|
|
__block BOOL didProcessObject = NO;
|
|
ASRunLoopQueue *queue = [[ASRunLoopQueue alloc] initWithRunLoop:CFRunLoopGetMain() retainObjects:NO handler:^(id _Nonnull dequeuedItem, BOOL isQueueDrained) {
|
|
if (dequeuedItem == weakObject) {
|
|
didProcessObject = YES;
|
|
}
|
|
}];
|
|
[queue enqueue:object];
|
|
object = nil;
|
|
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:kRunLoopRunTime]];
|
|
XCTAssertFalse(didProcessObject);
|
|
}
|
|
|
|
- (void)testWeakQueueWithAllDeallocatedObjectsIsDrained
|
|
{
|
|
ASRunLoopQueue *queue = [[ASRunLoopQueue alloc] initWithRunLoop:CFRunLoopGetMain() retainObjects:NO handler:nil];
|
|
id object = [[NSObject alloc] init];
|
|
[queue enqueue:object];
|
|
object = nil;
|
|
XCTAssertFalse(queue.isEmpty);
|
|
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:kRunLoopRunTime]];
|
|
XCTAssertTrue(queue.isEmpty);
|
|
}
|
|
|
|
- (void)testASCATransactionQueueDisable
|
|
{
|
|
ASCATransactionQueue *queue = [[ASCATransactionQueue alloc] init];
|
|
[queue disable];
|
|
QueueObject *object = [[QueueObject alloc] init];
|
|
[[ASCATransactionQueue sharedQueue] enqueue:object];
|
|
XCTAssertTrue([queue isEmpty]);
|
|
XCTAssertTrue([queue disabled]);
|
|
}
|
|
|
|
- (void)testASCATransactionQueueProcess
|
|
{
|
|
ASCATransactionQueue *queue = [[ASCATransactionQueue alloc] init];
|
|
QueueObject *object = [[QueueObject alloc] init];
|
|
[queue enqueue:object];
|
|
XCTAssertFalse(object.queueObjectProcessed);
|
|
ASCATransactionQueueWait();
|
|
XCTAssertTrue(object.queueObjectProcessed);
|
|
}
|
|
|
|
@end
|