diff --git a/.swiftlint.yml b/.swiftlint.yml index 35f12269..df94ebbd 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -75,7 +75,6 @@ opt_in_rules: - toggle_bool - unavailable_function - unneeded_parentheses_in_closure_argument - - unowned_variable_capture - vertical_parameter_alignment_on_call - vertical_whitespace_closing_braces - vertical_whitespace_opening_braces diff --git a/Makefile b/Makefile index 15af50e2..f2f4eabd 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ MAKEFLAGS += --no-builtin-rules MAKEFLAGS += --no-print-directory BIN := .tmp/bin LICENSE_HEADER_YEAR_RANGE := 2022-2024 -CONFORMANCE_PROTO_REF := 33aff469e6358823e925f2ef3f915b9b809e8124 -CONFORMANCE_RUNNER_TAG := v1.0.1 +CONFORMANCE_PROTO_REF := dfa2dd3e064de6ce56423c569804475e190b4445 +CONFORMANCE_RUNNER_TAG := v1.0.3 EXAMPLES_PROTO_REF := e74547031f662f81a62f5e95ebaa9f7037e0c41b LICENSE_HEADER_VERSION := v1.35.1 LICENSE_IGNORE := -e Package.swift \ diff --git a/Tests/ConformanceClient/GeneratedSources/connectrpc/conformance/v1/client_compat.pb.swift b/Tests/ConformanceClient/GeneratedSources/connectrpc/conformance/v1/client_compat.pb.swift index af37245c..dc36c745 100644 --- a/Tests/ConformanceClient/GeneratedSources/connectrpc/conformance/v1/client_compat.pb.swift +++ b/Tests/ConformanceClient/GeneratedSources/connectrpc/conformance/v1/client_compat.pb.swift @@ -143,7 +143,8 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest: @unchecked Sendable { /// Clears the value of `method`. Subsequent reads from it will return its default value. mutating func clearMethod() {_uniqueStorage()._method = nil} - /// The stream type of `method` (i.e. Unary, Client-Streaming, Server-Streaming, Full Duplex Bidi, or Half Duplex Bidi). + /// The stream type of `method` (i.e. unary, client stream, server stream, full-duplex bidi + /// stream, or half-duplex bidi stream). /// When writing test cases, this is a required field. var streamType: Connectrpc_Conformance_V1_StreamType { get {return _storage._streamType} @@ -170,9 +171,9 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest: @unchecked Sendable { /// The actual request messages that will sent to the server. /// The type URL for all entries should be equal to the request type of the /// method. - /// There must be exactly one for unary and server-stream methods but - /// can be zero or more for client- and bidi-stream methods. - /// For client- and bidi-stream methods, all entries will have the + /// There must be exactly one for unary and server stream methods but + /// can be zero or more for client and bidi stream methods. + /// For client and bidi stream methods, all entries will have the /// same type URL. var requestMessages: [SwiftProtobuf.Google_Protobuf_Any] { get {return _storage._requestMessages} @@ -191,7 +192,7 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest: @unchecked Sendable { mutating func clearTimeoutMs() {_uniqueStorage()._timeoutMs = nil} /// Wait this many milliseconds before sending a request message. - /// For client- or bidi-streaming requests, this delay should be + /// For client or bidi stream methods, this delay should be /// applied before each request sent. var requestDelayMs: UInt32 { get {return _storage._requestDelayMs} @@ -243,8 +244,9 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest: @unchecked Sendable { /// When present, the client should cancel *instead of* /// closing the send side of the stream, after all requests - /// have been sent. This applies only to client and bidi - /// stream RPCs. + /// have been sent. + /// + /// This applies only to client and bidi stream RPCs. var beforeCloseSend: SwiftProtobuf.Google_Protobuf_Empty { get { if case .beforeCloseSend(let v)? = cancelTiming {return v} @@ -256,6 +258,20 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest: @unchecked Sendable { /// When present, the client should delay for this many /// milliseconds after closing the send side of the stream /// and then cancel. + /// + /// This applies to all types of RPCs. + /// + /// For unary and server stream RPCs, where the API usually + /// does not allow explicitly closing the send side, the + /// cancellation should be done immediately after invoking + /// the RPC (which should implicitly send the one-and-only + /// request and then close the send-side). + /// + /// For APIs where unary RPCs block until the response + /// is received, there is no point after the request is + /// sent but before a response is received to cancel. So + /// the client must arrange for the RPC to be canceled + /// asynchronously before invoking the blocking unary call. var afterCloseSendMs: UInt32 { get { if case .afterCloseSendMs(let v)? = cancelTiming {return v} @@ -266,6 +282,8 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest: @unchecked Sendable { /// When present, the client should cancel right after /// reading this number of response messages from the stream. + /// When present, this will be greater than zero. + /// /// This applies only to server and bidi stream RPCs. var afterNumResponses: UInt32 { get { @@ -285,15 +303,32 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest: @unchecked Sendable { enum OneOf_CancelTiming: Equatable, Sendable { /// When present, the client should cancel *instead of* /// closing the send side of the stream, after all requests - /// have been sent. This applies only to client and bidi - /// stream RPCs. + /// have been sent. + /// + /// This applies only to client and bidi stream RPCs. case beforeCloseSend(SwiftProtobuf.Google_Protobuf_Empty) /// When present, the client should delay for this many /// milliseconds after closing the send side of the stream /// and then cancel. + /// + /// This applies to all types of RPCs. + /// + /// For unary and server stream RPCs, where the API usually + /// does not allow explicitly closing the send side, the + /// cancellation should be done immediately after invoking + /// the RPC (which should implicitly send the one-and-only + /// request and then close the send-side). + /// + /// For APIs where unary RPCs block until the response + /// is received, there is no point after the request is + /// sent but before a response is received to cancel. So + /// the client must arrange for the RPC to be canceled + /// asynchronously before invoking the blocking unary call. case afterCloseSendMs(UInt32) /// When present, the client should cancel right after /// reading this number of response messages from the stream. + /// When present, this will be greater than zero. + /// /// This applies only to server and bidi stream RPCs. case afterNumResponses(UInt32) @@ -375,8 +410,8 @@ struct Connectrpc_Conformance_V1_ClientResponseResult: Sendable { /// Servers should echo back payloads that they received as part of the request. /// This field should contain all the payloads the server echoed back. Note that - /// There will be zero-to-one for unary and client-stream methods and - /// zero-to-many for server- and bidi-stream methods. + /// There will be zero-to-one for unary and client stream methods and + /// zero-to-many for server and bidi stream methods. var payloads: [Connectrpc_Conformance_V1_ConformancePayload] = [] /// The error received from the actual RPC invocation. Note this is not representative diff --git a/Tests/ConformanceClient/GeneratedSources/connectrpc/conformance/v1/config.pb.swift b/Tests/ConformanceClient/GeneratedSources/connectrpc/conformance/v1/config.pb.swift index 3c8ed484..11b33913 100644 --- a/Tests/ConformanceClient/GeneratedSources/connectrpc/conformance/v1/config.pb.swift +++ b/Tests/ConformanceClient/GeneratedSources/connectrpc/conformance/v1/config.pb.swift @@ -127,6 +127,10 @@ enum Connectrpc_Conformance_V1_Codec: SwiftProtobuf.Enum, Swift.CaseIterable { case unspecified // = 0 case proto // = 1 case json // = 2 + + /// not used; will be ignored + /// + /// NOTE: This enum value was marked as deprecated in the .proto file case text // = 3 case UNRECOGNIZED(Int) diff --git a/Tests/ConformanceClient/Sources/ConformanceInvoker.swift b/Tests/ConformanceClient/Sources/ConformanceInvoker.swift index 6cbd921a..9c7a1bc0 100644 --- a/Tests/ConformanceClient/Sources/ConformanceInvoker.swift +++ b/Tests/ConformanceClient/Sources/ConformanceInvoker.swift @@ -155,10 +155,25 @@ final class ConformanceInvoker { let unaryRequest = try Connectrpc_Conformance_V1_UnaryRequest( unpackingAny: self.context.requestMessages[0] ) - let response = await self.client.unary( - request: unaryRequest, - headers: .fromConformanceHeaders(self.context.requestHeaders) - ) + let task = Task { [unowned self] in + return await self.client.unary( + request: unaryRequest, + headers: .fromConformanceHeaders(self.context.requestHeaders) + ) + } + + switch self.context.cancel.cancelTiming { + case .beforeCloseSend: + task.cancel() + case .afterCloseSendMs(let milliseconds): + DispatchQueue.global().asyncAfter(deadline: .now() + .milliseconds(Int(milliseconds))) { + task.cancel() + } + case .afterNumResponses, .none: + break + } + + let response = await task.value return .with { responseResult in responseResult.responseHeaders = response.headers.toConformanceHeaders() responseResult.responseTrailers = response.trailers.toConformanceHeaders() @@ -174,10 +189,25 @@ final class ConformanceInvoker { let unaryRequest = try Connectrpc_Conformance_V1_IdempotentUnaryRequest( unpackingAny: self.context.requestMessages[0] ) - let response = await self.client.idempotentUnary( - request: unaryRequest, - headers: .fromConformanceHeaders(self.context.requestHeaders) - ) + let task = Task { [unowned self] in + return await self.client.idempotentUnary( + request: unaryRequest, + headers: .fromConformanceHeaders(self.context.requestHeaders) + ) + } + + switch self.context.cancel.cancelTiming { + case .beforeCloseSend: + task.cancel() + case .afterCloseSendMs(let milliseconds): + DispatchQueue.global().asyncAfter(deadline: .now() + .milliseconds(Int(milliseconds))) { + task.cancel() + } + case .afterNumResponses, .none: + break + } + + let response = await task.value return .with { responseResult in responseResult.responseHeaders = response.headers.toConformanceHeaders() responseResult.responseTrailers = response.trailers.toConformanceHeaders() diff --git a/Tests/UnitTests/ConnectLibraryTests/GeneratedSources/connectrpc/conformance/v1/client_compat.pb.swift b/Tests/UnitTests/ConnectLibraryTests/GeneratedSources/connectrpc/conformance/v1/client_compat.pb.swift index 14888b4f..d6cdf89d 100644 --- a/Tests/UnitTests/ConnectLibraryTests/GeneratedSources/connectrpc/conformance/v1/client_compat.pb.swift +++ b/Tests/UnitTests/ConnectLibraryTests/GeneratedSources/connectrpc/conformance/v1/client_compat.pb.swift @@ -143,7 +143,8 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest { /// Clears the value of `method`. Subsequent reads from it will return its default value. mutating func clearMethod() {_uniqueStorage()._method = nil} - /// The stream type of `method` (i.e. Unary, Client-Streaming, Server-Streaming, Full Duplex Bidi, or Half Duplex Bidi). + /// The stream type of `method` (i.e. unary, client stream, server stream, full-duplex bidi + /// stream, or half-duplex bidi stream). /// When writing test cases, this is a required field. var streamType: Connectrpc_Conformance_V1_StreamType { get {return _storage._streamType} @@ -170,9 +171,9 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest { /// The actual request messages that will sent to the server. /// The type URL for all entries should be equal to the request type of the /// method. - /// There must be exactly one for unary and server-stream methods but - /// can be zero or more for client- and bidi-stream methods. - /// For client- and bidi-stream methods, all entries will have the + /// There must be exactly one for unary and server stream methods but + /// can be zero or more for client and bidi stream methods. + /// For client and bidi stream methods, all entries will have the /// same type URL. var requestMessages: [SwiftProtobuf.Google_Protobuf_Any] { get {return _storage._requestMessages} @@ -191,7 +192,7 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest { mutating func clearTimeoutMs() {_uniqueStorage()._timeoutMs = nil} /// Wait this many milliseconds before sending a request message. - /// For client- or bidi-streaming requests, this delay should be + /// For client or bidi stream methods, this delay should be /// applied before each request sent. var requestDelayMs: UInt32 { get {return _storage._requestDelayMs} @@ -243,8 +244,9 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest { /// When present, the client should cancel *instead of* /// closing the send side of the stream, after all requests - /// have been sent. This applies only to client and bidi - /// stream RPCs. + /// have been sent. + /// + /// This applies only to client and bidi stream RPCs. var beforeCloseSend: SwiftProtobuf.Google_Protobuf_Empty { get { if case .beforeCloseSend(let v)? = cancelTiming {return v} @@ -256,6 +258,20 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest { /// When present, the client should delay for this many /// milliseconds after closing the send side of the stream /// and then cancel. + /// + /// This applies to all types of RPCs. + /// + /// For unary and server stream RPCs, where the API usually + /// does not allow explicitly closing the send side, the + /// cancellation should be done immediately after invoking + /// the RPC (which should implicitly send the one-and-only + /// request and then close the send-side). + /// + /// For APIs where unary RPCs block until the response + /// is received, there is no point after the request is + /// sent but before a response is received to cancel. So + /// the client must arrange for the RPC to be canceled + /// asynchronously before invoking the blocking unary call. var afterCloseSendMs: UInt32 { get { if case .afterCloseSendMs(let v)? = cancelTiming {return v} @@ -266,6 +282,8 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest { /// When present, the client should cancel right after /// reading this number of response messages from the stream. + /// When present, this will be greater than zero. + /// /// This applies only to server and bidi stream RPCs. var afterNumResponses: UInt32 { get { @@ -285,15 +303,32 @@ struct Connectrpc_Conformance_V1_ClientCompatRequest { enum OneOf_CancelTiming: Equatable { /// When present, the client should cancel *instead of* /// closing the send side of the stream, after all requests - /// have been sent. This applies only to client and bidi - /// stream RPCs. + /// have been sent. + /// + /// This applies only to client and bidi stream RPCs. case beforeCloseSend(SwiftProtobuf.Google_Protobuf_Empty) /// When present, the client should delay for this many /// milliseconds after closing the send side of the stream /// and then cancel. + /// + /// This applies to all types of RPCs. + /// + /// For unary and server stream RPCs, where the API usually + /// does not allow explicitly closing the send side, the + /// cancellation should be done immediately after invoking + /// the RPC (which should implicitly send the one-and-only + /// request and then close the send-side). + /// + /// For APIs where unary RPCs block until the response + /// is received, there is no point after the request is + /// sent but before a response is received to cancel. So + /// the client must arrange for the RPC to be canceled + /// asynchronously before invoking the blocking unary call. case afterCloseSendMs(UInt32) /// When present, the client should cancel right after /// reading this number of response messages from the stream. + /// When present, this will be greater than zero. + /// /// This applies only to server and bidi stream RPCs. case afterNumResponses(UInt32) @@ -415,8 +450,8 @@ struct Connectrpc_Conformance_V1_ClientResponseResult { /// Servers should echo back payloads that they received as part of the request. /// This field should contain all the payloads the server echoed back. Note that - /// There will be zero-to-one for unary and client-stream methods and - /// zero-to-many for server- and bidi-stream methods. + /// There will be zero-to-one for unary and client stream methods and + /// zero-to-many for server and bidi stream methods. var payloads: [Connectrpc_Conformance_V1_ConformancePayload] = [] /// The error received from the actual RPC invocation. Note this is not representative diff --git a/Tests/UnitTests/ConnectLibraryTests/GeneratedSources/connectrpc/conformance/v1/config.pb.swift b/Tests/UnitTests/ConnectLibraryTests/GeneratedSources/connectrpc/conformance/v1/config.pb.swift index e23ae23c..9b0f58b5 100644 --- a/Tests/UnitTests/ConnectLibraryTests/GeneratedSources/connectrpc/conformance/v1/config.pb.swift +++ b/Tests/UnitTests/ConnectLibraryTests/GeneratedSources/connectrpc/conformance/v1/config.pb.swift @@ -139,6 +139,8 @@ enum Connectrpc_Conformance_V1_Codec: SwiftProtobuf.Enum { case unspecified // = 0 case proto // = 1 case json // = 2 + + /// not used; will be ignored case text // = 3 case UNRECOGNIZED(Int)