mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00

git-subtree-dir: submodules/AsyncDisplayKit git-subtree-mainline: d06f423e0ed3df1fed9bd10d79ee312a9179b632 git-subtree-split: 02bedc12816e251ad71777f9d2578329b6d2bef6
202 lines
6.9 KiB
Plaintext
202 lines
6.9 KiB
Plaintext
//
|
|
// ASRunLoopQueueTests.mm
|
|
// Texture
|
|
//
|
|
// Copyright (c) Pinterest, Inc. All rights reserved.
|
|
// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
|
|
#import "ASTestCase.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) BOOL queueObjectProcessed;
|
|
@end
|
|
|
|
@implementation QueueObject
|
|
- (void)prepareForCATransactionCommit
|
|
{
|
|
self.queueObjectProcessed = YES;
|
|
}
|
|
@end
|
|
|
|
@interface ASRunLoopQueueTests : ASTestCase
|
|
|
|
@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
|
|
{
|
|
// Disable coalescing.
|
|
ASConfiguration *config = [[ASConfiguration alloc] init];
|
|
config.experimentalFeatures = kNilOptions;
|
|
[ASConfigurationManager test_resetWithConfiguration:config];
|
|
|
|
ASCATransactionQueue *queue = [[ASCATransactionQueue alloc] init];
|
|
QueueObject *object = [[QueueObject alloc] init];
|
|
XCTAssertFalse(object.queueObjectProcessed);
|
|
[queue enqueue:object];
|
|
XCTAssertTrue(object.queueObjectProcessed);
|
|
XCTAssertTrue([queue isEmpty]);
|
|
XCTAssertFalse(queue.enabled);
|
|
}
|
|
|
|
- (void)testASCATransactionQueueProcess
|
|
{
|
|
ASConfiguration *config = [[ASConfiguration alloc] initWithDictionary:nil];
|
|
config.experimentalFeatures = ASExperimentalInterfaceStateCoalescing;
|
|
[ASConfigurationManager test_resetWithConfiguration:config];
|
|
|
|
ASCATransactionQueue *queue = [[ASCATransactionQueue alloc] init];
|
|
QueueObject *object = [[QueueObject alloc] init];
|
|
[queue enqueue:object];
|
|
XCTAssertFalse(object.queueObjectProcessed);
|
|
ASCATransactionQueueWait(queue);
|
|
XCTAssertTrue(object.queueObjectProcessed);
|
|
XCTAssertTrue(queue.enabled);
|
|
}
|
|
|
|
@end
|