Files
swift-mirror/test/Concurrency/Runtime/actor_assume_executor.swift
2025-04-24 09:21:32 +02:00

162 lines
4.8 KiB
Swift

// RUN: %empty-directory(%t)
// RUN: %target-build-swift -target %target-swift-5.1-abi-triple -parse-as-library %s -o %t/a.out
// RUN: %target-codesign %t/a.out
// RUN: %env-SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=legacy %target-run %t/a.out
// REQUIRES: executable_test
// REQUIRES: concurrency
// REQUIRES: concurrency_runtime
// TODO: The actual reason is that we do these %env- tricks, which e.g. Windows is confused about
// REQUIRES: libdispatch
// UNSUPPORTED: back_deploy_concurrency
// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: freestanding
import StdlibUnittest
func checkAssumeMainActor(echo: MainActorEcho) /* synchronous! */ {
// Echo.get("any") // error: MainActor isolated, cannot perform async call here
MainActor.assumeIsolated {
let input = "example"
let got = echo.get(input)
precondition(got == "example", "Expected echo to match \(input)")
}
}
@MainActor
func mainActorCallCheck(echo: MainActorEcho) {
checkAssumeMainActor(echo: echo)
}
actor MainFriend {
nonisolated var unownedExecutor: UnownedSerialExecutor {
MainActor.sharedUnownedExecutor
}
func callCheck(echo: MainActorEcho) {
checkAssumeMainActor(echo: echo)
}
}
func checkAssumeSomeone(someone: SomeoneOnDefaultExecutor) /* synchronous */ {
// someone.something // can't access, would need a hop but we can't
someone.assumeIsolated { someone in
let something = someone.something
let expected = "isolated something"
precondition(something == expected, "expected '\(expected)', got: \(something)")
}
}
actor SomeoneOnDefaultExecutor {
func callCheckMainActor(echo: MainActorEcho) {
checkAssumeMainActor(echo: echo)
}
func callCheckSomeone() {
checkAssumeSomeone(someone: self)
}
var something: String {
"isolated something"
}
}
actor SomeonesFriend {
let someone: SomeoneOnDefaultExecutor
nonisolated var unownedExecutor: UnownedSerialExecutor {
self.someone.unownedExecutor
}
init(someone: SomeoneOnDefaultExecutor) {
self.someone = someone
}
func callCheckSomeone() {
checkAssumeSomeone(someone: someone)
}
}
actor CompleteStranger {
let someone: SomeoneOnDefaultExecutor
init(someone: SomeoneOnDefaultExecutor) {
self.someone = someone
}
func callCheckSomeone() {
checkAssumeSomeone(someone: someone)
}
}
@MainActor
final class MainActorEcho {
func get(_ key: String) -> String {
key
}
}
@main struct Main {
static func main() async {
let tests = TestSuite("AssumeActorExecutor")
let echo = MainActorEcho()
if #available(SwiftStdlib 5.1, *) {
// === MainActor --------------------------------------------------------
tests.test("MainActor.assumeIsolated: assume the main executor, from 'main() async'") {
await checkAssumeMainActor(echo: echo)
}
tests.test("MainActor.assumeIsolated: assume the main executor, from MainActor method") {
await mainActorCallCheck(echo: echo)
}
tests.test("MainActor.assumeIsolated: assume the main executor, from actor on MainActor executor") {
await MainFriend().callCheck(echo: echo)
}
#if !os(WASI)
tests.test("MainActor.assumeIsolated: wrongly assume the main executor, from actor on other executor") {
expectCrashLater(withMessage: "Incorrect actor executor assumption; Expected 'MainActor' executor.")
await SomeoneOnDefaultExecutor().callCheckMainActor(echo: echo)
}
#endif
// === some Actor -------------------------------------------------------
let someone = SomeoneOnDefaultExecutor()
#if !os(WASI)
tests.test("assumeOnActorExecutor: wrongly assume someone's executor, from 'main() async'") {
expectCrashLater(withMessage: "Incorrect actor executor assumption; Expected same executor as a.SomeoneOnDefaultExecutor.")
checkAssumeSomeone(someone: someone)
}
tests.test("assumeOnActorExecutor: wrongly assume someone's executor, from MainActor method") {
expectCrashLater(withMessage: "Incorrect actor executor assumption; Expected same executor as a.SomeoneOnDefaultExecutor.")
checkAssumeSomeone(someone: someone)
}
#endif
tests.test("assumeOnActorExecutor: assume someone's executor, from SomeoneOnDefaultExecutor") {
await someone.callCheckSomeone()
}
tests.test("assumeOnActorExecutor: assume someone's executor, from actor on the SomeoneOnDefaultExecutor.unownedExecutor") {
await SomeonesFriend(someone: someone).callCheckSomeone()
}
#if !os(WASI)
tests.test("assumeOnActorExecutor: wrongly assume the main executor, from actor on other executor") {
expectCrashLater(withMessage: "Incorrect actor executor assumption; Expected same executor as a.SomeoneOnDefaultExecutor.")
await CompleteStranger(someone: someone).callCheckSomeone()
}
#endif
}
await runAllTestsAsync()
}
}