Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
stephencelis committed Jul 10, 2023
1 parent 7e00028 commit 49a241c
Show file tree
Hide file tree
Showing 22 changed files with 162 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,6 @@ private let pointFreeColors = [

struct CountdownDemo_Previews: PreviewProvider {
static var previews: some View {
let _ = swift_task_enqueueGlobal_hook = { job, _ in
MainActor.shared.enqueue(job)
}

CountdownDemo(clock: .immediate)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,25 +48,6 @@ final class NumberFactModelTests: XCTestCase {
XCTAssertEqual(model.fact, "0 is a good number.")
}

func testFactClearsOut_MainSerialExecutor() async {
swift_task_enqueueGlobal_hook = { job, _ in
MainActor.shared.enqueue(job)
}

let model = withDependencies {
$0.numberFact.fact = { "\($0) is a good number." }
} operation: {
NumberFactModel()
}
model.fact = "An old fact about 0."

let task = Task { await model.getFactButtonTapped() }
await Task.yield()
XCTAssertEqual(model.fact, nil)
await task.value
XCTAssertEqual(model.fact, "0 is a good number.")
}

func testFactIsLoading() async {
let fact = AsyncStream.makeStream(of: String.self)

Expand All @@ -88,26 +69,6 @@ final class NumberFactModelTests: XCTestCase {
XCTAssertEqual(model.isLoading, false)
}

func testFactIsLoading_MainSerialExecutor() async {
swift_task_enqueueGlobal_hook = { job, _ in
MainActor.shared.enqueue(job)
}

let model = withDependencies {
$0.numberFact.fact = { "\($0) is a good number." }
} operation: {
NumberFactModel()
}
model.fact = "An old fact about 0."

let task = Task { await model.getFactButtonTapped() }
await Task.yield()
XCTAssertEqual(model.isLoading, true)
await task.value
XCTAssertEqual(model.fact, "0 is a good number.")
XCTAssertEqual(model.isLoading, false)
}

func testBackToBackGetFact() async throws {
let fact0 = AsyncStream.makeStream(of: String.self)
let fact1 = AsyncStream.makeStream(of: String.self)
Expand Down Expand Up @@ -138,38 +99,7 @@ final class NumberFactModelTests: XCTestCase {
await task1.value
XCTAssertEqual(model.fact, "0 is a great number.")
}

func testBackToBackGetFact_MainSerialExecutor() async throws {
swift_task_enqueueGlobal_hook = { job, _ in
MainActor.shared.enqueue(job)
}

let callCount = LockIsolated(0)

let model = withDependencies {
$0.numberFact.fact = { number in
callCount.withValue { $0 += 1 }
if callCount.value == 1 {
return "0 is a better number."
} else if callCount.value == 2 {
return "0 is a great number."
} else {
fatalError()
}
}
} operation: {
NumberFactModel()
}

let task0 = Task { await model.getFactButtonTapped() }
let task1 = Task { await model.getFactButtonTapped() }
await Task.yield()
await task0.value
await task1.value
XCTAssertEqual(model.fact, "0 is a great number.")
}



func testCancel() async {
let model = withDependencies {
$0.numberFact.fact = { _ in try await Task.never() }
Expand All @@ -182,65 +112,25 @@ final class NumberFactModelTests: XCTestCase {
await task.value
XCTAssertEqual(model.fact, nil)
}

func testCancel_MainSerialExecutor() async {
swift_task_enqueueGlobal_hook = { job, _ in
MainActor.shared.enqueue(job)
}

let model = withDependencies {
$0.numberFact.fact = {
await Task.yield()
try Task.checkCancellation()
return "\($0) is a good number."
}
} operation: {
NumberFactModel()
}
let task = Task { await model.getFactButtonTapped() }
await Task.yield()
model.cancelButtonTapped()
await task.value
XCTAssertEqual(model.fact, nil)
}



func testScreenshots() async {
let model = NumberFactModel()

let task = Task { await model.onTask() }

await Task.megaYield()
NotificationCenter.default.post(name: UIApplication.userDidTakeScreenshotNotification, object: nil)
while model.count != 1 {
await Task.yield()
}
XCTAssertEqual(model.count, 1)

NotificationCenter.default.post(name: UIApplication.userDidTakeScreenshotNotification, object: nil)
while model.count != 2 {
await Task.yield()
}
XCTAssertEqual(model.count, 2)
}

func testScreenshots_MainSerialExecutor() async {
swift_task_enqueueGlobal_hook = { job, _ in
MainActor.shared.enqueue(job)
}

let model = NumberFactModel()

let task = Task { await model.onTask() }
await Task.yield()
NotificationCenter.default.post(name: UIApplication.userDidTakeScreenshotNotification, object: nil)
await Task.yield()
XCTAssertEqual(model.count, 1)

NotificationCenter.default.post(name: UIApplication.userDidTakeScreenshotNotification, object: nil)
await Task.yield()
XCTAssertEqual(model.count, 2)
}
}

extension Task where Success == Never, Failure == Never {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ final class ReliablyTestingAsyncTests: XCTestCase {
let values = LockIsolated([Int]())
let task = Task {
values.withValue { $0.append(1) }
print(#line, { Thread.current }())
}
values.withValue { $0.append(2) }
print(#line, { Thread.current }())
await task.value
XCTAssertEqual(values.value, [2, 1])
}
Expand All @@ -40,11 +38,9 @@ final class ReliablyTestingAsyncTests: XCTestCase {
let values = LockIsolated([Int]())
let task1 = Task {
values.withValue { $0.append(1) }
print({ Thread.current }())
}
let task2 = Task {
values.withValue { $0.append(2) }
print({ Thread.current }())
}
_ = await (task1.value, task2.value)
XCTAssertEqual(values.value, [1, 2])
Expand Down Expand Up @@ -102,11 +98,7 @@ final class ReliablyTestingAsyncTests: XCTestCase {
}
for task in tasks { await task.value }

XCTAssertEqual(
values.value,
Array(0...count).map { $0 * 2 } // evens less than or equal to max
+ Array(0...count).map { $0 * 2 + 1 } // odds less than or equal to max
)
XCTAssertEqual(values.value, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21])
}

func testYieldScheduling_MainSerialExecutor() async {
Expand All @@ -125,36 +117,28 @@ final class ReliablyTestingAsyncTests: XCTestCase {
}
for task in tasks { await task.value }

XCTAssertEqual(
values.value,
Array(0...count).map { $0 * 2 } // evens less than or equal to max
+ Array(0...count).map { $0 * 2 + 1 } // odds less than or equal to max
)
XCTAssertEqual(values.value, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21])
}
/*

[task0, task1, task2]

/*
[{task0}, task1, task2]
[0]

[{task1}, task2, task0]
[task2, task0, task1]
[0, 2]

[{task2}, task0, task1]
[task0, task1, task2]
[0, 2, 4]

[{task0}, task1, task2]
[task1, task2]
[0, 2, 4, 1]

[{task1}, task2]
[task2]
[0, 2, 4, 1, 3]

[{task2}]
[0, 2, 4, 1, 3, 5]

[]
[0, 2, 4, 1, 3, 5]

*/

@MainActor
Expand Down
5 changes: 5 additions & 0 deletions 0241-reliably-testing-async-pt4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## [Point-Free](https://www.pointfree.co)

> #### This directory contains code from Point-Free Episode: [Reliable Async Tests: πŸ₯Ή](https://www.pointfree.co/episodes/ep241-reliable-async-tests)
>
> We continue our deep dive into advanced Swift concurrency by exploring the concept of β€œexecutors” to better understand its global enqueue hook. We will then put this hook to work and finally have reliable, 100% deterministic async tests.
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ private let pointFreeColors = [

struct CountdownDemo_Previews: PreviewProvider {
static var previews: some View {
let _ = swift_task_enqueueGlobal_hook = { job, _ in
MainActor.shared.enqueue(job)
}

CountdownDemo(clock: .immediate)
}
}
Loading

0 comments on commit 49a241c

Please sign in to comment.