|
| 1 | +// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking -parse-as-library) | %FileCheck %s |
| 2 | + |
| 3 | +// REQUIRES: executable_test |
| 4 | +// REQUIRES: concurrency |
| 5 | +// REQUIRES: distributed |
| 6 | + |
| 7 | +// UNSUPPORTED: OS=windows-msvc |
| 8 | + |
| 9 | +import Distributed |
| 10 | + |
| 11 | +@available(SwiftStdlib 5.5, *) |
| 12 | +distributed actor ParamsDA { |
| 13 | + |
| 14 | + // CHECK: argument.label: Optional("a") |
| 15 | + // CHECK: argument.name: a |
| 16 | + // CHECK: argument.effectiveLabel: a |
| 17 | + distributed func callMe(a: String) {} |
| 18 | + |
| 19 | + // CHECK: argument.label: Optional("b") |
| 20 | + // CHECK: argument.name: c |
| 21 | + // CHECK: argument.effectiveLabel: b |
| 22 | + distributed func callMe(b c: String) {} |
| 23 | + |
| 24 | + // CHECK: argument.label: nil |
| 25 | + // CHECK: argument.name: d |
| 26 | + // CHECK: argument.effectiveLabel: _ |
| 27 | + distributed func callMe(_ d: String) {} |
| 28 | + |
| 29 | + // CHECK: argument.label: nil |
| 30 | + // CHECK: argument.name: p0 |
| 31 | + // CHECK: argument.effectiveLabel: _ |
| 32 | + distributed func callMe2(_: String) {} |
| 33 | +} |
| 34 | + |
| 35 | +@available(SwiftStdlib 5.5, *) |
| 36 | +typealias DefaultDistributedActorSystem = FakeActorSystem |
| 37 | + |
| 38 | +@main struct Main { |
| 39 | + static func main() async { |
| 40 | + let system = FakeActorSystem() |
| 41 | + let pda = try! ParamsDA.resolve(id: .init(parse: "x"), using: system) |
| 42 | + print("--- (a a)") |
| 43 | + try! await pda.callMe(a: "") |
| 44 | + print("--- (b c)") |
| 45 | + try! await pda.callMe(b: "") |
| 46 | + print("--- (_ d)") |
| 47 | + try! await pda.callMe(_: "") |
| 48 | + print("--- (_)") |
| 49 | + try! await pda.callMe2(_: "") |
| 50 | + print("OK") |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | + |
| 55 | +// ==== Fake Transport --------------------------------------------------------- |
| 56 | +struct ActorAddress: Sendable, Hashable, Codable { |
| 57 | + let address: String |
| 58 | + init(parse address: String) { |
| 59 | + self.address = address |
| 60 | + } |
| 61 | +} |
| 62 | + |
| 63 | +struct FakeActorSystem: DistributedActorSystem { |
| 64 | + typealias ActorID = ActorAddress |
| 65 | + typealias InvocationDecoder = FakeInvocationDecoder |
| 66 | + typealias InvocationEncoder = FakeInvocationEncoder |
| 67 | + typealias SerializationRequirement = Codable |
| 68 | + typealias ResultHandler = FakeResultHandler |
| 69 | + |
| 70 | + func resolve<Act>(id: ActorID, as actorType: Act.Type) |
| 71 | + throws -> Act? where Act: DistributedActor { |
| 72 | + return nil |
| 73 | + } |
| 74 | + |
| 75 | + func assignID<Act>(_ actorType: Act.Type) -> ActorID |
| 76 | + where Act: DistributedActor { |
| 77 | + let id = ActorAddress(parse: "xxx") |
| 78 | + return id |
| 79 | + } |
| 80 | + |
| 81 | + func actorReady<Act>(_ actor: Act) |
| 82 | + where Act: DistributedActor, |
| 83 | + Act.ID == ActorID { |
| 84 | + } |
| 85 | + |
| 86 | + func resignID(_ id: ActorID) { |
| 87 | + } |
| 88 | + |
| 89 | + func makeInvocationEncoder() -> InvocationEncoder { |
| 90 | + .init() |
| 91 | + } |
| 92 | + |
| 93 | + func remoteCall<Act, Err, Res>( |
| 94 | + on actor: Act, |
| 95 | + target: RemoteCallTarget, |
| 96 | + invocation invocationEncoder: inout InvocationEncoder, |
| 97 | + throwing: Err.Type, |
| 98 | + returning: Res.Type |
| 99 | + ) async throws -> Res |
| 100 | + where Act: DistributedActor, |
| 101 | + Act.ID == ActorID, |
| 102 | + Err: Error, |
| 103 | + Res: SerializationRequirement { |
| 104 | + fatalError("INVOKED REMOTE CALL") |
| 105 | + } |
| 106 | + |
| 107 | + func remoteCallVoid<Act, Err>( |
| 108 | + on actor: Act, |
| 109 | + target: RemoteCallTarget, |
| 110 | + invocation invocationEncoder: inout InvocationEncoder, |
| 111 | + throwing: Err.Type |
| 112 | + ) async throws |
| 113 | + where Act: DistributedActor, |
| 114 | + Act.ID == ActorID, |
| 115 | + Err: Error { |
| 116 | + return // expected; mock out replying |
| 117 | + } |
| 118 | +} |
| 119 | + |
| 120 | +struct FakeInvocationEncoder: DistributedTargetInvocationEncoder { |
| 121 | + typealias SerializationRequirement = Codable |
| 122 | + |
| 123 | + var substitutions: [Any.Type] = [] |
| 124 | + var arguments: [Any] = [] |
| 125 | + var returnType: Any.Type? = nil |
| 126 | + var errorType: Any.Type? = nil |
| 127 | + |
| 128 | + mutating func recordGenericSubstitution<T>(_ type: T.Type) throws { |
| 129 | + substitutions.append(type) |
| 130 | + } |
| 131 | + mutating func recordArgument<Value: SerializationRequirement>(_ argument: RemoteCallArgument<Value>) throws { |
| 132 | + print("argument.label: \(String(describing: argument.label))") |
| 133 | + print("argument.name: \(argument.name)") |
| 134 | + print("argument.effectiveLabel: \(argument.effectiveLabel)") |
| 135 | + arguments.append(argument.value) |
| 136 | + } |
| 137 | + mutating func recordErrorType<E: Error>(_ type: E.Type) throws { |
| 138 | + self.errorType = type |
| 139 | + } |
| 140 | + mutating func recordReturnType<R: SerializationRequirement>(_ type: R.Type) throws { |
| 141 | + self.returnType = type |
| 142 | + } |
| 143 | + mutating func doneRecording() throws {} |
| 144 | + |
| 145 | + // For testing only |
| 146 | + func makeDecoder() -> FakeInvocationDecoder { |
| 147 | + return .init( |
| 148 | + args: arguments, |
| 149 | + substitutions: substitutions, |
| 150 | + returnType: returnType, |
| 151 | + errorType: errorType |
| 152 | + ) |
| 153 | + } |
| 154 | +} |
| 155 | + |
| 156 | + |
| 157 | +class FakeInvocationDecoder : DistributedTargetInvocationDecoder { |
| 158 | + typealias SerializationRequirement = Codable |
| 159 | + |
| 160 | + var arguments: [Any] = [] |
| 161 | + var substitutions: [Any.Type] = [] |
| 162 | + var returnType: Any.Type? = nil |
| 163 | + var errorType: Any.Type? = nil |
| 164 | + |
| 165 | + init( |
| 166 | + args: [Any], |
| 167 | + substitutions: [Any.Type] = [], |
| 168 | + returnType: Any.Type? = nil, |
| 169 | + errorType: Any.Type? = nil |
| 170 | + ) { |
| 171 | + self.arguments = args |
| 172 | + self.substitutions = substitutions |
| 173 | + self.returnType = returnType |
| 174 | + self.errorType = errorType |
| 175 | + } |
| 176 | + |
| 177 | + // === Receiving / decoding ------------------------------------------------- |
| 178 | + func decodeGenericSubstitutions() throws -> [Any.Type] { |
| 179 | + return substitutions |
| 180 | + } |
| 181 | + |
| 182 | + var argumentIndex: Int = 0 |
| 183 | + func decodeNextArgument<Argument: SerializationRequirement>() throws -> Argument { |
| 184 | + guard argumentIndex < arguments.count else { |
| 185 | + fatalError("Attempted to decode more arguments than stored! Index: \(argumentIndex), args: \(arguments)") |
| 186 | + } |
| 187 | + |
| 188 | + let anyArgument = arguments[argumentIndex] |
| 189 | + guard let argument = anyArgument as? Argument else { |
| 190 | + fatalError("Cannot cast argument\(anyArgument) to expected \(Argument.self)") |
| 191 | + } |
| 192 | + |
| 193 | + if (argumentIndex == 0 && Argument.self == Int???.self) { |
| 194 | + throw ExecuteDistributedTargetError(message: "Failed to decode of Int??? (for a test)") |
| 195 | + } |
| 196 | + |
| 197 | + argumentIndex += 1 |
| 198 | + return argument |
| 199 | + } |
| 200 | + |
| 201 | + func decodeErrorType() throws -> Any.Type? { |
| 202 | + self.errorType |
| 203 | + } |
| 204 | + |
| 205 | + func decodeReturnType() throws -> Any.Type? { |
| 206 | + self.returnType |
| 207 | + } |
| 208 | +} |
| 209 | + |
| 210 | +@available(SwiftStdlib 5.5, *) |
| 211 | +struct FakeResultHandler: DistributedTargetInvocationResultHandler { |
| 212 | + typealias SerializationRequirement = Codable |
| 213 | + |
| 214 | + func onReturn<Success: SerializationRequirement>(value: Success) async throws { |
| 215 | + print("RETURN: \(value)") |
| 216 | + } |
| 217 | + func onReturnVoid() async throws { |
| 218 | + print("RETURN VOID: ()") |
| 219 | + } |
| 220 | + func onThrow<Err: Error>(error: Err) async throws { |
| 221 | + print("ERROR: \(error)") |
| 222 | + } |
| 223 | +} |
| 224 | + |
| 225 | +// ==== ------------------------------------------------------------------------ |
0 commit comments