-
Notifications
You must be signed in to change notification settings - Fork 420
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Delay creating event observers for client streaming calls
Motivation: Providers for client and bidirectional streaming calls require the user provide a future stream-event handler to handle requests from the client. However, these methods get called as the pipeline handling an incoming call is being configured, as these methods also expose promises for response (for client streaming) and call status (for bidirectional streaming) it is possible for these to be fulfilled before the pipeline has been configured. Since no handler is in place to deal with the promised types the server will fatal error as the first handler in place will fail to unwrap the promised type. Modifications: Delay the creation of event observers for client and bidirectional streaming calls until their handlers have been added to the pipeline. Result: Client streaming and bidirectional streaming calls can fulfill their response and status promises outside of their stream handlers.
- Loading branch information
Showing
4 changed files
with
137 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* Copyright 2019, gRPC Authors All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
import Foundation | ||
import GRPC | ||
import NIO | ||
import XCTest | ||
|
||
class ImmediatelyFailingEchoProvider: Echo_EchoProvider { | ||
static let status: GRPCStatus = .init(code: .unavailable, message: nil) | ||
|
||
func get( | ||
request: Echo_EchoRequest, | ||
context: StatusOnlyCallContext | ||
) -> EventLoopFuture<Echo_EchoResponse> { | ||
return context.eventLoop.makeFailedFuture(ImmediatelyFailingEchoProvider.status) | ||
} | ||
|
||
func expand( | ||
request: Echo_EchoRequest, | ||
context: StreamingResponseCallContext<Echo_EchoResponse> | ||
) -> EventLoopFuture<GRPCStatus> { | ||
return context.eventLoop.makeFailedFuture(ImmediatelyFailingEchoProvider.status) | ||
} | ||
|
||
func collect( | ||
context: UnaryResponseCallContext<Echo_EchoResponse> | ||
) -> EventLoopFuture<(StreamEvent<Echo_EchoRequest>) -> Void> { | ||
context.responsePromise.fail(ImmediatelyFailingEchoProvider.status) | ||
return context.eventLoop.makeSucceededFuture({ _ in | ||
// no-op | ||
}) | ||
} | ||
|
||
func update( | ||
context: StreamingResponseCallContext<Echo_EchoResponse> | ||
) -> EventLoopFuture<(StreamEvent<Echo_EchoRequest>) -> Void> { | ||
context.statusPromise.fail(ImmediatelyFailingEchoProvider.status) | ||
return context.eventLoop.makeSucceededFuture({ _ in | ||
// no-op | ||
}) | ||
} | ||
} | ||
|
||
class ImmediatelyFailingProviderTests: EchoTestCaseBase { | ||
override func makeEchoProvider() -> Echo_EchoProvider { | ||
return ImmediatelyFailingEchoProvider() | ||
} | ||
|
||
func testUnary() throws { | ||
let expcectation = self.makeStatusExpectation() | ||
let call = self.client.get(Echo_EchoRequest(text: "foo")) | ||
call.status.map { $0.code }.assertEqual(.unavailable, fulfill: expcectation) | ||
|
||
self.wait(for: [expcectation], timeout: self.defaultTestTimeout) | ||
} | ||
|
||
func testServerStreaming() throws { | ||
let expcectation = self.makeStatusExpectation() | ||
let call = self.client.expand(Echo_EchoRequest(text: "foo")) { response in | ||
XCTFail("unexpected response: \(response)") | ||
} | ||
|
||
call.status.map { $0.code }.assertEqual(.unavailable, fulfill: expcectation) | ||
self.wait(for: [expcectation], timeout: self.defaultTestTimeout) | ||
} | ||
|
||
func testClientStreaming() throws { | ||
let expcectation = self.makeStatusExpectation() | ||
let call = self.client.collect() | ||
|
||
call.status.map { $0.code }.assertEqual(.unavailable, fulfill: expcectation) | ||
self.wait(for: [expcectation], timeout: self.defaultTestTimeout) | ||
} | ||
|
||
func testBidirectionalStreaming() throws { | ||
let expcectation = self.makeStatusExpectation() | ||
let call = self.client.update { response in | ||
XCTFail("unexpected response: \(response)") | ||
} | ||
|
||
call.status.map { $0.code }.assertEqual(.unavailable, fulfill: expcectation) | ||
self.wait(for: [expcectation], timeout: self.defaultTestTimeout) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters