-
-
Notifications
You must be signed in to change notification settings - Fork 51
/
Copy pathWebWorkerTaskExecutorTests.swift
154 lines (128 loc) · 4.94 KB
/
WebWorkerTaskExecutorTests.swift
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
149
150
151
152
153
154
#if compiler(>=6.1) && _runtime(_multithreaded)
import XCTest
import JavaScriptKit
import _CJavaScriptKit // For swjs_get_worker_thread_id
@testable import JavaScriptEventLoop
@_extern(wasm, module: "JavaScriptEventLoopTestSupportTests", name: "isMainThread")
func isMainThread() -> Bool
final class WebWorkerTaskExecutorTests: XCTestCase {
override func setUp() {
WebWorkerTaskExecutor.installGlobalExecutor()
}
func testTaskRunOnMainThread() async throws {
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1)
XCTAssertTrue(isMainThread())
let task = Task(executorPreference: executor) {
return isMainThread()
}
let taskRunOnMainThread = await task.value
// The task should run on the worker thread
XCTAssertFalse(taskRunOnMainThread)
// After the task is done, back to the main thread
XCTAssertTrue(isMainThread())
executor.terminate()
}
func testWithPreferenceBlock() async throws {
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1)
await withTaskExecutorPreference(executor) {
XCTAssertFalse(isMainThread())
}
}
func testAwaitInsideTask() async throws {
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1)
let task = Task(executorPreference: executor) {
await Task.yield()
_ = try await JSPromise.resolve(1).value
return isMainThread()
}
let taskRunOnMainThread = try await task.value
XCTAssertFalse(taskRunOnMainThread)
executor.terminate()
}
func testSleepInsideTask() async throws {
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1)
let task = Task(executorPreference: executor) {
XCTAssertFalse(isMainThread())
try await Task.sleep(nanoseconds: 10)
XCTAssertFalse(isMainThread())
try await Task.sleep(nanoseconds: 100)
XCTAssertFalse(isMainThread())
let clock = ContinuousClock()
try await clock.sleep(for: .milliseconds(10))
return isMainThread()
}
let taskRunOnMainThread = try await task.value
XCTAssertFalse(taskRunOnMainThread)
executor.terminate()
}
func testMainActorRun() async throws {
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1)
let task = Task(executorPreference: executor) {
await MainActor.run {
return isMainThread()
}
}
let taskRunOnMainThread = await task.value
// FIXME: The block passed to `MainActor.run` should run on the main thread
// XCTAssertTrue(taskRunOnMainThread)
XCTAssertFalse(taskRunOnMainThread)
// After the task is done, back to the main thread
XCTAssertTrue(isMainThread())
executor.terminate()
}
func testTaskGroupRunOnSameThread() async throws {
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 3)
let mainTid = swjs_get_worker_thread_id()
await withTaskExecutorPreference(executor) {
let tid = swjs_get_worker_thread_id()
await withTaskGroup(of: Int32.self) { group in
group.addTask {
return swjs_get_worker_thread_id()
}
group.addTask {
return swjs_get_worker_thread_id()
}
for await id in group {
XCTAssertEqual(id, tid)
XCTAssertNotEqual(id, mainTid)
}
}
}
executor.terminate()
}
func testTaskGroupRunOnDifferentThreads() async throws {
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 2)
struct Item: Hashable {
let type: String
let tid: Int32
let value: Int
init(_ type: String, _ tid: Int32, _ value: Int) {
self.type = type
self.tid = tid
self.value = value
}
}
await withTaskGroup(of: Item.self) { group in
group.addTask {
let tid = swjs_get_worker_thread_id()
return Item("main", tid, 0)
}
let numberOffloadedTasks = 10
for i in 0..<numberOffloadedTasks {
group.addTask(executorPreference: executor) {
let tid = swjs_get_worker_thread_id()
return Item("worker", tid, i)
}
}
var items: [Item] = []
for await item in group {
items.append(item)
}
XCTAssertFalse(Task.isCancelled)
XCTAssertEqual(items.count, numberOffloadedTasks + 1)
XCTAssertEqual(items.map(\.value).sorted(), [0] + Array(0..<numberOffloadedTasks))
}
executor.terminate()
}
}
#endif