Skip to content

Commit dc218bb

Browse files
committed
fixed MainActor executable regression test
1 parent 91e2246 commit dc218bb

File tree

1 file changed

+89
-17
lines changed

1 file changed

+89
-17
lines changed
Lines changed: 89 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,110 @@
1-
// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-concurrency %import-libdispatch) | %FileCheck %s
1+
// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-concurrency) | %FileCheck %s
22

33
// REQUIRES: executable_test
44
// REQUIRES: concurrency
5-
// REQUIRES: libdispatch
65

6+
// REQUIRES: OS=macosx || OS=ios
7+
// FIXME: should not require Darwin to run this test once we have async main!
8+
9+
// for exit(:Int)
710
#if canImport(Darwin)
811
import Darwin
912
#elseif canImport(Glibc)
1013
import Glibc
1114
#endif
1215

13-
import Foundation
16+
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
17+
import Dispatch
18+
#endif
1419

15-
// CHECK: starting
16-
// CHECK-NOT: ERROR
17-
// CHECK: launched
18-
// CHECK-NOT: ERROR
19-
// CHECK: hello from main actor!
20+
/// @returns true iff the expected answer is actually the case, i.e., correct.
21+
/// If the current queue does not match expectations, this function may return
22+
/// false or just crash the program with non-zero exit code, depending on SDK.
23+
func checkIfMainQueue(expectedAnswer expected: Bool) -> Bool {
24+
// FIXME: until we start using dispatch on Linux, we only check
25+
// which queue we're on with Darwin platforms.
26+
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
27+
if #available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *) {
28+
dispatchPrecondition(condition: expected ? .onQueue(DispatchQueue.main)
29+
: .notOnQueue(DispatchQueue.main))
30+
31+
}
32+
#endif
33+
return true
34+
}
35+
36+
actor class A {
37+
func onCorrectQueue() -> Bool {
38+
if checkIfMainQueue(expectedAnswer: false) {
39+
print("on actor instance's queue")
40+
return true
41+
}
42+
print("ERROR: not on actor instance's queue")
43+
return false
44+
}
45+
}
46+
47+
@MainActor func exitTest(success: Bool) -> Never {
48+
if !success {
49+
exit(EXIT_FAILURE)
50+
}
51+
52+
if checkIfMainQueue(expectedAnswer: true) {
53+
print("on main queue again!")
54+
} else {
55+
print("ERROR: left the main queue?")
56+
}
2057

21-
@MainActor func helloMainActor() -> Never {
22-
if Thread.isMainThread {
58+
exit(EXIT_SUCCESS)
59+
}
60+
61+
@MainActor func enterMainActor() async -> Never {
62+
var ok = checkIfMainQueue(expectedAnswer: true)
63+
if ok {
2364
print("hello from main actor!")
24-
exit(EXIT_SUCCESS)
2565
} else {
26-
print("ERROR: not on correct thread!")
27-
exit(EXIT_FAILURE)
66+
print("ERROR: not on correct queue!")
2867
}
68+
69+
// try calling a function on another actor.
70+
let someActor = A()
71+
let successfulActorSwitch = await someActor.onCorrectQueue()
72+
ok = ok && successfulActorSwitch
73+
74+
exitTest(success: ok)
2975
}
3076

3177
func someFunc() async {
32-
await helloMainActor()
78+
guard checkIfMainQueue(expectedAnswer: false) else {
79+
print("ERROR: did not expect detatched task to run on main queue!")
80+
exit(EXIT_FAILURE)
81+
}
82+
await enterMainActor()
3383
}
3484

85+
86+
// CHECK: starting
87+
// CHECK-NOT: ERROR
88+
// CHECK: hello from main actor!
89+
// CHECK-NOT: ERROR
90+
// CHECK: on actor instance's queue
91+
// CHECK-NOT: ERROR
92+
// CHECK: on main queue again!
93+
94+
import CoreFoundation
95+
3596
print("starting")
36-
let _ = Task.runDetached(operation: someFunc)
37-
print("launched")
38-
dispatchMain() // give up the main queue.
97+
Task.runDetached(operation: someFunc)
98+
CFRunLoopRun()
99+
100+
// FIXME: remove the use of CFRunLoopRun and the CoreFoundation import
101+
// in favor of the below once we have async main support.
102+
// don't forget to add -parse-as-library to the RUN line
103+
/*
104+
@main struct RunIt {
105+
static func main() async {
106+
print("starting")
107+
await someFunc()
108+
}
109+
}
110+
*/

0 commit comments

Comments
 (0)