@@ -39,6 +39,8 @@ class TestOperationQueue : XCTestCase {
39
39
( " test_CustomOperationReady " , test_CustomOperationReady) ,
40
40
( " test_DependencyCycleBreak " , test_DependencyCycleBreak) ,
41
41
( " test_Lifecycle " , test_Lifecycle) ,
42
+ ( " test_ConcurrentOperations " , test_ConcurrentOperations) ,
43
+ ( " test_ConcurrentOperationsWithDependenciesAndCompletions " , test_ConcurrentOperationsWithDependenciesAndCompletions) ,
42
44
]
43
45
}
44
46
@@ -672,6 +674,58 @@ class TestOperationQueue : XCTestCase {
672
674
Thread . sleep ( forTimeInterval: 1 ) // Let queue to be deallocated
673
675
XCTAssertNil ( weakQueue, " Queue should be deallocated at this point " )
674
676
}
677
+
678
+ func test_ConcurrentOperations( ) {
679
+ let queue = OperationQueue ( )
680
+ queue. maxConcurrentOperationCount = 2
681
+
682
+ // Running several iterations helps to reveal use-after-dealloc crashes
683
+ for _ in 0 ..< 3 {
684
+ let didRunOp1 = expectation ( description: " Did run first operation " )
685
+ let didRunOp2 = expectation ( description: " Did run second operation " )
686
+
687
+ queue. addOperation {
688
+ self . wait ( for: [ didRunOp2] , timeout: 0.2 )
689
+ didRunOp1. fulfill ( )
690
+ }
691
+ queue. addOperation {
692
+ didRunOp2. fulfill ( )
693
+ }
694
+
695
+ self . wait ( for: [ didRunOp1] , timeout: 0.3 )
696
+ }
697
+ }
698
+
699
+ func test_ConcurrentOperationsWithDependenciesAndCompletions( ) {
700
+ let queue = OperationQueue ( )
701
+ queue. maxConcurrentOperationCount = 2
702
+
703
+ // Running several iterations helps to reveal use-after-dealloc crashes
704
+ for _ in 0 ..< 3 {
705
+ let didRunOp1 = expectation ( description: " Did run first operation " )
706
+ let didRunOp1Completion = expectation ( description: " Did run first operation completion " )
707
+ let didRunOp1Dependency = expectation ( description: " Did run first operation dependency " )
708
+ let didRunOp2 = expectation ( description: " Did run second operation " )
709
+
710
+ let op1 = BlockOperation {
711
+ self . wait ( for: [ didRunOp1Dependency, didRunOp2] , timeout: 0.2 )
712
+ didRunOp1. fulfill ( )
713
+ }
714
+ op1. completionBlock = {
715
+ didRunOp1Completion. fulfill ( )
716
+ }
717
+ let op1Dependency = BlockOperation {
718
+ didRunOp1Dependency. fulfill ( )
719
+ }
720
+ queue. addOperations ( [ op1, op1Dependency] , waitUntilFinished: false )
721
+ queue. addOperation {
722
+ didRunOp2. fulfill ( )
723
+ }
724
+
725
+ self . wait ( for: [ didRunOp1, didRunOp1Completion] , timeout: 0.3 )
726
+ }
727
+ }
728
+
675
729
}
676
730
677
731
class AsyncOperation : Operation {
0 commit comments