Skip to content

Commit cd22b68

Browse files
committed
Bump version and add tests for new queue-blocking behaviour.
1 parent f8da85b commit cd22b68

File tree

4 files changed

+96
-19
lines changed

4 files changed

+96
-19
lines changed

.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ShopGun-Future.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22
s.name = "ShopGun-Future"
33
s.module_name = "Future"
4-
s.version = "0.3.0"
4+
s.version = "0.4.0"
55
s.summary = "🕰 A simple Swift Future type"
66

77
s.description = <<-DESC

Sources/Future.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ extension Future {
109109

110110
return Future { cb in
111111
queue.asyncAfter(deadline: .now() + delay) {
112-
var grp: DispatchGroup? = blocksQueue ? DispatchGroup() : nil
112+
let grp: DispatchGroup? = blocksQueue ? DispatchGroup() : nil
113113
grp?.enter()
114114

115115
future.run { value in

Tests/FutureTests.swift

+87-17
Original file line numberDiff line numberDiff line change
@@ -99,58 +99,128 @@ class FutureTests: XCTestCase {
9999
let workQ = DispatchQueue(label: "WorkQueue")
100100
let completionQ = DispatchQueue(label: "CompletionQueue")
101101

102-
let expectIsAsyncA = self.expectation(description: "Is Async")
103-
var resA: Int = 2
102+
let expectIsAsync = self.expectation(description: "Is Async")
103+
var res: Int = 2
104104
Future<Int>(work: {
105105
// is working on the correct queue
106106
XCTAssertEqual(DispatchQueue.currentLabel, workQ.label)
107107

108-
return resA * 2
108+
return res * 2
109109
})
110110
.async(delay: 1, on: workQ, completesOn: completionQ)
111111
.run {
112112
let end = Date.timeIntervalSinceReferenceDate
113-
resA = $0
113+
res = $0
114114

115115
// work has been done
116-
XCTAssertEqual(resA, 4)
116+
XCTAssertEqual(res, 4)
117117
// it was delayed
118118
XCTAssert(end - start > 1)
119119
// is completing on the correct queue
120120
XCTAssertEqual(DispatchQueue.currentLabel, completionQ.label)
121121

122-
expectIsAsyncA.fulfill()
122+
expectIsAsync.fulfill()
123123
}
124124

125125
// it is async
126-
XCTAssertEqual(resA, 2)
127-
128-
self.wait(for: [expectIsAsyncA], timeout: 5)
126+
XCTAssertEqual(res, 2)
129127

128+
self.wait(for: [expectIsAsync], timeout: 5)
129+
}
130+
131+
func testAsyncOnMain() {
130132

131-
let expectIsAsyncB = self.expectation(description: "Is Async")
132-
var resB: Int = 2
133+
let expectIsAsync = self.expectation(description: "Is Async")
134+
var res: Int = 2
133135
Future<Int>(work: {
134136
// is working on the correct queue
135137
XCTAssertEqual(DispatchQueue.currentLabel, DispatchQueue.main.label)
136138

137-
return resB * 2
139+
return res * 2
138140
})
139141
.asyncOnMain()
140142
.run {
141-
resB = $0
143+
res = $0
142144

143-
XCTAssertEqual(resB, 4)
145+
XCTAssertEqual(res, 4)
144146

145147
// is completing on the correct queue
146148
XCTAssertEqual(DispatchQueue.currentLabel, DispatchQueue.main.label)
147149

148-
expectIsAsyncB.fulfill()
150+
expectIsAsync.fulfill()
149151
}
150152

151153
// it is async
152-
XCTAssertEqual(resB, 2)
153-
self.wait(for: [expectIsAsyncB], timeout: 5)
154+
XCTAssertEqual(res, 2)
155+
self.wait(for: [expectIsAsync], timeout: 5)
156+
}
157+
158+
func testAsyncBlockingQueue() {
159+
160+
let start = Date.timeIntervalSinceReferenceDate
161+
162+
let workQ = DispatchQueue(label: "WorkQueue")
163+
let completionQ = DispatchQueue(label: "CompletionQueue")
164+
165+
let expectIsAsync = self.expectation(description: "Is Async")
166+
var res: Int = 2
167+
Future<Int>(run: { cb in
168+
// is working on the correct queue
169+
XCTAssertEqual(DispatchQueue.currentLabel, workQ.label)
170+
171+
// wait a second before completing the work
172+
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
173+
XCTAssertEqual(res, 2)
174+
res *= 2
175+
cb(res)
176+
}
177+
})
178+
.async(delay: 0, on: workQ, blocksQueue: true, completesOn: completionQ)
179+
.run { returnedRes in
180+
let end = Date.timeIntervalSinceReferenceDate
181+
182+
// Note: this callback occurs _after_ the queue is unblocked
183+
// so returnedRes may not equal res (as the other work may have already occurred.
184+
185+
// work has been done
186+
XCTAssertEqual(returnedRes, 4)
187+
// it was delayed
188+
XCTAssert(end - start > 1)
189+
// is completing on the correct queue
190+
XCTAssertEqual(DispatchQueue.currentLabel, completionQ.label)
191+
}
192+
193+
// start some other work on the same queue.
194+
Future<Int>(work: {
195+
// is working on the correct queue
196+
XCTAssertEqual(DispatchQueue.currentLabel, workQ.label)
197+
198+
// the previously defined future has been run first
199+
XCTAssertEqual(res, 4)
200+
201+
return res + 1
202+
})
203+
.async(delay: 0, on: workQ, blocksQueue: true, completesOn: completionQ)
204+
.run {
205+
let end = Date.timeIntervalSinceReferenceDate
206+
res = $0
207+
208+
// work has been done (after the previous work)
209+
XCTAssertEqual(res, 5)
210+
// it was delayed (waiting for prev work to finish)
211+
XCTAssert(end - start > 1)
212+
// is completing on the correct queue
213+
XCTAssertEqual(DispatchQueue.currentLabel, completionQ.label)
214+
215+
expectIsAsync.fulfill()
216+
}
217+
218+
// it is async - the res hasnt been changed yet
219+
XCTAssertEqual(res, 2)
220+
221+
self.wait(for: [expectIsAsync], timeout: 5)
222+
223+
XCTAssertEqual(res, 5)
154224
}
155225

156226
func testParallel() {

0 commit comments

Comments
 (0)