|
|
|
@ -32,6 +32,7 @@ |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include <memory> |
|
|
|
|
#include <thread> |
|
|
|
|
|
|
|
|
|
#include <grpc++/channel.h> |
|
|
|
|
#include <grpc++/client_context.h> |
|
|
|
@ -104,7 +105,10 @@ class Verifier : public PollingCheckRegion { |
|
|
|
|
expectations_[tag(i)] = expect_ok; |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
void Verify(CompletionQueue* cq) { |
|
|
|
|
|
|
|
|
|
void Verify(CompletionQueue* cq) { Verify(cq, false); } |
|
|
|
|
|
|
|
|
|
void Verify(CompletionQueue* cq, bool ignore_ok) { |
|
|
|
|
GPR_ASSERT(!expectations_.empty()); |
|
|
|
|
while (!expectations_.empty()) { |
|
|
|
|
bool ok; |
|
|
|
@ -122,7 +126,9 @@ class Verifier : public PollingCheckRegion { |
|
|
|
|
} |
|
|
|
|
auto it = expectations_.find(got_tag); |
|
|
|
|
EXPECT_TRUE(it != expectations_.end()); |
|
|
|
|
EXPECT_EQ(it->second, ok); |
|
|
|
|
if (!ignore_ok) { |
|
|
|
|
EXPECT_EQ(it->second, ok); |
|
|
|
|
} |
|
|
|
|
expectations_.erase(it); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -217,7 +223,7 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<bool> { |
|
|
|
|
grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); |
|
|
|
|
|
|
|
|
|
send_request.set_message("Hello"); |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( |
|
|
|
|
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); |
|
|
|
|
|
|
|
|
|
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), |
|
|
|
@ -270,7 +276,7 @@ TEST_P(AsyncEnd2endTest, AsyncNextRpc) { |
|
|
|
|
grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); |
|
|
|
|
|
|
|
|
|
send_request.set_message("Hello"); |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( |
|
|
|
|
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); |
|
|
|
|
|
|
|
|
|
std::chrono::system_clock::time_point time_now( |
|
|
|
@ -315,7 +321,7 @@ TEST_P(AsyncEnd2endTest, SimpleClientStreaming) { |
|
|
|
|
ServerAsyncReader<EchoResponse, EchoRequest> srv_stream(&srv_ctx); |
|
|
|
|
|
|
|
|
|
send_request.set_message("Hello"); |
|
|
|
|
std::unique_ptr<ClientAsyncWriter<EchoRequest> > cli_stream( |
|
|
|
|
std::unique_ptr<ClientAsyncWriter<EchoRequest>> cli_stream( |
|
|
|
|
stub_->AsyncRequestStream(&cli_ctx, &recv_response, cq_.get(), tag(1))); |
|
|
|
|
|
|
|
|
|
service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), |
|
|
|
@ -368,7 +374,7 @@ TEST_P(AsyncEnd2endTest, SimpleServerStreaming) { |
|
|
|
|
ServerAsyncWriter<EchoResponse> srv_stream(&srv_ctx); |
|
|
|
|
|
|
|
|
|
send_request.set_message("Hello"); |
|
|
|
|
std::unique_ptr<ClientAsyncReader<EchoResponse> > cli_stream( |
|
|
|
|
std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream( |
|
|
|
|
stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1))); |
|
|
|
|
|
|
|
|
|
service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, |
|
|
|
@ -418,7 +424,7 @@ TEST_P(AsyncEnd2endTest, SimpleBidiStreaming) { |
|
|
|
|
ServerAsyncReaderWriter<EchoResponse, EchoRequest> srv_stream(&srv_ctx); |
|
|
|
|
|
|
|
|
|
send_request.set_message("Hello"); |
|
|
|
|
std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse> > |
|
|
|
|
std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>> |
|
|
|
|
cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1))); |
|
|
|
|
|
|
|
|
|
service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), |
|
|
|
@ -476,7 +482,7 @@ TEST_P(AsyncEnd2endTest, ClientInitialMetadataRpc) { |
|
|
|
|
cli_ctx.AddMetadata(meta1.first, meta1.second); |
|
|
|
|
cli_ctx.AddMetadata(meta2.first, meta2.second); |
|
|
|
|
|
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( |
|
|
|
|
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); |
|
|
|
|
|
|
|
|
|
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), |
|
|
|
@ -519,7 +525,7 @@ TEST_P(AsyncEnd2endTest, ServerInitialMetadataRpc) { |
|
|
|
|
std::pair<grpc::string, grpc::string> meta1("key1", "val1"); |
|
|
|
|
std::pair<grpc::string, grpc::string> meta2("key2", "val2"); |
|
|
|
|
|
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( |
|
|
|
|
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); |
|
|
|
|
|
|
|
|
|
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), |
|
|
|
@ -568,7 +574,7 @@ TEST_P(AsyncEnd2endTest, ServerTrailingMetadataRpc) { |
|
|
|
|
std::pair<grpc::string, grpc::string> meta1("key1", "val1"); |
|
|
|
|
std::pair<grpc::string, grpc::string> meta2("key2", "val2"); |
|
|
|
|
|
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( |
|
|
|
|
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); |
|
|
|
|
|
|
|
|
|
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), |
|
|
|
@ -629,7 +635,7 @@ TEST_P(AsyncEnd2endTest, MetadataRpc) { |
|
|
|
|
cli_ctx.AddMetadata(meta1.first, meta1.second); |
|
|
|
|
cli_ctx.AddMetadata(meta2.first, meta2.second); |
|
|
|
|
|
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( |
|
|
|
|
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); |
|
|
|
|
|
|
|
|
|
service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), |
|
|
|
@ -690,7 +696,7 @@ TEST_P(AsyncEnd2endTest, ServerCheckCancellation) { |
|
|
|
|
grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); |
|
|
|
|
|
|
|
|
|
send_request.set_message("Hello"); |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( |
|
|
|
|
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); |
|
|
|
|
|
|
|
|
|
srv_ctx.AsyncNotifyWhenDone(tag(5)); |
|
|
|
@ -725,7 +731,7 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) { |
|
|
|
|
grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); |
|
|
|
|
|
|
|
|
|
send_request.set_message("Hello"); |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( |
|
|
|
|
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); |
|
|
|
|
|
|
|
|
|
srv_ctx.AsyncNotifyWhenDone(tag(5)); |
|
|
|
@ -759,7 +765,7 @@ TEST_P(AsyncEnd2endTest, UnimplementedRpc) { |
|
|
|
|
|
|
|
|
|
ClientContext cli_ctx; |
|
|
|
|
send_request.set_message("Hello"); |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( |
|
|
|
|
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( |
|
|
|
|
stub->AsyncUnimplemented(&cli_ctx, send_request, cq_.get())); |
|
|
|
|
|
|
|
|
|
response_reader->Finish(&recv_response, &recv_status, tag(4)); |
|
|
|
@ -769,8 +775,384 @@ TEST_P(AsyncEnd2endTest, UnimplementedRpc) { |
|
|
|
|
EXPECT_EQ("", recv_status.error_message()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This class is for testing scenarios where RPCs are cancelled on the server
|
|
|
|
|
// by calling ServerContext::TryCancel()
|
|
|
|
|
class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { |
|
|
|
|
protected: |
|
|
|
|
typedef enum { |
|
|
|
|
DO_NOT_CANCEL = 0, |
|
|
|
|
CANCEL_BEFORE_PROCESSING, |
|
|
|
|
CANCEL_DURING_PROCESSING, |
|
|
|
|
CANCEL_AFTER_PROCESSING |
|
|
|
|
} ServerTryCancelRequestPhase; |
|
|
|
|
|
|
|
|
|
void ServerTryCancel(ServerContext* context) { |
|
|
|
|
EXPECT_FALSE(context->IsCancelled()); |
|
|
|
|
context->TryCancel(); |
|
|
|
|
gpr_log(GPR_INFO, "Server called TryCancel()"); |
|
|
|
|
EXPECT_TRUE(context->IsCancelled()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Helper for testing client-streaming RPCs which are cancelled on the server.
|
|
|
|
|
// Depending on the value of server_try_cancel parameter, this will test one
|
|
|
|
|
// of the following three scenarios:
|
|
|
|
|
// CANCEL_BEFORE_PROCESSING: Rpc is cancelled by the server before reading
|
|
|
|
|
// any messages from the client
|
|
|
|
|
//
|
|
|
|
|
// CANCEL_DURING_PROCESSING: Rpc is cancelled by the server while reading
|
|
|
|
|
// messages from the client
|
|
|
|
|
//
|
|
|
|
|
// CANCEL_AFTER PROCESSING: Rpc is cancelled by server after reading all
|
|
|
|
|
// messages from the client (but before sending any status back to the
|
|
|
|
|
// client)
|
|
|
|
|
void TestClientStreamingServerCancel( |
|
|
|
|
ServerTryCancelRequestPhase server_try_cancel) { |
|
|
|
|
ResetStub(); |
|
|
|
|
|
|
|
|
|
EchoRequest send_request; |
|
|
|
|
EchoRequest recv_request; |
|
|
|
|
EchoResponse send_response; |
|
|
|
|
EchoResponse recv_response; |
|
|
|
|
Status recv_status; |
|
|
|
|
|
|
|
|
|
ClientContext cli_ctx; |
|
|
|
|
ServerContext srv_ctx; |
|
|
|
|
ServerAsyncReader<EchoResponse, EchoRequest> srv_stream(&srv_ctx); |
|
|
|
|
|
|
|
|
|
// Initiate the 'RequestStream' call on client
|
|
|
|
|
std::unique_ptr<ClientAsyncWriter<EchoRequest>> cli_stream( |
|
|
|
|
stub_->AsyncRequestStream(&cli_ctx, &recv_response, cq_.get(), tag(1))); |
|
|
|
|
Verifier(GetParam()).Expect(1, true).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
// On the server, request to be notified of 'RequestStream' calls
|
|
|
|
|
// and receive the 'RequestStream' call just made by the client
|
|
|
|
|
service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), |
|
|
|
|
tag(2)); |
|
|
|
|
Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
// Client sends 3 messages (tags 3, 4 and 5)
|
|
|
|
|
for (int tag_idx = 3; tag_idx <= 5; tag_idx++) { |
|
|
|
|
send_request.set_message("Ping " + std::to_string(tag_idx)); |
|
|
|
|
cli_stream->Write(send_request, tag(tag_idx)); |
|
|
|
|
Verifier(GetParam()).Expect(tag_idx, true).Verify(cq_.get()); |
|
|
|
|
} |
|
|
|
|
cli_stream->WritesDone(tag(6)); |
|
|
|
|
Verifier(GetParam()).Expect(6, true).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
bool expected_server_cq_result = true; |
|
|
|
|
bool ignore_cq_result = false; |
|
|
|
|
|
|
|
|
|
if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { |
|
|
|
|
ServerTryCancel(&srv_ctx); |
|
|
|
|
|
|
|
|
|
// Since cancellation is done before server reads any results, we know
|
|
|
|
|
// for sure that all cq results will return false from this point forward
|
|
|
|
|
expected_server_cq_result = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::thread* server_try_cancel_thd = NULL; |
|
|
|
|
if (server_try_cancel == CANCEL_DURING_PROCESSING) { |
|
|
|
|
server_try_cancel_thd = new std::thread( |
|
|
|
|
&AsyncEnd2endServerTryCancelTest::ServerTryCancel, this, &srv_ctx); |
|
|
|
|
// Server will cancel the RPC in a parallel thread while reading the
|
|
|
|
|
// requests from the client. Since the cancellation can happen at anytime,
|
|
|
|
|
// some of the cq results (i.e those until cancellation) might be true but
|
|
|
|
|
// its non deterministic. So better to ignore the cq results
|
|
|
|
|
ignore_cq_result = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Server reads 3 messages (tags 6, 7 and 8)
|
|
|
|
|
for (int tag_idx = 6; tag_idx <= 8; tag_idx++) { |
|
|
|
|
srv_stream.Read(&recv_request, tag(tag_idx)); |
|
|
|
|
Verifier(GetParam()) |
|
|
|
|
.Expect(tag_idx, expected_server_cq_result) |
|
|
|
|
.Verify(cq_.get(), ignore_cq_result); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (server_try_cancel_thd != NULL) { |
|
|
|
|
server_try_cancel_thd->join(); |
|
|
|
|
delete server_try_cancel_thd; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (server_try_cancel == CANCEL_AFTER_PROCESSING) { |
|
|
|
|
ServerTryCancel(&srv_ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// The RPC has been cancelled at this point for sure (i.e irrespective of
|
|
|
|
|
// the value of `server_try_cancel` is). So, from this point forward, we
|
|
|
|
|
// know that cq results are supposed to return false on server.
|
|
|
|
|
|
|
|
|
|
// Server sends the final message and cancelled status (but the RPC is
|
|
|
|
|
// already cancelled at this point. So we expect the operation to fail)
|
|
|
|
|
srv_stream.Finish(send_response, Status::CANCELLED, tag(9)); |
|
|
|
|
Verifier(GetParam()).Expect(9, false).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
// Client will see the cancellation
|
|
|
|
|
cli_stream->Finish(&recv_status, tag(10)); |
|
|
|
|
// TODO(sreek): The expectation here should be true. This is a bug (github
|
|
|
|
|
// issue #4972)
|
|
|
|
|
Verifier(GetParam()).Expect(10, false).Verify(cq_.get()); |
|
|
|
|
EXPECT_FALSE(recv_status.ok()); |
|
|
|
|
EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Helper for testing server-streaming RPCs which are cancelled on the server.
|
|
|
|
|
// Depending on the value of server_try_cancel parameter, this will test one
|
|
|
|
|
// of the following three scenarios:
|
|
|
|
|
// CANCEL_BEFORE_PROCESSING: Rpc is cancelled by the server before sending
|
|
|
|
|
// any messages to the client
|
|
|
|
|
//
|
|
|
|
|
// CANCEL_DURING_PROCESSING: Rpc is cancelled by the server while sending
|
|
|
|
|
// messages to the client
|
|
|
|
|
//
|
|
|
|
|
// CANCEL_AFTER PROCESSING: Rpc is cancelled by server after sending all
|
|
|
|
|
// messages to the client (but before sending any status back to the
|
|
|
|
|
// client)
|
|
|
|
|
void TestServerStreamingServerCancel( |
|
|
|
|
ServerTryCancelRequestPhase server_try_cancel) { |
|
|
|
|
ResetStub(); |
|
|
|
|
|
|
|
|
|
EchoRequest send_request; |
|
|
|
|
EchoRequest recv_request; |
|
|
|
|
EchoResponse send_response; |
|
|
|
|
EchoResponse recv_response; |
|
|
|
|
Status recv_status; |
|
|
|
|
ClientContext cli_ctx; |
|
|
|
|
ServerContext srv_ctx; |
|
|
|
|
ServerAsyncWriter<EchoResponse> srv_stream(&srv_ctx); |
|
|
|
|
|
|
|
|
|
send_request.set_message("Ping"); |
|
|
|
|
// Initiate the 'ResponseStream' call on the client
|
|
|
|
|
std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream( |
|
|
|
|
stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1))); |
|
|
|
|
Verifier(GetParam()).Expect(1, true).Verify(cq_.get()); |
|
|
|
|
// On the server, request to be notified of 'ResponseStream' calls and
|
|
|
|
|
// receive the call just made by the client
|
|
|
|
|
service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, |
|
|
|
|
cq_.get(), cq_.get(), tag(2)); |
|
|
|
|
Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); |
|
|
|
|
EXPECT_EQ(send_request.message(), recv_request.message()); |
|
|
|
|
|
|
|
|
|
bool expected_cq_result = true; |
|
|
|
|
bool ignore_cq_result = false; |
|
|
|
|
|
|
|
|
|
if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { |
|
|
|
|
ServerTryCancel(&srv_ctx); |
|
|
|
|
|
|
|
|
|
// We know for sure that all cq results will be false from this point
|
|
|
|
|
// since the server cancelled the RPC
|
|
|
|
|
expected_cq_result = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::thread* server_try_cancel_thd = NULL; |
|
|
|
|
if (server_try_cancel == CANCEL_DURING_PROCESSING) { |
|
|
|
|
server_try_cancel_thd = new std::thread( |
|
|
|
|
&AsyncEnd2endServerTryCancelTest::ServerTryCancel, this, &srv_ctx); |
|
|
|
|
|
|
|
|
|
// Server will cancel the RPC in a parallel thread while writing responses
|
|
|
|
|
// to the client. Since the cancellation can happen at anytime, some of
|
|
|
|
|
// the cq results (i.e those until cancellation) might be true but it is
|
|
|
|
|
// non deterministic. So better to ignore the cq results
|
|
|
|
|
ignore_cq_result = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Server sends three messages (tags 3, 4 and 5)
|
|
|
|
|
for (int tag_idx = 3; tag_idx <= 5; tag_idx++) { |
|
|
|
|
send_response.set_message("Pong " + std::to_string(tag_idx)); |
|
|
|
|
srv_stream.Write(send_response, tag(tag_idx)); |
|
|
|
|
Verifier(GetParam()) |
|
|
|
|
.Expect(tag_idx, expected_cq_result) |
|
|
|
|
.Verify(cq_.get(), ignore_cq_result); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (server_try_cancel_thd != NULL) { |
|
|
|
|
server_try_cancel_thd->join(); |
|
|
|
|
delete server_try_cancel_thd; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (server_try_cancel == CANCEL_AFTER_PROCESSING) { |
|
|
|
|
ServerTryCancel(&srv_ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Client attemts to read the three messages from the server
|
|
|
|
|
for (int tag_idx = 6; tag_idx <= 8; tag_idx++) { |
|
|
|
|
cli_stream->Read(&recv_response, tag(tag_idx)); |
|
|
|
|
Verifier(GetParam()) |
|
|
|
|
.Expect(tag_idx, expected_cq_result) |
|
|
|
|
.Verify(cq_.get(), ignore_cq_result); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// The RPC has been cancelled at this point for sure (i.e irrespective of
|
|
|
|
|
// the value of `server_try_cancel` is). So, from this point forward, we
|
|
|
|
|
// know that cq results are supposed to return false on server.
|
|
|
|
|
|
|
|
|
|
// Server finishes the stream (but the RPC is already cancelled)
|
|
|
|
|
srv_stream.Finish(Status::CANCELLED, tag(9)); |
|
|
|
|
Verifier(GetParam()).Expect(9, false).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
// Client will see the cancellation
|
|
|
|
|
cli_stream->Finish(&recv_status, tag(10)); |
|
|
|
|
Verifier(GetParam()).Expect(10, true).Verify(cq_.get()); |
|
|
|
|
EXPECT_FALSE(recv_status.ok()); |
|
|
|
|
EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Helper for testing bidirectinal-streaming RPCs which are cancelled on the
|
|
|
|
|
// server.
|
|
|
|
|
//
|
|
|
|
|
// Depending on the value of server_try_cancel parameter, this will
|
|
|
|
|
// test one of the following three scenarios:
|
|
|
|
|
// CANCEL_BEFORE_PROCESSING: Rpc is cancelled by the server before reading/
|
|
|
|
|
// writing any messages from/to the client
|
|
|
|
|
//
|
|
|
|
|
// CANCEL_DURING_PROCESSING: Rpc is cancelled by the server while reading
|
|
|
|
|
// messages from the client
|
|
|
|
|
//
|
|
|
|
|
// CANCEL_AFTER PROCESSING: Rpc is cancelled by server after reading all
|
|
|
|
|
// messages from the client (but before sending any status back to the
|
|
|
|
|
// client)
|
|
|
|
|
void TestBidiStreamingServerCancel( |
|
|
|
|
ServerTryCancelRequestPhase server_try_cancel) { |
|
|
|
|
ResetStub(); |
|
|
|
|
|
|
|
|
|
EchoRequest send_request; |
|
|
|
|
EchoRequest recv_request; |
|
|
|
|
EchoResponse send_response; |
|
|
|
|
EchoResponse recv_response; |
|
|
|
|
Status recv_status; |
|
|
|
|
ClientContext cli_ctx; |
|
|
|
|
ServerContext srv_ctx; |
|
|
|
|
ServerAsyncReaderWriter<EchoResponse, EchoRequest> srv_stream(&srv_ctx); |
|
|
|
|
|
|
|
|
|
// Initiate the call from the client side
|
|
|
|
|
std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>> |
|
|
|
|
cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1))); |
|
|
|
|
Verifier(GetParam()).Expect(1, true).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
// On the server, request to be notified of the 'BidiStream' call and
|
|
|
|
|
// receive the call just made by the client
|
|
|
|
|
service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), |
|
|
|
|
tag(2)); |
|
|
|
|
Verifier(GetParam()).Expect(2, true).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
// Client sends the first and the only message
|
|
|
|
|
send_request.set_message("Ping"); |
|
|
|
|
cli_stream->Write(send_request, tag(3)); |
|
|
|
|
Verifier(GetParam()).Expect(3, true).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
bool expected_cq_result = true; |
|
|
|
|
bool ignore_cq_result = false; |
|
|
|
|
|
|
|
|
|
if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { |
|
|
|
|
ServerTryCancel(&srv_ctx); |
|
|
|
|
|
|
|
|
|
// We know for sure that all cq results will be false from this point
|
|
|
|
|
// since the server cancelled the RPC
|
|
|
|
|
expected_cq_result = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::thread* server_try_cancel_thd = NULL; |
|
|
|
|
if (server_try_cancel == CANCEL_DURING_PROCESSING) { |
|
|
|
|
server_try_cancel_thd = new std::thread( |
|
|
|
|
&AsyncEnd2endServerTryCancelTest::ServerTryCancel, this, &srv_ctx); |
|
|
|
|
|
|
|
|
|
// Since server is going to cancel the RPC in a parallel thread, some of
|
|
|
|
|
// the cq results (i.e those until the cancellation) might be true. Since
|
|
|
|
|
// that number is non-deterministic, it is better to ignore the cq results
|
|
|
|
|
ignore_cq_result = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
srv_stream.Read(&recv_request, tag(4)); |
|
|
|
|
Verifier(GetParam()) |
|
|
|
|
.Expect(4, expected_cq_result) |
|
|
|
|
.Verify(cq_.get(), ignore_cq_result); |
|
|
|
|
|
|
|
|
|
send_response.set_message("Pong"); |
|
|
|
|
srv_stream.Write(send_response, tag(5)); |
|
|
|
|
Verifier(GetParam()) |
|
|
|
|
.Expect(5, expected_cq_result) |
|
|
|
|
.Verify(cq_.get(), ignore_cq_result); |
|
|
|
|
|
|
|
|
|
cli_stream->Read(&recv_response, tag(6)); |
|
|
|
|
Verifier(GetParam()) |
|
|
|
|
.Expect(6, expected_cq_result) |
|
|
|
|
.Verify(cq_.get(), ignore_cq_result); |
|
|
|
|
|
|
|
|
|
// This is expected to succeed in all cases
|
|
|
|
|
cli_stream->WritesDone(tag(7)); |
|
|
|
|
Verifier(GetParam()).Expect(7, true).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
// This is expected to fail in all cases i.e for all values of
|
|
|
|
|
// server_try_cancel. This is becasue at this point, either there are no
|
|
|
|
|
// more msgs from the client (because client called WritesDone) or the RPC
|
|
|
|
|
// is cancelled on the server
|
|
|
|
|
srv_stream.Read(&recv_request, tag(8)); |
|
|
|
|
Verifier(GetParam()).Expect(8, false).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
if (server_try_cancel_thd != NULL) { |
|
|
|
|
server_try_cancel_thd->join(); |
|
|
|
|
delete server_try_cancel_thd; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (server_try_cancel == CANCEL_AFTER_PROCESSING) { |
|
|
|
|
ServerTryCancel(&srv_ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// The RPC has been cancelled at this point for sure (i.e irrespective of
|
|
|
|
|
// the value of `server_try_cancel` is). So, from this point forward, we
|
|
|
|
|
// know that cq results are supposed to return false on server.
|
|
|
|
|
|
|
|
|
|
srv_stream.Finish(Status::CANCELLED, tag(9)); |
|
|
|
|
Verifier(GetParam()).Expect(9, false).Verify(cq_.get()); |
|
|
|
|
|
|
|
|
|
cli_stream->Finish(&recv_status, tag(10)); |
|
|
|
|
Verifier(GetParam()).Expect(10, true).Verify(cq_.get()); |
|
|
|
|
EXPECT_FALSE(recv_status.ok()); |
|
|
|
|
EXPECT_EQ(grpc::StatusCode::CANCELLED, recv_status.error_code()); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
TEST_P(AsyncEnd2endServerTryCancelTest, ClientStreamingServerTryCancelBefore) { |
|
|
|
|
TestClientStreamingServerCancel(CANCEL_BEFORE_PROCESSING); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(AsyncEnd2endServerTryCancelTest, ClientStreamingServerTryCancelDuring) { |
|
|
|
|
TestClientStreamingServerCancel(CANCEL_DURING_PROCESSING); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(AsyncEnd2endServerTryCancelTest, ClientStreamingServerTryCancelAfter) { |
|
|
|
|
TestClientStreamingServerCancel(CANCEL_AFTER_PROCESSING); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(AsyncEnd2endServerTryCancelTest, ServerStreamingServerTryCancelBefore) { |
|
|
|
|
TestServerStreamingServerCancel(CANCEL_BEFORE_PROCESSING); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(AsyncEnd2endServerTryCancelTest, ServerStreamingServerTryCancelDuring) { |
|
|
|
|
TestServerStreamingServerCancel(CANCEL_DURING_PROCESSING); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(AsyncEnd2endServerTryCancelTest, ServerStreamingServerTryCancelAfter) { |
|
|
|
|
TestServerStreamingServerCancel(CANCEL_AFTER_PROCESSING); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(AsyncEnd2endServerTryCancelTest, ServerBidiStreamingTryCancelBefore) { |
|
|
|
|
TestBidiStreamingServerCancel(CANCEL_BEFORE_PROCESSING); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(AsyncEnd2endServerTryCancelTest, ServerBidiStreamingTryCancelDuring) { |
|
|
|
|
TestBidiStreamingServerCancel(CANCEL_DURING_PROCESSING); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(AsyncEnd2endServerTryCancelTest, ServerBidiStreamingTryCancelAfter) { |
|
|
|
|
TestBidiStreamingServerCancel(CANCEL_AFTER_PROCESSING); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
INSTANTIATE_TEST_CASE_P(AsyncEnd2end, AsyncEnd2endTest, |
|
|
|
|
::testing::Values(false, true)); |
|
|
|
|
INSTANTIATE_TEST_CASE_P(AsyncEnd2endServerTryCancel, |
|
|
|
|
AsyncEnd2endServerTryCancelTest, |
|
|
|
|
::testing::Values(false)); |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
} // namespace testing
|
|
|
|
|