1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
//
// OperationConditionTests.swift
// MullvadVPNTests
//
// Created by pronebird on 02/06/2022.
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
import Operations
import XCTest
@testable import MullvadMockData
@MainActor
class OperationConditionTests: XCTestCase {
func testTrueCondition() {
let expectConditionEvaluation = expectation(description: "Expect condition evaluation")
let expectOperationToExecute = expectation(description: "Expect operation to execute")
let operation = AsyncBlockOperation {
expectOperationToExecute.fulfill()
}
let blockCondition = BlockCondition { _, completion in
expectConditionEvaluation.fulfill()
completion(true)
}
operation.addCondition(blockCondition)
let operationQueue = AsyncOperationQueue()
operationQueue.addOperation(operation)
waitForExpectations(timeout: .UnitTest.timeout)
}
func testFalseCondition() {
let expectConditionEvaluation = expectation(description: "Expect condition evaluation")
let expectOperationToNeverExecute = expectation(
description: "Expect operation to never execute"
)
expectOperationToNeverExecute.isInverted = true
let operation = AsyncBlockOperation {
expectOperationToNeverExecute.fulfill()
}
let blockCondition = BlockCondition { _, completion in
expectConditionEvaluation.fulfill()
completion(false)
}
operation.addCondition(blockCondition)
let operationQueue = AsyncOperationQueue()
operationQueue.addOperation(operation)
wait(for: [expectOperationToNeverExecute], timeout: .UnitTest.invertedTimeout)
wait(for: [expectConditionEvaluation], timeout: .UnitTest.timeout)
}
func testNoCancelledDependenciesCondition() {
let expectToNeverExecute = expectation(description: "Expect child to never execute.")
expectToNeverExecute.isInverted = true
let parent = BlockOperation()
parent.cancel()
let child = AsyncBlockOperation {
expectToNeverExecute.fulfill()
}
child.addDependency(parent)
child.addCondition(NoCancelledDependenciesCondition())
let operationQueue = AsyncOperationQueue()
operationQueue.addOperations([parent, child], waitUntilFinished: false)
waitForExpectations(timeout: .UnitTest.invertedTimeout)
}
func testNoFailedDependenciesCondition() {
let expectToNeverExecute = expectation(description: "Expect child to never execute.")
expectToNeverExecute.isInverted = true
let parent = ResultBlockOperation<Void> {
throw URLError(.badURL)
}
let child = AsyncBlockOperation {
expectToNeverExecute.fulfill()
}
child.addDependency(parent)
child.addCondition(NoFailedDependenciesCondition(ignoreCancellations: false))
let operationQueue = AsyncOperationQueue()
operationQueue.addOperations([parent, child], waitUntilFinished: false)
waitForExpectations(timeout: .UnitTest.invertedTimeout)
}
func testNoFailedDependenciesIgnoringCancellationsCondition() {
let expectToExecute = expectation(description: "Expect child to execute.")
let parent = BlockOperation()
parent.cancel()
let child = AsyncBlockOperation {
expectToExecute.fulfill()
}
child.addDependency(parent)
child.addCondition(NoFailedDependenciesCondition(ignoreCancellations: true))
let operationQueue = AsyncOperationQueue()
operationQueue.addOperations([parent, child], waitUntilFinished: false)
waitForExpectations(timeout: .UnitTest.timeout)
}
func testMutuallyExclusiveCondition() {
let expectFirstOperationExecution = expectation(
description: "Expect first operation to execute first"
)
let expectSecondOperationExecution = expectation(
description: "Expect second operation to execute last"
)
let exclusiveCategory = "exclusiveOperations"
let operationQueue = AsyncOperationQueue()
let firstOperation = AsyncBlockOperation { finish in
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
expectFirstOperationExecution.fulfill()
finish(nil)
}
}
firstOperation.addCondition(MutuallyExclusive(category: exclusiveCategory))
let secondOperation = AsyncBlockOperation {
expectSecondOperationExecution.fulfill()
}
secondOperation.addCondition(MutuallyExclusive(category: exclusiveCategory))
operationQueue.addOperations([firstOperation, secondOperation], waitUntilFinished: false)
let expectations = [expectFirstOperationExecution, expectSecondOperationExecution]
wait(for: expectations, timeout: .UnitTest.timeout, enforceOrder: true)
}
}
|