diff options
author | dvshkurko <dvshkurko@yandex-team.ru> | 2022-02-10 16:45:52 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:52 +0300 |
commit | c768a99151e47c3a4bb7b92c514d256abd301c4d (patch) | |
tree | 1a2c5ffcf89eb53ecd79dbc9bc0a195c27404d0c /contrib/libs/grpc/test/cpp | |
parent | 321ee9bce31ec6e238be26dbcbe539cffa2c3309 (diff) | |
download | ydb-c768a99151e47c3a4bb7b92c514d256abd301c4d.tar.gz |
Restoring authorship annotation for <dvshkurko@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/grpc/test/cpp')
55 files changed, 18547 insertions, 18547 deletions
diff --git a/contrib/libs/grpc/test/cpp/README-iOS.md b/contrib/libs/grpc/test/cpp/README-iOS.md index faef8aaf5f..898931085b 100644 --- a/contrib/libs/grpc/test/cpp/README-iOS.md +++ b/contrib/libs/grpc/test/cpp/README-iOS.md @@ -1,52 +1,52 @@ -## C++ tests on iOS - -[GTMGoogleTestRunner](https://github.com/google/google-toolbox-for-mac/blob/master/UnitTesting/GTMGoogleTestRunner.mm) is used to convert googletest cases to XCTest that can be run on iOS. GTMGoogleTestRunner doesn't execute the `main` function, so we can't have any test logic in `main`. -However, it's ok to call `::testing::InitGoogleTest` in `main`, as `GTMGoogleTestRunner` [calls InitGoogleTest](https://github.com/google/google-toolbox-for-mac/blob/master/UnitTesting/GTMGoogleTestRunner.mm#L151). -`grpc::testing::TestEnvironment` can also be called from `main`, as it does some test initialization (install crash handler, seed RNG) that's not strictly required to run testcases on iOS. - - -## Porting exising C++ tests to run on iOS - -Please follow these guidelines when porting tests to run on iOS: - -- Tests need to use the googletest framework -- Any setup/teardown code in `main` needs to be moved to `SetUpTestCase`/`TearDownTestCase`, and `TEST` needs to be changed to `TEST_F`. -- [Death tests](https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#death-tests) are not supported on iOS, so use the `*_IF_SUPPORTED()` macros to ensure that your code compiles on iOS. - -For example, the following test -```c++ -TEST(MyTest, TestOne) { - ASSERT_DEATH(ThisShouldDie(), ""); -} - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - grpc_init(); - return RUN_ALL_TESTS(); - grpc_shutdown(); -} -``` - -should be changed to -```c++ -class MyTest : public ::testing::Test { - protected: - static void SetUpTestCase() { grpc_init(); } - static void TearDownTestCase() { grpc_shutdown(); } -}; - -TEST_F(MyTest, TestOne) { - ASSERT_DEATH_IF_SUPPORTED(ThisShouldDie(), ""); -} - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} -``` - -## Limitations - -Due to a [limitation](https://github.com/google/google-toolbox-for-mac/blob/master/UnitTesting/GTMGoogleTestRunner.mm#L48-L56) in GTMGoogleTestRunner, `SetUpTestCase`/`TeardownTestCase` will be called before/after *every* individual test case, similar to `SetUp`/`TearDown`. +## C++ tests on iOS + +[GTMGoogleTestRunner](https://github.com/google/google-toolbox-for-mac/blob/master/UnitTesting/GTMGoogleTestRunner.mm) is used to convert googletest cases to XCTest that can be run on iOS. GTMGoogleTestRunner doesn't execute the `main` function, so we can't have any test logic in `main`. +However, it's ok to call `::testing::InitGoogleTest` in `main`, as `GTMGoogleTestRunner` [calls InitGoogleTest](https://github.com/google/google-toolbox-for-mac/blob/master/UnitTesting/GTMGoogleTestRunner.mm#L151). +`grpc::testing::TestEnvironment` can also be called from `main`, as it does some test initialization (install crash handler, seed RNG) that's not strictly required to run testcases on iOS. + + +## Porting exising C++ tests to run on iOS + +Please follow these guidelines when porting tests to run on iOS: + +- Tests need to use the googletest framework +- Any setup/teardown code in `main` needs to be moved to `SetUpTestCase`/`TearDownTestCase`, and `TEST` needs to be changed to `TEST_F`. +- [Death tests](https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#death-tests) are not supported on iOS, so use the `*_IF_SUPPORTED()` macros to ensure that your code compiles on iOS. + +For example, the following test +```c++ +TEST(MyTest, TestOne) { + ASSERT_DEATH(ThisShouldDie(), ""); +} + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + grpc_init(); + return RUN_ALL_TESTS(); + grpc_shutdown(); +} +``` + +should be changed to +```c++ +class MyTest : public ::testing::Test { + protected: + static void SetUpTestCase() { grpc_init(); } + static void TearDownTestCase() { grpc_shutdown(); } +}; + +TEST_F(MyTest, TestOne) { + ASSERT_DEATH_IF_SUPPORTED(ThisShouldDie(), ""); +} + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} +``` + +## Limitations + +Due to a [limitation](https://github.com/google/google-toolbox-for-mac/blob/master/UnitTesting/GTMGoogleTestRunner.mm#L48-L56) in GTMGoogleTestRunner, `SetUpTestCase`/`TeardownTestCase` will be called before/after *every* individual test case, similar to `SetUp`/`TearDown`. diff --git a/contrib/libs/grpc/test/cpp/end2end/async_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/async_end2end_test.cc index 85d8db87dc..45df8718f9 100644 --- a/contrib/libs/grpc/test/cpp/end2end/async_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/async_end2end_test.cc @@ -1,360 +1,360 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <cinttypes> -#include <memory> -#include <thread> - -#include <grpc/grpc.h> -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/ext/health_check_service_server_builder_option.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/core/ext/filters/client_channel/backup_poller.h" -#include "src/core/lib/gpr/tls.h" -#include "src/core/lib/iomgr/port.h" -#include "src/proto/grpc/health/v1/health.grpc.pb.h" -#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/util/string_ref_helper.h" -#include "test/cpp/util/test_credentials_provider.h" - -#ifdef GRPC_POSIX_SOCKET_EV -#include "src/core/lib/iomgr/ev_posix.h" -#endif // GRPC_POSIX_SOCKET_EV - -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; -using grpc::testing::kTlsCredentialsType; -using std::chrono::system_clock; - -namespace grpc { -namespace testing { - -namespace { - -void* tag(int i) { return (void*)static_cast<intptr_t>(i); } -int detag(void* p) { return static_cast<int>(reinterpret_cast<intptr_t>(p)); } - -class Verifier { - public: - Verifier() : lambda_run_(false) {} - // Expect sets the expected ok value for a specific tag - Verifier& Expect(int i, bool expect_ok) { - return ExpectUnless(i, expect_ok, false); - } - // ExpectUnless sets the expected ok value for a specific tag - // unless the tag was already marked seen (as a result of ExpectMaybe) - Verifier& ExpectUnless(int i, bool expect_ok, bool seen) { - if (!seen) { - expectations_[tag(i)] = expect_ok; - } - return *this; - } - // ExpectMaybe sets the expected ok value for a specific tag, but does not - // require it to appear - // If it does, sets *seen to true - Verifier& ExpectMaybe(int i, bool expect_ok, bool* seen) { - if (!*seen) { - maybe_expectations_[tag(i)] = MaybeExpect{expect_ok, seen}; - } - return *this; - } - - // Next waits for 1 async tag to complete, checks its - // expectations, and returns the tag - int Next(CompletionQueue* cq, bool ignore_ok) { - bool ok; - void* got_tag; - EXPECT_TRUE(cq->Next(&got_tag, &ok)); - GotTag(got_tag, ok, ignore_ok); - return detag(got_tag); - } - - template <typename T> - CompletionQueue::NextStatus DoOnceThenAsyncNext( - CompletionQueue* cq, void** got_tag, bool* ok, T deadline, - std::function<void(void)> lambda) { - if (lambda_run_) { - return cq->AsyncNext(got_tag, ok, deadline); - } else { - lambda_run_ = true; - return cq->DoThenAsyncNext(lambda, got_tag, ok, deadline); - } - } - - // Verify keeps calling Next until all currently set - // expected tags are complete - void Verify(CompletionQueue* cq) { Verify(cq, false); } - - // This version of Verify allows optionally ignoring the - // outcome of the expectation - void Verify(CompletionQueue* cq, bool ignore_ok) { - GPR_ASSERT(!expectations_.empty() || !maybe_expectations_.empty()); - while (!expectations_.empty()) { - Next(cq, ignore_ok); - } +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <cinttypes> +#include <memory> +#include <thread> + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/ext/health_check_service_server_builder_option.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/core/ext/filters/client_channel/backup_poller.h" +#include "src/core/lib/gpr/tls.h" +#include "src/core/lib/iomgr/port.h" +#include "src/proto/grpc/health/v1/health.grpc.pb.h" +#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/util/string_ref_helper.h" +#include "test/cpp/util/test_credentials_provider.h" + +#ifdef GRPC_POSIX_SOCKET_EV +#include "src/core/lib/iomgr/ev_posix.h" +#endif // GRPC_POSIX_SOCKET_EV + +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; +using grpc::testing::kTlsCredentialsType; +using std::chrono::system_clock; + +namespace grpc { +namespace testing { + +namespace { + +void* tag(int i) { return (void*)static_cast<intptr_t>(i); } +int detag(void* p) { return static_cast<int>(reinterpret_cast<intptr_t>(p)); } + +class Verifier { + public: + Verifier() : lambda_run_(false) {} + // Expect sets the expected ok value for a specific tag + Verifier& Expect(int i, bool expect_ok) { + return ExpectUnless(i, expect_ok, false); + } + // ExpectUnless sets the expected ok value for a specific tag + // unless the tag was already marked seen (as a result of ExpectMaybe) + Verifier& ExpectUnless(int i, bool expect_ok, bool seen) { + if (!seen) { + expectations_[tag(i)] = expect_ok; + } + return *this; + } + // ExpectMaybe sets the expected ok value for a specific tag, but does not + // require it to appear + // If it does, sets *seen to true + Verifier& ExpectMaybe(int i, bool expect_ok, bool* seen) { + if (!*seen) { + maybe_expectations_[tag(i)] = MaybeExpect{expect_ok, seen}; + } + return *this; + } + + // Next waits for 1 async tag to complete, checks its + // expectations, and returns the tag + int Next(CompletionQueue* cq, bool ignore_ok) { + bool ok; + void* got_tag; + EXPECT_TRUE(cq->Next(&got_tag, &ok)); + GotTag(got_tag, ok, ignore_ok); + return detag(got_tag); + } + + template <typename T> + CompletionQueue::NextStatus DoOnceThenAsyncNext( + CompletionQueue* cq, void** got_tag, bool* ok, T deadline, + std::function<void(void)> lambda) { + if (lambda_run_) { + return cq->AsyncNext(got_tag, ok, deadline); + } else { + lambda_run_ = true; + return cq->DoThenAsyncNext(lambda, got_tag, ok, deadline); + } + } + + // Verify keeps calling Next until all currently set + // expected tags are complete + void Verify(CompletionQueue* cq) { Verify(cq, false); } + + // This version of Verify allows optionally ignoring the + // outcome of the expectation + void Verify(CompletionQueue* cq, bool ignore_ok) { + GPR_ASSERT(!expectations_.empty() || !maybe_expectations_.empty()); + while (!expectations_.empty()) { + Next(cq, ignore_ok); + } maybe_expectations_.clear(); - } - - // This version of Verify stops after a certain deadline - void Verify(CompletionQueue* cq, - std::chrono::system_clock::time_point deadline) { - if (expectations_.empty()) { - bool ok; - void* got_tag; - EXPECT_EQ(cq->AsyncNext(&got_tag, &ok, deadline), - CompletionQueue::TIMEOUT); - } else { - while (!expectations_.empty()) { - bool ok; - void* got_tag; - EXPECT_EQ(cq->AsyncNext(&got_tag, &ok, deadline), - CompletionQueue::GOT_EVENT); - GotTag(got_tag, ok, false); - } - } + } + + // This version of Verify stops after a certain deadline + void Verify(CompletionQueue* cq, + std::chrono::system_clock::time_point deadline) { + if (expectations_.empty()) { + bool ok; + void* got_tag; + EXPECT_EQ(cq->AsyncNext(&got_tag, &ok, deadline), + CompletionQueue::TIMEOUT); + } else { + while (!expectations_.empty()) { + bool ok; + void* got_tag; + EXPECT_EQ(cq->AsyncNext(&got_tag, &ok, deadline), + CompletionQueue::GOT_EVENT); + GotTag(got_tag, ok, false); + } + } maybe_expectations_.clear(); - } - - // This version of Verify stops after a certain deadline, and uses the - // DoThenAsyncNext API - // to call the lambda - void Verify(CompletionQueue* cq, - std::chrono::system_clock::time_point deadline, - const std::function<void(void)>& lambda) { - if (expectations_.empty()) { - bool ok; - void* got_tag; - EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), - CompletionQueue::TIMEOUT); - } else { - while (!expectations_.empty()) { - bool ok; - void* got_tag; - EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), - CompletionQueue::GOT_EVENT); - GotTag(got_tag, ok, false); - } - } + } + + // This version of Verify stops after a certain deadline, and uses the + // DoThenAsyncNext API + // to call the lambda + void Verify(CompletionQueue* cq, + std::chrono::system_clock::time_point deadline, + const std::function<void(void)>& lambda) { + if (expectations_.empty()) { + bool ok; + void* got_tag; + EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), + CompletionQueue::TIMEOUT); + } else { + while (!expectations_.empty()) { + bool ok; + void* got_tag; + EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), + CompletionQueue::GOT_EVENT); + GotTag(got_tag, ok, false); + } + } maybe_expectations_.clear(); - } - - private: - void GotTag(void* got_tag, bool ok, bool ignore_ok) { - auto it = expectations_.find(got_tag); - if (it != expectations_.end()) { - if (!ignore_ok) { - EXPECT_EQ(it->second, ok); - } - expectations_.erase(it); - } else { - auto it2 = maybe_expectations_.find(got_tag); - if (it2 != maybe_expectations_.end()) { - if (it2->second.seen != nullptr) { - EXPECT_FALSE(*it2->second.seen); - *it2->second.seen = true; - } - if (!ignore_ok) { - EXPECT_EQ(it2->second.ok, ok); - } + } + + private: + void GotTag(void* got_tag, bool ok, bool ignore_ok) { + auto it = expectations_.find(got_tag); + if (it != expectations_.end()) { + if (!ignore_ok) { + EXPECT_EQ(it->second, ok); + } + expectations_.erase(it); + } else { + auto it2 = maybe_expectations_.find(got_tag); + if (it2 != maybe_expectations_.end()) { + if (it2->second.seen != nullptr) { + EXPECT_FALSE(*it2->second.seen); + *it2->second.seen = true; + } + if (!ignore_ok) { + EXPECT_EQ(it2->second.ok, ok); + } maybe_expectations_.erase(it2); - } else { - gpr_log(GPR_ERROR, "Unexpected tag: %p", got_tag); - abort(); - } - } - } - - struct MaybeExpect { - bool ok; - bool* seen; - }; - - std::map<void*, bool> expectations_; - std::map<void*, MaybeExpect> maybe_expectations_; - bool lambda_run_; -}; - -bool plugin_has_sync_methods(std::unique_ptr<ServerBuilderPlugin>& plugin) { - return plugin->has_sync_methods(); -} - -// This class disables the server builder plugins that may add sync services to -// the server. If there are sync services, UnimplementedRpc test will triger -// the sync unknown rpc routine on the server side, rather than the async one -// that needs to be tested here. -class ServerBuilderSyncPluginDisabler : public ::grpc::ServerBuilderOption { - public: - void UpdateArguments(ChannelArguments* /*arg*/) override {} - - void UpdatePlugins( - std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) override { - plugins->erase(std::remove_if(plugins->begin(), plugins->end(), - plugin_has_sync_methods), - plugins->end()); - } -}; - -class TestScenario { - public: + } else { + gpr_log(GPR_ERROR, "Unexpected tag: %p", got_tag); + abort(); + } + } + } + + struct MaybeExpect { + bool ok; + bool* seen; + }; + + std::map<void*, bool> expectations_; + std::map<void*, MaybeExpect> maybe_expectations_; + bool lambda_run_; +}; + +bool plugin_has_sync_methods(std::unique_ptr<ServerBuilderPlugin>& plugin) { + return plugin->has_sync_methods(); +} + +// This class disables the server builder plugins that may add sync services to +// the server. If there are sync services, UnimplementedRpc test will triger +// the sync unknown rpc routine on the server side, rather than the async one +// that needs to be tested here. +class ServerBuilderSyncPluginDisabler : public ::grpc::ServerBuilderOption { + public: + void UpdateArguments(ChannelArguments* /*arg*/) override {} + + void UpdatePlugins( + std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) override { + plugins->erase(std::remove_if(plugins->begin(), plugins->end(), + plugin_has_sync_methods), + plugins->end()); + } +}; + +class TestScenario { + public: TestScenario(bool inproc_stub, const TString& creds_type, bool hcs, const TString& content) - : inproc(inproc_stub), - health_check_service(hcs), - credentials_type(creds_type), - message_content(content) {} - void Log() const; - bool inproc; - bool health_check_service; + : inproc(inproc_stub), + health_check_service(hcs), + credentials_type(creds_type), + message_content(content) {} + void Log() const; + bool inproc; + bool health_check_service; const TString credentials_type; const TString message_content; -}; - -static std::ostream& operator<<(std::ostream& out, - const TestScenario& scenario) { - return out << "TestScenario{inproc=" << (scenario.inproc ? "true" : "false") - << ", credentials='" << scenario.credentials_type - << ", health_check_service=" - << (scenario.health_check_service ? "true" : "false") - << "', message_size=" << scenario.message_content.size() << "}"; -} - -void TestScenario::Log() const { - std::ostringstream out; - out << *this; - gpr_log(GPR_DEBUG, "%s", out.str().c_str()); -} - -class HealthCheck : public health::v1::Health::Service {}; - -class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> { - protected: - AsyncEnd2endTest() { GetParam().Log(); } - - void SetUp() override { - port_ = grpc_pick_unused_port_or_die(); - server_address_ << "localhost:" << port_; - - // Setup server - BuildAndStartServer(); - } - - void TearDown() override { - server_->Shutdown(); - void* ignored_tag; - bool ignored_ok; - cq_->Shutdown(); - while (cq_->Next(&ignored_tag, &ignored_ok)) - ; - stub_.reset(); - grpc_recycle_unused_port(port_); - } - - void BuildAndStartServer() { - ServerBuilder builder; - auto server_creds = GetCredentialsProvider()->GetServerCredentials( - GetParam().credentials_type); - builder.AddListeningPort(server_address_.str(), server_creds); - service_.reset(new grpc::testing::EchoTestService::AsyncService()); - builder.RegisterService(service_.get()); - if (GetParam().health_check_service) { - builder.RegisterService(&health_check_); - } - cq_ = builder.AddCompletionQueue(); - - // TODO(zyc): make a test option to choose wheather sync plugins should be - // deleted - std::unique_ptr<ServerBuilderOption> sync_plugin_disabler( - new ServerBuilderSyncPluginDisabler()); - builder.SetOption(move(sync_plugin_disabler)); - server_ = builder.BuildAndStart(); - } - - void ResetStub() { - ChannelArguments args; - auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( - GetParam().credentials_type, &args); - std::shared_ptr<Channel> channel = - !(GetParam().inproc) ? ::grpc::CreateCustomChannel( - server_address_.str(), channel_creds, args) - : server_->InProcessChannel(args); - stub_ = grpc::testing::EchoTestService::NewStub(channel); - } - - void SendRpc(int num_rpcs) { - for (int i = 0; i < num_rpcs; i++) { - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message(GetParam().message_content); - 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(), cq_.get(), tag(2)); - - response_reader->Finish(&recv_response, &recv_status, tag(4)); - - Verifier().Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - response_writer.Finish(send_response, Status::OK, tag(3)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - } - } - - std::unique_ptr<ServerCompletionQueue> cq_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - std::unique_ptr<grpc::testing::EchoTestService::AsyncService> service_; - HealthCheck health_check_; - std::ostringstream server_address_; - int port_; -}; - -TEST_P(AsyncEnd2endTest, SimpleRpc) { - ResetStub(); - SendRpc(1); -} - +}; + +static std::ostream& operator<<(std::ostream& out, + const TestScenario& scenario) { + return out << "TestScenario{inproc=" << (scenario.inproc ? "true" : "false") + << ", credentials='" << scenario.credentials_type + << ", health_check_service=" + << (scenario.health_check_service ? "true" : "false") + << "', message_size=" << scenario.message_content.size() << "}"; +} + +void TestScenario::Log() const { + std::ostringstream out; + out << *this; + gpr_log(GPR_DEBUG, "%s", out.str().c_str()); +} + +class HealthCheck : public health::v1::Health::Service {}; + +class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> { + protected: + AsyncEnd2endTest() { GetParam().Log(); } + + void SetUp() override { + port_ = grpc_pick_unused_port_or_die(); + server_address_ << "localhost:" << port_; + + // Setup server + BuildAndStartServer(); + } + + void TearDown() override { + server_->Shutdown(); + void* ignored_tag; + bool ignored_ok; + cq_->Shutdown(); + while (cq_->Next(&ignored_tag, &ignored_ok)) + ; + stub_.reset(); + grpc_recycle_unused_port(port_); + } + + void BuildAndStartServer() { + ServerBuilder builder; + auto server_creds = GetCredentialsProvider()->GetServerCredentials( + GetParam().credentials_type); + builder.AddListeningPort(server_address_.str(), server_creds); + service_.reset(new grpc::testing::EchoTestService::AsyncService()); + builder.RegisterService(service_.get()); + if (GetParam().health_check_service) { + builder.RegisterService(&health_check_); + } + cq_ = builder.AddCompletionQueue(); + + // TODO(zyc): make a test option to choose wheather sync plugins should be + // deleted + std::unique_ptr<ServerBuilderOption> sync_plugin_disabler( + new ServerBuilderSyncPluginDisabler()); + builder.SetOption(move(sync_plugin_disabler)); + server_ = builder.BuildAndStart(); + } + + void ResetStub() { + ChannelArguments args; + auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); + std::shared_ptr<Channel> channel = + !(GetParam().inproc) ? ::grpc::CreateCustomChannel( + server_address_.str(), channel_creds, args) + : server_->InProcessChannel(args); + stub_ = grpc::testing::EchoTestService::NewStub(channel); + } + + void SendRpc(int num_rpcs) { + for (int i = 0; i < num_rpcs; i++) { + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message(GetParam().message_content); + 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(), cq_.get(), tag(2)); + + response_reader->Finish(&recv_response, &recv_status, tag(4)); + + Verifier().Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + response_writer.Finish(send_response, Status::OK, tag(3)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + } + } + + std::unique_ptr<ServerCompletionQueue> cq_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + std::unique_ptr<grpc::testing::EchoTestService::AsyncService> service_; + HealthCheck health_check_; + std::ostringstream server_address_; + int port_; +}; + +TEST_P(AsyncEnd2endTest, SimpleRpc) { + ResetStub(); + SendRpc(1); +} + TEST_P(AsyncEnd2endTest, SimpleRpcWithExpectedError) { ResetStub(); @@ -401,1509 +401,1509 @@ TEST_P(AsyncEnd2endTest, SimpleRpcWithExpectedError) { EXPECT_FALSE(srv_ctx.IsCancelled()); } -TEST_P(AsyncEnd2endTest, SequentialRpcs) { - ResetStub(); - SendRpc(10); -} - -TEST_P(AsyncEnd2endTest, ReconnectChannel) { - // GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS is set to 100ms in main() - if (GetParam().inproc) { - return; - } - int poller_slowdown_factor = 1; -#ifdef GRPC_POSIX_SOCKET_EV - // It needs 2 pollset_works to reconnect the channel with polling engine - // "poll" - grpc_core::UniquePtr<char> poller = GPR_GLOBAL_CONFIG_GET(grpc_poll_strategy); - if (0 == strcmp(poller.get(), "poll")) { - poller_slowdown_factor = 2; - } -#endif // GRPC_POSIX_SOCKET_EV - ResetStub(); - SendRpc(1); - server_->Shutdown(); - void* ignored_tag; - bool ignored_ok; - cq_->Shutdown(); - while (cq_->Next(&ignored_tag, &ignored_ok)) - ; - BuildAndStartServer(); - // It needs more than GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS time to - // reconnect the channel. - gpr_sleep_until(gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_millis( - 300 * poller_slowdown_factor * grpc_test_slowdown_factor(), - GPR_TIMESPAN))); - SendRpc(1); -} - -// We do not need to protect notify because the use is synchronized. -void ServerWait(Server* server, int* notify) { - server->Wait(); - *notify = 1; -} -TEST_P(AsyncEnd2endTest, WaitAndShutdownTest) { - int notify = 0; - std::thread wait_thread(&ServerWait, server_.get(), ¬ify); - ResetStub(); - SendRpc(1); - EXPECT_EQ(0, notify); - server_->Shutdown(); - wait_thread.join(); - EXPECT_EQ(1, notify); -} - -TEST_P(AsyncEnd2endTest, ShutdownThenWait) { - ResetStub(); - SendRpc(1); - std::thread t([this]() { server_->Shutdown(); }); - server_->Wait(); - t.join(); -} - -// Test a simple RPC using the async version of Next -TEST_P(AsyncEnd2endTest, AsyncNextRpc) { - ResetStub(); - - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message(GetParam().message_content); - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); - - std::chrono::system_clock::time_point time_now( - std::chrono::system_clock::now()); - std::chrono::system_clock::time_point time_limit( - std::chrono::system_clock::now() + std::chrono::seconds(10)); - Verifier().Verify(cq_.get(), time_now); - Verifier().Verify(cq_.get(), time_now); - - service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), - cq_.get(), tag(2)); - response_reader->Finish(&recv_response, &recv_status, tag(4)); - - Verifier().Expect(2, true).Verify(cq_.get(), time_limit); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - response_writer.Finish(send_response, Status::OK, tag(3)); - Verifier().Expect(3, true).Expect(4, true).Verify( - cq_.get(), std::chrono::system_clock::time_point::max()); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); -} - -// Test a simple RPC using the async version of Next -TEST_P(AsyncEnd2endTest, DoThenAsyncNextRpc) { - ResetStub(); - - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message(GetParam().message_content); - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); - - std::chrono::system_clock::time_point time_now( - std::chrono::system_clock::now()); - std::chrono::system_clock::time_point time_limit( - std::chrono::system_clock::now() + std::chrono::seconds(10)); - Verifier().Verify(cq_.get(), time_now); - Verifier().Verify(cq_.get(), time_now); - - auto resp_writer_ptr = &response_writer; - auto lambda_2 = [&, this, resp_writer_ptr]() { - service_->RequestEcho(&srv_ctx, &recv_request, resp_writer_ptr, cq_.get(), - cq_.get(), tag(2)); - }; - response_reader->Finish(&recv_response, &recv_status, tag(4)); - - Verifier().Expect(2, true).Verify(cq_.get(), time_limit, lambda_2); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - auto lambda_3 = [resp_writer_ptr, send_response]() { - resp_writer_ptr->Finish(send_response, Status::OK, tag(3)); - }; - Verifier().Expect(3, true).Expect(4, true).Verify( - cq_.get(), std::chrono::system_clock::time_point::max(), lambda_3); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); -} - -// Two pings and a final pong. -TEST_P(AsyncEnd2endTest, SimpleClientStreaming) { - 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); - - send_request.set_message(GetParam().message_content); - 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(), - tag(2)); - - Verifier().Expect(2, true).Expect(1, true).Verify(cq_.get()); - - cli_stream->Write(send_request, tag(3)); - srv_stream.Read(&recv_request, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - cli_stream->Write(send_request, tag(5)); - srv_stream.Read(&recv_request, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - - EXPECT_EQ(send_request.message(), recv_request.message()); - cli_stream->WritesDone(tag(7)); - srv_stream.Read(&recv_request, tag(8)); - Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); - - send_response.set_message(recv_request.message()); - srv_stream.Finish(send_response, Status::OK, tag(9)); - cli_stream->Finish(&recv_status, tag(10)); - Verifier().Expect(9, true).Expect(10, true).Verify(cq_.get()); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); -} - -// Two pings and a final pong. -TEST_P(AsyncEnd2endTest, SimpleClientStreamingWithCoalescingApi) { - 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); - - send_request.set_message(GetParam().message_content); - cli_ctx.set_initial_metadata_corked(true); - // tag:1 never comes up since no op is performed - 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(), - tag(2)); - - cli_stream->Write(send_request, tag(3)); - - bool seen3 = false; - - Verifier().Expect(2, true).ExpectMaybe(3, true, &seen3).Verify(cq_.get()); - - srv_stream.Read(&recv_request, tag(4)); - - Verifier().ExpectUnless(3, true, seen3).Expect(4, true).Verify(cq_.get()); - - EXPECT_EQ(send_request.message(), recv_request.message()); - - cli_stream->WriteLast(send_request, WriteOptions(), tag(5)); - srv_stream.Read(&recv_request, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - srv_stream.Read(&recv_request, tag(7)); - Verifier().Expect(7, false).Verify(cq_.get()); - - send_response.set_message(recv_request.message()); - srv_stream.Finish(send_response, Status::OK, tag(8)); - cli_stream->Finish(&recv_status, tag(9)); - Verifier().Expect(8, true).Expect(9, true).Verify(cq_.get()); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); -} - -// One ping, two pongs. -TEST_P(AsyncEnd2endTest, SimpleServerStreaming) { - 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(GetParam().message_content); - 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, - cq_.get(), cq_.get(), tag(2)); - - Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - srv_stream.Write(send_response, tag(3)); - cli_stream->Read(&recv_response, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - srv_stream.Write(send_response, tag(5)); - cli_stream->Read(&recv_response, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - srv_stream.Finish(Status::OK, tag(7)); - cli_stream->Read(&recv_response, tag(8)); - Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); - - cli_stream->Finish(&recv_status, tag(9)); - Verifier().Expect(9, true).Verify(cq_.get()); - - EXPECT_TRUE(recv_status.ok()); -} - -// One ping, two pongs. Using WriteAndFinish API -TEST_P(AsyncEnd2endTest, SimpleServerStreamingWithCoalescingApiWAF) { - 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(GetParam().message_content); - 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, - cq_.get(), cq_.get(), tag(2)); - - Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - srv_stream.Write(send_response, tag(3)); - cli_stream->Read(&recv_response, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - srv_stream.WriteAndFinish(send_response, WriteOptions(), Status::OK, tag(5)); - cli_stream->Read(&recv_response, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - cli_stream->Read(&recv_response, tag(7)); - Verifier().Expect(7, false).Verify(cq_.get()); - - cli_stream->Finish(&recv_status, tag(8)); - Verifier().Expect(8, true).Verify(cq_.get()); - - EXPECT_TRUE(recv_status.ok()); -} - -// One ping, two pongs. Using WriteLast API -TEST_P(AsyncEnd2endTest, SimpleServerStreamingWithCoalescingApiWL) { - 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(GetParam().message_content); - 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, - cq_.get(), cq_.get(), tag(2)); - - Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - srv_stream.Write(send_response, tag(3)); - cli_stream->Read(&recv_response, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - srv_stream.WriteLast(send_response, WriteOptions(), tag(5)); - cli_stream->Read(&recv_response, tag(6)); - srv_stream.Finish(Status::OK, tag(7)); - Verifier().Expect(5, true).Expect(6, true).Expect(7, true).Verify(cq_.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - cli_stream->Read(&recv_response, tag(8)); - Verifier().Expect(8, false).Verify(cq_.get()); - - cli_stream->Finish(&recv_status, tag(9)); - Verifier().Expect(9, true).Verify(cq_.get()); - - EXPECT_TRUE(recv_status.ok()); -} - -// One ping, one pong. -TEST_P(AsyncEnd2endTest, SimpleBidiStreaming) { - 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); - - send_request.set_message(GetParam().message_content); - 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(), - tag(2)); - - Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); - - cli_stream->Write(send_request, tag(3)); - srv_stream.Read(&recv_request, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - srv_stream.Write(send_response, tag(5)); - cli_stream->Read(&recv_response, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - cli_stream->WritesDone(tag(7)); - srv_stream.Read(&recv_request, tag(8)); - Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); - - srv_stream.Finish(Status::OK, tag(9)); - cli_stream->Finish(&recv_status, tag(10)); - Verifier().Expect(9, true).Expect(10, true).Verify(cq_.get()); - - EXPECT_TRUE(recv_status.ok()); -} - -// One ping, one pong. Using server:WriteAndFinish api -TEST_P(AsyncEnd2endTest, SimpleBidiStreamingWithCoalescingApiWAF) { - 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); - - send_request.set_message(GetParam().message_content); - cli_ctx.set_initial_metadata_corked(true); - 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(), - tag(2)); - - cli_stream->WriteLast(send_request, WriteOptions(), tag(3)); - - bool seen3 = false; - - Verifier().Expect(2, true).ExpectMaybe(3, true, &seen3).Verify(cq_.get()); - - srv_stream.Read(&recv_request, tag(4)); - - Verifier().ExpectUnless(3, true, seen3).Expect(4, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - srv_stream.Read(&recv_request, tag(5)); - Verifier().Expect(5, false).Verify(cq_.get()); - - send_response.set_message(recv_request.message()); - srv_stream.WriteAndFinish(send_response, WriteOptions(), Status::OK, tag(6)); - cli_stream->Read(&recv_response, tag(7)); - Verifier().Expect(6, true).Expect(7, true).Verify(cq_.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - cli_stream->Finish(&recv_status, tag(8)); - Verifier().Expect(8, true).Verify(cq_.get()); - - EXPECT_TRUE(recv_status.ok()); -} - -// One ping, one pong. Using server:WriteLast api -TEST_P(AsyncEnd2endTest, SimpleBidiStreamingWithCoalescingApiWL) { - 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); - - send_request.set_message(GetParam().message_content); - cli_ctx.set_initial_metadata_corked(true); - 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(), - tag(2)); - - cli_stream->WriteLast(send_request, WriteOptions(), tag(3)); - - bool seen3 = false; - - Verifier().Expect(2, true).ExpectMaybe(3, true, &seen3).Verify(cq_.get()); - - srv_stream.Read(&recv_request, tag(4)); - - Verifier().ExpectUnless(3, true, seen3).Expect(4, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - srv_stream.Read(&recv_request, tag(5)); - Verifier().Expect(5, false).Verify(cq_.get()); - - send_response.set_message(recv_request.message()); - srv_stream.WriteLast(send_response, WriteOptions(), tag(6)); - srv_stream.Finish(Status::OK, tag(7)); - cli_stream->Read(&recv_response, tag(8)); - Verifier().Expect(6, true).Expect(7, true).Expect(8, true).Verify(cq_.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - cli_stream->Finish(&recv_status, tag(9)); - Verifier().Expect(9, true).Verify(cq_.get()); - - EXPECT_TRUE(recv_status.ok()); -} - -// Metadata tests -TEST_P(AsyncEnd2endTest, ClientInitialMetadataRpc) { - ResetStub(); - - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message(GetParam().message_content); +TEST_P(AsyncEnd2endTest, SequentialRpcs) { + ResetStub(); + SendRpc(10); +} + +TEST_P(AsyncEnd2endTest, ReconnectChannel) { + // GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS is set to 100ms in main() + if (GetParam().inproc) { + return; + } + int poller_slowdown_factor = 1; +#ifdef GRPC_POSIX_SOCKET_EV + // It needs 2 pollset_works to reconnect the channel with polling engine + // "poll" + grpc_core::UniquePtr<char> poller = GPR_GLOBAL_CONFIG_GET(grpc_poll_strategy); + if (0 == strcmp(poller.get(), "poll")) { + poller_slowdown_factor = 2; + } +#endif // GRPC_POSIX_SOCKET_EV + ResetStub(); + SendRpc(1); + server_->Shutdown(); + void* ignored_tag; + bool ignored_ok; + cq_->Shutdown(); + while (cq_->Next(&ignored_tag, &ignored_ok)) + ; + BuildAndStartServer(); + // It needs more than GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS time to + // reconnect the channel. + gpr_sleep_until(gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis( + 300 * poller_slowdown_factor * grpc_test_slowdown_factor(), + GPR_TIMESPAN))); + SendRpc(1); +} + +// We do not need to protect notify because the use is synchronized. +void ServerWait(Server* server, int* notify) { + server->Wait(); + *notify = 1; +} +TEST_P(AsyncEnd2endTest, WaitAndShutdownTest) { + int notify = 0; + std::thread wait_thread(&ServerWait, server_.get(), ¬ify); + ResetStub(); + SendRpc(1); + EXPECT_EQ(0, notify); + server_->Shutdown(); + wait_thread.join(); + EXPECT_EQ(1, notify); +} + +TEST_P(AsyncEnd2endTest, ShutdownThenWait) { + ResetStub(); + SendRpc(1); + std::thread t([this]() { server_->Shutdown(); }); + server_->Wait(); + t.join(); +} + +// Test a simple RPC using the async version of Next +TEST_P(AsyncEnd2endTest, AsyncNextRpc) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message(GetParam().message_content); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); + + std::chrono::system_clock::time_point time_now( + std::chrono::system_clock::now()); + std::chrono::system_clock::time_point time_limit( + std::chrono::system_clock::now() + std::chrono::seconds(10)); + Verifier().Verify(cq_.get(), time_now); + Verifier().Verify(cq_.get(), time_now); + + service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), + cq_.get(), tag(2)); + response_reader->Finish(&recv_response, &recv_status, tag(4)); + + Verifier().Expect(2, true).Verify(cq_.get(), time_limit); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + response_writer.Finish(send_response, Status::OK, tag(3)); + Verifier().Expect(3, true).Expect(4, true).Verify( + cq_.get(), std::chrono::system_clock::time_point::max()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); +} + +// Test a simple RPC using the async version of Next +TEST_P(AsyncEnd2endTest, DoThenAsyncNextRpc) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message(GetParam().message_content); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); + + std::chrono::system_clock::time_point time_now( + std::chrono::system_clock::now()); + std::chrono::system_clock::time_point time_limit( + std::chrono::system_clock::now() + std::chrono::seconds(10)); + Verifier().Verify(cq_.get(), time_now); + Verifier().Verify(cq_.get(), time_now); + + auto resp_writer_ptr = &response_writer; + auto lambda_2 = [&, this, resp_writer_ptr]() { + service_->RequestEcho(&srv_ctx, &recv_request, resp_writer_ptr, cq_.get(), + cq_.get(), tag(2)); + }; + response_reader->Finish(&recv_response, &recv_status, tag(4)); + + Verifier().Expect(2, true).Verify(cq_.get(), time_limit, lambda_2); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + auto lambda_3 = [resp_writer_ptr, send_response]() { + resp_writer_ptr->Finish(send_response, Status::OK, tag(3)); + }; + Verifier().Expect(3, true).Expect(4, true).Verify( + cq_.get(), std::chrono::system_clock::time_point::max(), lambda_3); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); +} + +// Two pings and a final pong. +TEST_P(AsyncEnd2endTest, SimpleClientStreaming) { + 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); + + send_request.set_message(GetParam().message_content); + 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(), + tag(2)); + + Verifier().Expect(2, true).Expect(1, true).Verify(cq_.get()); + + cli_stream->Write(send_request, tag(3)); + srv_stream.Read(&recv_request, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + cli_stream->Write(send_request, tag(5)); + srv_stream.Read(&recv_request, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + + EXPECT_EQ(send_request.message(), recv_request.message()); + cli_stream->WritesDone(tag(7)); + srv_stream.Read(&recv_request, tag(8)); + Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); + + send_response.set_message(recv_request.message()); + srv_stream.Finish(send_response, Status::OK, tag(9)); + cli_stream->Finish(&recv_status, tag(10)); + Verifier().Expect(9, true).Expect(10, true).Verify(cq_.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); +} + +// Two pings and a final pong. +TEST_P(AsyncEnd2endTest, SimpleClientStreamingWithCoalescingApi) { + 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); + + send_request.set_message(GetParam().message_content); + cli_ctx.set_initial_metadata_corked(true); + // tag:1 never comes up since no op is performed + 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(), + tag(2)); + + cli_stream->Write(send_request, tag(3)); + + bool seen3 = false; + + Verifier().Expect(2, true).ExpectMaybe(3, true, &seen3).Verify(cq_.get()); + + srv_stream.Read(&recv_request, tag(4)); + + Verifier().ExpectUnless(3, true, seen3).Expect(4, true).Verify(cq_.get()); + + EXPECT_EQ(send_request.message(), recv_request.message()); + + cli_stream->WriteLast(send_request, WriteOptions(), tag(5)); + srv_stream.Read(&recv_request, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + srv_stream.Read(&recv_request, tag(7)); + Verifier().Expect(7, false).Verify(cq_.get()); + + send_response.set_message(recv_request.message()); + srv_stream.Finish(send_response, Status::OK, tag(8)); + cli_stream->Finish(&recv_status, tag(9)); + Verifier().Expect(8, true).Expect(9, true).Verify(cq_.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); +} + +// One ping, two pongs. +TEST_P(AsyncEnd2endTest, SimpleServerStreaming) { + 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(GetParam().message_content); + 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, + cq_.get(), cq_.get(), tag(2)); + + Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + srv_stream.Write(send_response, tag(3)); + cli_stream->Read(&recv_response, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + srv_stream.Write(send_response, tag(5)); + cli_stream->Read(&recv_response, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + srv_stream.Finish(Status::OK, tag(7)); + cli_stream->Read(&recv_response, tag(8)); + Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); + + cli_stream->Finish(&recv_status, tag(9)); + Verifier().Expect(9, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + +// One ping, two pongs. Using WriteAndFinish API +TEST_P(AsyncEnd2endTest, SimpleServerStreamingWithCoalescingApiWAF) { + 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(GetParam().message_content); + 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, + cq_.get(), cq_.get(), tag(2)); + + Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + srv_stream.Write(send_response, tag(3)); + cli_stream->Read(&recv_response, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + srv_stream.WriteAndFinish(send_response, WriteOptions(), Status::OK, tag(5)); + cli_stream->Read(&recv_response, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->Read(&recv_response, tag(7)); + Verifier().Expect(7, false).Verify(cq_.get()); + + cli_stream->Finish(&recv_status, tag(8)); + Verifier().Expect(8, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + +// One ping, two pongs. Using WriteLast API +TEST_P(AsyncEnd2endTest, SimpleServerStreamingWithCoalescingApiWL) { + 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(GetParam().message_content); + 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, + cq_.get(), cq_.get(), tag(2)); + + Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + srv_stream.Write(send_response, tag(3)); + cli_stream->Read(&recv_response, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + srv_stream.WriteLast(send_response, WriteOptions(), tag(5)); + cli_stream->Read(&recv_response, tag(6)); + srv_stream.Finish(Status::OK, tag(7)); + Verifier().Expect(5, true).Expect(6, true).Expect(7, true).Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->Read(&recv_response, tag(8)); + Verifier().Expect(8, false).Verify(cq_.get()); + + cli_stream->Finish(&recv_status, tag(9)); + Verifier().Expect(9, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + +// One ping, one pong. +TEST_P(AsyncEnd2endTest, SimpleBidiStreaming) { + 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); + + send_request.set_message(GetParam().message_content); + 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(), + tag(2)); + + Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); + + cli_stream->Write(send_request, tag(3)); + srv_stream.Read(&recv_request, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + srv_stream.Write(send_response, tag(5)); + cli_stream->Read(&recv_response, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->WritesDone(tag(7)); + srv_stream.Read(&recv_request, tag(8)); + Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); + + srv_stream.Finish(Status::OK, tag(9)); + cli_stream->Finish(&recv_status, tag(10)); + Verifier().Expect(9, true).Expect(10, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + +// One ping, one pong. Using server:WriteAndFinish api +TEST_P(AsyncEnd2endTest, SimpleBidiStreamingWithCoalescingApiWAF) { + 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); + + send_request.set_message(GetParam().message_content); + cli_ctx.set_initial_metadata_corked(true); + 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(), + tag(2)); + + cli_stream->WriteLast(send_request, WriteOptions(), tag(3)); + + bool seen3 = false; + + Verifier().Expect(2, true).ExpectMaybe(3, true, &seen3).Verify(cq_.get()); + + srv_stream.Read(&recv_request, tag(4)); + + Verifier().ExpectUnless(3, true, seen3).Expect(4, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + srv_stream.Read(&recv_request, tag(5)); + Verifier().Expect(5, false).Verify(cq_.get()); + + send_response.set_message(recv_request.message()); + srv_stream.WriteAndFinish(send_response, WriteOptions(), Status::OK, tag(6)); + cli_stream->Read(&recv_response, tag(7)); + Verifier().Expect(6, true).Expect(7, true).Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->Finish(&recv_status, tag(8)); + Verifier().Expect(8, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + +// One ping, one pong. Using server:WriteLast api +TEST_P(AsyncEnd2endTest, SimpleBidiStreamingWithCoalescingApiWL) { + 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); + + send_request.set_message(GetParam().message_content); + cli_ctx.set_initial_metadata_corked(true); + 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(), + tag(2)); + + cli_stream->WriteLast(send_request, WriteOptions(), tag(3)); + + bool seen3 = false; + + Verifier().Expect(2, true).ExpectMaybe(3, true, &seen3).Verify(cq_.get()); + + srv_stream.Read(&recv_request, tag(4)); + + Verifier().ExpectUnless(3, true, seen3).Expect(4, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + srv_stream.Read(&recv_request, tag(5)); + Verifier().Expect(5, false).Verify(cq_.get()); + + send_response.set_message(recv_request.message()); + srv_stream.WriteLast(send_response, WriteOptions(), tag(6)); + srv_stream.Finish(Status::OK, tag(7)); + cli_stream->Read(&recv_response, tag(8)); + Verifier().Expect(6, true).Expect(7, true).Expect(8, true).Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->Finish(&recv_status, tag(9)); + Verifier().Expect(9, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + +// Metadata tests +TEST_P(AsyncEnd2endTest, ClientInitialMetadataRpc) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message(GetParam().message_content); std::pair<TString, TString> meta1("key1", "val1"); std::pair<TString, TString> meta2("key2", "val2"); std::pair<TString, TString> meta3("g.r.d-bin", "xyz"); - cli_ctx.AddMetadata(meta1.first, meta1.second); - cli_ctx.AddMetadata(meta2.first, meta2.second); - cli_ctx.AddMetadata(meta3.first, meta3.second); - - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); - response_reader->Finish(&recv_response, &recv_status, tag(4)); - - service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), - cq_.get(), tag(2)); - Verifier().Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - const auto& client_initial_metadata = srv_ctx.client_metadata(); - EXPECT_EQ(meta1.second, - ToString(client_initial_metadata.find(meta1.first)->second)); - EXPECT_EQ(meta2.second, - ToString(client_initial_metadata.find(meta2.first)->second)); - EXPECT_EQ(meta3.second, - ToString(client_initial_metadata.find(meta3.first)->second)); - EXPECT_GE(client_initial_metadata.size(), static_cast<size_t>(2)); - - send_response.set_message(recv_request.message()); - response_writer.Finish(send_response, Status::OK, tag(3)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); -} - -TEST_P(AsyncEnd2endTest, ServerInitialMetadataRpc) { - ResetStub(); - - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message(GetParam().message_content); + cli_ctx.AddMetadata(meta1.first, meta1.second); + cli_ctx.AddMetadata(meta2.first, meta2.second); + cli_ctx.AddMetadata(meta3.first, meta3.second); + + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); + response_reader->Finish(&recv_response, &recv_status, tag(4)); + + service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), + cq_.get(), tag(2)); + Verifier().Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + const auto& client_initial_metadata = srv_ctx.client_metadata(); + EXPECT_EQ(meta1.second, + ToString(client_initial_metadata.find(meta1.first)->second)); + EXPECT_EQ(meta2.second, + ToString(client_initial_metadata.find(meta2.first)->second)); + EXPECT_EQ(meta3.second, + ToString(client_initial_metadata.find(meta3.first)->second)); + EXPECT_GE(client_initial_metadata.size(), static_cast<size_t>(2)); + + send_response.set_message(recv_request.message()); + response_writer.Finish(send_response, Status::OK, tag(3)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); +} + +TEST_P(AsyncEnd2endTest, ServerInitialMetadataRpc) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message(GetParam().message_content); std::pair<TString, TString> meta1("key1", "val1"); std::pair<TString, TString> meta2("key2", "val2"); - - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); - response_reader->ReadInitialMetadata(tag(4)); - - service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), - cq_.get(), tag(2)); - Verifier().Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - srv_ctx.AddInitialMetadata(meta1.first, meta1.second); - srv_ctx.AddInitialMetadata(meta2.first, meta2.second); - response_writer.SendInitialMetadata(tag(3)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - const auto& server_initial_metadata = cli_ctx.GetServerInitialMetadata(); - EXPECT_EQ(meta1.second, - ToString(server_initial_metadata.find(meta1.first)->second)); - EXPECT_EQ(meta2.second, - ToString(server_initial_metadata.find(meta2.first)->second)); - EXPECT_EQ(static_cast<size_t>(2), server_initial_metadata.size()); - - send_response.set_message(recv_request.message()); - response_writer.Finish(send_response, Status::OK, tag(5)); - response_reader->Finish(&recv_response, &recv_status, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); -} - -// 1 ping, 2 pongs. -TEST_P(AsyncEnd2endTest, ServerInitialMetadataServerStreaming) { - 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); - + + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); + response_reader->ReadInitialMetadata(tag(4)); + + service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), + cq_.get(), tag(2)); + Verifier().Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + srv_ctx.AddInitialMetadata(meta1.first, meta1.second); + srv_ctx.AddInitialMetadata(meta2.first, meta2.second); + response_writer.SendInitialMetadata(tag(3)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + const auto& server_initial_metadata = cli_ctx.GetServerInitialMetadata(); + EXPECT_EQ(meta1.second, + ToString(server_initial_metadata.find(meta1.first)->second)); + EXPECT_EQ(meta2.second, + ToString(server_initial_metadata.find(meta2.first)->second)); + EXPECT_EQ(static_cast<size_t>(2), server_initial_metadata.size()); + + send_response.set_message(recv_request.message()); + response_writer.Finish(send_response, Status::OK, tag(5)); + response_reader->Finish(&recv_response, &recv_status, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); +} + +// 1 ping, 2 pongs. +TEST_P(AsyncEnd2endTest, ServerInitialMetadataServerStreaming) { + 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); + std::pair<::TString, ::TString> meta1("key1", "val1"); std::pair<::TString, ::TString> meta2("key2", "val2"); - - std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream( - stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1))); - cli_stream->ReadInitialMetadata(tag(11)); - service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, - cq_.get(), cq_.get(), tag(2)); - - Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); - - srv_ctx.AddInitialMetadata(meta1.first, meta1.second); - srv_ctx.AddInitialMetadata(meta2.first, meta2.second); - srv_stream.SendInitialMetadata(tag(10)); - Verifier().Expect(10, true).Expect(11, true).Verify(cq_.get()); - auto server_initial_metadata = cli_ctx.GetServerInitialMetadata(); - EXPECT_EQ(meta1.second, - ToString(server_initial_metadata.find(meta1.first)->second)); - EXPECT_EQ(meta2.second, - ToString(server_initial_metadata.find(meta2.first)->second)); - EXPECT_EQ(static_cast<size_t>(2), server_initial_metadata.size()); - - srv_stream.Write(send_response, tag(3)); - - cli_stream->Read(&recv_response, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - - srv_stream.Write(send_response, tag(5)); - cli_stream->Read(&recv_response, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - - srv_stream.Finish(Status::OK, tag(7)); - cli_stream->Read(&recv_response, tag(8)); - Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); - - cli_stream->Finish(&recv_status, tag(9)); - Verifier().Expect(9, true).Verify(cq_.get()); - - EXPECT_TRUE(recv_status.ok()); -} - -// 1 ping, 2 pongs. -// Test for server initial metadata being sent implicitly -TEST_P(AsyncEnd2endTest, ServerInitialMetadataServerStreamingImplicit) { - 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(GetParam().message_content); + + std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream( + stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1))); + cli_stream->ReadInitialMetadata(tag(11)); + service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, + cq_.get(), cq_.get(), tag(2)); + + Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); + + srv_ctx.AddInitialMetadata(meta1.first, meta1.second); + srv_ctx.AddInitialMetadata(meta2.first, meta2.second); + srv_stream.SendInitialMetadata(tag(10)); + Verifier().Expect(10, true).Expect(11, true).Verify(cq_.get()); + auto server_initial_metadata = cli_ctx.GetServerInitialMetadata(); + EXPECT_EQ(meta1.second, + ToString(server_initial_metadata.find(meta1.first)->second)); + EXPECT_EQ(meta2.second, + ToString(server_initial_metadata.find(meta2.first)->second)); + EXPECT_EQ(static_cast<size_t>(2), server_initial_metadata.size()); + + srv_stream.Write(send_response, tag(3)); + + cli_stream->Read(&recv_response, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + + srv_stream.Write(send_response, tag(5)); + cli_stream->Read(&recv_response, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + + srv_stream.Finish(Status::OK, tag(7)); + cli_stream->Read(&recv_response, tag(8)); + Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); + + cli_stream->Finish(&recv_status, tag(9)); + Verifier().Expect(9, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + +// 1 ping, 2 pongs. +// Test for server initial metadata being sent implicitly +TEST_P(AsyncEnd2endTest, ServerInitialMetadataServerStreamingImplicit) { + 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(GetParam().message_content); std::pair<::TString, ::TString> meta1("key1", "val1"); std::pair<::TString, ::TString> meta2("key2", "val2"); - - 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, - cq_.get(), cq_.get(), tag(2)); - - Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - srv_ctx.AddInitialMetadata(meta1.first, meta1.second); - srv_ctx.AddInitialMetadata(meta2.first, meta2.second); - send_response.set_message(recv_request.message()); - srv_stream.Write(send_response, tag(3)); - - cli_stream->Read(&recv_response, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - auto server_initial_metadata = cli_ctx.GetServerInitialMetadata(); - EXPECT_EQ(meta1.second, - ToString(server_initial_metadata.find(meta1.first)->second)); - EXPECT_EQ(meta2.second, - ToString(server_initial_metadata.find(meta2.first)->second)); - EXPECT_EQ(static_cast<size_t>(2), server_initial_metadata.size()); - - srv_stream.Write(send_response, tag(5)); - cli_stream->Read(&recv_response, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - - srv_stream.Finish(Status::OK, tag(7)); - cli_stream->Read(&recv_response, tag(8)); - Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); - - cli_stream->Finish(&recv_status, tag(9)); - Verifier().Expect(9, true).Verify(cq_.get()); - - EXPECT_TRUE(recv_status.ok()); -} - -TEST_P(AsyncEnd2endTest, ServerTrailingMetadataRpc) { - ResetStub(); - - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message(GetParam().message_content); + + 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, + cq_.get(), cq_.get(), tag(2)); + + Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + srv_ctx.AddInitialMetadata(meta1.first, meta1.second); + srv_ctx.AddInitialMetadata(meta2.first, meta2.second); + send_response.set_message(recv_request.message()); + srv_stream.Write(send_response, tag(3)); + + cli_stream->Read(&recv_response, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + auto server_initial_metadata = cli_ctx.GetServerInitialMetadata(); + EXPECT_EQ(meta1.second, + ToString(server_initial_metadata.find(meta1.first)->second)); + EXPECT_EQ(meta2.second, + ToString(server_initial_metadata.find(meta2.first)->second)); + EXPECT_EQ(static_cast<size_t>(2), server_initial_metadata.size()); + + srv_stream.Write(send_response, tag(5)); + cli_stream->Read(&recv_response, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + + srv_stream.Finish(Status::OK, tag(7)); + cli_stream->Read(&recv_response, tag(8)); + Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); + + cli_stream->Finish(&recv_status, tag(9)); + Verifier().Expect(9, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status.ok()); +} + +TEST_P(AsyncEnd2endTest, ServerTrailingMetadataRpc) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message(GetParam().message_content); std::pair<TString, TString> meta1("key1", "val1"); std::pair<TString, TString> meta2("key2", "val2"); - - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); - response_reader->Finish(&recv_response, &recv_status, tag(5)); - - service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), - cq_.get(), tag(2)); - Verifier().Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - response_writer.SendInitialMetadata(tag(3)); - Verifier().Expect(3, true).Verify(cq_.get()); - - send_response.set_message(recv_request.message()); - srv_ctx.AddTrailingMetadata(meta1.first, meta1.second); - srv_ctx.AddTrailingMetadata(meta2.first, meta2.second); - response_writer.Finish(send_response, Status::OK, tag(4)); - - Verifier().Expect(4, true).Expect(5, true).Verify(cq_.get()); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - const auto& server_trailing_metadata = cli_ctx.GetServerTrailingMetadata(); - EXPECT_EQ(meta1.second, - ToString(server_trailing_metadata.find(meta1.first)->second)); - EXPECT_EQ(meta2.second, - ToString(server_trailing_metadata.find(meta2.first)->second)); - EXPECT_EQ(static_cast<size_t>(2), server_trailing_metadata.size()); -} - -TEST_P(AsyncEnd2endTest, MetadataRpc) { - ResetStub(); - - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message(GetParam().message_content); + + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); + response_reader->Finish(&recv_response, &recv_status, tag(5)); + + service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), + cq_.get(), tag(2)); + Verifier().Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + response_writer.SendInitialMetadata(tag(3)); + Verifier().Expect(3, true).Verify(cq_.get()); + + send_response.set_message(recv_request.message()); + srv_ctx.AddTrailingMetadata(meta1.first, meta1.second); + srv_ctx.AddTrailingMetadata(meta2.first, meta2.second); + response_writer.Finish(send_response, Status::OK, tag(4)); + + Verifier().Expect(4, true).Expect(5, true).Verify(cq_.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + const auto& server_trailing_metadata = cli_ctx.GetServerTrailingMetadata(); + EXPECT_EQ(meta1.second, + ToString(server_trailing_metadata.find(meta1.first)->second)); + EXPECT_EQ(meta2.second, + ToString(server_trailing_metadata.find(meta2.first)->second)); + EXPECT_EQ(static_cast<size_t>(2), server_trailing_metadata.size()); +} + +TEST_P(AsyncEnd2endTest, MetadataRpc) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message(GetParam().message_content); std::pair<TString, TString> meta1("key1", "val1"); std::pair<TString, TString> meta2( - "key2-bin", + "key2-bin", TString("\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc", 13)); std::pair<TString, TString> meta3("key3", "val3"); std::pair<TString, TString> meta6( - "key4-bin", + "key4-bin", TString("\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d", 14)); std::pair<TString, TString> meta5("key5", "val5"); std::pair<TString, TString> meta4( - "key6-bin", + "key6-bin", TString( - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee", 15)); - - cli_ctx.AddMetadata(meta1.first, meta1.second); - cli_ctx.AddMetadata(meta2.first, meta2.second); - - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); - response_reader->ReadInitialMetadata(tag(4)); - - service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), - cq_.get(), tag(2)); - Verifier().Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - const auto& client_initial_metadata = srv_ctx.client_metadata(); - EXPECT_EQ(meta1.second, - ToString(client_initial_metadata.find(meta1.first)->second)); - EXPECT_EQ(meta2.second, - ToString(client_initial_metadata.find(meta2.first)->second)); - EXPECT_GE(client_initial_metadata.size(), static_cast<size_t>(2)); - - srv_ctx.AddInitialMetadata(meta3.first, meta3.second); - srv_ctx.AddInitialMetadata(meta4.first, meta4.second); - response_writer.SendInitialMetadata(tag(3)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - const auto& server_initial_metadata = cli_ctx.GetServerInitialMetadata(); - EXPECT_EQ(meta3.second, - ToString(server_initial_metadata.find(meta3.first)->second)); - EXPECT_EQ(meta4.second, - ToString(server_initial_metadata.find(meta4.first)->second)); - EXPECT_GE(server_initial_metadata.size(), static_cast<size_t>(2)); - - send_response.set_message(recv_request.message()); - srv_ctx.AddTrailingMetadata(meta5.first, meta5.second); - srv_ctx.AddTrailingMetadata(meta6.first, meta6.second); - response_writer.Finish(send_response, Status::OK, tag(5)); - response_reader->Finish(&recv_response, &recv_status, tag(6)); - - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - const auto& server_trailing_metadata = cli_ctx.GetServerTrailingMetadata(); - EXPECT_EQ(meta5.second, - ToString(server_trailing_metadata.find(meta5.first)->second)); - EXPECT_EQ(meta6.second, - ToString(server_trailing_metadata.find(meta6.first)->second)); - EXPECT_GE(server_trailing_metadata.size(), static_cast<size_t>(2)); -} - -// Server uses AsyncNotifyWhenDone API to check for cancellation -TEST_P(AsyncEnd2endTest, ServerCheckCancellation) { - ResetStub(); - - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message(GetParam().message_content); - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); - response_reader->Finish(&recv_response, &recv_status, tag(4)); - - srv_ctx.AsyncNotifyWhenDone(tag(5)); - service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), - cq_.get(), tag(2)); - - Verifier().Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - cli_ctx.TryCancel(); - Verifier().Expect(5, true).Expect(4, true).Verify(cq_.get()); - EXPECT_TRUE(srv_ctx.IsCancelled()); - - EXPECT_EQ(StatusCode::CANCELLED, recv_status.error_code()); -} - -// Server uses AsyncNotifyWhenDone API to check for normal finish -TEST_P(AsyncEnd2endTest, ServerCheckDone) { - ResetStub(); - - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message(GetParam().message_content); - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); - response_reader->Finish(&recv_response, &recv_status, tag(4)); - - srv_ctx.AsyncNotifyWhenDone(tag(5)); - service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), - cq_.get(), tag(2)); - - Verifier().Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - response_writer.Finish(send_response, Status::OK, tag(3)); - Verifier().Expect(3, true).Expect(4, true).Expect(5, true).Verify(cq_.get()); - EXPECT_FALSE(srv_ctx.IsCancelled()); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); -} - -TEST_P(AsyncEnd2endTest, UnimplementedRpc) { - ChannelArguments args; - const auto& channel_creds = GetCredentialsProvider()->GetChannelCredentials( - GetParam().credentials_type, &args); - std::shared_ptr<Channel> channel = - !(GetParam().inproc) ? ::grpc::CreateCustomChannel(server_address_.str(), - channel_creds, args) - : server_->InProcessChannel(args); - std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; - stub = grpc::testing::UnimplementedEchoService::NewStub(channel); - EchoRequest send_request; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - send_request.set_message(GetParam().message_content); - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub->AsyncUnimplemented(&cli_ctx, send_request, cq_.get())); - - response_reader->Finish(&recv_response, &recv_status, tag(4)); - Verifier().Expect(4, true).Verify(cq_.get()); - - EXPECT_EQ(StatusCode::UNIMPLEMENTED, recv_status.error_code()); - EXPECT_EQ("", recv_status.error_message()); -} - -// This class is for testing scenarios where RPCs are cancelled on the server -// by calling ServerContext::TryCancel(). Server uses AsyncNotifyWhenDone -// API to check for cancellation -class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { - protected: - typedef enum { - DO_NOT_CANCEL = 0, - CANCEL_BEFORE_PROCESSING, - CANCEL_DURING_PROCESSING, - CANCEL_AFTER_PROCESSING - } ServerTryCancelRequestPhase; - - // 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 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 - CompletionQueue cli_cq; - - std::unique_ptr<ClientAsyncWriter<EchoRequest>> cli_stream( - stub_->AsyncRequestStream(&cli_ctx, &recv_response, &cli_cq, tag(1))); - - // On the server, request to be notified of 'RequestStream' calls - // and receive the 'RequestStream' call just made by the client - srv_ctx.AsyncNotifyWhenDone(tag(11)); - service_->RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), - tag(2)); - std::thread t1([&cli_cq] { Verifier().Expect(1, true).Verify(&cli_cq); }); - Verifier().Expect(2, true).Verify(cq_.get()); - t1.join(); - - bool expected_server_cq_result = true; - bool expected_client_cq_result = true; - - if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { - srv_ctx.TryCancel(); - Verifier().Expect(11, true).Verify(cq_.get()); - EXPECT_TRUE(srv_ctx.IsCancelled()); - - // Since cancellation is done before server reads any results, we know - // for sure that all server cq results will return false from this - // point forward - expected_server_cq_result = false; - expected_client_cq_result = false; - } - - bool ignore_client_cq_result = - (server_try_cancel == CANCEL_DURING_PROCESSING) || - (server_try_cancel == CANCEL_BEFORE_PROCESSING); - - std::thread cli_thread([&cli_cq, &cli_stream, &expected_client_cq_result, - &ignore_client_cq_result] { - EchoRequest send_request; - // Client sends 3 messages (tags 3, 4 and 5) - for (int tag_idx = 3; tag_idx <= 5; tag_idx++) { + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee", 15)); + + cli_ctx.AddMetadata(meta1.first, meta1.second); + cli_ctx.AddMetadata(meta2.first, meta2.second); + + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); + response_reader->ReadInitialMetadata(tag(4)); + + service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), + cq_.get(), tag(2)); + Verifier().Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + const auto& client_initial_metadata = srv_ctx.client_metadata(); + EXPECT_EQ(meta1.second, + ToString(client_initial_metadata.find(meta1.first)->second)); + EXPECT_EQ(meta2.second, + ToString(client_initial_metadata.find(meta2.first)->second)); + EXPECT_GE(client_initial_metadata.size(), static_cast<size_t>(2)); + + srv_ctx.AddInitialMetadata(meta3.first, meta3.second); + srv_ctx.AddInitialMetadata(meta4.first, meta4.second); + response_writer.SendInitialMetadata(tag(3)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + const auto& server_initial_metadata = cli_ctx.GetServerInitialMetadata(); + EXPECT_EQ(meta3.second, + ToString(server_initial_metadata.find(meta3.first)->second)); + EXPECT_EQ(meta4.second, + ToString(server_initial_metadata.find(meta4.first)->second)); + EXPECT_GE(server_initial_metadata.size(), static_cast<size_t>(2)); + + send_response.set_message(recv_request.message()); + srv_ctx.AddTrailingMetadata(meta5.first, meta5.second); + srv_ctx.AddTrailingMetadata(meta6.first, meta6.second); + response_writer.Finish(send_response, Status::OK, tag(5)); + response_reader->Finish(&recv_response, &recv_status, tag(6)); + + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + const auto& server_trailing_metadata = cli_ctx.GetServerTrailingMetadata(); + EXPECT_EQ(meta5.second, + ToString(server_trailing_metadata.find(meta5.first)->second)); + EXPECT_EQ(meta6.second, + ToString(server_trailing_metadata.find(meta6.first)->second)); + EXPECT_GE(server_trailing_metadata.size(), static_cast<size_t>(2)); +} + +// Server uses AsyncNotifyWhenDone API to check for cancellation +TEST_P(AsyncEnd2endTest, ServerCheckCancellation) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message(GetParam().message_content); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); + response_reader->Finish(&recv_response, &recv_status, tag(4)); + + srv_ctx.AsyncNotifyWhenDone(tag(5)); + service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), + cq_.get(), tag(2)); + + Verifier().Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + cli_ctx.TryCancel(); + Verifier().Expect(5, true).Expect(4, true).Verify(cq_.get()); + EXPECT_TRUE(srv_ctx.IsCancelled()); + + EXPECT_EQ(StatusCode::CANCELLED, recv_status.error_code()); +} + +// Server uses AsyncNotifyWhenDone API to check for normal finish +TEST_P(AsyncEnd2endTest, ServerCheckDone) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message(GetParam().message_content); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); + response_reader->Finish(&recv_response, &recv_status, tag(4)); + + srv_ctx.AsyncNotifyWhenDone(tag(5)); + service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(), + cq_.get(), tag(2)); + + Verifier().Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + response_writer.Finish(send_response, Status::OK, tag(3)); + Verifier().Expect(3, true).Expect(4, true).Expect(5, true).Verify(cq_.get()); + EXPECT_FALSE(srv_ctx.IsCancelled()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); +} + +TEST_P(AsyncEnd2endTest, UnimplementedRpc) { + ChannelArguments args; + const auto& channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); + std::shared_ptr<Channel> channel = + !(GetParam().inproc) ? ::grpc::CreateCustomChannel(server_address_.str(), + channel_creds, args) + : server_->InProcessChannel(args); + std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; + stub = grpc::testing::UnimplementedEchoService::NewStub(channel); + EchoRequest send_request; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + send_request.set_message(GetParam().message_content); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub->AsyncUnimplemented(&cli_ctx, send_request, cq_.get())); + + response_reader->Finish(&recv_response, &recv_status, tag(4)); + Verifier().Expect(4, true).Verify(cq_.get()); + + EXPECT_EQ(StatusCode::UNIMPLEMENTED, recv_status.error_code()); + EXPECT_EQ("", recv_status.error_message()); +} + +// This class is for testing scenarios where RPCs are cancelled on the server +// by calling ServerContext::TryCancel(). Server uses AsyncNotifyWhenDone +// API to check for cancellation +class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest { + protected: + typedef enum { + DO_NOT_CANCEL = 0, + CANCEL_BEFORE_PROCESSING, + CANCEL_DURING_PROCESSING, + CANCEL_AFTER_PROCESSING + } ServerTryCancelRequestPhase; + + // 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 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 + CompletionQueue cli_cq; + + std::unique_ptr<ClientAsyncWriter<EchoRequest>> cli_stream( + stub_->AsyncRequestStream(&cli_ctx, &recv_response, &cli_cq, tag(1))); + + // On the server, request to be notified of 'RequestStream' calls + // and receive the 'RequestStream' call just made by the client + srv_ctx.AsyncNotifyWhenDone(tag(11)); + service_->RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), + tag(2)); + std::thread t1([&cli_cq] { Verifier().Expect(1, true).Verify(&cli_cq); }); + Verifier().Expect(2, true).Verify(cq_.get()); + t1.join(); + + bool expected_server_cq_result = true; + bool expected_client_cq_result = true; + + if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { + srv_ctx.TryCancel(); + Verifier().Expect(11, true).Verify(cq_.get()); + EXPECT_TRUE(srv_ctx.IsCancelled()); + + // Since cancellation is done before server reads any results, we know + // for sure that all server cq results will return false from this + // point forward + expected_server_cq_result = false; + expected_client_cq_result = false; + } + + bool ignore_client_cq_result = + (server_try_cancel == CANCEL_DURING_PROCESSING) || + (server_try_cancel == CANCEL_BEFORE_PROCESSING); + + std::thread cli_thread([&cli_cq, &cli_stream, &expected_client_cq_result, + &ignore_client_cq_result] { + EchoRequest send_request; + // Client sends 3 messages (tags 3, 4 and 5) + for (int tag_idx = 3; tag_idx <= 5; tag_idx++) { send_request.set_message("Ping " + ToString(tag_idx)); - cli_stream->Write(send_request, tag(tag_idx)); - Verifier() - .Expect(tag_idx, expected_client_cq_result) - .Verify(&cli_cq, ignore_client_cq_result); - } - cli_stream->WritesDone(tag(6)); - // Ignore ok on WritesDone since cancel can affect it - Verifier() - .Expect(6, expected_client_cq_result) - .Verify(&cli_cq, ignore_client_cq_result); - }); - - bool ignore_cq_result = false; - bool want_done_tag = false; - std::thread* server_try_cancel_thd = nullptr; - - auto verif = Verifier(); - - if (server_try_cancel == CANCEL_DURING_PROCESSING) { - server_try_cancel_thd = - new std::thread([&srv_ctx] { srv_ctx.TryCancel(); }); - // 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; - // Expect that we might possibly see the done tag that - // indicates cancellation completion in this case - want_done_tag = true; - verif.Expect(11, true); - } - - // Server reads 3 messages (tags 6, 7 and 8) - // But if want_done_tag is true, we might also see tag 11 - for (int tag_idx = 6; tag_idx <= 8; tag_idx++) { - srv_stream.Read(&recv_request, tag(tag_idx)); - // Note that we'll add something to the verifier and verify that - // something was seen, but it might be tag 11 and not what we - // just added - int got_tag = verif.Expect(tag_idx, expected_server_cq_result) - .Next(cq_.get(), ignore_cq_result); - GPR_ASSERT((got_tag == tag_idx) || (got_tag == 11 && want_done_tag)); - if (got_tag == 11) { - EXPECT_TRUE(srv_ctx.IsCancelled()); - want_done_tag = false; - // Now get the other entry that we were waiting on - EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), tag_idx); - } - } - - cli_thread.join(); - - if (server_try_cancel_thd != nullptr) { - server_try_cancel_thd->join(); - delete server_try_cancel_thd; - } - - if (server_try_cancel == CANCEL_AFTER_PROCESSING) { - srv_ctx.TryCancel(); - want_done_tag = true; - verif.Expect(11, true); - } - - if (want_done_tag) { - verif.Verify(cq_.get()); - EXPECT_TRUE(srv_ctx.IsCancelled()); - want_done_tag = false; - } - - // 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().Expect(9, false).Verify(cq_.get()); - - // Client will see the cancellation - cli_stream->Finish(&recv_status, tag(10)); - Verifier().Expect(10, true).Verify(&cli_cq); - EXPECT_FALSE(recv_status.ok()); - EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code()); - - cli_cq.Shutdown(); - void* dummy_tag; - bool dummy_ok; - while (cli_cq.Next(&dummy_tag, &dummy_ok)) { - } - } - - // 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; - 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 - CompletionQueue cli_cq; - std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream( - stub_->AsyncResponseStream(&cli_ctx, send_request, &cli_cq, tag(1))); - // On the server, request to be notified of 'ResponseStream' calls and - // receive the call just made by the client - srv_ctx.AsyncNotifyWhenDone(tag(11)); - service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, - cq_.get(), cq_.get(), tag(2)); - - std::thread t1([&cli_cq] { Verifier().Expect(1, true).Verify(&cli_cq); }); - Verifier().Expect(2, true).Verify(cq_.get()); - t1.join(); - - EXPECT_EQ(send_request.message(), recv_request.message()); - - bool expected_cq_result = true; - bool ignore_cq_result = false; - bool want_done_tag = false; - bool expected_client_cq_result = true; - bool ignore_client_cq_result = - (server_try_cancel != CANCEL_BEFORE_PROCESSING); - - if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { - srv_ctx.TryCancel(); - Verifier().Expect(11, true).Verify(cq_.get()); - EXPECT_TRUE(srv_ctx.IsCancelled()); - - // We know for sure that all cq results will be false from this point - // since the server cancelled the RPC - expected_cq_result = false; - expected_client_cq_result = false; - } - - std::thread cli_thread([&cli_cq, &cli_stream, &expected_client_cq_result, - &ignore_client_cq_result] { - // Client attempts to read the three messages from the server - for (int tag_idx = 6; tag_idx <= 8; tag_idx++) { - EchoResponse recv_response; - cli_stream->Read(&recv_response, tag(tag_idx)); - Verifier() - .Expect(tag_idx, expected_client_cq_result) - .Verify(&cli_cq, ignore_client_cq_result); - } - }); - - std::thread* server_try_cancel_thd = nullptr; - - auto verif = Verifier(); - - if (server_try_cancel == CANCEL_DURING_PROCESSING) { - server_try_cancel_thd = - new std::thread([&srv_ctx] { srv_ctx.TryCancel(); }); - - // 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; - // Expect that we might possibly see the done tag that - // indicates cancellation completion in this case - want_done_tag = true; - verif.Expect(11, true); - } - - // Server sends three messages (tags 3, 4 and 5) - // But if want_done tag is true, we might also see tag 11 - for (int tag_idx = 3; tag_idx <= 5; tag_idx++) { + cli_stream->Write(send_request, tag(tag_idx)); + Verifier() + .Expect(tag_idx, expected_client_cq_result) + .Verify(&cli_cq, ignore_client_cq_result); + } + cli_stream->WritesDone(tag(6)); + // Ignore ok on WritesDone since cancel can affect it + Verifier() + .Expect(6, expected_client_cq_result) + .Verify(&cli_cq, ignore_client_cq_result); + }); + + bool ignore_cq_result = false; + bool want_done_tag = false; + std::thread* server_try_cancel_thd = nullptr; + + auto verif = Verifier(); + + if (server_try_cancel == CANCEL_DURING_PROCESSING) { + server_try_cancel_thd = + new std::thread([&srv_ctx] { srv_ctx.TryCancel(); }); + // 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; + // Expect that we might possibly see the done tag that + // indicates cancellation completion in this case + want_done_tag = true; + verif.Expect(11, true); + } + + // Server reads 3 messages (tags 6, 7 and 8) + // But if want_done_tag is true, we might also see tag 11 + for (int tag_idx = 6; tag_idx <= 8; tag_idx++) { + srv_stream.Read(&recv_request, tag(tag_idx)); + // Note that we'll add something to the verifier and verify that + // something was seen, but it might be tag 11 and not what we + // just added + int got_tag = verif.Expect(tag_idx, expected_server_cq_result) + .Next(cq_.get(), ignore_cq_result); + GPR_ASSERT((got_tag == tag_idx) || (got_tag == 11 && want_done_tag)); + if (got_tag == 11) { + EXPECT_TRUE(srv_ctx.IsCancelled()); + want_done_tag = false; + // Now get the other entry that we were waiting on + EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), tag_idx); + } + } + + cli_thread.join(); + + if (server_try_cancel_thd != nullptr) { + server_try_cancel_thd->join(); + delete server_try_cancel_thd; + } + + if (server_try_cancel == CANCEL_AFTER_PROCESSING) { + srv_ctx.TryCancel(); + want_done_tag = true; + verif.Expect(11, true); + } + + if (want_done_tag) { + verif.Verify(cq_.get()); + EXPECT_TRUE(srv_ctx.IsCancelled()); + want_done_tag = false; + } + + // 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().Expect(9, false).Verify(cq_.get()); + + // Client will see the cancellation + cli_stream->Finish(&recv_status, tag(10)); + Verifier().Expect(10, true).Verify(&cli_cq); + EXPECT_FALSE(recv_status.ok()); + EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code()); + + cli_cq.Shutdown(); + void* dummy_tag; + bool dummy_ok; + while (cli_cq.Next(&dummy_tag, &dummy_ok)) { + } + } + + // 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; + 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 + CompletionQueue cli_cq; + std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream( + stub_->AsyncResponseStream(&cli_ctx, send_request, &cli_cq, tag(1))); + // On the server, request to be notified of 'ResponseStream' calls and + // receive the call just made by the client + srv_ctx.AsyncNotifyWhenDone(tag(11)); + service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, + cq_.get(), cq_.get(), tag(2)); + + std::thread t1([&cli_cq] { Verifier().Expect(1, true).Verify(&cli_cq); }); + Verifier().Expect(2, true).Verify(cq_.get()); + t1.join(); + + EXPECT_EQ(send_request.message(), recv_request.message()); + + bool expected_cq_result = true; + bool ignore_cq_result = false; + bool want_done_tag = false; + bool expected_client_cq_result = true; + bool ignore_client_cq_result = + (server_try_cancel != CANCEL_BEFORE_PROCESSING); + + if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { + srv_ctx.TryCancel(); + Verifier().Expect(11, true).Verify(cq_.get()); + EXPECT_TRUE(srv_ctx.IsCancelled()); + + // We know for sure that all cq results will be false from this point + // since the server cancelled the RPC + expected_cq_result = false; + expected_client_cq_result = false; + } + + std::thread cli_thread([&cli_cq, &cli_stream, &expected_client_cq_result, + &ignore_client_cq_result] { + // Client attempts to read the three messages from the server + for (int tag_idx = 6; tag_idx <= 8; tag_idx++) { + EchoResponse recv_response; + cli_stream->Read(&recv_response, tag(tag_idx)); + Verifier() + .Expect(tag_idx, expected_client_cq_result) + .Verify(&cli_cq, ignore_client_cq_result); + } + }); + + std::thread* server_try_cancel_thd = nullptr; + + auto verif = Verifier(); + + if (server_try_cancel == CANCEL_DURING_PROCESSING) { + server_try_cancel_thd = + new std::thread([&srv_ctx] { srv_ctx.TryCancel(); }); + + // 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; + // Expect that we might possibly see the done tag that + // indicates cancellation completion in this case + want_done_tag = true; + verif.Expect(11, true); + } + + // Server sends three messages (tags 3, 4 and 5) + // But if want_done tag is true, we might also see tag 11 + for (int tag_idx = 3; tag_idx <= 5; tag_idx++) { send_response.set_message("Pong " + ToString(tag_idx)); - srv_stream.Write(send_response, tag(tag_idx)); - // Note that we'll add something to the verifier and verify that - // something was seen, but it might be tag 11 and not what we - // just added - int got_tag = verif.Expect(tag_idx, expected_cq_result) - .Next(cq_.get(), ignore_cq_result); - GPR_ASSERT((got_tag == tag_idx) || (got_tag == 11 && want_done_tag)); - if (got_tag == 11) { - EXPECT_TRUE(srv_ctx.IsCancelled()); - want_done_tag = false; - // Now get the other entry that we were waiting on - EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), tag_idx); - } - } - - if (server_try_cancel_thd != nullptr) { - server_try_cancel_thd->join(); - delete server_try_cancel_thd; - } - - if (server_try_cancel == CANCEL_AFTER_PROCESSING) { - srv_ctx.TryCancel(); - want_done_tag = true; - verif.Expect(11, true); - } - - if (want_done_tag) { - verif.Verify(cq_.get()); - EXPECT_TRUE(srv_ctx.IsCancelled()); - want_done_tag = false; - } - - cli_thread.join(); - - // 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().Expect(9, false).Verify(cq_.get()); - - // Client will see the cancellation - cli_stream->Finish(&recv_status, tag(10)); - Verifier().Expect(10, true).Verify(&cli_cq); - EXPECT_FALSE(recv_status.ok()); - EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code()); - - cli_cq.Shutdown(); - void* dummy_tag; - bool dummy_ok; - while (cli_cq.Next(&dummy_tag, &dummy_ok)) { - } - } - - // 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))); - - // On the server, request to be notified of the 'BidiStream' call and - // receive the call just made by the client - srv_ctx.AsyncNotifyWhenDone(tag(11)); - service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), - tag(2)); - Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); - - auto verif = Verifier(); - - // Client sends the first and the only message - send_request.set_message("Ping"); - cli_stream->Write(send_request, tag(3)); - verif.Expect(3, true); - - bool expected_cq_result = true; - bool ignore_cq_result = false; - bool want_done_tag = false; - - int got_tag, got_tag2; - bool tag_3_done = false; - - if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { - srv_ctx.TryCancel(); - verif.Expect(11, true); - // We know for sure that all server cq results will be false from - // this point since the server cancelled the RPC. However, we can't - // say for sure about the client - expected_cq_result = false; - ignore_cq_result = true; - - do { - got_tag = verif.Next(cq_.get(), ignore_cq_result); - GPR_ASSERT(((got_tag == 3) && !tag_3_done) || (got_tag == 11)); - if (got_tag == 3) { - tag_3_done = true; - } - } while (got_tag != 11); - EXPECT_TRUE(srv_ctx.IsCancelled()); - } - - std::thread* server_try_cancel_thd = nullptr; - - if (server_try_cancel == CANCEL_DURING_PROCESSING) { - server_try_cancel_thd = - new std::thread([&srv_ctx] { srv_ctx.TryCancel(); }); - - // 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; - // Expect that we might possibly see the done tag that - // indicates cancellation completion in this case - want_done_tag = true; - verif.Expect(11, true); - } - - srv_stream.Read(&recv_request, tag(4)); - verif.Expect(4, expected_cq_result); - got_tag = tag_3_done ? 3 : verif.Next(cq_.get(), ignore_cq_result); - got_tag2 = verif.Next(cq_.get(), ignore_cq_result); - GPR_ASSERT((got_tag == 3) || (got_tag == 4) || - (got_tag == 11 && want_done_tag)); - GPR_ASSERT((got_tag2 == 3) || (got_tag2 == 4) || - (got_tag2 == 11 && want_done_tag)); - // If we get 3 and 4, we don't need to wait for 11, but if - // we get 11, we should also clear 3 and 4 - if (got_tag + got_tag2 != 7) { - EXPECT_TRUE(srv_ctx.IsCancelled()); - want_done_tag = false; - got_tag = verif.Next(cq_.get(), ignore_cq_result); - GPR_ASSERT((got_tag == 3) || (got_tag == 4)); - } - - send_response.set_message("Pong"); - srv_stream.Write(send_response, tag(5)); - verif.Expect(5, expected_cq_result); - - cli_stream->Read(&recv_response, tag(6)); - verif.Expect(6, expected_cq_result); - got_tag = verif.Next(cq_.get(), ignore_cq_result); - got_tag2 = verif.Next(cq_.get(), ignore_cq_result); - GPR_ASSERT((got_tag == 5) || (got_tag == 6) || - (got_tag == 11 && want_done_tag)); - GPR_ASSERT((got_tag2 == 5) || (got_tag2 == 6) || - (got_tag2 == 11 && want_done_tag)); - // If we get 5 and 6, we don't need to wait for 11, but if - // we get 11, we should also clear 5 and 6 - if (got_tag + got_tag2 != 11) { - EXPECT_TRUE(srv_ctx.IsCancelled()); - want_done_tag = false; - got_tag = verif.Next(cq_.get(), ignore_cq_result); - GPR_ASSERT((got_tag == 5) || (got_tag == 6)); - } - - // This is expected to succeed in all cases - cli_stream->WritesDone(tag(7)); - verif.Expect(7, true); - // TODO(vjpai): Consider whether the following is too flexible - // or whether it should just be reset to ignore_cq_result - bool ignore_cq_wd_result = - ignore_cq_result || (server_try_cancel == CANCEL_BEFORE_PROCESSING); - got_tag = verif.Next(cq_.get(), ignore_cq_wd_result); - GPR_ASSERT((got_tag == 7) || (got_tag == 11 && want_done_tag)); - if (got_tag == 11) { - EXPECT_TRUE(srv_ctx.IsCancelled()); - want_done_tag = false; - // Now get the other entry that we were waiting on - EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_wd_result), 7); - } - - // This is expected to fail in all cases i.e for all values of - // server_try_cancel. This is because 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)); - verif.Expect(8, false); - got_tag = verif.Next(cq_.get(), ignore_cq_result); - GPR_ASSERT((got_tag == 8) || (got_tag == 11 && want_done_tag)); - if (got_tag == 11) { - EXPECT_TRUE(srv_ctx.IsCancelled()); - want_done_tag = false; - // Now get the other entry that we were waiting on - EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 8); - } - - if (server_try_cancel_thd != nullptr) { - server_try_cancel_thd->join(); - delete server_try_cancel_thd; - } - - if (server_try_cancel == CANCEL_AFTER_PROCESSING) { - srv_ctx.TryCancel(); - want_done_tag = true; - verif.Expect(11, true); - } - - if (want_done_tag) { - verif.Verify(cq_.get()); - EXPECT_TRUE(srv_ctx.IsCancelled()); - want_done_tag = false; - } - - // 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().Expect(9, false).Verify(cq_.get()); - - cli_stream->Finish(&recv_status, tag(10)); - Verifier().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); -} - -std::vector<TestScenario> CreateTestScenarios(bool /*test_secure*/, - bool test_message_size_limit) { - std::vector<TestScenario> scenarios; + srv_stream.Write(send_response, tag(tag_idx)); + // Note that we'll add something to the verifier and verify that + // something was seen, but it might be tag 11 and not what we + // just added + int got_tag = verif.Expect(tag_idx, expected_cq_result) + .Next(cq_.get(), ignore_cq_result); + GPR_ASSERT((got_tag == tag_idx) || (got_tag == 11 && want_done_tag)); + if (got_tag == 11) { + EXPECT_TRUE(srv_ctx.IsCancelled()); + want_done_tag = false; + // Now get the other entry that we were waiting on + EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), tag_idx); + } + } + + if (server_try_cancel_thd != nullptr) { + server_try_cancel_thd->join(); + delete server_try_cancel_thd; + } + + if (server_try_cancel == CANCEL_AFTER_PROCESSING) { + srv_ctx.TryCancel(); + want_done_tag = true; + verif.Expect(11, true); + } + + if (want_done_tag) { + verif.Verify(cq_.get()); + EXPECT_TRUE(srv_ctx.IsCancelled()); + want_done_tag = false; + } + + cli_thread.join(); + + // 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().Expect(9, false).Verify(cq_.get()); + + // Client will see the cancellation + cli_stream->Finish(&recv_status, tag(10)); + Verifier().Expect(10, true).Verify(&cli_cq); + EXPECT_FALSE(recv_status.ok()); + EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code()); + + cli_cq.Shutdown(); + void* dummy_tag; + bool dummy_ok; + while (cli_cq.Next(&dummy_tag, &dummy_ok)) { + } + } + + // 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))); + + // On the server, request to be notified of the 'BidiStream' call and + // receive the call just made by the client + srv_ctx.AsyncNotifyWhenDone(tag(11)); + service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(), + tag(2)); + Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); + + auto verif = Verifier(); + + // Client sends the first and the only message + send_request.set_message("Ping"); + cli_stream->Write(send_request, tag(3)); + verif.Expect(3, true); + + bool expected_cq_result = true; + bool ignore_cq_result = false; + bool want_done_tag = false; + + int got_tag, got_tag2; + bool tag_3_done = false; + + if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { + srv_ctx.TryCancel(); + verif.Expect(11, true); + // We know for sure that all server cq results will be false from + // this point since the server cancelled the RPC. However, we can't + // say for sure about the client + expected_cq_result = false; + ignore_cq_result = true; + + do { + got_tag = verif.Next(cq_.get(), ignore_cq_result); + GPR_ASSERT(((got_tag == 3) && !tag_3_done) || (got_tag == 11)); + if (got_tag == 3) { + tag_3_done = true; + } + } while (got_tag != 11); + EXPECT_TRUE(srv_ctx.IsCancelled()); + } + + std::thread* server_try_cancel_thd = nullptr; + + if (server_try_cancel == CANCEL_DURING_PROCESSING) { + server_try_cancel_thd = + new std::thread([&srv_ctx] { srv_ctx.TryCancel(); }); + + // 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; + // Expect that we might possibly see the done tag that + // indicates cancellation completion in this case + want_done_tag = true; + verif.Expect(11, true); + } + + srv_stream.Read(&recv_request, tag(4)); + verif.Expect(4, expected_cq_result); + got_tag = tag_3_done ? 3 : verif.Next(cq_.get(), ignore_cq_result); + got_tag2 = verif.Next(cq_.get(), ignore_cq_result); + GPR_ASSERT((got_tag == 3) || (got_tag == 4) || + (got_tag == 11 && want_done_tag)); + GPR_ASSERT((got_tag2 == 3) || (got_tag2 == 4) || + (got_tag2 == 11 && want_done_tag)); + // If we get 3 and 4, we don't need to wait for 11, but if + // we get 11, we should also clear 3 and 4 + if (got_tag + got_tag2 != 7) { + EXPECT_TRUE(srv_ctx.IsCancelled()); + want_done_tag = false; + got_tag = verif.Next(cq_.get(), ignore_cq_result); + GPR_ASSERT((got_tag == 3) || (got_tag == 4)); + } + + send_response.set_message("Pong"); + srv_stream.Write(send_response, tag(5)); + verif.Expect(5, expected_cq_result); + + cli_stream->Read(&recv_response, tag(6)); + verif.Expect(6, expected_cq_result); + got_tag = verif.Next(cq_.get(), ignore_cq_result); + got_tag2 = verif.Next(cq_.get(), ignore_cq_result); + GPR_ASSERT((got_tag == 5) || (got_tag == 6) || + (got_tag == 11 && want_done_tag)); + GPR_ASSERT((got_tag2 == 5) || (got_tag2 == 6) || + (got_tag2 == 11 && want_done_tag)); + // If we get 5 and 6, we don't need to wait for 11, but if + // we get 11, we should also clear 5 and 6 + if (got_tag + got_tag2 != 11) { + EXPECT_TRUE(srv_ctx.IsCancelled()); + want_done_tag = false; + got_tag = verif.Next(cq_.get(), ignore_cq_result); + GPR_ASSERT((got_tag == 5) || (got_tag == 6)); + } + + // This is expected to succeed in all cases + cli_stream->WritesDone(tag(7)); + verif.Expect(7, true); + // TODO(vjpai): Consider whether the following is too flexible + // or whether it should just be reset to ignore_cq_result + bool ignore_cq_wd_result = + ignore_cq_result || (server_try_cancel == CANCEL_BEFORE_PROCESSING); + got_tag = verif.Next(cq_.get(), ignore_cq_wd_result); + GPR_ASSERT((got_tag == 7) || (got_tag == 11 && want_done_tag)); + if (got_tag == 11) { + EXPECT_TRUE(srv_ctx.IsCancelled()); + want_done_tag = false; + // Now get the other entry that we were waiting on + EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_wd_result), 7); + } + + // This is expected to fail in all cases i.e for all values of + // server_try_cancel. This is because 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)); + verif.Expect(8, false); + got_tag = verif.Next(cq_.get(), ignore_cq_result); + GPR_ASSERT((got_tag == 8) || (got_tag == 11 && want_done_tag)); + if (got_tag == 11) { + EXPECT_TRUE(srv_ctx.IsCancelled()); + want_done_tag = false; + // Now get the other entry that we were waiting on + EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 8); + } + + if (server_try_cancel_thd != nullptr) { + server_try_cancel_thd->join(); + delete server_try_cancel_thd; + } + + if (server_try_cancel == CANCEL_AFTER_PROCESSING) { + srv_ctx.TryCancel(); + want_done_tag = true; + verif.Expect(11, true); + } + + if (want_done_tag) { + verif.Verify(cq_.get()); + EXPECT_TRUE(srv_ctx.IsCancelled()); + want_done_tag = false; + } + + // 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().Expect(9, false).Verify(cq_.get()); + + cli_stream->Finish(&recv_status, tag(10)); + Verifier().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); +} + +std::vector<TestScenario> CreateTestScenarios(bool /*test_secure*/, + bool test_message_size_limit) { + std::vector<TestScenario> scenarios; std::vector<TString> credentials_types; std::vector<TString> messages; - - auto insec_ok = [] { - // Only allow insecure credentials type when it is registered with the - // provider. User may create providers that do not have insecure. - return GetCredentialsProvider()->GetChannelCredentials( - kInsecureCredentialsType, nullptr) != nullptr; - }; - - if (insec_ok()) { - credentials_types.push_back(kInsecureCredentialsType); - } - auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList(); - for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) { - credentials_types.push_back(*sec); - } - GPR_ASSERT(!credentials_types.empty()); - - messages.push_back("Hello"); - if (test_message_size_limit) { - for (size_t k = 1; k < GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH / 1024; - k *= 32) { + + auto insec_ok = [] { + // Only allow insecure credentials type when it is registered with the + // provider. User may create providers that do not have insecure. + return GetCredentialsProvider()->GetChannelCredentials( + kInsecureCredentialsType, nullptr) != nullptr; + }; + + if (insec_ok()) { + credentials_types.push_back(kInsecureCredentialsType); + } + auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList(); + for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) { + credentials_types.push_back(*sec); + } + GPR_ASSERT(!credentials_types.empty()); + + messages.push_back("Hello"); + if (test_message_size_limit) { + for (size_t k = 1; k < GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH / 1024; + k *= 32) { TString big_msg; - for (size_t i = 0; i < k * 1024; ++i) { - char c = 'a' + (i % 26); - big_msg += c; - } - messages.push_back(big_msg); - } + for (size_t i = 0; i < k * 1024; ++i) { + char c = 'a' + (i % 26); + big_msg += c; + } + messages.push_back(big_msg); + } if (!BuiltUnderMsan()) { // 4MB message processing with SSL is very slow under msan // (causes timeouts) and doesn't really increase the signal from tests. @@ -1911,42 +1911,42 @@ std::vector<TestScenario> CreateTestScenarios(bool /*test_secure*/, messages.push_back( TString(GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH - 100, 'a')); } - } - - // TODO (sreek) Renable tests with health check service after the issue - // https://github.com/grpc/grpc/issues/11223 is resolved - for (auto health_check_service : {false}) { - for (auto msg = messages.begin(); msg != messages.end(); msg++) { - for (auto cred = credentials_types.begin(); - cred != credentials_types.end(); ++cred) { - scenarios.emplace_back(false, *cred, health_check_service, *msg); - } - if (insec_ok()) { - scenarios.emplace_back(true, kInsecureCredentialsType, - health_check_service, *msg); - } - } - } - return scenarios; -} - -INSTANTIATE_TEST_SUITE_P(AsyncEnd2end, AsyncEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(true, true))); -INSTANTIATE_TEST_SUITE_P(AsyncEnd2endServerTryCancel, - AsyncEnd2endServerTryCancelTest, - ::testing::ValuesIn(CreateTestScenarios(false, - false))); - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - // Change the backup poll interval from 5s to 100ms to speed up the - // ReconnectChannel test - GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 100); - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - int ret = RUN_ALL_TESTS(); - return ret; -} + } + + // TODO (sreek) Renable tests with health check service after the issue + // https://github.com/grpc/grpc/issues/11223 is resolved + for (auto health_check_service : {false}) { + for (auto msg = messages.begin(); msg != messages.end(); msg++) { + for (auto cred = credentials_types.begin(); + cred != credentials_types.end(); ++cred) { + scenarios.emplace_back(false, *cred, health_check_service, *msg); + } + if (insec_ok()) { + scenarios.emplace_back(true, kInsecureCredentialsType, + health_check_service, *msg); + } + } + } + return scenarios; +} + +INSTANTIATE_TEST_SUITE_P(AsyncEnd2end, AsyncEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(true, true))); +INSTANTIATE_TEST_SUITE_P(AsyncEnd2endServerTryCancel, + AsyncEnd2endServerTryCancelTest, + ::testing::ValuesIn(CreateTestScenarios(false, + false))); + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + // Change the backup poll interval from 5s to 100ms to speed up the + // ReconnectChannel test + GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 100); + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + int ret = RUN_ALL_TESTS(); + return ret; +} diff --git a/contrib/libs/grpc/test/cpp/end2end/channelz_service_test.cc b/contrib/libs/grpc/test/cpp/end2end/channelz_service_test.cc index 2f9c840a0f..9c723bebb6 100644 --- a/contrib/libs/grpc/test/cpp/end2end/channelz_service_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/channelz_service_test.cc @@ -1,767 +1,767 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ - -#include <grpc/support/port_platform.h> - -#include <grpc/grpc.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/security/credentials.h> -#include <grpcpp/security/server_credentials.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include <grpcpp/ext/channelz_service_plugin.h> -#include "src/core/lib/gpr/env.h" -#include "src/proto/grpc/channelz/channelz.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/test_service_impl.h" - -#include <gtest/gtest.h> - -using grpc::channelz::v1::GetChannelRequest; -using grpc::channelz::v1::GetChannelResponse; -using grpc::channelz::v1::GetServerRequest; -using grpc::channelz::v1::GetServerResponse; -using grpc::channelz::v1::GetServerSocketsRequest; -using grpc::channelz::v1::GetServerSocketsResponse; -using grpc::channelz::v1::GetServersRequest; -using grpc::channelz::v1::GetServersResponse; -using grpc::channelz::v1::GetSocketRequest; -using grpc::channelz::v1::GetSocketResponse; -using grpc::channelz::v1::GetSubchannelRequest; -using grpc::channelz::v1::GetSubchannelResponse; -using grpc::channelz::v1::GetTopChannelsRequest; -using grpc::channelz::v1::GetTopChannelsResponse; - -namespace grpc { -namespace testing { -namespace { - -// Proxy service supports N backends. Sends RPC to backend dictated by -// request->backend_channel_idx(). -class Proxy : public ::grpc::testing::EchoTestService::Service { - public: - Proxy() {} - - void AddChannelToBackend(const std::shared_ptr<Channel>& channel) { - stubs_.push_back(grpc::testing::EchoTestService::NewStub(channel)); - } - - Status Echo(ServerContext* server_context, const EchoRequest* request, - EchoResponse* response) override { - std::unique_ptr<ClientContext> client_context = - ClientContext::FromServerContext(*server_context); - size_t idx = request->param().backend_channel_idx(); - GPR_ASSERT(idx < stubs_.size()); - return stubs_[idx]->Echo(client_context.get(), *request, response); - } - - Status BidiStream(ServerContext* server_context, - ServerReaderWriter<EchoResponse, EchoRequest>* - stream_from_client) override { - EchoRequest request; - EchoResponse response; - std::unique_ptr<ClientContext> client_context = - ClientContext::FromServerContext(*server_context); - - // always use the first proxy for streaming - auto stream_to_backend = stubs_[0]->BidiStream(client_context.get()); - while (stream_from_client->Read(&request)) { - stream_to_backend->Write(request); - stream_to_backend->Read(&response); - stream_from_client->Write(response); - } - - stream_to_backend->WritesDone(); - return stream_to_backend->Finish(); - } - - private: - std::vector<std::unique_ptr<::grpc::testing::EchoTestService::Stub>> stubs_; -}; - -} // namespace - -class ChannelzServerTest : public ::testing::Test { - public: - ChannelzServerTest() {} - static void SetUpTestCase() { -#if TARGET_OS_IPHONE - // Workaround Apple CFStream bug - gpr_setenv("grpc_cfstream", "0"); -#endif - } - void SetUp() override { - // ensure channel server is brought up on all severs we build. - ::grpc::channelz::experimental::InitChannelzService(); - - // We set up a proxy server with channelz enabled. - proxy_port_ = grpc_pick_unused_port_or_die(); - ServerBuilder proxy_builder; +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ + +#include <grpc/support/port_platform.h> + +#include <grpc/grpc.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/security/credentials.h> +#include <grpcpp/security/server_credentials.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include <grpcpp/ext/channelz_service_plugin.h> +#include "src/core/lib/gpr/env.h" +#include "src/proto/grpc/channelz/channelz.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" + +#include <gtest/gtest.h> + +using grpc::channelz::v1::GetChannelRequest; +using grpc::channelz::v1::GetChannelResponse; +using grpc::channelz::v1::GetServerRequest; +using grpc::channelz::v1::GetServerResponse; +using grpc::channelz::v1::GetServerSocketsRequest; +using grpc::channelz::v1::GetServerSocketsResponse; +using grpc::channelz::v1::GetServersRequest; +using grpc::channelz::v1::GetServersResponse; +using grpc::channelz::v1::GetSocketRequest; +using grpc::channelz::v1::GetSocketResponse; +using grpc::channelz::v1::GetSubchannelRequest; +using grpc::channelz::v1::GetSubchannelResponse; +using grpc::channelz::v1::GetTopChannelsRequest; +using grpc::channelz::v1::GetTopChannelsResponse; + +namespace grpc { +namespace testing { +namespace { + +// Proxy service supports N backends. Sends RPC to backend dictated by +// request->backend_channel_idx(). +class Proxy : public ::grpc::testing::EchoTestService::Service { + public: + Proxy() {} + + void AddChannelToBackend(const std::shared_ptr<Channel>& channel) { + stubs_.push_back(grpc::testing::EchoTestService::NewStub(channel)); + } + + Status Echo(ServerContext* server_context, const EchoRequest* request, + EchoResponse* response) override { + std::unique_ptr<ClientContext> client_context = + ClientContext::FromServerContext(*server_context); + size_t idx = request->param().backend_channel_idx(); + GPR_ASSERT(idx < stubs_.size()); + return stubs_[idx]->Echo(client_context.get(), *request, response); + } + + Status BidiStream(ServerContext* server_context, + ServerReaderWriter<EchoResponse, EchoRequest>* + stream_from_client) override { + EchoRequest request; + EchoResponse response; + std::unique_ptr<ClientContext> client_context = + ClientContext::FromServerContext(*server_context); + + // always use the first proxy for streaming + auto stream_to_backend = stubs_[0]->BidiStream(client_context.get()); + while (stream_from_client->Read(&request)) { + stream_to_backend->Write(request); + stream_to_backend->Read(&response); + stream_from_client->Write(response); + } + + stream_to_backend->WritesDone(); + return stream_to_backend->Finish(); + } + + private: + std::vector<std::unique_ptr<::grpc::testing::EchoTestService::Stub>> stubs_; +}; + +} // namespace + +class ChannelzServerTest : public ::testing::Test { + public: + ChannelzServerTest() {} + static void SetUpTestCase() { +#if TARGET_OS_IPHONE + // Workaround Apple CFStream bug + gpr_setenv("grpc_cfstream", "0"); +#endif + } + void SetUp() override { + // ensure channel server is brought up on all severs we build. + ::grpc::channelz::experimental::InitChannelzService(); + + // We set up a proxy server with channelz enabled. + proxy_port_ = grpc_pick_unused_port_or_die(); + ServerBuilder proxy_builder; TString proxy_server_address = "localhost:" + to_string(proxy_port_); - proxy_builder.AddListeningPort(proxy_server_address, - InsecureServerCredentials()); - // forces channelz and channel tracing to be enabled. - proxy_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 1); - proxy_builder.AddChannelArgument( - GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024); - proxy_builder.RegisterService(&proxy_service_); - proxy_server_ = proxy_builder.BuildAndStart(); - } - - // Sets the proxy up to have an arbitrary number of backends. - void ConfigureProxy(size_t num_backends) { - backends_.resize(num_backends); - for (size_t i = 0; i < num_backends; ++i) { - // create a new backend. - backends_[i].port = grpc_pick_unused_port_or_die(); - ServerBuilder backend_builder; + proxy_builder.AddListeningPort(proxy_server_address, + InsecureServerCredentials()); + // forces channelz and channel tracing to be enabled. + proxy_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 1); + proxy_builder.AddChannelArgument( + GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024); + proxy_builder.RegisterService(&proxy_service_); + proxy_server_ = proxy_builder.BuildAndStart(); + } + + // Sets the proxy up to have an arbitrary number of backends. + void ConfigureProxy(size_t num_backends) { + backends_.resize(num_backends); + for (size_t i = 0; i < num_backends; ++i) { + // create a new backend. + backends_[i].port = grpc_pick_unused_port_or_die(); + ServerBuilder backend_builder; TString backend_server_address = - "localhost:" + to_string(backends_[i].port); - backend_builder.AddListeningPort(backend_server_address, - InsecureServerCredentials()); - backends_[i].service.reset(new TestServiceImpl); - // ensure that the backend itself has channelz disabled. - backend_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 0); - backend_builder.RegisterService(backends_[i].service.get()); - backends_[i].server = backend_builder.BuildAndStart(); - // set up a channel to the backend. We ensure that this channel has - // channelz enabled since these channels (proxy outbound to backends) - // are the ones that our test will actually be validating. - ChannelArguments args; - args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 1); - args.SetInt(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024); - std::shared_ptr<Channel> channel_to_backend = ::grpc::CreateCustomChannel( - backend_server_address, InsecureChannelCredentials(), args); - proxy_service_.AddChannelToBackend(channel_to_backend); - } - } - - void ResetStubs() { - string target = "dns:localhost:" + to_string(proxy_port_); - ChannelArguments args; - // disable channelz. We only want to focus on proxy to backend outbound. - args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0); - std::shared_ptr<Channel> channel = - ::grpc::CreateCustomChannel(target, InsecureChannelCredentials(), args); - channelz_stub_ = grpc::channelz::v1::Channelz::NewStub(channel); - echo_stub_ = grpc::testing::EchoTestService::NewStub(channel); - } - - std::unique_ptr<grpc::testing::EchoTestService::Stub> NewEchoStub() { - string target = "dns:localhost:" + to_string(proxy_port_); - ChannelArguments args; - // disable channelz. We only want to focus on proxy to backend outbound. - args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0); - // This ensures that gRPC will not do connection sharing. - args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, true); - std::shared_ptr<Channel> channel = - ::grpc::CreateCustomChannel(target, InsecureChannelCredentials(), args); - return grpc::testing::EchoTestService::NewStub(channel); - } - - void SendSuccessfulEcho(int channel_idx) { - EchoRequest request; - EchoResponse response; - request.set_message("Hello channelz"); - request.mutable_param()->set_backend_channel_idx(channel_idx); - ClientContext context; - Status s = echo_stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - } - - void SendSuccessfulStream(int num_messages) { - EchoRequest request; - EchoResponse response; - request.set_message("Hello channelz"); - ClientContext context; - auto stream_to_proxy = echo_stub_->BidiStream(&context); - for (int i = 0; i < num_messages; ++i) { - EXPECT_TRUE(stream_to_proxy->Write(request)); - EXPECT_TRUE(stream_to_proxy->Read(&response)); - } - stream_to_proxy->WritesDone(); - Status s = stream_to_proxy->Finish(); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - } - - void SendFailedEcho(int channel_idx) { - EchoRequest request; - EchoResponse response; - request.set_message("Hello channelz"); - request.mutable_param()->set_backend_channel_idx(channel_idx); - auto* error = request.mutable_param()->mutable_expected_error(); - error->set_code(13); // INTERNAL - error->set_error_message("error"); - ClientContext context; - Status s = echo_stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - } - - // Uses GetTopChannels to return the channel_id of a particular channel, - // so that the unit tests may test GetChannel call. - intptr_t GetChannelId(int channel_idx) { - GetTopChannelsRequest request; - GetTopChannelsResponse response; - request.set_start_channel_id(0); - ClientContext context; - Status s = channelz_stub_->GetTopChannels(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_GT(response.channel_size(), channel_idx); - return response.channel(channel_idx).ref().channel_id(); - } - - static string to_string(const int number) { - std::stringstream strs; - strs << number; - return strs.str(); - } - - protected: - // package of data needed for each backend server. - struct BackendData { - std::unique_ptr<Server> server; - int port; - std::unique_ptr<TestServiceImpl> service; - }; - - std::unique_ptr<grpc::channelz::v1::Channelz::Stub> channelz_stub_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> echo_stub_; - - // proxy server to ping with channelz requests. - std::unique_ptr<Server> proxy_server_; - int proxy_port_; - Proxy proxy_service_; - - // backends. All implement the echo service. - std::vector<BackendData> backends_; -}; - -TEST_F(ChannelzServerTest, BasicTest) { - ResetStubs(); - ConfigureProxy(1); - GetTopChannelsRequest request; - GetTopChannelsResponse response; - request.set_start_channel_id(0); - ClientContext context; - Status s = channelz_stub_->GetTopChannels(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.channel_size(), 1); -} - -TEST_F(ChannelzServerTest, HighStartId) { - ResetStubs(); - ConfigureProxy(1); - GetTopChannelsRequest request; - GetTopChannelsResponse response; - request.set_start_channel_id(10000); - ClientContext context; - Status s = channelz_stub_->GetTopChannels(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.channel_size(), 0); -} - -TEST_F(ChannelzServerTest, SuccessfulRequestTest) { - ResetStubs(); - ConfigureProxy(1); - SendSuccessfulEcho(0); - GetChannelRequest request; - GetChannelResponse response; - request.set_channel_id(GetChannelId(0)); - ClientContext context; - Status s = channelz_stub_->GetChannel(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.channel().data().calls_started(), 1); - EXPECT_EQ(response.channel().data().calls_succeeded(), 1); - EXPECT_EQ(response.channel().data().calls_failed(), 0); -} - -TEST_F(ChannelzServerTest, FailedRequestTest) { - ResetStubs(); - ConfigureProxy(1); - SendFailedEcho(0); - GetChannelRequest request; - GetChannelResponse response; - request.set_channel_id(GetChannelId(0)); - ClientContext context; - Status s = channelz_stub_->GetChannel(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.channel().data().calls_started(), 1); - EXPECT_EQ(response.channel().data().calls_succeeded(), 0); - EXPECT_EQ(response.channel().data().calls_failed(), 1); -} - -TEST_F(ChannelzServerTest, ManyRequestsTest) { - ResetStubs(); - ConfigureProxy(1); - // send some RPCs - const int kNumSuccess = 10; - const int kNumFailed = 11; - for (int i = 0; i < kNumSuccess; ++i) { - SendSuccessfulEcho(0); - } - for (int i = 0; i < kNumFailed; ++i) { - SendFailedEcho(0); - } - GetChannelRequest request; - GetChannelResponse response; - request.set_channel_id(GetChannelId(0)); - ClientContext context; - Status s = channelz_stub_->GetChannel(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.channel().data().calls_started(), - kNumSuccess + kNumFailed); - EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess); - EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed); -} - -TEST_F(ChannelzServerTest, ManyChannels) { - ResetStubs(); - const int kNumChannels = 4; - ConfigureProxy(kNumChannels); - GetTopChannelsRequest request; - GetTopChannelsResponse response; - request.set_start_channel_id(0); - ClientContext context; - Status s = channelz_stub_->GetTopChannels(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.channel_size(), kNumChannels); -} - -TEST_F(ChannelzServerTest, ManyRequestsManyChannels) { - ResetStubs(); - const int kNumChannels = 4; - ConfigureProxy(kNumChannels); - const int kNumSuccess = 10; - const int kNumFailed = 11; - for (int i = 0; i < kNumSuccess; ++i) { - SendSuccessfulEcho(0); - SendSuccessfulEcho(2); - } - for (int i = 0; i < kNumFailed; ++i) { - SendFailedEcho(1); - SendFailedEcho(2); - } - - // the first channel saw only successes - { - GetChannelRequest request; - GetChannelResponse response; - request.set_channel_id(GetChannelId(0)); - ClientContext context; - Status s = channelz_stub_->GetChannel(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.channel().data().calls_started(), kNumSuccess); - EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess); - EXPECT_EQ(response.channel().data().calls_failed(), 0); - } - - // the second channel saw only failures - { - GetChannelRequest request; - GetChannelResponse response; - request.set_channel_id(GetChannelId(1)); - ClientContext context; - Status s = channelz_stub_->GetChannel(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.channel().data().calls_started(), kNumFailed); - EXPECT_EQ(response.channel().data().calls_succeeded(), 0); - EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed); - } - - // the third channel saw both - { - GetChannelRequest request; - GetChannelResponse response; - request.set_channel_id(GetChannelId(2)); - ClientContext context; - Status s = channelz_stub_->GetChannel(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.channel().data().calls_started(), - kNumSuccess + kNumFailed); - EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess); - EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed); - } - - // the fourth channel saw nothing - { - GetChannelRequest request; - GetChannelResponse response; - request.set_channel_id(GetChannelId(3)); - ClientContext context; - Status s = channelz_stub_->GetChannel(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.channel().data().calls_started(), 0); - EXPECT_EQ(response.channel().data().calls_succeeded(), 0); - EXPECT_EQ(response.channel().data().calls_failed(), 0); - } -} - -TEST_F(ChannelzServerTest, ManySubchannels) { - ResetStubs(); - const int kNumChannels = 4; - ConfigureProxy(kNumChannels); - const int kNumSuccess = 10; - const int kNumFailed = 11; - for (int i = 0; i < kNumSuccess; ++i) { - SendSuccessfulEcho(0); - SendSuccessfulEcho(2); - } - for (int i = 0; i < kNumFailed; ++i) { - SendFailedEcho(1); - SendFailedEcho(2); - } - GetTopChannelsRequest gtc_request; - GetTopChannelsResponse gtc_response; - gtc_request.set_start_channel_id(0); - ClientContext context; - Status s = - channelz_stub_->GetTopChannels(&context, gtc_request, >c_response); - EXPECT_TRUE(s.ok()) << s.error_message(); - EXPECT_EQ(gtc_response.channel_size(), kNumChannels); - for (int i = 0; i < gtc_response.channel_size(); ++i) { - // if the channel sent no RPCs, then expect no subchannels to have been - // created. - if (gtc_response.channel(i).data().calls_started() == 0) { - EXPECT_EQ(gtc_response.channel(i).subchannel_ref_size(), 0); - continue; - } - // The resolver must return at least one address. - ASSERT_GT(gtc_response.channel(i).subchannel_ref_size(), 0); - GetSubchannelRequest gsc_request; - GetSubchannelResponse gsc_response; - gsc_request.set_subchannel_id( - gtc_response.channel(i).subchannel_ref(0).subchannel_id()); - ClientContext context; - Status s = - channelz_stub_->GetSubchannel(&context, gsc_request, &gsc_response); - EXPECT_TRUE(s.ok()) << s.error_message(); - EXPECT_EQ(gtc_response.channel(i).data().calls_started(), - gsc_response.subchannel().data().calls_started()); - EXPECT_EQ(gtc_response.channel(i).data().calls_succeeded(), - gsc_response.subchannel().data().calls_succeeded()); - EXPECT_EQ(gtc_response.channel(i).data().calls_failed(), - gsc_response.subchannel().data().calls_failed()); - } -} - -TEST_F(ChannelzServerTest, BasicServerTest) { - ResetStubs(); - ConfigureProxy(1); - GetServersRequest request; - GetServersResponse response; - request.set_start_server_id(0); - ClientContext context; - Status s = channelz_stub_->GetServers(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.server_size(), 1); -} - -TEST_F(ChannelzServerTest, BasicGetServerTest) { - ResetStubs(); - ConfigureProxy(1); - GetServersRequest get_servers_request; - GetServersResponse get_servers_response; - get_servers_request.set_start_server_id(0); - ClientContext get_servers_context; - Status s = channelz_stub_->GetServers( - &get_servers_context, get_servers_request, &get_servers_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(get_servers_response.server_size(), 1); - GetServerRequest get_server_request; - GetServerResponse get_server_response; - get_server_request.set_server_id( - get_servers_response.server(0).ref().server_id()); - ClientContext get_server_context; - s = channelz_stub_->GetServer(&get_server_context, get_server_request, - &get_server_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(get_servers_response.server(0).ref().server_id(), - get_server_response.server().ref().server_id()); -} - -TEST_F(ChannelzServerTest, ServerCallTest) { - ResetStubs(); - ConfigureProxy(1); - const int kNumSuccess = 10; - const int kNumFailed = 11; - for (int i = 0; i < kNumSuccess; ++i) { - SendSuccessfulEcho(0); - } - for (int i = 0; i < kNumFailed; ++i) { - SendFailedEcho(0); - } - GetServersRequest request; - GetServersResponse response; - request.set_start_server_id(0); - ClientContext context; - Status s = channelz_stub_->GetServers(&context, request, &response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(response.server_size(), 1); - EXPECT_EQ(response.server(0).data().calls_succeeded(), kNumSuccess); - EXPECT_EQ(response.server(0).data().calls_failed(), kNumFailed); - // This is success+failure+1 because the call that retrieved this information - // will be counted as started. It will not track success/failure until after - // it has returned, so that is not included in the response. - EXPECT_EQ(response.server(0).data().calls_started(), - kNumSuccess + kNumFailed + 1); -} - -TEST_F(ChannelzServerTest, ManySubchannelsAndSockets) { - ResetStubs(); - const int kNumChannels = 4; - ConfigureProxy(kNumChannels); - const int kNumSuccess = 10; - const int kNumFailed = 11; - for (int i = 0; i < kNumSuccess; ++i) { - SendSuccessfulEcho(0); - SendSuccessfulEcho(2); - } - for (int i = 0; i < kNumFailed; ++i) { - SendFailedEcho(1); - SendFailedEcho(2); - } - GetTopChannelsRequest gtc_request; - GetTopChannelsResponse gtc_response; - gtc_request.set_start_channel_id(0); - ClientContext context; - Status s = - channelz_stub_->GetTopChannels(&context, gtc_request, >c_response); - EXPECT_TRUE(s.ok()) << s.error_message(); - EXPECT_EQ(gtc_response.channel_size(), kNumChannels); - for (int i = 0; i < gtc_response.channel_size(); ++i) { - // if the channel sent no RPCs, then expect no subchannels to have been - // created. - if (gtc_response.channel(i).data().calls_started() == 0) { - EXPECT_EQ(gtc_response.channel(i).subchannel_ref_size(), 0); - continue; - } - // The resolver must return at least one address. - ASSERT_GT(gtc_response.channel(i).subchannel_ref_size(), 0); - // First grab the subchannel - GetSubchannelRequest get_subchannel_req; - GetSubchannelResponse get_subchannel_resp; - get_subchannel_req.set_subchannel_id( - gtc_response.channel(i).subchannel_ref(0).subchannel_id()); - ClientContext get_subchannel_ctx; - Status s = channelz_stub_->GetSubchannel( - &get_subchannel_ctx, get_subchannel_req, &get_subchannel_resp); - EXPECT_TRUE(s.ok()) << s.error_message(); - EXPECT_EQ(get_subchannel_resp.subchannel().socket_ref_size(), 1); - // Now grab the socket. - GetSocketRequest get_socket_req; - GetSocketResponse get_socket_resp; - ClientContext get_socket_ctx; - get_socket_req.set_socket_id( - get_subchannel_resp.subchannel().socket_ref(0).socket_id()); - s = channelz_stub_->GetSocket(&get_socket_ctx, get_socket_req, - &get_socket_resp); - EXPECT_TRUE( - get_subchannel_resp.subchannel().socket_ref(0).name().find("http")); - EXPECT_TRUE(s.ok()) << s.error_message(); - // calls started == streams started AND stream succeeded. Since none of - // these RPCs were canceled, all of the streams will succeeded even though - // the RPCs they represent might have failed. - EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(), - get_socket_resp.socket().data().streams_started()); - EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(), - get_socket_resp.socket().data().streams_succeeded()); - // All of the calls were unary, so calls started == messages sent. - EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(), - get_socket_resp.socket().data().messages_sent()); - // We only get responses when the RPC was successful, so - // calls succeeded == messages received. - EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_succeeded(), - get_socket_resp.socket().data().messages_received()); - } -} - -TEST_F(ChannelzServerTest, StreamingRPC) { - ResetStubs(); - ConfigureProxy(1); - const int kNumMessages = 5; - SendSuccessfulStream(kNumMessages); - // Get the channel - GetChannelRequest get_channel_request; - GetChannelResponse get_channel_response; - get_channel_request.set_channel_id(GetChannelId(0)); - ClientContext get_channel_context; - Status s = channelz_stub_->GetChannel( - &get_channel_context, get_channel_request, &get_channel_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(get_channel_response.channel().data().calls_started(), 1); - EXPECT_EQ(get_channel_response.channel().data().calls_succeeded(), 1); - EXPECT_EQ(get_channel_response.channel().data().calls_failed(), 0); - // Get the subchannel - ASSERT_GT(get_channel_response.channel().subchannel_ref_size(), 0); - GetSubchannelRequest get_subchannel_request; - GetSubchannelResponse get_subchannel_response; - ClientContext get_subchannel_context; - get_subchannel_request.set_subchannel_id( - get_channel_response.channel().subchannel_ref(0).subchannel_id()); - s = channelz_stub_->GetSubchannel(&get_subchannel_context, - get_subchannel_request, - &get_subchannel_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(get_subchannel_response.subchannel().data().calls_started(), 1); - EXPECT_EQ(get_subchannel_response.subchannel().data().calls_succeeded(), 1); - EXPECT_EQ(get_subchannel_response.subchannel().data().calls_failed(), 0); - // Get the socket - ASSERT_GT(get_subchannel_response.subchannel().socket_ref_size(), 0); - GetSocketRequest get_socket_request; - GetSocketResponse get_socket_response; - ClientContext get_socket_context; - get_socket_request.set_socket_id( - get_subchannel_response.subchannel().socket_ref(0).socket_id()); - EXPECT_TRUE( - get_subchannel_response.subchannel().socket_ref(0).name().find("http")); - s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request, - &get_socket_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(get_socket_response.socket().data().streams_started(), 1); - EXPECT_EQ(get_socket_response.socket().data().streams_succeeded(), 1); - EXPECT_EQ(get_socket_response.socket().data().streams_failed(), 0); - EXPECT_EQ(get_socket_response.socket().data().messages_sent(), kNumMessages); - EXPECT_EQ(get_socket_response.socket().data().messages_received(), - kNumMessages); -} - -TEST_F(ChannelzServerTest, GetServerSocketsTest) { - ResetStubs(); - ConfigureProxy(1); - GetServersRequest get_server_request; - GetServersResponse get_server_response; - get_server_request.set_start_server_id(0); - ClientContext get_server_context; - Status s = channelz_stub_->GetServers(&get_server_context, get_server_request, - &get_server_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(get_server_response.server_size(), 1); - GetServerSocketsRequest get_server_sockets_request; - GetServerSocketsResponse get_server_sockets_response; - get_server_sockets_request.set_server_id( - get_server_response.server(0).ref().server_id()); - get_server_sockets_request.set_start_socket_id(0); - ClientContext get_server_sockets_context; - s = channelz_stub_->GetServerSockets(&get_server_sockets_context, - get_server_sockets_request, - &get_server_sockets_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(get_server_sockets_response.socket_ref_size(), 1); - EXPECT_TRUE(get_server_sockets_response.socket_ref(0).name().find("http")); -} - -TEST_F(ChannelzServerTest, GetServerSocketsPaginationTest) { - ResetStubs(); - ConfigureProxy(1); - std::vector<std::unique_ptr<grpc::testing::EchoTestService::Stub>> stubs; - const int kNumServerSocketsCreated = 20; - for (int i = 0; i < kNumServerSocketsCreated; ++i) { - stubs.push_back(NewEchoStub()); - EchoRequest request; - EchoResponse response; - request.set_message("Hello channelz"); - request.mutable_param()->set_backend_channel_idx(0); - ClientContext context; - Status s = stubs.back()->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - } - GetServersRequest get_server_request; - GetServersResponse get_server_response; - get_server_request.set_start_server_id(0); - ClientContext get_server_context; - Status s = channelz_stub_->GetServers(&get_server_context, get_server_request, - &get_server_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(get_server_response.server_size(), 1); - // Make a request that gets all of the serversockets - { - GetServerSocketsRequest get_server_sockets_request; - GetServerSocketsResponse get_server_sockets_response; - get_server_sockets_request.set_server_id( - get_server_response.server(0).ref().server_id()); - get_server_sockets_request.set_start_socket_id(0); - ClientContext get_server_sockets_context; - s = channelz_stub_->GetServerSockets(&get_server_sockets_context, - get_server_sockets_request, - &get_server_sockets_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - // We add one to account the channelz stub that will end up creating - // a serversocket. - EXPECT_EQ(get_server_sockets_response.socket_ref_size(), - kNumServerSocketsCreated + 1); - EXPECT_TRUE(get_server_sockets_response.end()); - } - // Now we make a request that exercises pagination. - { - GetServerSocketsRequest get_server_sockets_request; - GetServerSocketsResponse get_server_sockets_response; - get_server_sockets_request.set_server_id( - get_server_response.server(0).ref().server_id()); - get_server_sockets_request.set_start_socket_id(0); - const int kMaxResults = 10; - get_server_sockets_request.set_max_results(kMaxResults); - ClientContext get_server_sockets_context; - s = channelz_stub_->GetServerSockets(&get_server_sockets_context, - get_server_sockets_request, - &get_server_sockets_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(get_server_sockets_response.socket_ref_size(), kMaxResults); - EXPECT_FALSE(get_server_sockets_response.end()); - } -} - -TEST_F(ChannelzServerTest, GetServerListenSocketsTest) { - ResetStubs(); - ConfigureProxy(1); - GetServersRequest get_server_request; - GetServersResponse get_server_response; - get_server_request.set_start_server_id(0); - ClientContext get_server_context; - Status s = channelz_stub_->GetServers(&get_server_context, get_server_request, - &get_server_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - EXPECT_EQ(get_server_response.server_size(), 1); - EXPECT_EQ(get_server_response.server(0).listen_socket_size(), 1); - GetSocketRequest get_socket_request; - GetSocketResponse get_socket_response; - get_socket_request.set_socket_id( - get_server_response.server(0).listen_socket(0).socket_id()); - EXPECT_TRUE( - get_server_response.server(0).listen_socket(0).name().find("http")); - ClientContext get_socket_context; - s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request, - &get_socket_response); - EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); -} - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + "localhost:" + to_string(backends_[i].port); + backend_builder.AddListeningPort(backend_server_address, + InsecureServerCredentials()); + backends_[i].service.reset(new TestServiceImpl); + // ensure that the backend itself has channelz disabled. + backend_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 0); + backend_builder.RegisterService(backends_[i].service.get()); + backends_[i].server = backend_builder.BuildAndStart(); + // set up a channel to the backend. We ensure that this channel has + // channelz enabled since these channels (proxy outbound to backends) + // are the ones that our test will actually be validating. + ChannelArguments args; + args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 1); + args.SetInt(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024); + std::shared_ptr<Channel> channel_to_backend = ::grpc::CreateCustomChannel( + backend_server_address, InsecureChannelCredentials(), args); + proxy_service_.AddChannelToBackend(channel_to_backend); + } + } + + void ResetStubs() { + string target = "dns:localhost:" + to_string(proxy_port_); + ChannelArguments args; + // disable channelz. We only want to focus on proxy to backend outbound. + args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0); + std::shared_ptr<Channel> channel = + ::grpc::CreateCustomChannel(target, InsecureChannelCredentials(), args); + channelz_stub_ = grpc::channelz::v1::Channelz::NewStub(channel); + echo_stub_ = grpc::testing::EchoTestService::NewStub(channel); + } + + std::unique_ptr<grpc::testing::EchoTestService::Stub> NewEchoStub() { + string target = "dns:localhost:" + to_string(proxy_port_); + ChannelArguments args; + // disable channelz. We only want to focus on proxy to backend outbound. + args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0); + // This ensures that gRPC will not do connection sharing. + args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, true); + std::shared_ptr<Channel> channel = + ::grpc::CreateCustomChannel(target, InsecureChannelCredentials(), args); + return grpc::testing::EchoTestService::NewStub(channel); + } + + void SendSuccessfulEcho(int channel_idx) { + EchoRequest request; + EchoResponse response; + request.set_message("Hello channelz"); + request.mutable_param()->set_backend_channel_idx(channel_idx); + ClientContext context; + Status s = echo_stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + } + + void SendSuccessfulStream(int num_messages) { + EchoRequest request; + EchoResponse response; + request.set_message("Hello channelz"); + ClientContext context; + auto stream_to_proxy = echo_stub_->BidiStream(&context); + for (int i = 0; i < num_messages; ++i) { + EXPECT_TRUE(stream_to_proxy->Write(request)); + EXPECT_TRUE(stream_to_proxy->Read(&response)); + } + stream_to_proxy->WritesDone(); + Status s = stream_to_proxy->Finish(); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + } + + void SendFailedEcho(int channel_idx) { + EchoRequest request; + EchoResponse response; + request.set_message("Hello channelz"); + request.mutable_param()->set_backend_channel_idx(channel_idx); + auto* error = request.mutable_param()->mutable_expected_error(); + error->set_code(13); // INTERNAL + error->set_error_message("error"); + ClientContext context; + Status s = echo_stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + } + + // Uses GetTopChannels to return the channel_id of a particular channel, + // so that the unit tests may test GetChannel call. + intptr_t GetChannelId(int channel_idx) { + GetTopChannelsRequest request; + GetTopChannelsResponse response; + request.set_start_channel_id(0); + ClientContext context; + Status s = channelz_stub_->GetTopChannels(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_GT(response.channel_size(), channel_idx); + return response.channel(channel_idx).ref().channel_id(); + } + + static string to_string(const int number) { + std::stringstream strs; + strs << number; + return strs.str(); + } + + protected: + // package of data needed for each backend server. + struct BackendData { + std::unique_ptr<Server> server; + int port; + std::unique_ptr<TestServiceImpl> service; + }; + + std::unique_ptr<grpc::channelz::v1::Channelz::Stub> channelz_stub_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> echo_stub_; + + // proxy server to ping with channelz requests. + std::unique_ptr<Server> proxy_server_; + int proxy_port_; + Proxy proxy_service_; + + // backends. All implement the echo service. + std::vector<BackendData> backends_; +}; + +TEST_F(ChannelzServerTest, BasicTest) { + ResetStubs(); + ConfigureProxy(1); + GetTopChannelsRequest request; + GetTopChannelsResponse response; + request.set_start_channel_id(0); + ClientContext context; + Status s = channelz_stub_->GetTopChannels(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.channel_size(), 1); +} + +TEST_F(ChannelzServerTest, HighStartId) { + ResetStubs(); + ConfigureProxy(1); + GetTopChannelsRequest request; + GetTopChannelsResponse response; + request.set_start_channel_id(10000); + ClientContext context; + Status s = channelz_stub_->GetTopChannels(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.channel_size(), 0); +} + +TEST_F(ChannelzServerTest, SuccessfulRequestTest) { + ResetStubs(); + ConfigureProxy(1); + SendSuccessfulEcho(0); + GetChannelRequest request; + GetChannelResponse response; + request.set_channel_id(GetChannelId(0)); + ClientContext context; + Status s = channelz_stub_->GetChannel(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.channel().data().calls_started(), 1); + EXPECT_EQ(response.channel().data().calls_succeeded(), 1); + EXPECT_EQ(response.channel().data().calls_failed(), 0); +} + +TEST_F(ChannelzServerTest, FailedRequestTest) { + ResetStubs(); + ConfigureProxy(1); + SendFailedEcho(0); + GetChannelRequest request; + GetChannelResponse response; + request.set_channel_id(GetChannelId(0)); + ClientContext context; + Status s = channelz_stub_->GetChannel(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.channel().data().calls_started(), 1); + EXPECT_EQ(response.channel().data().calls_succeeded(), 0); + EXPECT_EQ(response.channel().data().calls_failed(), 1); +} + +TEST_F(ChannelzServerTest, ManyRequestsTest) { + ResetStubs(); + ConfigureProxy(1); + // send some RPCs + const int kNumSuccess = 10; + const int kNumFailed = 11; + for (int i = 0; i < kNumSuccess; ++i) { + SendSuccessfulEcho(0); + } + for (int i = 0; i < kNumFailed; ++i) { + SendFailedEcho(0); + } + GetChannelRequest request; + GetChannelResponse response; + request.set_channel_id(GetChannelId(0)); + ClientContext context; + Status s = channelz_stub_->GetChannel(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.channel().data().calls_started(), + kNumSuccess + kNumFailed); + EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess); + EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed); +} + +TEST_F(ChannelzServerTest, ManyChannels) { + ResetStubs(); + const int kNumChannels = 4; + ConfigureProxy(kNumChannels); + GetTopChannelsRequest request; + GetTopChannelsResponse response; + request.set_start_channel_id(0); + ClientContext context; + Status s = channelz_stub_->GetTopChannels(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.channel_size(), kNumChannels); +} + +TEST_F(ChannelzServerTest, ManyRequestsManyChannels) { + ResetStubs(); + const int kNumChannels = 4; + ConfigureProxy(kNumChannels); + const int kNumSuccess = 10; + const int kNumFailed = 11; + for (int i = 0; i < kNumSuccess; ++i) { + SendSuccessfulEcho(0); + SendSuccessfulEcho(2); + } + for (int i = 0; i < kNumFailed; ++i) { + SendFailedEcho(1); + SendFailedEcho(2); + } + + // the first channel saw only successes + { + GetChannelRequest request; + GetChannelResponse response; + request.set_channel_id(GetChannelId(0)); + ClientContext context; + Status s = channelz_stub_->GetChannel(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.channel().data().calls_started(), kNumSuccess); + EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess); + EXPECT_EQ(response.channel().data().calls_failed(), 0); + } + + // the second channel saw only failures + { + GetChannelRequest request; + GetChannelResponse response; + request.set_channel_id(GetChannelId(1)); + ClientContext context; + Status s = channelz_stub_->GetChannel(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.channel().data().calls_started(), kNumFailed); + EXPECT_EQ(response.channel().data().calls_succeeded(), 0); + EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed); + } + + // the third channel saw both + { + GetChannelRequest request; + GetChannelResponse response; + request.set_channel_id(GetChannelId(2)); + ClientContext context; + Status s = channelz_stub_->GetChannel(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.channel().data().calls_started(), + kNumSuccess + kNumFailed); + EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess); + EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed); + } + + // the fourth channel saw nothing + { + GetChannelRequest request; + GetChannelResponse response; + request.set_channel_id(GetChannelId(3)); + ClientContext context; + Status s = channelz_stub_->GetChannel(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.channel().data().calls_started(), 0); + EXPECT_EQ(response.channel().data().calls_succeeded(), 0); + EXPECT_EQ(response.channel().data().calls_failed(), 0); + } +} + +TEST_F(ChannelzServerTest, ManySubchannels) { + ResetStubs(); + const int kNumChannels = 4; + ConfigureProxy(kNumChannels); + const int kNumSuccess = 10; + const int kNumFailed = 11; + for (int i = 0; i < kNumSuccess; ++i) { + SendSuccessfulEcho(0); + SendSuccessfulEcho(2); + } + for (int i = 0; i < kNumFailed; ++i) { + SendFailedEcho(1); + SendFailedEcho(2); + } + GetTopChannelsRequest gtc_request; + GetTopChannelsResponse gtc_response; + gtc_request.set_start_channel_id(0); + ClientContext context; + Status s = + channelz_stub_->GetTopChannels(&context, gtc_request, >c_response); + EXPECT_TRUE(s.ok()) << s.error_message(); + EXPECT_EQ(gtc_response.channel_size(), kNumChannels); + for (int i = 0; i < gtc_response.channel_size(); ++i) { + // if the channel sent no RPCs, then expect no subchannels to have been + // created. + if (gtc_response.channel(i).data().calls_started() == 0) { + EXPECT_EQ(gtc_response.channel(i).subchannel_ref_size(), 0); + continue; + } + // The resolver must return at least one address. + ASSERT_GT(gtc_response.channel(i).subchannel_ref_size(), 0); + GetSubchannelRequest gsc_request; + GetSubchannelResponse gsc_response; + gsc_request.set_subchannel_id( + gtc_response.channel(i).subchannel_ref(0).subchannel_id()); + ClientContext context; + Status s = + channelz_stub_->GetSubchannel(&context, gsc_request, &gsc_response); + EXPECT_TRUE(s.ok()) << s.error_message(); + EXPECT_EQ(gtc_response.channel(i).data().calls_started(), + gsc_response.subchannel().data().calls_started()); + EXPECT_EQ(gtc_response.channel(i).data().calls_succeeded(), + gsc_response.subchannel().data().calls_succeeded()); + EXPECT_EQ(gtc_response.channel(i).data().calls_failed(), + gsc_response.subchannel().data().calls_failed()); + } +} + +TEST_F(ChannelzServerTest, BasicServerTest) { + ResetStubs(); + ConfigureProxy(1); + GetServersRequest request; + GetServersResponse response; + request.set_start_server_id(0); + ClientContext context; + Status s = channelz_stub_->GetServers(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.server_size(), 1); +} + +TEST_F(ChannelzServerTest, BasicGetServerTest) { + ResetStubs(); + ConfigureProxy(1); + GetServersRequest get_servers_request; + GetServersResponse get_servers_response; + get_servers_request.set_start_server_id(0); + ClientContext get_servers_context; + Status s = channelz_stub_->GetServers( + &get_servers_context, get_servers_request, &get_servers_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_servers_response.server_size(), 1); + GetServerRequest get_server_request; + GetServerResponse get_server_response; + get_server_request.set_server_id( + get_servers_response.server(0).ref().server_id()); + ClientContext get_server_context; + s = channelz_stub_->GetServer(&get_server_context, get_server_request, + &get_server_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_servers_response.server(0).ref().server_id(), + get_server_response.server().ref().server_id()); +} + +TEST_F(ChannelzServerTest, ServerCallTest) { + ResetStubs(); + ConfigureProxy(1); + const int kNumSuccess = 10; + const int kNumFailed = 11; + for (int i = 0; i < kNumSuccess; ++i) { + SendSuccessfulEcho(0); + } + for (int i = 0; i < kNumFailed; ++i) { + SendFailedEcho(0); + } + GetServersRequest request; + GetServersResponse response; + request.set_start_server_id(0); + ClientContext context; + Status s = channelz_stub_->GetServers(&context, request, &response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(response.server_size(), 1); + EXPECT_EQ(response.server(0).data().calls_succeeded(), kNumSuccess); + EXPECT_EQ(response.server(0).data().calls_failed(), kNumFailed); + // This is success+failure+1 because the call that retrieved this information + // will be counted as started. It will not track success/failure until after + // it has returned, so that is not included in the response. + EXPECT_EQ(response.server(0).data().calls_started(), + kNumSuccess + kNumFailed + 1); +} + +TEST_F(ChannelzServerTest, ManySubchannelsAndSockets) { + ResetStubs(); + const int kNumChannels = 4; + ConfigureProxy(kNumChannels); + const int kNumSuccess = 10; + const int kNumFailed = 11; + for (int i = 0; i < kNumSuccess; ++i) { + SendSuccessfulEcho(0); + SendSuccessfulEcho(2); + } + for (int i = 0; i < kNumFailed; ++i) { + SendFailedEcho(1); + SendFailedEcho(2); + } + GetTopChannelsRequest gtc_request; + GetTopChannelsResponse gtc_response; + gtc_request.set_start_channel_id(0); + ClientContext context; + Status s = + channelz_stub_->GetTopChannels(&context, gtc_request, >c_response); + EXPECT_TRUE(s.ok()) << s.error_message(); + EXPECT_EQ(gtc_response.channel_size(), kNumChannels); + for (int i = 0; i < gtc_response.channel_size(); ++i) { + // if the channel sent no RPCs, then expect no subchannels to have been + // created. + if (gtc_response.channel(i).data().calls_started() == 0) { + EXPECT_EQ(gtc_response.channel(i).subchannel_ref_size(), 0); + continue; + } + // The resolver must return at least one address. + ASSERT_GT(gtc_response.channel(i).subchannel_ref_size(), 0); + // First grab the subchannel + GetSubchannelRequest get_subchannel_req; + GetSubchannelResponse get_subchannel_resp; + get_subchannel_req.set_subchannel_id( + gtc_response.channel(i).subchannel_ref(0).subchannel_id()); + ClientContext get_subchannel_ctx; + Status s = channelz_stub_->GetSubchannel( + &get_subchannel_ctx, get_subchannel_req, &get_subchannel_resp); + EXPECT_TRUE(s.ok()) << s.error_message(); + EXPECT_EQ(get_subchannel_resp.subchannel().socket_ref_size(), 1); + // Now grab the socket. + GetSocketRequest get_socket_req; + GetSocketResponse get_socket_resp; + ClientContext get_socket_ctx; + get_socket_req.set_socket_id( + get_subchannel_resp.subchannel().socket_ref(0).socket_id()); + s = channelz_stub_->GetSocket(&get_socket_ctx, get_socket_req, + &get_socket_resp); + EXPECT_TRUE( + get_subchannel_resp.subchannel().socket_ref(0).name().find("http")); + EXPECT_TRUE(s.ok()) << s.error_message(); + // calls started == streams started AND stream succeeded. Since none of + // these RPCs were canceled, all of the streams will succeeded even though + // the RPCs they represent might have failed. + EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(), + get_socket_resp.socket().data().streams_started()); + EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(), + get_socket_resp.socket().data().streams_succeeded()); + // All of the calls were unary, so calls started == messages sent. + EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(), + get_socket_resp.socket().data().messages_sent()); + // We only get responses when the RPC was successful, so + // calls succeeded == messages received. + EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_succeeded(), + get_socket_resp.socket().data().messages_received()); + } +} + +TEST_F(ChannelzServerTest, StreamingRPC) { + ResetStubs(); + ConfigureProxy(1); + const int kNumMessages = 5; + SendSuccessfulStream(kNumMessages); + // Get the channel + GetChannelRequest get_channel_request; + GetChannelResponse get_channel_response; + get_channel_request.set_channel_id(GetChannelId(0)); + ClientContext get_channel_context; + Status s = channelz_stub_->GetChannel( + &get_channel_context, get_channel_request, &get_channel_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_channel_response.channel().data().calls_started(), 1); + EXPECT_EQ(get_channel_response.channel().data().calls_succeeded(), 1); + EXPECT_EQ(get_channel_response.channel().data().calls_failed(), 0); + // Get the subchannel + ASSERT_GT(get_channel_response.channel().subchannel_ref_size(), 0); + GetSubchannelRequest get_subchannel_request; + GetSubchannelResponse get_subchannel_response; + ClientContext get_subchannel_context; + get_subchannel_request.set_subchannel_id( + get_channel_response.channel().subchannel_ref(0).subchannel_id()); + s = channelz_stub_->GetSubchannel(&get_subchannel_context, + get_subchannel_request, + &get_subchannel_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_subchannel_response.subchannel().data().calls_started(), 1); + EXPECT_EQ(get_subchannel_response.subchannel().data().calls_succeeded(), 1); + EXPECT_EQ(get_subchannel_response.subchannel().data().calls_failed(), 0); + // Get the socket + ASSERT_GT(get_subchannel_response.subchannel().socket_ref_size(), 0); + GetSocketRequest get_socket_request; + GetSocketResponse get_socket_response; + ClientContext get_socket_context; + get_socket_request.set_socket_id( + get_subchannel_response.subchannel().socket_ref(0).socket_id()); + EXPECT_TRUE( + get_subchannel_response.subchannel().socket_ref(0).name().find("http")); + s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request, + &get_socket_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_socket_response.socket().data().streams_started(), 1); + EXPECT_EQ(get_socket_response.socket().data().streams_succeeded(), 1); + EXPECT_EQ(get_socket_response.socket().data().streams_failed(), 0); + EXPECT_EQ(get_socket_response.socket().data().messages_sent(), kNumMessages); + EXPECT_EQ(get_socket_response.socket().data().messages_received(), + kNumMessages); +} + +TEST_F(ChannelzServerTest, GetServerSocketsTest) { + ResetStubs(); + ConfigureProxy(1); + GetServersRequest get_server_request; + GetServersResponse get_server_response; + get_server_request.set_start_server_id(0); + ClientContext get_server_context; + Status s = channelz_stub_->GetServers(&get_server_context, get_server_request, + &get_server_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_server_response.server_size(), 1); + GetServerSocketsRequest get_server_sockets_request; + GetServerSocketsResponse get_server_sockets_response; + get_server_sockets_request.set_server_id( + get_server_response.server(0).ref().server_id()); + get_server_sockets_request.set_start_socket_id(0); + ClientContext get_server_sockets_context; + s = channelz_stub_->GetServerSockets(&get_server_sockets_context, + get_server_sockets_request, + &get_server_sockets_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_server_sockets_response.socket_ref_size(), 1); + EXPECT_TRUE(get_server_sockets_response.socket_ref(0).name().find("http")); +} + +TEST_F(ChannelzServerTest, GetServerSocketsPaginationTest) { + ResetStubs(); + ConfigureProxy(1); + std::vector<std::unique_ptr<grpc::testing::EchoTestService::Stub>> stubs; + const int kNumServerSocketsCreated = 20; + for (int i = 0; i < kNumServerSocketsCreated; ++i) { + stubs.push_back(NewEchoStub()); + EchoRequest request; + EchoResponse response; + request.set_message("Hello channelz"); + request.mutable_param()->set_backend_channel_idx(0); + ClientContext context; + Status s = stubs.back()->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + } + GetServersRequest get_server_request; + GetServersResponse get_server_response; + get_server_request.set_start_server_id(0); + ClientContext get_server_context; + Status s = channelz_stub_->GetServers(&get_server_context, get_server_request, + &get_server_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_server_response.server_size(), 1); + // Make a request that gets all of the serversockets + { + GetServerSocketsRequest get_server_sockets_request; + GetServerSocketsResponse get_server_sockets_response; + get_server_sockets_request.set_server_id( + get_server_response.server(0).ref().server_id()); + get_server_sockets_request.set_start_socket_id(0); + ClientContext get_server_sockets_context; + s = channelz_stub_->GetServerSockets(&get_server_sockets_context, + get_server_sockets_request, + &get_server_sockets_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + // We add one to account the channelz stub that will end up creating + // a serversocket. + EXPECT_EQ(get_server_sockets_response.socket_ref_size(), + kNumServerSocketsCreated + 1); + EXPECT_TRUE(get_server_sockets_response.end()); + } + // Now we make a request that exercises pagination. + { + GetServerSocketsRequest get_server_sockets_request; + GetServerSocketsResponse get_server_sockets_response; + get_server_sockets_request.set_server_id( + get_server_response.server(0).ref().server_id()); + get_server_sockets_request.set_start_socket_id(0); + const int kMaxResults = 10; + get_server_sockets_request.set_max_results(kMaxResults); + ClientContext get_server_sockets_context; + s = channelz_stub_->GetServerSockets(&get_server_sockets_context, + get_server_sockets_request, + &get_server_sockets_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_server_sockets_response.socket_ref_size(), kMaxResults); + EXPECT_FALSE(get_server_sockets_response.end()); + } +} + +TEST_F(ChannelzServerTest, GetServerListenSocketsTest) { + ResetStubs(); + ConfigureProxy(1); + GetServersRequest get_server_request; + GetServersResponse get_server_response; + get_server_request.set_start_server_id(0); + ClientContext get_server_context; + Status s = channelz_stub_->GetServers(&get_server_context, get_server_request, + &get_server_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_server_response.server_size(), 1); + EXPECT_EQ(get_server_response.server(0).listen_socket_size(), 1); + GetSocketRequest get_socket_request; + GetSocketResponse get_socket_response; + get_socket_request.set_socket_id( + get_server_response.server(0).listen_socket(0).socket_id()); + EXPECT_TRUE( + get_server_response.server(0).listen_socket(0).name().find("http")); + ClientContext get_socket_context; + s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request, + &get_socket_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/client_callback_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/client_callback_end2end_test.cc index 53efd793d4..12cb40a953 100644 --- a/contrib/libs/grpc/test/cpp/end2end/client_callback_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/client_callback_end2end_test.cc @@ -1,32 +1,32 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ - -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/generic/generic_stub.h> -#include <grpcpp/impl/codegen/proto_utils.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> -#include <grpcpp/support/client_callback.h> +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ + +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/generic/generic_stub.h> +#include <grpcpp/impl/codegen/proto_utils.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> +#include <grpcpp/support/client_callback.h> #include <gtest/gtest.h> - + #include <algorithm> #include <condition_variable> #include <functional> @@ -34,330 +34,330 @@ #include <sstream> #include <thread> -#include "src/core/lib/gpr/env.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/interceptors_util.h" -#include "test/cpp/end2end/test_service_impl.h" -#include "test/cpp/util/byte_buffer_proto_helper.h" -#include "test/cpp/util/string_ref_helper.h" -#include "test/cpp/util/test_credentials_provider.h" - -// MAYBE_SKIP_TEST is a macro to determine if this particular test configuration -// should be skipped based on a decision made at SetUp time. In particular, any -// callback tests can only be run if the iomgr can run in the background or if -// the transport is in-process. -#define MAYBE_SKIP_TEST \ - do { \ - if (do_not_test_) { \ - return; \ - } \ - } while (0) - -namespace grpc { -namespace testing { -namespace { - -enum class Protocol { INPROC, TCP }; - -class TestScenario { - public: - TestScenario(bool serve_callback, Protocol protocol, bool intercept, +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/interceptors_util.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" +#include "test/cpp/util/string_ref_helper.h" +#include "test/cpp/util/test_credentials_provider.h" + +// MAYBE_SKIP_TEST is a macro to determine if this particular test configuration +// should be skipped based on a decision made at SetUp time. In particular, any +// callback tests can only be run if the iomgr can run in the background or if +// the transport is in-process. +#define MAYBE_SKIP_TEST \ + do { \ + if (do_not_test_) { \ + return; \ + } \ + } while (0) + +namespace grpc { +namespace testing { +namespace { + +enum class Protocol { INPROC, TCP }; + +class TestScenario { + public: + TestScenario(bool serve_callback, Protocol protocol, bool intercept, const TString& creds_type) - : callback_server(serve_callback), - protocol(protocol), - use_interceptors(intercept), - credentials_type(creds_type) {} - void Log() const; - bool callback_server; - Protocol protocol; - bool use_interceptors; + : callback_server(serve_callback), + protocol(protocol), + use_interceptors(intercept), + credentials_type(creds_type) {} + void Log() const; + bool callback_server; + Protocol protocol; + bool use_interceptors; const TString credentials_type; -}; - -static std::ostream& operator<<(std::ostream& out, - const TestScenario& scenario) { - return out << "TestScenario{callback_server=" - << (scenario.callback_server ? "true" : "false") << ",protocol=" - << (scenario.protocol == Protocol::INPROC ? "INPROC" : "TCP") - << ",intercept=" << (scenario.use_interceptors ? "true" : "false") - << ",creds=" << scenario.credentials_type << "}"; -} - -void TestScenario::Log() const { - std::ostringstream out; - out << *this; - gpr_log(GPR_DEBUG, "%s", out.str().c_str()); -} - -class ClientCallbackEnd2endTest - : public ::testing::TestWithParam<TestScenario> { - protected: - ClientCallbackEnd2endTest() { GetParam().Log(); } - - void SetUp() override { - ServerBuilder builder; - - auto server_creds = GetCredentialsProvider()->GetServerCredentials( - GetParam().credentials_type); - // TODO(vjpai): Support testing of AuthMetadataProcessor - - if (GetParam().protocol == Protocol::TCP) { - picked_port_ = grpc_pick_unused_port_or_die(); - server_address_ << "localhost:" << picked_port_; - builder.AddListeningPort(server_address_.str(), server_creds); - } - if (!GetParam().callback_server) { - builder.RegisterService(&service_); - } else { - builder.RegisterService(&callback_service_); - } - - if (GetParam().use_interceptors) { - std::vector< - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> - creators; - // Add 20 dummy server interceptors - creators.reserve(20); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - builder.experimental().SetInterceptorCreators(std::move(creators)); - } - - server_ = builder.BuildAndStart(); - is_server_started_ = true; - if (GetParam().protocol == Protocol::TCP && - !grpc_iomgr_run_in_background()) { - do_not_test_ = true; - } - } - - void ResetStub() { - ChannelArguments args; - auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( - GetParam().credentials_type, &args); - switch (GetParam().protocol) { - case Protocol::TCP: - if (!GetParam().use_interceptors) { - channel_ = ::grpc::CreateCustomChannel(server_address_.str(), - channel_creds, args); - } else { - channel_ = CreateCustomChannelWithInterceptors( - server_address_.str(), channel_creds, args, - CreateDummyClientInterceptors()); - } - break; - case Protocol::INPROC: - if (!GetParam().use_interceptors) { - channel_ = server_->InProcessChannel(args); - } else { - channel_ = server_->experimental().InProcessChannelWithInterceptors( - args, CreateDummyClientInterceptors()); - } - break; - default: - assert(false); - } - stub_ = grpc::testing::EchoTestService::NewStub(channel_); - generic_stub_.reset(new GenericStub(channel_)); - DummyInterceptor::Reset(); - } - - void TearDown() override { - if (is_server_started_) { - // Although we would normally do an explicit shutdown, the server - // should also work correctly with just a destructor call. The regular - // end2end test uses explicit shutdown, so let this one just do reset. - server_.reset(); - } - if (picked_port_ > 0) { - grpc_recycle_unused_port(picked_port_); - } - } - - void SendRpcs(int num_rpcs, bool with_binary_metadata) { +}; + +static std::ostream& operator<<(std::ostream& out, + const TestScenario& scenario) { + return out << "TestScenario{callback_server=" + << (scenario.callback_server ? "true" : "false") << ",protocol=" + << (scenario.protocol == Protocol::INPROC ? "INPROC" : "TCP") + << ",intercept=" << (scenario.use_interceptors ? "true" : "false") + << ",creds=" << scenario.credentials_type << "}"; +} + +void TestScenario::Log() const { + std::ostringstream out; + out << *this; + gpr_log(GPR_DEBUG, "%s", out.str().c_str()); +} + +class ClientCallbackEnd2endTest + : public ::testing::TestWithParam<TestScenario> { + protected: + ClientCallbackEnd2endTest() { GetParam().Log(); } + + void SetUp() override { + ServerBuilder builder; + + auto server_creds = GetCredentialsProvider()->GetServerCredentials( + GetParam().credentials_type); + // TODO(vjpai): Support testing of AuthMetadataProcessor + + if (GetParam().protocol == Protocol::TCP) { + picked_port_ = grpc_pick_unused_port_or_die(); + server_address_ << "localhost:" << picked_port_; + builder.AddListeningPort(server_address_.str(), server_creds); + } + if (!GetParam().callback_server) { + builder.RegisterService(&service_); + } else { + builder.RegisterService(&callback_service_); + } + + if (GetParam().use_interceptors) { + std::vector< + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + // Add 20 dummy server interceptors + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + } + + server_ = builder.BuildAndStart(); + is_server_started_ = true; + if (GetParam().protocol == Protocol::TCP && + !grpc_iomgr_run_in_background()) { + do_not_test_ = true; + } + } + + void ResetStub() { + ChannelArguments args; + auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); + switch (GetParam().protocol) { + case Protocol::TCP: + if (!GetParam().use_interceptors) { + channel_ = ::grpc::CreateCustomChannel(server_address_.str(), + channel_creds, args); + } else { + channel_ = CreateCustomChannelWithInterceptors( + server_address_.str(), channel_creds, args, + CreateDummyClientInterceptors()); + } + break; + case Protocol::INPROC: + if (!GetParam().use_interceptors) { + channel_ = server_->InProcessChannel(args); + } else { + channel_ = server_->experimental().InProcessChannelWithInterceptors( + args, CreateDummyClientInterceptors()); + } + break; + default: + assert(false); + } + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + generic_stub_.reset(new GenericStub(channel_)); + DummyInterceptor::Reset(); + } + + void TearDown() override { + if (is_server_started_) { + // Although we would normally do an explicit shutdown, the server + // should also work correctly with just a destructor call. The regular + // end2end test uses explicit shutdown, so let this one just do reset. + server_.reset(); + } + if (picked_port_ > 0) { + grpc_recycle_unused_port(picked_port_); + } + } + + void SendRpcs(int num_rpcs, bool with_binary_metadata) { TString test_string(""); - for (int i = 0; i < num_rpcs; i++) { - EchoRequest request; - EchoResponse response; - ClientContext cli_ctx; - - test_string += "Hello world. "; - request.set_message(test_string); + for (int i = 0; i < num_rpcs; i++) { + EchoRequest request; + EchoResponse response; + ClientContext cli_ctx; + + test_string += "Hello world. "; + request.set_message(test_string); TString val; - if (with_binary_metadata) { - request.mutable_param()->set_echo_metadata(true); - char bytes[8] = {'\0', '\1', '\2', '\3', - '\4', '\5', '\6', static_cast<char>(i)}; + if (with_binary_metadata) { + request.mutable_param()->set_echo_metadata(true); + char bytes[8] = {'\0', '\1', '\2', '\3', + '\4', '\5', '\6', static_cast<char>(i)}; val = TString(bytes, 8); - cli_ctx.AddMetadata("custom-bin", val); - } - - cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP); - - std::mutex mu; - std::condition_variable cv; - bool done = false; - stub_->experimental_async()->Echo( - &cli_ctx, &request, &response, - [&cli_ctx, &request, &response, &done, &mu, &cv, val, - with_binary_metadata](Status s) { - GPR_ASSERT(s.ok()); - - EXPECT_EQ(request.message(), response.message()); - if (with_binary_metadata) { - EXPECT_EQ( - 1u, cli_ctx.GetServerTrailingMetadata().count("custom-bin")); - EXPECT_EQ(val, ToString(cli_ctx.GetServerTrailingMetadata() - .find("custom-bin") - ->second)); - } - std::lock_guard<std::mutex> l(mu); - done = true; - cv.notify_one(); - }); - std::unique_lock<std::mutex> l(mu); - while (!done) { - cv.wait(l); - } - } - } - - void SendRpcsGeneric(int num_rpcs, bool maybe_except) { + cli_ctx.AddMetadata("custom-bin", val); + } + + cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP); + + std::mutex mu; + std::condition_variable cv; + bool done = false; + stub_->experimental_async()->Echo( + &cli_ctx, &request, &response, + [&cli_ctx, &request, &response, &done, &mu, &cv, val, + with_binary_metadata](Status s) { + GPR_ASSERT(s.ok()); + + EXPECT_EQ(request.message(), response.message()); + if (with_binary_metadata) { + EXPECT_EQ( + 1u, cli_ctx.GetServerTrailingMetadata().count("custom-bin")); + EXPECT_EQ(val, ToString(cli_ctx.GetServerTrailingMetadata() + .find("custom-bin") + ->second)); + } + std::lock_guard<std::mutex> l(mu); + done = true; + cv.notify_one(); + }); + std::unique_lock<std::mutex> l(mu); + while (!done) { + cv.wait(l); + } + } + } + + void SendRpcsGeneric(int num_rpcs, bool maybe_except) { const TString kMethodName("/grpc.testing.EchoTestService/Echo"); TString test_string(""); - for (int i = 0; i < num_rpcs; i++) { - EchoRequest request; - std::unique_ptr<ByteBuffer> send_buf; - ByteBuffer recv_buf; - ClientContext cli_ctx; - - test_string += "Hello world. "; - request.set_message(test_string); - send_buf = SerializeToByteBuffer(&request); - - std::mutex mu; - std::condition_variable cv; - bool done = false; - generic_stub_->experimental().UnaryCall( - &cli_ctx, kMethodName, send_buf.get(), &recv_buf, - [&request, &recv_buf, &done, &mu, &cv, maybe_except](Status s) { - GPR_ASSERT(s.ok()); - - EchoResponse response; - EXPECT_TRUE(ParseFromByteBuffer(&recv_buf, &response)); - EXPECT_EQ(request.message(), response.message()); - std::lock_guard<std::mutex> l(mu); - done = true; - cv.notify_one(); -#if GRPC_ALLOW_EXCEPTIONS - if (maybe_except) { - throw - 1; - } -#else - GPR_ASSERT(!maybe_except); -#endif - }); - std::unique_lock<std::mutex> l(mu); - while (!done) { - cv.wait(l); - } - } - } - + for (int i = 0; i < num_rpcs; i++) { + EchoRequest request; + std::unique_ptr<ByteBuffer> send_buf; + ByteBuffer recv_buf; + ClientContext cli_ctx; + + test_string += "Hello world. "; + request.set_message(test_string); + send_buf = SerializeToByteBuffer(&request); + + std::mutex mu; + std::condition_variable cv; + bool done = false; + generic_stub_->experimental().UnaryCall( + &cli_ctx, kMethodName, send_buf.get(), &recv_buf, + [&request, &recv_buf, &done, &mu, &cv, maybe_except](Status s) { + GPR_ASSERT(s.ok()); + + EchoResponse response; + EXPECT_TRUE(ParseFromByteBuffer(&recv_buf, &response)); + EXPECT_EQ(request.message(), response.message()); + std::lock_guard<std::mutex> l(mu); + done = true; + cv.notify_one(); +#if GRPC_ALLOW_EXCEPTIONS + if (maybe_except) { + throw - 1; + } +#else + GPR_ASSERT(!maybe_except); +#endif + }); + std::unique_lock<std::mutex> l(mu); + while (!done) { + cv.wait(l); + } + } + } + void SendGenericEchoAsBidi(int num_rpcs, int reuses, bool do_writes_done) { const TString kMethodName("/grpc.testing.EchoTestService/Echo"); TString test_string(""); - for (int i = 0; i < num_rpcs; i++) { - test_string += "Hello world. "; - class Client : public grpc::experimental::ClientBidiReactor<ByteBuffer, - ByteBuffer> { - public: + for (int i = 0; i < num_rpcs; i++) { + test_string += "Hello world. "; + class Client : public grpc::experimental::ClientBidiReactor<ByteBuffer, + ByteBuffer> { + public: Client(ClientCallbackEnd2endTest* test, const TString& method_name, const TString& test_str, int reuses, bool do_writes_done) : reuses_remaining_(reuses), do_writes_done_(do_writes_done) { - activate_ = [this, test, method_name, test_str] { - if (reuses_remaining_ > 0) { - cli_ctx_.reset(new ClientContext); - reuses_remaining_--; - test->generic_stub_->experimental().PrepareBidiStreamingCall( - cli_ctx_.get(), method_name, this); - request_.set_message(test_str); - send_buf_ = SerializeToByteBuffer(&request_); - StartWrite(send_buf_.get()); - StartRead(&recv_buf_); - StartCall(); - } else { - std::unique_lock<std::mutex> l(mu_); - done_ = true; - cv_.notify_one(); - } - }; - activate_(); - } + activate_ = [this, test, method_name, test_str] { + if (reuses_remaining_ > 0) { + cli_ctx_.reset(new ClientContext); + reuses_remaining_--; + test->generic_stub_->experimental().PrepareBidiStreamingCall( + cli_ctx_.get(), method_name, this); + request_.set_message(test_str); + send_buf_ = SerializeToByteBuffer(&request_); + StartWrite(send_buf_.get()); + StartRead(&recv_buf_); + StartCall(); + } else { + std::unique_lock<std::mutex> l(mu_); + done_ = true; + cv_.notify_one(); + } + }; + activate_(); + } void OnWriteDone(bool /*ok*/) override { if (do_writes_done_) { StartWritesDone(); } } - void OnReadDone(bool /*ok*/) override { - EchoResponse response; - EXPECT_TRUE(ParseFromByteBuffer(&recv_buf_, &response)); - EXPECT_EQ(request_.message(), response.message()); - }; - void OnDone(const Status& s) override { - EXPECT_TRUE(s.ok()); - activate_(); - } - void Await() { - std::unique_lock<std::mutex> l(mu_); - while (!done_) { - cv_.wait(l); - } - } - - EchoRequest request_; - std::unique_ptr<ByteBuffer> send_buf_; - ByteBuffer recv_buf_; - std::unique_ptr<ClientContext> cli_ctx_; - int reuses_remaining_; - std::function<void()> activate_; - std::mutex mu_; - std::condition_variable cv_; - bool done_ = false; + void OnReadDone(bool /*ok*/) override { + EchoResponse response; + EXPECT_TRUE(ParseFromByteBuffer(&recv_buf_, &response)); + EXPECT_EQ(request_.message(), response.message()); + }; + void OnDone(const Status& s) override { + EXPECT_TRUE(s.ok()); + activate_(); + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + EchoRequest request_; + std::unique_ptr<ByteBuffer> send_buf_; + ByteBuffer recv_buf_; + std::unique_ptr<ClientContext> cli_ctx_; + int reuses_remaining_; + std::function<void()> activate_; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; const bool do_writes_done_; }; - + Client rpc(this, kMethodName, test_string, reuses, do_writes_done); - rpc.Await(); - } - } - bool do_not_test_{false}; - bool is_server_started_{false}; - int picked_port_{0}; - std::shared_ptr<Channel> channel_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<grpc::GenericStub> generic_stub_; - TestServiceImpl service_; - CallbackTestServiceImpl callback_service_; - std::unique_ptr<Server> server_; - std::ostringstream server_address_; -}; - -TEST_P(ClientCallbackEnd2endTest, SimpleRpc) { - MAYBE_SKIP_TEST; - ResetStub(); - SendRpcs(1, false); -} - + rpc.Await(); + } + } + bool do_not_test_{false}; + bool is_server_started_{false}; + int picked_port_{0}; + std::shared_ptr<Channel> channel_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<grpc::GenericStub> generic_stub_; + TestServiceImpl service_; + CallbackTestServiceImpl callback_service_; + std::unique_ptr<Server> server_; + std::ostringstream server_address_; +}; + +TEST_P(ClientCallbackEnd2endTest, SimpleRpc) { + MAYBE_SKIP_TEST; + ResetStub(); + SendRpcs(1, false); +} + TEST_P(ClientCallbackEnd2endTest, SimpleRpcExpectedError) { - MAYBE_SKIP_TEST; - ResetStub(); + MAYBE_SKIP_TEST; + ResetStub(); EchoRequest request; EchoResponse response; @@ -370,9 +370,9 @@ TEST_P(ClientCallbackEnd2endTest, SimpleRpcExpectedError) { *request.mutable_param()->mutable_expected_error() = error_status; std::mutex mu; - std::condition_variable cv; - bool done = false; - + std::condition_variable cv; + bool done = false; + stub_->experimental_async()->Echo( &cli_ctx, &request, &response, [&response, &done, &mu, &cv, &error_status](Status s) { @@ -385,11 +385,11 @@ TEST_P(ClientCallbackEnd2endTest, SimpleRpcExpectedError) { }); std::unique_lock<std::mutex> l(mu); - while (!done) { - cv.wait(l); - } -} - + while (!done) { + cv.wait(l); + } +} + TEST_P(ClientCallbackEnd2endTest, SimpleRpcUnderLockNested) { MAYBE_SKIP_TEST; ResetStub(); @@ -451,415 +451,415 @@ TEST_P(ClientCallbackEnd2endTest, SimpleRpcUnderLockNested) { } } -TEST_P(ClientCallbackEnd2endTest, SimpleRpcUnderLock) { - MAYBE_SKIP_TEST; - ResetStub(); - std::mutex mu; - std::condition_variable cv; - bool done = false; - EchoRequest request; - request.set_message("Hello locked world."); - EchoResponse response; - ClientContext cli_ctx; - { - std::lock_guard<std::mutex> l(mu); - stub_->experimental_async()->Echo( - &cli_ctx, &request, &response, - [&mu, &cv, &done, &request, &response](Status s) { - std::lock_guard<std::mutex> l(mu); - EXPECT_TRUE(s.ok()); - EXPECT_EQ(request.message(), response.message()); - done = true; - cv.notify_one(); - }); - } - std::unique_lock<std::mutex> l(mu); - while (!done) { - cv.wait(l); - } -} - -TEST_P(ClientCallbackEnd2endTest, SequentialRpcs) { - MAYBE_SKIP_TEST; - ResetStub(); - SendRpcs(10, false); -} - -TEST_P(ClientCallbackEnd2endTest, SendClientInitialMetadata) { - MAYBE_SKIP_TEST; - ResetStub(); - SimpleRequest request; - SimpleResponse response; - ClientContext cli_ctx; - - cli_ctx.AddMetadata(kCheckClientInitialMetadataKey, - kCheckClientInitialMetadataVal); - - std::mutex mu; - std::condition_variable cv; - bool done = false; - stub_->experimental_async()->CheckClientInitialMetadata( - &cli_ctx, &request, &response, [&done, &mu, &cv](Status s) { - GPR_ASSERT(s.ok()); - - std::lock_guard<std::mutex> l(mu); - done = true; - cv.notify_one(); - }); - std::unique_lock<std::mutex> l(mu); - while (!done) { - cv.wait(l); - } -} - -TEST_P(ClientCallbackEnd2endTest, SimpleRpcWithBinaryMetadata) { - MAYBE_SKIP_TEST; - ResetStub(); - SendRpcs(1, true); -} - -TEST_P(ClientCallbackEnd2endTest, SequentialRpcsWithVariedBinaryMetadataValue) { - MAYBE_SKIP_TEST; - ResetStub(); - SendRpcs(10, true); -} - -TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcs) { - MAYBE_SKIP_TEST; - ResetStub(); - SendRpcsGeneric(10, false); -} - -TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidi) { - MAYBE_SKIP_TEST; - ResetStub(); +TEST_P(ClientCallbackEnd2endTest, SimpleRpcUnderLock) { + MAYBE_SKIP_TEST; + ResetStub(); + std::mutex mu; + std::condition_variable cv; + bool done = false; + EchoRequest request; + request.set_message("Hello locked world."); + EchoResponse response; + ClientContext cli_ctx; + { + std::lock_guard<std::mutex> l(mu); + stub_->experimental_async()->Echo( + &cli_ctx, &request, &response, + [&mu, &cv, &done, &request, &response](Status s) { + std::lock_guard<std::mutex> l(mu); + EXPECT_TRUE(s.ok()); + EXPECT_EQ(request.message(), response.message()); + done = true; + cv.notify_one(); + }); + } + std::unique_lock<std::mutex> l(mu); + while (!done) { + cv.wait(l); + } +} + +TEST_P(ClientCallbackEnd2endTest, SequentialRpcs) { + MAYBE_SKIP_TEST; + ResetStub(); + SendRpcs(10, false); +} + +TEST_P(ClientCallbackEnd2endTest, SendClientInitialMetadata) { + MAYBE_SKIP_TEST; + ResetStub(); + SimpleRequest request; + SimpleResponse response; + ClientContext cli_ctx; + + cli_ctx.AddMetadata(kCheckClientInitialMetadataKey, + kCheckClientInitialMetadataVal); + + std::mutex mu; + std::condition_variable cv; + bool done = false; + stub_->experimental_async()->CheckClientInitialMetadata( + &cli_ctx, &request, &response, [&done, &mu, &cv](Status s) { + GPR_ASSERT(s.ok()); + + std::lock_guard<std::mutex> l(mu); + done = true; + cv.notify_one(); + }); + std::unique_lock<std::mutex> l(mu); + while (!done) { + cv.wait(l); + } +} + +TEST_P(ClientCallbackEnd2endTest, SimpleRpcWithBinaryMetadata) { + MAYBE_SKIP_TEST; + ResetStub(); + SendRpcs(1, true); +} + +TEST_P(ClientCallbackEnd2endTest, SequentialRpcsWithVariedBinaryMetadataValue) { + MAYBE_SKIP_TEST; + ResetStub(); + SendRpcs(10, true); +} + +TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcs) { + MAYBE_SKIP_TEST; + ResetStub(); + SendRpcsGeneric(10, false); +} + +TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidi) { + MAYBE_SKIP_TEST; + ResetStub(); SendGenericEchoAsBidi(10, 1, /*do_writes_done=*/true); -} - -TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidiWithReactorReuse) { - MAYBE_SKIP_TEST; - ResetStub(); +} + +TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidiWithReactorReuse) { + MAYBE_SKIP_TEST; + ResetStub(); SendGenericEchoAsBidi(10, 10, /*do_writes_done=*/true); -} - +} + TEST_P(ClientCallbackEnd2endTest, GenericRpcNoWritesDone) { MAYBE_SKIP_TEST; ResetStub(); SendGenericEchoAsBidi(1, 1, /*do_writes_done=*/false); } -#if GRPC_ALLOW_EXCEPTIONS -TEST_P(ClientCallbackEnd2endTest, ExceptingRpc) { - MAYBE_SKIP_TEST; - ResetStub(); - SendRpcsGeneric(10, true); -} -#endif - -TEST_P(ClientCallbackEnd2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { - MAYBE_SKIP_TEST; - ResetStub(); - std::vector<std::thread> threads; - threads.reserve(10); - for (int i = 0; i < 10; ++i) { - threads.emplace_back([this] { SendRpcs(10, true); }); - } - for (int i = 0; i < 10; ++i) { - threads[i].join(); - } -} - -TEST_P(ClientCallbackEnd2endTest, MultipleRpcs) { - MAYBE_SKIP_TEST; - ResetStub(); - std::vector<std::thread> threads; - threads.reserve(10); - for (int i = 0; i < 10; ++i) { - threads.emplace_back([this] { SendRpcs(10, false); }); - } - for (int i = 0; i < 10; ++i) { - threads[i].join(); - } -} - -TEST_P(ClientCallbackEnd2endTest, CancelRpcBeforeStart) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - request.set_message("hello"); - context.TryCancel(); - - std::mutex mu; - std::condition_variable cv; - bool done = false; - stub_->experimental_async()->Echo( - &context, &request, &response, [&response, &done, &mu, &cv](Status s) { - EXPECT_EQ("", response.message()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - std::lock_guard<std::mutex> l(mu); - done = true; - cv.notify_one(); - }); - std::unique_lock<std::mutex> l(mu); - while (!done) { - cv.wait(l); - } - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -TEST_P(ClientCallbackEnd2endTest, RequestEchoServerCancel) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - request.set_message("hello"); - context.AddMetadata(kServerTryCancelRequest, +#if GRPC_ALLOW_EXCEPTIONS +TEST_P(ClientCallbackEnd2endTest, ExceptingRpc) { + MAYBE_SKIP_TEST; + ResetStub(); + SendRpcsGeneric(10, true); +} +#endif + +TEST_P(ClientCallbackEnd2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { + MAYBE_SKIP_TEST; + ResetStub(); + std::vector<std::thread> threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) { + threads.emplace_back([this] { SendRpcs(10, true); }); + } + for (int i = 0; i < 10; ++i) { + threads[i].join(); + } +} + +TEST_P(ClientCallbackEnd2endTest, MultipleRpcs) { + MAYBE_SKIP_TEST; + ResetStub(); + std::vector<std::thread> threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) { + threads.emplace_back([this] { SendRpcs(10, false); }); + } + for (int i = 0; i < 10; ++i) { + threads[i].join(); + } +} + +TEST_P(ClientCallbackEnd2endTest, CancelRpcBeforeStart) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("hello"); + context.TryCancel(); + + std::mutex mu; + std::condition_variable cv; + bool done = false; + stub_->experimental_async()->Echo( + &context, &request, &response, [&response, &done, &mu, &cv](Status s) { + EXPECT_EQ("", response.message()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + std::lock_guard<std::mutex> l(mu); + done = true; + cv.notify_one(); + }); + std::unique_lock<std::mutex> l(mu); + while (!done) { + cv.wait(l); + } + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +TEST_P(ClientCallbackEnd2endTest, RequestEchoServerCancel) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("hello"); + context.AddMetadata(kServerTryCancelRequest, ToString(CANCEL_BEFORE_PROCESSING)); - - std::mutex mu; - std::condition_variable cv; - bool done = false; - stub_->experimental_async()->Echo( - &context, &request, &response, [&done, &mu, &cv](Status s) { - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - std::lock_guard<std::mutex> l(mu); - done = true; - cv.notify_one(); - }); - std::unique_lock<std::mutex> l(mu); - while (!done) { - cv.wait(l); - } -} - -struct ClientCancelInfo { - bool cancel{false}; - int ops_before_cancel; - - ClientCancelInfo() : cancel{false} {} - explicit ClientCancelInfo(int ops) : cancel{true}, ops_before_cancel{ops} {} -}; - -class WriteClient : public grpc::experimental::ClientWriteReactor<EchoRequest> { - public: - WriteClient(grpc::testing::EchoTestService::Stub* stub, - ServerTryCancelRequestPhase server_try_cancel, - int num_msgs_to_send, ClientCancelInfo client_cancel = {}) - : server_try_cancel_(server_try_cancel), - num_msgs_to_send_(num_msgs_to_send), - client_cancel_{client_cancel} { + + std::mutex mu; + std::condition_variable cv; + bool done = false; + stub_->experimental_async()->Echo( + &context, &request, &response, [&done, &mu, &cv](Status s) { + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + std::lock_guard<std::mutex> l(mu); + done = true; + cv.notify_one(); + }); + std::unique_lock<std::mutex> l(mu); + while (!done) { + cv.wait(l); + } +} + +struct ClientCancelInfo { + bool cancel{false}; + int ops_before_cancel; + + ClientCancelInfo() : cancel{false} {} + explicit ClientCancelInfo(int ops) : cancel{true}, ops_before_cancel{ops} {} +}; + +class WriteClient : public grpc::experimental::ClientWriteReactor<EchoRequest> { + public: + WriteClient(grpc::testing::EchoTestService::Stub* stub, + ServerTryCancelRequestPhase server_try_cancel, + int num_msgs_to_send, ClientCancelInfo client_cancel = {}) + : server_try_cancel_(server_try_cancel), + num_msgs_to_send_(num_msgs_to_send), + client_cancel_{client_cancel} { TString msg{"Hello server."}; - for (int i = 0; i < num_msgs_to_send; i++) { - desired_ += msg; - } - if (server_try_cancel != DO_NOT_CANCEL) { - // Send server_try_cancel value in the client metadata - context_.AddMetadata(kServerTryCancelRequest, + for (int i = 0; i < num_msgs_to_send; i++) { + desired_ += msg; + } + if (server_try_cancel != DO_NOT_CANCEL) { + // Send server_try_cancel value in the client metadata + context_.AddMetadata(kServerTryCancelRequest, ToString(server_try_cancel)); - } - context_.set_initial_metadata_corked(true); - stub->experimental_async()->RequestStream(&context_, &response_, this); - StartCall(); - request_.set_message(msg); - MaybeWrite(); - } - void OnWriteDone(bool ok) override { - if (ok) { - num_msgs_sent_++; - MaybeWrite(); - } - } - void OnDone(const Status& s) override { - gpr_log(GPR_INFO, "Sent %d messages", num_msgs_sent_); - int num_to_send = - (client_cancel_.cancel) - ? std::min(num_msgs_to_send_, client_cancel_.ops_before_cancel) - : num_msgs_to_send_; - switch (server_try_cancel_) { - case CANCEL_BEFORE_PROCESSING: - case CANCEL_DURING_PROCESSING: - // If the RPC is canceled by server before / during messages from the - // client, it means that the client most likely did not get a chance to - // send all the messages it wanted to send. i.e num_msgs_sent <= - // num_msgs_to_send - EXPECT_LE(num_msgs_sent_, num_to_send); - break; - case DO_NOT_CANCEL: - case CANCEL_AFTER_PROCESSING: - // If the RPC was not canceled or canceled after all messages were read - // by the server, the client did get a chance to send all its messages - EXPECT_EQ(num_msgs_sent_, num_to_send); - break; - default: - assert(false); - break; - } - if ((server_try_cancel_ == DO_NOT_CANCEL) && !client_cancel_.cancel) { - EXPECT_TRUE(s.ok()); - EXPECT_EQ(response_.message(), desired_); - } else { - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - } - std::unique_lock<std::mutex> l(mu_); - done_ = true; - cv_.notify_one(); - } - void Await() { - std::unique_lock<std::mutex> l(mu_); - while (!done_) { - cv_.wait(l); - } - } - - private: - void MaybeWrite() { - if (client_cancel_.cancel && - num_msgs_sent_ == client_cancel_.ops_before_cancel) { - context_.TryCancel(); - } else if (num_msgs_to_send_ > num_msgs_sent_ + 1) { - StartWrite(&request_); - } else if (num_msgs_to_send_ == num_msgs_sent_ + 1) { - StartWriteLast(&request_, WriteOptions()); - } - } - EchoRequest request_; - EchoResponse response_; - ClientContext context_; - const ServerTryCancelRequestPhase server_try_cancel_; - int num_msgs_sent_{0}; - const int num_msgs_to_send_; + } + context_.set_initial_metadata_corked(true); + stub->experimental_async()->RequestStream(&context_, &response_, this); + StartCall(); + request_.set_message(msg); + MaybeWrite(); + } + void OnWriteDone(bool ok) override { + if (ok) { + num_msgs_sent_++; + MaybeWrite(); + } + } + void OnDone(const Status& s) override { + gpr_log(GPR_INFO, "Sent %d messages", num_msgs_sent_); + int num_to_send = + (client_cancel_.cancel) + ? std::min(num_msgs_to_send_, client_cancel_.ops_before_cancel) + : num_msgs_to_send_; + switch (server_try_cancel_) { + case CANCEL_BEFORE_PROCESSING: + case CANCEL_DURING_PROCESSING: + // If the RPC is canceled by server before / during messages from the + // client, it means that the client most likely did not get a chance to + // send all the messages it wanted to send. i.e num_msgs_sent <= + // num_msgs_to_send + EXPECT_LE(num_msgs_sent_, num_to_send); + break; + case DO_NOT_CANCEL: + case CANCEL_AFTER_PROCESSING: + // If the RPC was not canceled or canceled after all messages were read + // by the server, the client did get a chance to send all its messages + EXPECT_EQ(num_msgs_sent_, num_to_send); + break; + default: + assert(false); + break; + } + if ((server_try_cancel_ == DO_NOT_CANCEL) && !client_cancel_.cancel) { + EXPECT_TRUE(s.ok()); + EXPECT_EQ(response_.message(), desired_); + } else { + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + } + std::unique_lock<std::mutex> l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: + void MaybeWrite() { + if (client_cancel_.cancel && + num_msgs_sent_ == client_cancel_.ops_before_cancel) { + context_.TryCancel(); + } else if (num_msgs_to_send_ > num_msgs_sent_ + 1) { + StartWrite(&request_); + } else if (num_msgs_to_send_ == num_msgs_sent_ + 1) { + StartWriteLast(&request_, WriteOptions()); + } + } + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + const ServerTryCancelRequestPhase server_try_cancel_; + int num_msgs_sent_{0}; + const int num_msgs_to_send_; TString desired_; - const ClientCancelInfo client_cancel_; - std::mutex mu_; - std::condition_variable cv_; - bool done_ = false; -}; - -TEST_P(ClientCallbackEnd2endTest, RequestStream) { - MAYBE_SKIP_TEST; - ResetStub(); - WriteClient test{stub_.get(), DO_NOT_CANCEL, 3}; - test.Await(); - // Make sure that the server interceptors were not notified to cancel - if (GetParam().use_interceptors) { - EXPECT_EQ(0, DummyInterceptor::GetNumTimesCancel()); - } -} - -TEST_P(ClientCallbackEnd2endTest, ClientCancelsRequestStream) { - MAYBE_SKIP_TEST; - ResetStub(); - WriteClient test{stub_.get(), DO_NOT_CANCEL, 3, ClientCancelInfo{2}}; - test.Await(); - // Make sure that the server interceptors got the cancel - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Server to cancel before doing reading the request -TEST_P(ClientCallbackEnd2endTest, RequestStreamServerCancelBeforeReads) { - MAYBE_SKIP_TEST; - ResetStub(); - WriteClient test{stub_.get(), CANCEL_BEFORE_PROCESSING, 1}; - test.Await(); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Server to cancel while reading a request from the stream in parallel -TEST_P(ClientCallbackEnd2endTest, RequestStreamServerCancelDuringRead) { - MAYBE_SKIP_TEST; - ResetStub(); - WriteClient test{stub_.get(), CANCEL_DURING_PROCESSING, 10}; - test.Await(); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Server to cancel after reading all the requests but before returning to the -// client -TEST_P(ClientCallbackEnd2endTest, RequestStreamServerCancelAfterReads) { - MAYBE_SKIP_TEST; - ResetStub(); - WriteClient test{stub_.get(), CANCEL_AFTER_PROCESSING, 4}; - test.Await(); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -TEST_P(ClientCallbackEnd2endTest, UnaryReactor) { - MAYBE_SKIP_TEST; - ResetStub(); - class UnaryClient : public grpc::experimental::ClientUnaryReactor { - public: - UnaryClient(grpc::testing::EchoTestService::Stub* stub) { - cli_ctx_.AddMetadata("key1", "val1"); - cli_ctx_.AddMetadata("key2", "val2"); - request_.mutable_param()->set_echo_metadata_initially(true); - request_.set_message("Hello metadata"); - stub->experimental_async()->Echo(&cli_ctx_, &request_, &response_, this); - StartCall(); - } - void OnReadInitialMetadataDone(bool ok) override { - EXPECT_TRUE(ok); - EXPECT_EQ(1u, cli_ctx_.GetServerInitialMetadata().count("key1")); - EXPECT_EQ( - "val1", - ToString(cli_ctx_.GetServerInitialMetadata().find("key1")->second)); - EXPECT_EQ(1u, cli_ctx_.GetServerInitialMetadata().count("key2")); - EXPECT_EQ( - "val2", - ToString(cli_ctx_.GetServerInitialMetadata().find("key2")->second)); - initial_metadata_done_ = true; - } - void OnDone(const Status& s) override { - EXPECT_TRUE(initial_metadata_done_); - EXPECT_EQ(0u, cli_ctx_.GetServerTrailingMetadata().size()); - EXPECT_TRUE(s.ok()); - EXPECT_EQ(request_.message(), response_.message()); - std::unique_lock<std::mutex> l(mu_); - done_ = true; - cv_.notify_one(); - } - void Await() { - std::unique_lock<std::mutex> l(mu_); - while (!done_) { - cv_.wait(l); - } - } - - private: - EchoRequest request_; - EchoResponse response_; - ClientContext cli_ctx_; - std::mutex mu_; - std::condition_variable cv_; - bool done_{false}; - bool initial_metadata_done_{false}; - }; - - UnaryClient test{stub_.get()}; - test.Await(); - // Make sure that the server interceptors were not notified of a cancel - if (GetParam().use_interceptors) { - EXPECT_EQ(0, DummyInterceptor::GetNumTimesCancel()); - } -} - + const ClientCancelInfo client_cancel_; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; +}; + +TEST_P(ClientCallbackEnd2endTest, RequestStream) { + MAYBE_SKIP_TEST; + ResetStub(); + WriteClient test{stub_.get(), DO_NOT_CANCEL, 3}; + test.Await(); + // Make sure that the server interceptors were not notified to cancel + if (GetParam().use_interceptors) { + EXPECT_EQ(0, DummyInterceptor::GetNumTimesCancel()); + } +} + +TEST_P(ClientCallbackEnd2endTest, ClientCancelsRequestStream) { + MAYBE_SKIP_TEST; + ResetStub(); + WriteClient test{stub_.get(), DO_NOT_CANCEL, 3, ClientCancelInfo{2}}; + test.Await(); + // Make sure that the server interceptors got the cancel + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Server to cancel before doing reading the request +TEST_P(ClientCallbackEnd2endTest, RequestStreamServerCancelBeforeReads) { + MAYBE_SKIP_TEST; + ResetStub(); + WriteClient test{stub_.get(), CANCEL_BEFORE_PROCESSING, 1}; + test.Await(); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Server to cancel while reading a request from the stream in parallel +TEST_P(ClientCallbackEnd2endTest, RequestStreamServerCancelDuringRead) { + MAYBE_SKIP_TEST; + ResetStub(); + WriteClient test{stub_.get(), CANCEL_DURING_PROCESSING, 10}; + test.Await(); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Server to cancel after reading all the requests but before returning to the +// client +TEST_P(ClientCallbackEnd2endTest, RequestStreamServerCancelAfterReads) { + MAYBE_SKIP_TEST; + ResetStub(); + WriteClient test{stub_.get(), CANCEL_AFTER_PROCESSING, 4}; + test.Await(); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +TEST_P(ClientCallbackEnd2endTest, UnaryReactor) { + MAYBE_SKIP_TEST; + ResetStub(); + class UnaryClient : public grpc::experimental::ClientUnaryReactor { + public: + UnaryClient(grpc::testing::EchoTestService::Stub* stub) { + cli_ctx_.AddMetadata("key1", "val1"); + cli_ctx_.AddMetadata("key2", "val2"); + request_.mutable_param()->set_echo_metadata_initially(true); + request_.set_message("Hello metadata"); + stub->experimental_async()->Echo(&cli_ctx_, &request_, &response_, this); + StartCall(); + } + void OnReadInitialMetadataDone(bool ok) override { + EXPECT_TRUE(ok); + EXPECT_EQ(1u, cli_ctx_.GetServerInitialMetadata().count("key1")); + EXPECT_EQ( + "val1", + ToString(cli_ctx_.GetServerInitialMetadata().find("key1")->second)); + EXPECT_EQ(1u, cli_ctx_.GetServerInitialMetadata().count("key2")); + EXPECT_EQ( + "val2", + ToString(cli_ctx_.GetServerInitialMetadata().find("key2")->second)); + initial_metadata_done_ = true; + } + void OnDone(const Status& s) override { + EXPECT_TRUE(initial_metadata_done_); + EXPECT_EQ(0u, cli_ctx_.GetServerTrailingMetadata().size()); + EXPECT_TRUE(s.ok()); + EXPECT_EQ(request_.message(), response_.message()); + std::unique_lock<std::mutex> l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: + EchoRequest request_; + EchoResponse response_; + ClientContext cli_ctx_; + std::mutex mu_; + std::condition_variable cv_; + bool done_{false}; + bool initial_metadata_done_{false}; + }; + + UnaryClient test{stub_.get()}; + test.Await(); + // Make sure that the server interceptors were not notified of a cancel + if (GetParam().use_interceptors) { + EXPECT_EQ(0, DummyInterceptor::GetNumTimesCancel()); + } +} + TEST_P(ClientCallbackEnd2endTest, GenericUnaryReactor) { MAYBE_SKIP_TEST; ResetStub(); @@ -926,270 +926,270 @@ TEST_P(ClientCallbackEnd2endTest, GenericUnaryReactor) { } } -class ReadClient : public grpc::experimental::ClientReadReactor<EchoResponse> { - public: - ReadClient(grpc::testing::EchoTestService::Stub* stub, - ServerTryCancelRequestPhase server_try_cancel, - ClientCancelInfo client_cancel = {}) - : server_try_cancel_(server_try_cancel), client_cancel_{client_cancel} { - if (server_try_cancel_ != DO_NOT_CANCEL) { - // Send server_try_cancel value in the client metadata - context_.AddMetadata(kServerTryCancelRequest, +class ReadClient : public grpc::experimental::ClientReadReactor<EchoResponse> { + public: + ReadClient(grpc::testing::EchoTestService::Stub* stub, + ServerTryCancelRequestPhase server_try_cancel, + ClientCancelInfo client_cancel = {}) + : server_try_cancel_(server_try_cancel), client_cancel_{client_cancel} { + if (server_try_cancel_ != DO_NOT_CANCEL) { + // Send server_try_cancel value in the client metadata + context_.AddMetadata(kServerTryCancelRequest, ToString(server_try_cancel)); - } - request_.set_message("Hello client "); - stub->experimental_async()->ResponseStream(&context_, &request_, this); - if (client_cancel_.cancel && - reads_complete_ == client_cancel_.ops_before_cancel) { - context_.TryCancel(); - } - // Even if we cancel, read until failure because there might be responses - // pending - StartRead(&response_); - StartCall(); - } - void OnReadDone(bool ok) override { - if (!ok) { - if (server_try_cancel_ == DO_NOT_CANCEL && !client_cancel_.cancel) { - EXPECT_EQ(reads_complete_, kServerDefaultResponseStreamsToSend); - } - } else { - EXPECT_LE(reads_complete_, kServerDefaultResponseStreamsToSend); - EXPECT_EQ(response_.message(), + } + request_.set_message("Hello client "); + stub->experimental_async()->ResponseStream(&context_, &request_, this); + if (client_cancel_.cancel && + reads_complete_ == client_cancel_.ops_before_cancel) { + context_.TryCancel(); + } + // Even if we cancel, read until failure because there might be responses + // pending + StartRead(&response_); + StartCall(); + } + void OnReadDone(bool ok) override { + if (!ok) { + if (server_try_cancel_ == DO_NOT_CANCEL && !client_cancel_.cancel) { + EXPECT_EQ(reads_complete_, kServerDefaultResponseStreamsToSend); + } + } else { + EXPECT_LE(reads_complete_, kServerDefaultResponseStreamsToSend); + EXPECT_EQ(response_.message(), request_.message() + ToString(reads_complete_)); - reads_complete_++; - if (client_cancel_.cancel && - reads_complete_ == client_cancel_.ops_before_cancel) { - context_.TryCancel(); - } - // Even if we cancel, read until failure because there might be responses - // pending - StartRead(&response_); - } - } - void OnDone(const Status& s) override { - gpr_log(GPR_INFO, "Read %d messages", reads_complete_); - switch (server_try_cancel_) { - case DO_NOT_CANCEL: - if (!client_cancel_.cancel || client_cancel_.ops_before_cancel > - kServerDefaultResponseStreamsToSend) { - EXPECT_TRUE(s.ok()); - EXPECT_EQ(reads_complete_, kServerDefaultResponseStreamsToSend); - } else { - EXPECT_GE(reads_complete_, client_cancel_.ops_before_cancel); - EXPECT_LE(reads_complete_, kServerDefaultResponseStreamsToSend); - // Status might be ok or cancelled depending on whether server - // sent status before client cancel went through - if (!s.ok()) { - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - } - } - break; - case CANCEL_BEFORE_PROCESSING: - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - EXPECT_EQ(reads_complete_, 0); - break; - case CANCEL_DURING_PROCESSING: - case CANCEL_AFTER_PROCESSING: - // If server canceled while writing messages, client must have read - // less than or equal to the expected number of messages. Even if the - // server canceled after writing all messages, the RPC may be canceled - // before the Client got a chance to read all the messages. - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - EXPECT_LE(reads_complete_, kServerDefaultResponseStreamsToSend); - break; - default: - assert(false); - } - std::unique_lock<std::mutex> l(mu_); - done_ = true; - cv_.notify_one(); - } - void Await() { - std::unique_lock<std::mutex> l(mu_); - while (!done_) { - cv_.wait(l); - } - } - - private: - EchoRequest request_; - EchoResponse response_; - ClientContext context_; - const ServerTryCancelRequestPhase server_try_cancel_; - int reads_complete_{0}; - const ClientCancelInfo client_cancel_; - std::mutex mu_; - std::condition_variable cv_; - bool done_ = false; -}; - -TEST_P(ClientCallbackEnd2endTest, ResponseStream) { - MAYBE_SKIP_TEST; - ResetStub(); - ReadClient test{stub_.get(), DO_NOT_CANCEL}; - test.Await(); - // Make sure that the server interceptors were not notified of a cancel - if (GetParam().use_interceptors) { - EXPECT_EQ(0, DummyInterceptor::GetNumTimesCancel()); - } -} - -TEST_P(ClientCallbackEnd2endTest, ClientCancelsResponseStream) { - MAYBE_SKIP_TEST; - ResetStub(); - ReadClient test{stub_.get(), DO_NOT_CANCEL, ClientCancelInfo{2}}; - test.Await(); - // Because cancel in this case races with server finish, we can't be sure that - // server interceptors even see cancellation -} - -// Server to cancel before sending any response messages -TEST_P(ClientCallbackEnd2endTest, ResponseStreamServerCancelBefore) { - MAYBE_SKIP_TEST; - ResetStub(); - ReadClient test{stub_.get(), CANCEL_BEFORE_PROCESSING}; - test.Await(); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Server to cancel while writing a response to the stream in parallel -TEST_P(ClientCallbackEnd2endTest, ResponseStreamServerCancelDuring) { - MAYBE_SKIP_TEST; - ResetStub(); - ReadClient test{stub_.get(), CANCEL_DURING_PROCESSING}; - test.Await(); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Server to cancel after writing all the respones to the stream but before -// returning to the client -TEST_P(ClientCallbackEnd2endTest, ResponseStreamServerCancelAfter) { - MAYBE_SKIP_TEST; - ResetStub(); - ReadClient test{stub_.get(), CANCEL_AFTER_PROCESSING}; - test.Await(); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -class BidiClient - : public grpc::experimental::ClientBidiReactor<EchoRequest, EchoResponse> { - public: - BidiClient(grpc::testing::EchoTestService::Stub* stub, - ServerTryCancelRequestPhase server_try_cancel, + reads_complete_++; + if (client_cancel_.cancel && + reads_complete_ == client_cancel_.ops_before_cancel) { + context_.TryCancel(); + } + // Even if we cancel, read until failure because there might be responses + // pending + StartRead(&response_); + } + } + void OnDone(const Status& s) override { + gpr_log(GPR_INFO, "Read %d messages", reads_complete_); + switch (server_try_cancel_) { + case DO_NOT_CANCEL: + if (!client_cancel_.cancel || client_cancel_.ops_before_cancel > + kServerDefaultResponseStreamsToSend) { + EXPECT_TRUE(s.ok()); + EXPECT_EQ(reads_complete_, kServerDefaultResponseStreamsToSend); + } else { + EXPECT_GE(reads_complete_, client_cancel_.ops_before_cancel); + EXPECT_LE(reads_complete_, kServerDefaultResponseStreamsToSend); + // Status might be ok or cancelled depending on whether server + // sent status before client cancel went through + if (!s.ok()) { + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + } + } + break; + case CANCEL_BEFORE_PROCESSING: + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + EXPECT_EQ(reads_complete_, 0); + break; + case CANCEL_DURING_PROCESSING: + case CANCEL_AFTER_PROCESSING: + // If server canceled while writing messages, client must have read + // less than or equal to the expected number of messages. Even if the + // server canceled after writing all messages, the RPC may be canceled + // before the Client got a chance to read all the messages. + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + EXPECT_LE(reads_complete_, kServerDefaultResponseStreamsToSend); + break; + default: + assert(false); + } + std::unique_lock<std::mutex> l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + const ServerTryCancelRequestPhase server_try_cancel_; + int reads_complete_{0}; + const ClientCancelInfo client_cancel_; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; +}; + +TEST_P(ClientCallbackEnd2endTest, ResponseStream) { + MAYBE_SKIP_TEST; + ResetStub(); + ReadClient test{stub_.get(), DO_NOT_CANCEL}; + test.Await(); + // Make sure that the server interceptors were not notified of a cancel + if (GetParam().use_interceptors) { + EXPECT_EQ(0, DummyInterceptor::GetNumTimesCancel()); + } +} + +TEST_P(ClientCallbackEnd2endTest, ClientCancelsResponseStream) { + MAYBE_SKIP_TEST; + ResetStub(); + ReadClient test{stub_.get(), DO_NOT_CANCEL, ClientCancelInfo{2}}; + test.Await(); + // Because cancel in this case races with server finish, we can't be sure that + // server interceptors even see cancellation +} + +// Server to cancel before sending any response messages +TEST_P(ClientCallbackEnd2endTest, ResponseStreamServerCancelBefore) { + MAYBE_SKIP_TEST; + ResetStub(); + ReadClient test{stub_.get(), CANCEL_BEFORE_PROCESSING}; + test.Await(); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Server to cancel while writing a response to the stream in parallel +TEST_P(ClientCallbackEnd2endTest, ResponseStreamServerCancelDuring) { + MAYBE_SKIP_TEST; + ResetStub(); + ReadClient test{stub_.get(), CANCEL_DURING_PROCESSING}; + test.Await(); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Server to cancel after writing all the respones to the stream but before +// returning to the client +TEST_P(ClientCallbackEnd2endTest, ResponseStreamServerCancelAfter) { + MAYBE_SKIP_TEST; + ResetStub(); + ReadClient test{stub_.get(), CANCEL_AFTER_PROCESSING}; + test.Await(); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +class BidiClient + : public grpc::experimental::ClientBidiReactor<EchoRequest, EchoResponse> { + public: + BidiClient(grpc::testing::EchoTestService::Stub* stub, + ServerTryCancelRequestPhase server_try_cancel, int num_msgs_to_send, bool cork_metadata, bool first_write_async, ClientCancelInfo client_cancel = {}) - : server_try_cancel_(server_try_cancel), - msgs_to_send_{num_msgs_to_send}, - client_cancel_{client_cancel} { - if (server_try_cancel_ != DO_NOT_CANCEL) { - // Send server_try_cancel value in the client metadata - context_.AddMetadata(kServerTryCancelRequest, + : server_try_cancel_(server_try_cancel), + msgs_to_send_{num_msgs_to_send}, + client_cancel_{client_cancel} { + if (server_try_cancel_ != DO_NOT_CANCEL) { + // Send server_try_cancel value in the client metadata + context_.AddMetadata(kServerTryCancelRequest, ToString(server_try_cancel)); - } - request_.set_message("Hello fren "); + } + request_.set_message("Hello fren "); context_.set_initial_metadata_corked(cork_metadata); - stub->experimental_async()->BidiStream(&context_, this); + stub->experimental_async()->BidiStream(&context_, this); MaybeAsyncWrite(first_write_async); - StartRead(&response_); - StartCall(); - } - void OnReadDone(bool ok) override { - if (!ok) { - if (server_try_cancel_ == DO_NOT_CANCEL) { - if (!client_cancel_.cancel) { - EXPECT_EQ(reads_complete_, msgs_to_send_); - } else { - EXPECT_LE(reads_complete_, writes_complete_); - } - } - } else { - EXPECT_LE(reads_complete_, msgs_to_send_); - EXPECT_EQ(response_.message(), request_.message()); - reads_complete_++; - StartRead(&response_); - } - } - void OnWriteDone(bool ok) override { + StartRead(&response_); + StartCall(); + } + void OnReadDone(bool ok) override { + if (!ok) { + if (server_try_cancel_ == DO_NOT_CANCEL) { + if (!client_cancel_.cancel) { + EXPECT_EQ(reads_complete_, msgs_to_send_); + } else { + EXPECT_LE(reads_complete_, writes_complete_); + } + } + } else { + EXPECT_LE(reads_complete_, msgs_to_send_); + EXPECT_EQ(response_.message(), request_.message()); + reads_complete_++; + StartRead(&response_); + } + } + void OnWriteDone(bool ok) override { if (async_write_thread_.joinable()) { async_write_thread_.join(); RemoveHold(); } - if (server_try_cancel_ == DO_NOT_CANCEL) { - EXPECT_TRUE(ok); - } else if (!ok) { - return; - } - writes_complete_++; - MaybeWrite(); - } - void OnDone(const Status& s) override { - gpr_log(GPR_INFO, "Sent %d messages", writes_complete_); - gpr_log(GPR_INFO, "Read %d messages", reads_complete_); - switch (server_try_cancel_) { - case DO_NOT_CANCEL: - if (!client_cancel_.cancel || - client_cancel_.ops_before_cancel > msgs_to_send_) { - EXPECT_TRUE(s.ok()); - EXPECT_EQ(writes_complete_, msgs_to_send_); - EXPECT_EQ(reads_complete_, writes_complete_); - } else { - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - EXPECT_EQ(writes_complete_, client_cancel_.ops_before_cancel); - EXPECT_LE(reads_complete_, writes_complete_); - } - break; - case CANCEL_BEFORE_PROCESSING: - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - // The RPC is canceled before the server did any work or returned any - // reads, but it's possible that some writes took place first from the - // client - EXPECT_LE(writes_complete_, msgs_to_send_); - EXPECT_EQ(reads_complete_, 0); - break; - case CANCEL_DURING_PROCESSING: - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - EXPECT_LE(writes_complete_, msgs_to_send_); - EXPECT_LE(reads_complete_, writes_complete_); - break; - case CANCEL_AFTER_PROCESSING: - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - EXPECT_EQ(writes_complete_, msgs_to_send_); - // The Server canceled after reading the last message and after writing - // the message to the client. However, the RPC cancellation might have - // taken effect before the client actually read the response. - EXPECT_LE(reads_complete_, writes_complete_); - break; - default: - assert(false); - } - std::unique_lock<std::mutex> l(mu_); - done_ = true; - cv_.notify_one(); - } - void Await() { - std::unique_lock<std::mutex> l(mu_); - while (!done_) { - cv_.wait(l); - } - } - - private: + if (server_try_cancel_ == DO_NOT_CANCEL) { + EXPECT_TRUE(ok); + } else if (!ok) { + return; + } + writes_complete_++; + MaybeWrite(); + } + void OnDone(const Status& s) override { + gpr_log(GPR_INFO, "Sent %d messages", writes_complete_); + gpr_log(GPR_INFO, "Read %d messages", reads_complete_); + switch (server_try_cancel_) { + case DO_NOT_CANCEL: + if (!client_cancel_.cancel || + client_cancel_.ops_before_cancel > msgs_to_send_) { + EXPECT_TRUE(s.ok()); + EXPECT_EQ(writes_complete_, msgs_to_send_); + EXPECT_EQ(reads_complete_, writes_complete_); + } else { + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + EXPECT_EQ(writes_complete_, client_cancel_.ops_before_cancel); + EXPECT_LE(reads_complete_, writes_complete_); + } + break; + case CANCEL_BEFORE_PROCESSING: + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + // The RPC is canceled before the server did any work or returned any + // reads, but it's possible that some writes took place first from the + // client + EXPECT_LE(writes_complete_, msgs_to_send_); + EXPECT_EQ(reads_complete_, 0); + break; + case CANCEL_DURING_PROCESSING: + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + EXPECT_LE(writes_complete_, msgs_to_send_); + EXPECT_LE(reads_complete_, writes_complete_); + break; + case CANCEL_AFTER_PROCESSING: + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + EXPECT_EQ(writes_complete_, msgs_to_send_); + // The Server canceled after reading the last message and after writing + // the message to the client. However, the RPC cancellation might have + // taken effect before the client actually read the response. + EXPECT_LE(reads_complete_, writes_complete_); + break; + default: + assert(false); + } + std::unique_lock<std::mutex> l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: void MaybeAsyncWrite(bool first_write_async) { if (first_write_async) { // Make sure that we have a write to issue. @@ -1210,46 +1210,46 @@ class BidiClient } MaybeWrite(); } - void MaybeWrite() { - if (client_cancel_.cancel && - writes_complete_ == client_cancel_.ops_before_cancel) { - context_.TryCancel(); - } else if (writes_complete_ == msgs_to_send_) { - StartWritesDone(); - } else { - StartWrite(&request_); - } - } - EchoRequest request_; - EchoResponse response_; - ClientContext context_; - const ServerTryCancelRequestPhase server_try_cancel_; - int reads_complete_{0}; - int writes_complete_{0}; - const int msgs_to_send_; - const ClientCancelInfo client_cancel_; - std::mutex mu_; - std::condition_variable cv_; - bool done_ = false; + void MaybeWrite() { + if (client_cancel_.cancel && + writes_complete_ == client_cancel_.ops_before_cancel) { + context_.TryCancel(); + } else if (writes_complete_ == msgs_to_send_) { + StartWritesDone(); + } else { + StartWrite(&request_); + } + } + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + const ServerTryCancelRequestPhase server_try_cancel_; + int reads_complete_{0}; + int writes_complete_{0}; + const int msgs_to_send_; + const ClientCancelInfo client_cancel_; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; std::thread async_write_thread_; bool async_write_thread_start_ = false; std::mutex async_write_thread_mu_; std::condition_variable async_write_thread_cv_; -}; - -TEST_P(ClientCallbackEnd2endTest, BidiStream) { - MAYBE_SKIP_TEST; - ResetStub(); +}; + +TEST_P(ClientCallbackEnd2endTest, BidiStream) { + MAYBE_SKIP_TEST; + ResetStub(); BidiClient test(stub_.get(), DO_NOT_CANCEL, kServerDefaultResponseStreamsToSend, /*cork_metadata=*/false, /*first_write_async=*/false); - test.Await(); - // Make sure that the server interceptors were not notified of a cancel - if (GetParam().use_interceptors) { - EXPECT_EQ(0, DummyInterceptor::GetNumTimesCancel()); - } -} - + test.Await(); + // Make sure that the server interceptors were not notified of a cancel + if (GetParam().use_interceptors) { + EXPECT_EQ(0, DummyInterceptor::GetNumTimesCancel()); + } +} + TEST_P(ClientCallbackEnd2endTest, BidiStreamFirstWriteAsync) { MAYBE_SKIP_TEST; ResetStub(); @@ -1289,277 +1289,277 @@ TEST_P(ClientCallbackEnd2endTest, BidiStreamCorkedFirstWriteAsync) { } } -TEST_P(ClientCallbackEnd2endTest, ClientCancelsBidiStream) { - MAYBE_SKIP_TEST; - ResetStub(); +TEST_P(ClientCallbackEnd2endTest, ClientCancelsBidiStream) { + MAYBE_SKIP_TEST; + ResetStub(); BidiClient test(stub_.get(), DO_NOT_CANCEL, kServerDefaultResponseStreamsToSend, /*cork_metadata=*/false, /*first_write_async=*/false, ClientCancelInfo(2)); - test.Await(); - // Make sure that the server interceptors were notified of a cancel - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Server to cancel before reading/writing any requests/responses on the stream -TEST_P(ClientCallbackEnd2endTest, BidiStreamServerCancelBefore) { - MAYBE_SKIP_TEST; - ResetStub(); + test.Await(); + // Make sure that the server interceptors were notified of a cancel + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Server to cancel before reading/writing any requests/responses on the stream +TEST_P(ClientCallbackEnd2endTest, BidiStreamServerCancelBefore) { + MAYBE_SKIP_TEST; + ResetStub(); BidiClient test(stub_.get(), CANCEL_BEFORE_PROCESSING, /*num_msgs_to_send=*/2, /*cork_metadata=*/false, /*first_write_async=*/false); - test.Await(); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Server to cancel while reading/writing requests/responses on the stream in -// parallel -TEST_P(ClientCallbackEnd2endTest, BidiStreamServerCancelDuring) { - MAYBE_SKIP_TEST; - ResetStub(); + test.Await(); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Server to cancel while reading/writing requests/responses on the stream in +// parallel +TEST_P(ClientCallbackEnd2endTest, BidiStreamServerCancelDuring) { + MAYBE_SKIP_TEST; + ResetStub(); BidiClient test(stub_.get(), CANCEL_DURING_PROCESSING, /*num_msgs_to_send=*/10, /*cork_metadata=*/false, /*first_write_async=*/false); - test.Await(); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Server to cancel after reading/writing all requests/responses on the stream -// but before returning to the client -TEST_P(ClientCallbackEnd2endTest, BidiStreamServerCancelAfter) { - MAYBE_SKIP_TEST; - ResetStub(); + test.Await(); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Server to cancel after reading/writing all requests/responses on the stream +// but before returning to the client +TEST_P(ClientCallbackEnd2endTest, BidiStreamServerCancelAfter) { + MAYBE_SKIP_TEST; + ResetStub(); BidiClient test(stub_.get(), CANCEL_AFTER_PROCESSING, /*num_msgs_to_send=*/5, /*cork_metadata=*/false, /*first_write_async=*/false); - test.Await(); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -TEST_P(ClientCallbackEnd2endTest, SimultaneousReadAndWritesDone) { - MAYBE_SKIP_TEST; - ResetStub(); - class Client : public grpc::experimental::ClientBidiReactor<EchoRequest, - EchoResponse> { - public: - Client(grpc::testing::EchoTestService::Stub* stub) { - request_.set_message("Hello bidi "); - stub->experimental_async()->BidiStream(&context_, this); - StartWrite(&request_); - StartCall(); - } - void OnReadDone(bool ok) override { - EXPECT_TRUE(ok); - EXPECT_EQ(response_.message(), request_.message()); - } - void OnWriteDone(bool ok) override { - EXPECT_TRUE(ok); - // Now send out the simultaneous Read and WritesDone - StartWritesDone(); - StartRead(&response_); - } - void OnDone(const Status& s) override { - EXPECT_TRUE(s.ok()); - EXPECT_EQ(response_.message(), request_.message()); - std::unique_lock<std::mutex> l(mu_); - done_ = true; - cv_.notify_one(); - } - void Await() { - std::unique_lock<std::mutex> l(mu_); - while (!done_) { - cv_.wait(l); - } - } - - private: - EchoRequest request_; - EchoResponse response_; - ClientContext context_; - std::mutex mu_; - std::condition_variable cv_; - bool done_ = false; - } test{stub_.get()}; - - test.Await(); -} - -TEST_P(ClientCallbackEnd2endTest, UnimplementedRpc) { - MAYBE_SKIP_TEST; - ChannelArguments args; - const auto& channel_creds = GetCredentialsProvider()->GetChannelCredentials( - GetParam().credentials_type, &args); - std::shared_ptr<Channel> channel = - (GetParam().protocol == Protocol::TCP) - ? ::grpc::CreateCustomChannel(server_address_.str(), channel_creds, - args) - : server_->InProcessChannel(args); - std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; - stub = grpc::testing::UnimplementedEchoService::NewStub(channel); - EchoRequest request; - EchoResponse response; - ClientContext cli_ctx; - request.set_message("Hello world."); - std::mutex mu; - std::condition_variable cv; - bool done = false; - stub->experimental_async()->Unimplemented( - &cli_ctx, &request, &response, [&done, &mu, &cv](Status s) { - EXPECT_EQ(StatusCode::UNIMPLEMENTED, s.error_code()); - EXPECT_EQ("", s.error_message()); - - std::lock_guard<std::mutex> l(mu); - done = true; - cv.notify_one(); - }); - std::unique_lock<std::mutex> l(mu); - while (!done) { - cv.wait(l); - } -} - -TEST_P(ClientCallbackEnd2endTest, - ResponseStreamExtraReactionFlowReadsUntilDone) { - MAYBE_SKIP_TEST; - ResetStub(); - class ReadAllIncomingDataClient - : public grpc::experimental::ClientReadReactor<EchoResponse> { - public: - ReadAllIncomingDataClient(grpc::testing::EchoTestService::Stub* stub) { - request_.set_message("Hello client "); - stub->experimental_async()->ResponseStream(&context_, &request_, this); - } - bool WaitForReadDone() { - std::unique_lock<std::mutex> l(mu_); - while (!read_done_) { - read_cv_.wait(l); - } - read_done_ = false; - return read_ok_; - } - void Await() { - std::unique_lock<std::mutex> l(mu_); - while (!done_) { - done_cv_.wait(l); - } - } + test.Await(); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +TEST_P(ClientCallbackEnd2endTest, SimultaneousReadAndWritesDone) { + MAYBE_SKIP_TEST; + ResetStub(); + class Client : public grpc::experimental::ClientBidiReactor<EchoRequest, + EchoResponse> { + public: + Client(grpc::testing::EchoTestService::Stub* stub) { + request_.set_message("Hello bidi "); + stub->experimental_async()->BidiStream(&context_, this); + StartWrite(&request_); + StartCall(); + } + void OnReadDone(bool ok) override { + EXPECT_TRUE(ok); + EXPECT_EQ(response_.message(), request_.message()); + } + void OnWriteDone(bool ok) override { + EXPECT_TRUE(ok); + // Now send out the simultaneous Read and WritesDone + StartWritesDone(); + StartRead(&response_); + } + void OnDone(const Status& s) override { + EXPECT_TRUE(s.ok()); + EXPECT_EQ(response_.message(), request_.message()); + std::unique_lock<std::mutex> l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; + } test{stub_.get()}; + + test.Await(); +} + +TEST_P(ClientCallbackEnd2endTest, UnimplementedRpc) { + MAYBE_SKIP_TEST; + ChannelArguments args; + const auto& channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); + std::shared_ptr<Channel> channel = + (GetParam().protocol == Protocol::TCP) + ? ::grpc::CreateCustomChannel(server_address_.str(), channel_creds, + args) + : server_->InProcessChannel(args); + std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; + stub = grpc::testing::UnimplementedEchoService::NewStub(channel); + EchoRequest request; + EchoResponse response; + ClientContext cli_ctx; + request.set_message("Hello world."); + std::mutex mu; + std::condition_variable cv; + bool done = false; + stub->experimental_async()->Unimplemented( + &cli_ctx, &request, &response, [&done, &mu, &cv](Status s) { + EXPECT_EQ(StatusCode::UNIMPLEMENTED, s.error_code()); + EXPECT_EQ("", s.error_message()); + + std::lock_guard<std::mutex> l(mu); + done = true; + cv.notify_one(); + }); + std::unique_lock<std::mutex> l(mu); + while (!done) { + cv.wait(l); + } +} + +TEST_P(ClientCallbackEnd2endTest, + ResponseStreamExtraReactionFlowReadsUntilDone) { + MAYBE_SKIP_TEST; + ResetStub(); + class ReadAllIncomingDataClient + : public grpc::experimental::ClientReadReactor<EchoResponse> { + public: + ReadAllIncomingDataClient(grpc::testing::EchoTestService::Stub* stub) { + request_.set_message("Hello client "); + stub->experimental_async()->ResponseStream(&context_, &request_, this); + } + bool WaitForReadDone() { + std::unique_lock<std::mutex> l(mu_); + while (!read_done_) { + read_cv_.wait(l); + } + read_done_ = false; + return read_ok_; + } + void Await() { + std::unique_lock<std::mutex> l(mu_); + while (!done_) { + done_cv_.wait(l); + } + } // RemoveHold under the same lock used for OnDone to make sure that we don't // call OnDone directly or indirectly from the RemoveHold function. void RemoveHoldUnderLock() { std::unique_lock<std::mutex> l(mu_); RemoveHold(); } - const Status& status() { - std::unique_lock<std::mutex> l(mu_); - return status_; - } - - private: - void OnReadDone(bool ok) override { - std::unique_lock<std::mutex> l(mu_); - read_ok_ = ok; - read_done_ = true; - read_cv_.notify_one(); - } - void OnDone(const Status& s) override { - std::unique_lock<std::mutex> l(mu_); - done_ = true; - status_ = s; - done_cv_.notify_one(); - } - - EchoRequest request_; - EchoResponse response_; - ClientContext context_; - bool read_ok_ = false; - bool read_done_ = false; - std::mutex mu_; - std::condition_variable read_cv_; - std::condition_variable done_cv_; - bool done_ = false; - Status status_; - } client{stub_.get()}; - - int reads_complete = 0; - client.AddHold(); - client.StartCall(); - - EchoResponse response; - bool read_ok = true; - while (read_ok) { - client.StartRead(&response); - read_ok = client.WaitForReadDone(); - if (read_ok) { - ++reads_complete; - } - } + const Status& status() { + std::unique_lock<std::mutex> l(mu_); + return status_; + } + + private: + void OnReadDone(bool ok) override { + std::unique_lock<std::mutex> l(mu_); + read_ok_ = ok; + read_done_ = true; + read_cv_.notify_one(); + } + void OnDone(const Status& s) override { + std::unique_lock<std::mutex> l(mu_); + done_ = true; + status_ = s; + done_cv_.notify_one(); + } + + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + bool read_ok_ = false; + bool read_done_ = false; + std::mutex mu_; + std::condition_variable read_cv_; + std::condition_variable done_cv_; + bool done_ = false; + Status status_; + } client{stub_.get()}; + + int reads_complete = 0; + client.AddHold(); + client.StartCall(); + + EchoResponse response; + bool read_ok = true; + while (read_ok) { + client.StartRead(&response); + read_ok = client.WaitForReadDone(); + if (read_ok) { + ++reads_complete; + } + } client.RemoveHoldUnderLock(); - client.Await(); - - EXPECT_EQ(kServerDefaultResponseStreamsToSend, reads_complete); - EXPECT_EQ(client.status().error_code(), grpc::StatusCode::OK); -} - -std::vector<TestScenario> CreateTestScenarios(bool test_insecure) { -#if TARGET_OS_IPHONE - // Workaround Apple CFStream bug - gpr_setenv("grpc_cfstream", "0"); -#endif - - std::vector<TestScenario> scenarios; + client.Await(); + + EXPECT_EQ(kServerDefaultResponseStreamsToSend, reads_complete); + EXPECT_EQ(client.status().error_code(), grpc::StatusCode::OK); +} + +std::vector<TestScenario> CreateTestScenarios(bool test_insecure) { +#if TARGET_OS_IPHONE + // Workaround Apple CFStream bug + gpr_setenv("grpc_cfstream", "0"); +#endif + + std::vector<TestScenario> scenarios; std::vector<TString> credentials_types{ - GetCredentialsProvider()->GetSecureCredentialsTypeList()}; - auto insec_ok = [] { - // Only allow insecure credentials type when it is registered with the - // provider. User may create providers that do not have insecure. - return GetCredentialsProvider()->GetChannelCredentials( - kInsecureCredentialsType, nullptr) != nullptr; - }; - if (test_insecure && insec_ok()) { - credentials_types.push_back(kInsecureCredentialsType); - } - GPR_ASSERT(!credentials_types.empty()); - - bool barr[]{false, true}; - Protocol parr[]{Protocol::INPROC, Protocol::TCP}; - for (Protocol p : parr) { - for (const auto& cred : credentials_types) { - // TODO(vjpai): Test inproc with secure credentials when feasible - if (p == Protocol::INPROC && - (cred != kInsecureCredentialsType || !insec_ok())) { - continue; - } - for (bool callback_server : barr) { - for (bool use_interceptors : barr) { - scenarios.emplace_back(callback_server, p, use_interceptors, cred); - } - } - } - } - return scenarios; -} - -INSTANTIATE_TEST_SUITE_P(ClientCallbackEnd2endTest, ClientCallbackEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(true))); - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { + GetCredentialsProvider()->GetSecureCredentialsTypeList()}; + auto insec_ok = [] { + // Only allow insecure credentials type when it is registered with the + // provider. User may create providers that do not have insecure. + return GetCredentialsProvider()->GetChannelCredentials( + kInsecureCredentialsType, nullptr) != nullptr; + }; + if (test_insecure && insec_ok()) { + credentials_types.push_back(kInsecureCredentialsType); + } + GPR_ASSERT(!credentials_types.empty()); + + bool barr[]{false, true}; + Protocol parr[]{Protocol::INPROC, Protocol::TCP}; + for (Protocol p : parr) { + for (const auto& cred : credentials_types) { + // TODO(vjpai): Test inproc with secure credentials when feasible + if (p == Protocol::INPROC && + (cred != kInsecureCredentialsType || !insec_ok())) { + continue; + } + for (bool callback_server : barr) { + for (bool use_interceptors : barr) { + scenarios.emplace_back(callback_server, p, use_interceptors, cred); + } + } + } + } + return scenarios; +} + +INSTANTIATE_TEST_SUITE_P(ClientCallbackEnd2endTest, ClientCallbackEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(true))); + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); grpc::testing::TestEnvironment env(argc, argv); - grpc_init(); - int ret = RUN_ALL_TESTS(); - grpc_shutdown(); - return ret; -} + grpc_init(); + int ret = RUN_ALL_TESTS(); + grpc_shutdown(); + return ret; +} diff --git a/contrib/libs/grpc/test/cpp/end2end/client_crash_test.cc b/contrib/libs/grpc/test/cpp/end2end/client_crash_test.cc index 93131f8104..80e1869396 100644 --- a/contrib/libs/grpc/test/cpp/end2end/client_crash_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/client_crash_test.cc @@ -1,147 +1,147 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <grpc/grpc.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/util/subprocess.h" - -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; -using std::chrono::system_clock; - +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <grpc/grpc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/util/subprocess.h" + +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; +using std::chrono::system_clock; + static TString g_root; - -namespace grpc { -namespace testing { - -namespace { - -class CrashTest : public ::testing::Test { - protected: - CrashTest() {} - - std::unique_ptr<grpc::testing::EchoTestService::Stub> CreateServerAndStub() { - auto port = grpc_pick_unused_port_or_die(); - std::ostringstream addr_stream; - addr_stream << "localhost:" << port; - auto addr = addr_stream.str(); - server_.reset(new SubProcess({ - g_root + "/client_crash_test_server", - "--address=" + addr, - })); - GPR_ASSERT(server_); - return grpc::testing::EchoTestService::NewStub( - grpc::CreateChannel(addr, InsecureChannelCredentials())); - } - - void KillServer() { server_.reset(); } - - private: - std::unique_ptr<SubProcess> server_; -}; - -TEST_F(CrashTest, KillBeforeWrite) { - auto stub = CreateServerAndStub(); - - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_wait_for_ready(true); - - auto stream = stub->BidiStream(&context); - - request.set_message("Hello"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - KillServer(); - - request.set_message("You should be dead"); - // This may succeed or fail depending on the state of the TCP connection - stream->Write(request); - // But the read will definitely fail - EXPECT_FALSE(stream->Read(&response)); - - EXPECT_FALSE(stream->Finish().ok()); -} - -TEST_F(CrashTest, KillAfterWrite) { - auto stub = CreateServerAndStub(); - - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_wait_for_ready(true); - - auto stream = stub->BidiStream(&context); - - request.set_message("Hello"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - request.set_message("I'm going to kill you"); - EXPECT_TRUE(stream->Write(request)); - - KillServer(); - - // This may succeed or fail depending on how quick the server was - stream->Read(&response); - - EXPECT_FALSE(stream->Finish().ok()); -} - -} // namespace - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { + +namespace grpc { +namespace testing { + +namespace { + +class CrashTest : public ::testing::Test { + protected: + CrashTest() {} + + std::unique_ptr<grpc::testing::EchoTestService::Stub> CreateServerAndStub() { + auto port = grpc_pick_unused_port_or_die(); + std::ostringstream addr_stream; + addr_stream << "localhost:" << port; + auto addr = addr_stream.str(); + server_.reset(new SubProcess({ + g_root + "/client_crash_test_server", + "--address=" + addr, + })); + GPR_ASSERT(server_); + return grpc::testing::EchoTestService::NewStub( + grpc::CreateChannel(addr, InsecureChannelCredentials())); + } + + void KillServer() { server_.reset(); } + + private: + std::unique_ptr<SubProcess> server_; +}; + +TEST_F(CrashTest, KillBeforeWrite) { + auto stub = CreateServerAndStub(); + + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_wait_for_ready(true); + + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + KillServer(); + + request.set_message("You should be dead"); + // This may succeed or fail depending on the state of the TCP connection + stream->Write(request); + // But the read will definitely fail + EXPECT_FALSE(stream->Read(&response)); + + EXPECT_FALSE(stream->Finish().ok()); +} + +TEST_F(CrashTest, KillAfterWrite) { + auto stub = CreateServerAndStub(); + + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_wait_for_ready(true); + + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message("I'm going to kill you"); + EXPECT_TRUE(stream->Write(request)); + + KillServer(); + + // This may succeed or fail depending on how quick the server was + stream->Read(&response); + + EXPECT_FALSE(stream->Finish().ok()); +} + +} // namespace + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { TString me = argv[0]; - auto lslash = me.rfind('/'); + auto lslash = me.rfind('/'); if (lslash != TString::npos) { - g_root = me.substr(0, lslash); - } else { - g_root = "."; - } - - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - // Order seems to matter on these tests: run three times to eliminate that - for (int i = 0; i < 3; i++) { - if (RUN_ALL_TESTS() != 0) { - return 1; - } - } - return 0; -} + g_root = me.substr(0, lslash); + } else { + g_root = "."; + } + + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + // Order seems to matter on these tests: run three times to eliminate that + for (int i = 0; i < 3; i++) { + if (RUN_ALL_TESTS() != 0) { + return 1; + } + } + return 0; +} diff --git a/contrib/libs/grpc/test/cpp/end2end/client_crash_test_server.cc b/contrib/libs/grpc/test/cpp/end2end/client_crash_test_server.cc index a7e0dc3aa0..2d5be420f2 100644 --- a/contrib/libs/grpc/test/cpp/end2end/client_crash_test_server.cc +++ b/contrib/libs/grpc/test/cpp/end2end/client_crash_test_server.cc @@ -1,80 +1,80 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <gflags/gflags.h> -#include <iostream> -#include <memory> +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <gflags/gflags.h> +#include <iostream> +#include <memory> #include <util/generic/string.h> - -#include <grpc/support/log.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/cpp/util/test_config.h" - -DEFINE_string(address, "", "Address to bind to"); - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; - -// In some distros, gflags is in the namespace google, and in some others, -// in gflags. This hack is enabling us to find both. -namespace google {} -namespace gflags {} -using namespace google; -using namespace gflags; - -namespace grpc { -namespace testing { - -class ServiceImpl final : public ::grpc::testing::EchoTestService::Service { - Status BidiStream( - ServerContext* /*context*/, - ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { - EchoRequest request; - EchoResponse response; - while (stream->Read(&request)) { - gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); - response.set_message(request.message()); - stream->Write(response); - } - return Status::OK; - } -}; - -void RunServer() { - ServiceImpl service; - - ServerBuilder builder; - builder.AddListeningPort(FLAGS_address, grpc::InsecureServerCredentials()); - builder.RegisterService(&service); - std::unique_ptr<Server> server(builder.BuildAndStart()); - std::cout << "Server listening on " << FLAGS_address << std::endl; - server->Wait(); -} -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::InitTest(&argc, &argv, true); - grpc::testing::RunServer(); - - return 0; -} + +#include <grpc/support/log.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/cpp/util/test_config.h" + +DEFINE_string(address, "", "Address to bind to"); + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; + +// In some distros, gflags is in the namespace google, and in some others, +// in gflags. This hack is enabling us to find both. +namespace google {} +namespace gflags {} +using namespace google; +using namespace gflags; + +namespace grpc { +namespace testing { + +class ServiceImpl final : public ::grpc::testing::EchoTestService::Service { + Status BidiStream( + ServerContext* /*context*/, + ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { + EchoRequest request; + EchoResponse response; + while (stream->Read(&request)) { + gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); + response.set_message(request.message()); + stream->Write(response); + } + return Status::OK; + } +}; + +void RunServer() { + ServiceImpl service; + + ServerBuilder builder; + builder.AddListeningPort(FLAGS_address, grpc::InsecureServerCredentials()); + builder.RegisterService(&service); + std::unique_ptr<Server> server(builder.BuildAndStart()); + std::cout << "Server listening on " << FLAGS_address << std::endl; + server->Wait(); +} +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::InitTest(&argc, &argv, true); + grpc::testing::RunServer(); + + return 0; +} diff --git a/contrib/libs/grpc/test/cpp/end2end/client_interceptors_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/client_interceptors_end2end_test.cc index 18a9e98b71..956876d9f6 100644 --- a/contrib/libs/grpc/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -1,48 +1,48 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ - -#include <memory> -#include <vector> - -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/generic/generic_stub.h> -#include <grpcpp/impl/codegen/proto_utils.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> -#include <grpcpp/support/client_interceptor.h> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/interceptors_util.h" -#include "test/cpp/end2end/test_service_impl.h" -#include "test/cpp/util/byte_buffer_proto_helper.h" -#include "test/cpp/util/string_ref_helper.h" - -#include <gtest/gtest.h> - -namespace grpc { -namespace testing { -namespace { - +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ + +#include <memory> +#include <vector> + +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/generic/generic_stub.h> +#include <grpcpp/impl/codegen/proto_utils.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> +#include <grpcpp/support/client_interceptor.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/interceptors_util.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" +#include "test/cpp/util/string_ref_helper.h" + +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { +namespace { + enum class RPCType { kSyncUnary, kSyncClientStreaming, @@ -54,495 +54,495 @@ enum class RPCType { kAsyncCQBidiStreaming, }; -/* Hijacks Echo RPC and fills in the expected values */ -class HijackingInterceptor : public experimental::Interceptor { - public: - HijackingInterceptor(experimental::ClientRpcInfo* info) { - info_ = info; - // Make sure it is the right method - EXPECT_EQ(strcmp("/grpc.testing.EchoTestService/Echo", info->method()), 0); - EXPECT_EQ(info->type(), experimental::ClientRpcInfo::Type::UNARY); - } - - virtual void Intercept(experimental::InterceptorBatchMethods* methods) { - bool hijack = false; - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { - auto* map = methods->GetSendInitialMetadata(); - // Check that we can see the test metadata - ASSERT_EQ(map->size(), static_cast<unsigned>(1)); - auto iterator = map->begin(); - EXPECT_EQ("testkey", iterator->first); - EXPECT_EQ("testvalue", iterator->second); - hijack = true; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - EchoRequest req; - auto* buffer = methods->GetSerializedSendMessage(); - auto copied_buffer = *buffer; - EXPECT_TRUE( - SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) - .ok()); - EXPECT_EQ(req.message(), "Hello"); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { - // Got nothing to do here for now - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { - auto* map = methods->GetRecvInitialMetadata(); - // Got nothing better to do here for now - EXPECT_EQ(map->size(), static_cast<unsigned>(0)); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { - EchoResponse* resp = - static_cast<EchoResponse*>(methods->GetRecvMessage()); - // Check that we got the hijacked message, and re-insert the expected - // message - EXPECT_EQ(resp->message(), "Hello1"); - resp->set_message("Hello"); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_STATUS)) { - auto* map = methods->GetRecvTrailingMetadata(); - bool found = false; - // Check that we received the metadata as an echo - for (const auto& pair : *map) { - found = pair.first.starts_with("testkey") && - pair.second.starts_with("testvalue"); - if (found) break; - } - EXPECT_EQ(found, true); - auto* status = methods->GetRecvStatus(); - EXPECT_EQ(status->ok(), true); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_INITIAL_METADATA)) { - auto* map = methods->GetRecvInitialMetadata(); - // Got nothing better to do here at the moment - EXPECT_EQ(map->size(), static_cast<unsigned>(0)); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { - // Insert a different message than expected - EchoResponse* resp = - static_cast<EchoResponse*>(methods->GetRecvMessage()); - resp->set_message("Hello1"); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { - auto* map = methods->GetRecvTrailingMetadata(); - // insert the metadata that we want - EXPECT_EQ(map->size(), static_cast<unsigned>(0)); - map->insert(std::make_pair("testkey", "testvalue")); - auto* status = methods->GetRecvStatus(); - *status = Status(StatusCode::OK, ""); - } - if (hijack) { - methods->Hijack(); - } else { - methods->Proceed(); - } - } - - private: - experimental::ClientRpcInfo* info_; -}; - -class HijackingInterceptorFactory - : public experimental::ClientInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateClientInterceptor( - experimental::ClientRpcInfo* info) override { - return new HijackingInterceptor(info); - } -}; - -class HijackingInterceptorMakesAnotherCall : public experimental::Interceptor { - public: - HijackingInterceptorMakesAnotherCall(experimental::ClientRpcInfo* info) { - info_ = info; - // Make sure it is the right method - EXPECT_EQ(strcmp("/grpc.testing.EchoTestService/Echo", info->method()), 0); - } - - virtual void Intercept(experimental::InterceptorBatchMethods* methods) { - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { - auto* map = methods->GetSendInitialMetadata(); - // Check that we can see the test metadata - ASSERT_EQ(map->size(), static_cast<unsigned>(1)); - auto iterator = map->begin(); - EXPECT_EQ("testkey", iterator->first); - EXPECT_EQ("testvalue", iterator->second); - // Make a copy of the map - metadata_map_ = *map; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - EchoRequest req; - auto* buffer = methods->GetSerializedSendMessage(); - auto copied_buffer = *buffer; - EXPECT_TRUE( - SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) - .ok()); - EXPECT_EQ(req.message(), "Hello"); - req_ = req; - stub_ = grpc::testing::EchoTestService::NewStub( - methods->GetInterceptedChannel()); - ctx_.AddMetadata(metadata_map_.begin()->first, - metadata_map_.begin()->second); - stub_->experimental_async()->Echo(&ctx_, &req_, &resp_, - [this, methods](Status s) { - EXPECT_EQ(s.ok(), true); - EXPECT_EQ(resp_.message(), "Hello"); - methods->Hijack(); - }); - // This is a Unary RPC and we have got nothing interesting to do in the - // PRE_SEND_CLOSE interception hook point for this interceptor, so let's - // return here. (We do not want to call methods->Proceed(). When the new - // RPC returns, we will call methods->Hijack() instead.) - return; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { - // Got nothing to do here for now - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { - auto* map = methods->GetRecvInitialMetadata(); - // Got nothing better to do here for now - EXPECT_EQ(map->size(), static_cast<unsigned>(0)); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { - EchoResponse* resp = - static_cast<EchoResponse*>(methods->GetRecvMessage()); - // Check that we got the hijacked message, and re-insert the expected - // message - EXPECT_EQ(resp->message(), "Hello"); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_STATUS)) { - auto* map = methods->GetRecvTrailingMetadata(); - bool found = false; - // Check that we received the metadata as an echo - for (const auto& pair : *map) { - found = pair.first.starts_with("testkey") && - pair.second.starts_with("testvalue"); - if (found) break; - } - EXPECT_EQ(found, true); - auto* status = methods->GetRecvStatus(); - EXPECT_EQ(status->ok(), true); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_INITIAL_METADATA)) { - auto* map = methods->GetRecvInitialMetadata(); - // Got nothing better to do here at the moment - EXPECT_EQ(map->size(), static_cast<unsigned>(0)); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { - // Insert a different message than expected - EchoResponse* resp = - static_cast<EchoResponse*>(methods->GetRecvMessage()); - resp->set_message(resp_.message()); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { - auto* map = methods->GetRecvTrailingMetadata(); - // insert the metadata that we want - EXPECT_EQ(map->size(), static_cast<unsigned>(0)); - map->insert(std::make_pair("testkey", "testvalue")); - auto* status = methods->GetRecvStatus(); - *status = Status(StatusCode::OK, ""); - } - - methods->Proceed(); - } - - private: - experimental::ClientRpcInfo* info_; +/* Hijacks Echo RPC and fills in the expected values */ +class HijackingInterceptor : public experimental::Interceptor { + public: + HijackingInterceptor(experimental::ClientRpcInfo* info) { + info_ = info; + // Make sure it is the right method + EXPECT_EQ(strcmp("/grpc.testing.EchoTestService/Echo", info->method()), 0); + EXPECT_EQ(info->type(), experimental::ClientRpcInfo::Type::UNARY); + } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + bool hijack = false; + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + auto* map = methods->GetSendInitialMetadata(); + // Check that we can see the test metadata + ASSERT_EQ(map->size(), static_cast<unsigned>(1)); + auto iterator = map->begin(); + EXPECT_EQ("testkey", iterator->first); + EXPECT_EQ("testvalue", iterator->second); + hijack = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSerializedSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_EQ(req.message(), "Hello"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { + // Got nothing to do here for now + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + // Got nothing better to do here for now + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + // Check that we got the hijacked message, and re-insert the expected + // message + EXPECT_EQ(resp->message(), "Hello1"); + resp->set_message("Hello"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.starts_with("testkey") && + pair.second.starts_with("testvalue"); + if (found) break; + } + EXPECT_EQ(found, true); + auto* status = methods->GetRecvStatus(); + EXPECT_EQ(status->ok(), true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + // Got nothing better to do here at the moment + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { + // Insert a different message than expected + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + resp->set_message("Hello1"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + // insert the metadata that we want + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + map->insert(std::make_pair("testkey", "testvalue")); + auto* status = methods->GetRecvStatus(); + *status = Status(StatusCode::OK, ""); + } + if (hijack) { + methods->Hijack(); + } else { + methods->Proceed(); + } + } + + private: + experimental::ClientRpcInfo* info_; +}; + +class HijackingInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new HijackingInterceptor(info); + } +}; + +class HijackingInterceptorMakesAnotherCall : public experimental::Interceptor { + public: + HijackingInterceptorMakesAnotherCall(experimental::ClientRpcInfo* info) { + info_ = info; + // Make sure it is the right method + EXPECT_EQ(strcmp("/grpc.testing.EchoTestService/Echo", info->method()), 0); + } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + auto* map = methods->GetSendInitialMetadata(); + // Check that we can see the test metadata + ASSERT_EQ(map->size(), static_cast<unsigned>(1)); + auto iterator = map->begin(); + EXPECT_EQ("testkey", iterator->first); + EXPECT_EQ("testvalue", iterator->second); + // Make a copy of the map + metadata_map_ = *map; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSerializedSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_EQ(req.message(), "Hello"); + req_ = req; + stub_ = grpc::testing::EchoTestService::NewStub( + methods->GetInterceptedChannel()); + ctx_.AddMetadata(metadata_map_.begin()->first, + metadata_map_.begin()->second); + stub_->experimental_async()->Echo(&ctx_, &req_, &resp_, + [this, methods](Status s) { + EXPECT_EQ(s.ok(), true); + EXPECT_EQ(resp_.message(), "Hello"); + methods->Hijack(); + }); + // This is a Unary RPC and we have got nothing interesting to do in the + // PRE_SEND_CLOSE interception hook point for this interceptor, so let's + // return here. (We do not want to call methods->Proceed(). When the new + // RPC returns, we will call methods->Hijack() instead.) + return; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { + // Got nothing to do here for now + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + // Got nothing better to do here for now + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + // Check that we got the hijacked message, and re-insert the expected + // message + EXPECT_EQ(resp->message(), "Hello"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.starts_with("testkey") && + pair.second.starts_with("testvalue"); + if (found) break; + } + EXPECT_EQ(found, true); + auto* status = methods->GetRecvStatus(); + EXPECT_EQ(status->ok(), true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + // Got nothing better to do here at the moment + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { + // Insert a different message than expected + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + resp->set_message(resp_.message()); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + // insert the metadata that we want + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + map->insert(std::make_pair("testkey", "testvalue")); + auto* status = methods->GetRecvStatus(); + *status = Status(StatusCode::OK, ""); + } + + methods->Proceed(); + } + + private: + experimental::ClientRpcInfo* info_; std::multimap<TString, TString> metadata_map_; - ClientContext ctx_; - EchoRequest req_; - EchoResponse resp_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; -}; - -class HijackingInterceptorMakesAnotherCallFactory - : public experimental::ClientInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateClientInterceptor( - experimental::ClientRpcInfo* info) override { - return new HijackingInterceptorMakesAnotherCall(info); - } -}; - -class BidiStreamingRpcHijackingInterceptor : public experimental::Interceptor { - public: - BidiStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { - info_ = info; - } - - virtual void Intercept(experimental::InterceptorBatchMethods* methods) { - bool hijack = false; - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { - CheckMetadata(*methods->GetSendInitialMetadata(), "testkey", "testvalue"); - hijack = true; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - EchoRequest req; - auto* buffer = methods->GetSerializedSendMessage(); - auto copied_buffer = *buffer; - EXPECT_TRUE( - SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) - .ok()); - EXPECT_EQ(req.message().find("Hello"), 0u); - msg = req.message(); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { - // Got nothing to do here for now - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_STATUS)) { - CheckMetadata(*methods->GetRecvTrailingMetadata(), "testkey", - "testvalue"); - auto* status = methods->GetRecvStatus(); - EXPECT_EQ(status->ok(), true); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { - EchoResponse* resp = - static_cast<EchoResponse*>(methods->GetRecvMessage()); - resp->set_message(msg); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { - EXPECT_EQ(static_cast<EchoResponse*>(methods->GetRecvMessage()) - ->message() - .find("Hello"), - 0u); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { - auto* map = methods->GetRecvTrailingMetadata(); - // insert the metadata that we want - EXPECT_EQ(map->size(), static_cast<unsigned>(0)); - map->insert(std::make_pair("testkey", "testvalue")); - auto* status = methods->GetRecvStatus(); - *status = Status(StatusCode::OK, ""); - } - if (hijack) { - methods->Hijack(); - } else { - methods->Proceed(); - } - } - - private: - experimental::ClientRpcInfo* info_; + ClientContext ctx_; + EchoRequest req_; + EchoResponse resp_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; +}; + +class HijackingInterceptorMakesAnotherCallFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new HijackingInterceptorMakesAnotherCall(info); + } +}; + +class BidiStreamingRpcHijackingInterceptor : public experimental::Interceptor { + public: + BidiStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { + info_ = info; + } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + bool hijack = false; + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + CheckMetadata(*methods->GetSendInitialMetadata(), "testkey", "testvalue"); + hijack = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSerializedSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_EQ(req.message().find("Hello"), 0u); + msg = req.message(); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { + // Got nothing to do here for now + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_STATUS)) { + CheckMetadata(*methods->GetRecvTrailingMetadata(), "testkey", + "testvalue"); + auto* status = methods->GetRecvStatus(); + EXPECT_EQ(status->ok(), true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + resp->set_message(msg); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + EXPECT_EQ(static_cast<EchoResponse*>(methods->GetRecvMessage()) + ->message() + .find("Hello"), + 0u); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + // insert the metadata that we want + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + map->insert(std::make_pair("testkey", "testvalue")); + auto* status = methods->GetRecvStatus(); + *status = Status(StatusCode::OK, ""); + } + if (hijack) { + methods->Hijack(); + } else { + methods->Proceed(); + } + } + + private: + experimental::ClientRpcInfo* info_; TString msg; -}; - -class ClientStreamingRpcHijackingInterceptor - : public experimental::Interceptor { - public: - ClientStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { - info_ = info; - } - virtual void Intercept(experimental::InterceptorBatchMethods* methods) { - bool hijack = false; - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { - hijack = true; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - if (++count_ > 10) { - methods->FailHijackedSendMessage(); - } - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_SEND_MESSAGE)) { - EXPECT_FALSE(got_failed_send_); - got_failed_send_ = !methods->GetSendMessageStatus(); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { - auto* status = methods->GetRecvStatus(); - *status = Status(StatusCode::UNAVAILABLE, "Done sending 10 messages"); - } - if (hijack) { - methods->Hijack(); - } else { - methods->Proceed(); - } - } - - static bool GotFailedSend() { return got_failed_send_; } - - private: - experimental::ClientRpcInfo* info_; - int count_ = 0; - static bool got_failed_send_; -}; - -bool ClientStreamingRpcHijackingInterceptor::got_failed_send_ = false; - -class ClientStreamingRpcHijackingInterceptorFactory - : public experimental::ClientInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateClientInterceptor( - experimental::ClientRpcInfo* info) override { - return new ClientStreamingRpcHijackingInterceptor(info); - } -}; - -class ServerStreamingRpcHijackingInterceptor - : public experimental::Interceptor { - public: - ServerStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { - info_ = info; +}; + +class ClientStreamingRpcHijackingInterceptor + : public experimental::Interceptor { + public: + ClientStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { + info_ = info; + } + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + bool hijack = false; + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + hijack = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + if (++count_ > 10) { + methods->FailHijackedSendMessage(); + } + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_SEND_MESSAGE)) { + EXPECT_FALSE(got_failed_send_); + got_failed_send_ = !methods->GetSendMessageStatus(); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { + auto* status = methods->GetRecvStatus(); + *status = Status(StatusCode::UNAVAILABLE, "Done sending 10 messages"); + } + if (hijack) { + methods->Hijack(); + } else { + methods->Proceed(); + } + } + + static bool GotFailedSend() { return got_failed_send_; } + + private: + experimental::ClientRpcInfo* info_; + int count_ = 0; + static bool got_failed_send_; +}; + +bool ClientStreamingRpcHijackingInterceptor::got_failed_send_ = false; + +class ClientStreamingRpcHijackingInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new ClientStreamingRpcHijackingInterceptor(info); + } +}; + +class ServerStreamingRpcHijackingInterceptor + : public experimental::Interceptor { + public: + ServerStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { + info_ = info; got_failed_message_ = false; - } - - virtual void Intercept(experimental::InterceptorBatchMethods* methods) { - bool hijack = false; - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { - auto* map = methods->GetSendInitialMetadata(); - // Check that we can see the test metadata - ASSERT_EQ(map->size(), static_cast<unsigned>(1)); - auto iterator = map->begin(); - EXPECT_EQ("testkey", iterator->first); - EXPECT_EQ("testvalue", iterator->second); - hijack = true; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - EchoRequest req; - auto* buffer = methods->GetSerializedSendMessage(); - auto copied_buffer = *buffer; - EXPECT_TRUE( - SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) - .ok()); - EXPECT_EQ(req.message(), "Hello"); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { - // Got nothing to do here for now - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_STATUS)) { - auto* map = methods->GetRecvTrailingMetadata(); - bool found = false; - // Check that we received the metadata as an echo - for (const auto& pair : *map) { - found = pair.first.starts_with("testkey") && - pair.second.starts_with("testvalue"); - if (found) break; - } - EXPECT_EQ(found, true); - auto* status = methods->GetRecvStatus(); - EXPECT_EQ(status->ok(), true); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { - if (++count_ > 10) { - methods->FailHijackedRecvMessage(); - } - EchoResponse* resp = - static_cast<EchoResponse*>(methods->GetRecvMessage()); - resp->set_message("Hello"); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { - // Only the last message will be a failure - EXPECT_FALSE(got_failed_message_); - got_failed_message_ = methods->GetRecvMessage() == nullptr; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { - auto* map = methods->GetRecvTrailingMetadata(); - // insert the metadata that we want - EXPECT_EQ(map->size(), static_cast<unsigned>(0)); - map->insert(std::make_pair("testkey", "testvalue")); - auto* status = methods->GetRecvStatus(); - *status = Status(StatusCode::OK, ""); - } - if (hijack) { - methods->Hijack(); - } else { - methods->Proceed(); - } - } - - static bool GotFailedMessage() { return got_failed_message_; } - - private: - experimental::ClientRpcInfo* info_; - static bool got_failed_message_; - int count_ = 0; -}; - -bool ServerStreamingRpcHijackingInterceptor::got_failed_message_ = false; - -class ServerStreamingRpcHijackingInterceptorFactory - : public experimental::ClientInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateClientInterceptor( - experimental::ClientRpcInfo* info) override { - return new ServerStreamingRpcHijackingInterceptor(info); - } -}; - -class BidiStreamingRpcHijackingInterceptorFactory - : public experimental::ClientInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateClientInterceptor( - experimental::ClientRpcInfo* info) override { - return new BidiStreamingRpcHijackingInterceptor(info); - } -}; - -// The logging interceptor is for testing purposes only. It is used to verify -// that all the appropriate hook points are invoked for an RPC. The counts are -// reset each time a new object of LoggingInterceptor is created, so only a -// single RPC should be made on the channel before calling the Verify methods. -class LoggingInterceptor : public experimental::Interceptor { - public: - LoggingInterceptor(experimental::ClientRpcInfo* /*info*/) { - pre_send_initial_metadata_ = false; - pre_send_message_count_ = 0; - pre_send_close_ = false; - post_recv_initial_metadata_ = false; - post_recv_message_count_ = 0; - post_recv_status_ = false; - } - - virtual void Intercept(experimental::InterceptorBatchMethods* methods) { - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { - auto* map = methods->GetSendInitialMetadata(); - // Check that we can see the test metadata - ASSERT_EQ(map->size(), static_cast<unsigned>(1)); - auto iterator = map->begin(); - EXPECT_EQ("testkey", iterator->first); - EXPECT_EQ("testvalue", iterator->second); - ASSERT_FALSE(pre_send_initial_metadata_); - pre_send_initial_metadata_ = true; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - EchoRequest req; + } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + bool hijack = false; + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + auto* map = methods->GetSendInitialMetadata(); + // Check that we can see the test metadata + ASSERT_EQ(map->size(), static_cast<unsigned>(1)); + auto iterator = map->begin(); + EXPECT_EQ("testkey", iterator->first); + EXPECT_EQ("testvalue", iterator->second); + hijack = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSerializedSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_EQ(req.message(), "Hello"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { + // Got nothing to do here for now + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.starts_with("testkey") && + pair.second.starts_with("testvalue"); + if (found) break; + } + EXPECT_EQ(found, true); + auto* status = methods->GetRecvStatus(); + EXPECT_EQ(status->ok(), true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { + if (++count_ > 10) { + methods->FailHijackedRecvMessage(); + } + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + resp->set_message("Hello"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + // Only the last message will be a failure + EXPECT_FALSE(got_failed_message_); + got_failed_message_ = methods->GetRecvMessage() == nullptr; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + // insert the metadata that we want + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + map->insert(std::make_pair("testkey", "testvalue")); + auto* status = methods->GetRecvStatus(); + *status = Status(StatusCode::OK, ""); + } + if (hijack) { + methods->Hijack(); + } else { + methods->Proceed(); + } + } + + static bool GotFailedMessage() { return got_failed_message_; } + + private: + experimental::ClientRpcInfo* info_; + static bool got_failed_message_; + int count_ = 0; +}; + +bool ServerStreamingRpcHijackingInterceptor::got_failed_message_ = false; + +class ServerStreamingRpcHijackingInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new ServerStreamingRpcHijackingInterceptor(info); + } +}; + +class BidiStreamingRpcHijackingInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new BidiStreamingRpcHijackingInterceptor(info); + } +}; + +// The logging interceptor is for testing purposes only. It is used to verify +// that all the appropriate hook points are invoked for an RPC. The counts are +// reset each time a new object of LoggingInterceptor is created, so only a +// single RPC should be made on the channel before calling the Verify methods. +class LoggingInterceptor : public experimental::Interceptor { + public: + LoggingInterceptor(experimental::ClientRpcInfo* /*info*/) { + pre_send_initial_metadata_ = false; + pre_send_message_count_ = 0; + pre_send_close_ = false; + post_recv_initial_metadata_ = false; + post_recv_message_count_ = 0; + post_recv_status_ = false; + } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + auto* map = methods->GetSendInitialMetadata(); + // Check that we can see the test metadata + ASSERT_EQ(map->size(), static_cast<unsigned>(1)); + auto iterator = map->begin(); + EXPECT_EQ("testkey", iterator->first); + EXPECT_EQ("testvalue", iterator->second); + ASSERT_FALSE(pre_send_initial_metadata_); + pre_send_initial_metadata_ = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; auto* send_msg = methods->GetSendMessage(); if (send_msg == nullptr) { // We did not get the non-serialized form of the message. Get the @@ -559,53 +559,53 @@ class LoggingInterceptor : public experimental::Interceptor { static_cast<const EchoRequest*>(send_msg)->message().find("Hello"), 0u); } - auto* buffer = methods->GetSerializedSendMessage(); - auto copied_buffer = *buffer; - EXPECT_TRUE( - SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) - .ok()); - EXPECT_TRUE(req.message().find("Hello") == 0u); - pre_send_message_count_++; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { - // Got nothing to do here for now - pre_send_close_ = true; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { - auto* map = methods->GetRecvInitialMetadata(); - // Got nothing better to do here for now - EXPECT_EQ(map->size(), static_cast<unsigned>(0)); - post_recv_initial_metadata_ = true; - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { - EchoResponse* resp = - static_cast<EchoResponse*>(methods->GetRecvMessage()); - if (resp != nullptr) { - EXPECT_TRUE(resp->message().find("Hello") == 0u); - post_recv_message_count_++; - } - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_STATUS)) { - auto* map = methods->GetRecvTrailingMetadata(); - bool found = false; - // Check that we received the metadata as an echo - for (const auto& pair : *map) { - found = pair.first.starts_with("testkey") && - pair.second.starts_with("testvalue"); - if (found) break; - } - EXPECT_EQ(found, true); - auto* status = methods->GetRecvStatus(); - EXPECT_EQ(status->ok(), true); - post_recv_status_ = true; - } - methods->Proceed(); - } - + auto* buffer = methods->GetSerializedSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_TRUE(req.message().find("Hello") == 0u); + pre_send_message_count_++; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { + // Got nothing to do here for now + pre_send_close_ = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + // Got nothing better to do here for now + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + post_recv_initial_metadata_ = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + if (resp != nullptr) { + EXPECT_TRUE(resp->message().find("Hello") == 0u); + post_recv_message_count_++; + } + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.starts_with("testkey") && + pair.second.starts_with("testvalue"); + if (found) break; + } + EXPECT_EQ(found, true); + auto* status = methods->GetRecvStatus(); + EXPECT_EQ(status->ok(), true); + post_recv_status_ = true; + } + methods->Proceed(); + } + static void VerifyCall(RPCType type) { switch (type) { case RPCType::kSyncUnary: @@ -627,62 +627,62 @@ class LoggingInterceptor : public experimental::Interceptor { } } - static void VerifyCallCommon() { - EXPECT_TRUE(pre_send_initial_metadata_); - EXPECT_TRUE(pre_send_close_); - EXPECT_TRUE(post_recv_initial_metadata_); - EXPECT_TRUE(post_recv_status_); - } - - static void VerifyUnaryCall() { - VerifyCallCommon(); - EXPECT_EQ(pre_send_message_count_, 1); - EXPECT_EQ(post_recv_message_count_, 1); - } - - static void VerifyClientStreamingCall() { - VerifyCallCommon(); - EXPECT_EQ(pre_send_message_count_, kNumStreamingMessages); - EXPECT_EQ(post_recv_message_count_, 1); - } - - static void VerifyServerStreamingCall() { - VerifyCallCommon(); - EXPECT_EQ(pre_send_message_count_, 1); - EXPECT_EQ(post_recv_message_count_, kNumStreamingMessages); - } - - static void VerifyBidiStreamingCall() { - VerifyCallCommon(); - EXPECT_EQ(pre_send_message_count_, kNumStreamingMessages); - EXPECT_EQ(post_recv_message_count_, kNumStreamingMessages); - } - - private: - static bool pre_send_initial_metadata_; - static int pre_send_message_count_; - static bool pre_send_close_; - static bool post_recv_initial_metadata_; - static int post_recv_message_count_; - static bool post_recv_status_; -}; - -bool LoggingInterceptor::pre_send_initial_metadata_; -int LoggingInterceptor::pre_send_message_count_; -bool LoggingInterceptor::pre_send_close_; -bool LoggingInterceptor::post_recv_initial_metadata_; -int LoggingInterceptor::post_recv_message_count_; -bool LoggingInterceptor::post_recv_status_; - -class LoggingInterceptorFactory - : public experimental::ClientInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateClientInterceptor( - experimental::ClientRpcInfo* info) override { - return new LoggingInterceptor(info); - } -}; - + static void VerifyCallCommon() { + EXPECT_TRUE(pre_send_initial_metadata_); + EXPECT_TRUE(pre_send_close_); + EXPECT_TRUE(post_recv_initial_metadata_); + EXPECT_TRUE(post_recv_status_); + } + + static void VerifyUnaryCall() { + VerifyCallCommon(); + EXPECT_EQ(pre_send_message_count_, 1); + EXPECT_EQ(post_recv_message_count_, 1); + } + + static void VerifyClientStreamingCall() { + VerifyCallCommon(); + EXPECT_EQ(pre_send_message_count_, kNumStreamingMessages); + EXPECT_EQ(post_recv_message_count_, 1); + } + + static void VerifyServerStreamingCall() { + VerifyCallCommon(); + EXPECT_EQ(pre_send_message_count_, 1); + EXPECT_EQ(post_recv_message_count_, kNumStreamingMessages); + } + + static void VerifyBidiStreamingCall() { + VerifyCallCommon(); + EXPECT_EQ(pre_send_message_count_, kNumStreamingMessages); + EXPECT_EQ(post_recv_message_count_, kNumStreamingMessages); + } + + private: + static bool pre_send_initial_metadata_; + static int pre_send_message_count_; + static bool pre_send_close_; + static bool post_recv_initial_metadata_; + static int post_recv_message_count_; + static bool post_recv_status_; +}; + +bool LoggingInterceptor::pre_send_initial_metadata_; +int LoggingInterceptor::pre_send_message_count_; +bool LoggingInterceptor::pre_send_close_; +bool LoggingInterceptor::post_recv_initial_metadata_; +int LoggingInterceptor::post_recv_message_count_; +bool LoggingInterceptor::post_recv_status_; + +class LoggingInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new LoggingInterceptor(info); + } +}; + class TestScenario { public: explicit TestScenario(const RPCType& type) : type_(type) {} @@ -706,19 +706,19 @@ std::vector<TestScenario> CreateTestScenarios() { class ParameterizedClientInterceptorsEnd2endTest : public ::testing::TestWithParam<TestScenario> { - protected: + protected: ParameterizedClientInterceptorsEnd2endTest() { - int port = grpc_pick_unused_port_or_die(); - - ServerBuilder builder; + int port = grpc_pick_unused_port_or_die(); + + ServerBuilder builder; server_address_ = "localhost:" + ToString(port); - builder.AddListeningPort(server_address_, InsecureServerCredentials()); - builder.RegisterService(&service_); - server_ = builder.BuildAndStart(); - } - + builder.AddListeningPort(server_address_, InsecureServerCredentials()); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + ~ParameterizedClientInterceptorsEnd2endTest() { server_->Shutdown(); } - + void SendRPC(const std::shared_ptr<Channel>& channel) { switch (GetParam().type()) { case RPCType::kSyncUnary: @@ -750,30 +750,30 @@ class ParameterizedClientInterceptorsEnd2endTest TString server_address_; EchoTestServiceStreamingImpl service_; - std::unique_ptr<Server> server_; -}; - + std::unique_ptr<Server> server_; +}; + TEST_P(ParameterizedClientInterceptorsEnd2endTest, ClientInterceptorLoggingTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( - new LoggingInterceptorFactory())); - // Add 20 dummy interceptors - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); SendRPC(channel); LoggingInterceptor::VerifyCall(GetParam().type()); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + INSTANTIATE_TEST_SUITE_P(ParameterizedClientInterceptorsEnd2end, ParameterizedClientInterceptorsEnd2endTest, ::testing::ValuesIn(CreateTestScenarios())); @@ -798,86 +798,86 @@ class ClientInterceptorsEnd2endTest std::unique_ptr<Server> server_; }; -TEST_F(ClientInterceptorsEnd2endTest, - LameChannelClientInterceptorHijackingTest) { - ChannelArguments args; - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back(std::unique_ptr<HijackingInterceptorFactory>( - new HijackingInterceptorFactory())); - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, nullptr, args, std::move(creators)); - MakeCall(channel); -} - -TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorHijackingTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - // Add 20 dummy interceptors before hijacking interceptor - creators.reserve(20); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - creators.push_back(std::unique_ptr<HijackingInterceptorFactory>( - new HijackingInterceptorFactory())); - // Add 20 dummy interceptors after hijacking interceptor - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - MakeCall(channel); - // Make sure only 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - -TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLogThenHijackTest) { - ChannelArguments args; - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( - new LoggingInterceptorFactory())); - creators.push_back(std::unique_ptr<HijackingInterceptorFactory>( - new HijackingInterceptorFactory())); - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - MakeCall(channel); - LoggingInterceptor::VerifyUnaryCall(); -} - -TEST_F(ClientInterceptorsEnd2endTest, - ClientInterceptorHijackingMakesAnotherCallTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - // Add 5 dummy interceptors before hijacking interceptor - creators.reserve(5); - for (auto i = 0; i < 5; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - creators.push_back( - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>( - new HijackingInterceptorMakesAnotherCallFactory())); - // Add 7 dummy interceptors after hijacking interceptor - for (auto i = 0; i < 7; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - auto channel = server_->experimental().InProcessChannelWithInterceptors( - args, std::move(creators)); - - MakeCall(channel); - // Make sure all interceptors were run once, since the hijacking interceptor - // makes an RPC on the intercepted channel - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 12); -} - +TEST_F(ClientInterceptorsEnd2endTest, + LameChannelClientInterceptorHijackingTest) { + ChannelArguments args; + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<HijackingInterceptorFactory>( + new HijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, nullptr, args, std::move(creators)); + MakeCall(channel); +} + +TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorHijackingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 20 dummy interceptors before hijacking interceptor + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + creators.push_back(std::unique_ptr<HijackingInterceptorFactory>( + new HijackingInterceptorFactory())); + // Add 20 dummy interceptors after hijacking interceptor + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeCall(channel); + // Make sure only 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLogThenHijackTest) { + ChannelArguments args; + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + creators.push_back(std::unique_ptr<HijackingInterceptorFactory>( + new HijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeCall(channel); + LoggingInterceptor::VerifyUnaryCall(); +} + +TEST_F(ClientInterceptorsEnd2endTest, + ClientInterceptorHijackingMakesAnotherCallTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 5 dummy interceptors before hijacking interceptor + creators.reserve(5); + for (auto i = 0; i < 5; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + creators.push_back( + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>( + new HijackingInterceptorMakesAnotherCallFactory())); + // Add 7 dummy interceptors after hijacking interceptor + for (auto i = 0; i < 7; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = server_->experimental().InProcessChannelWithInterceptors( + args, std::move(creators)); + + MakeCall(channel); + // Make sure all interceptors were run once, since the hijacking interceptor + // makes an RPC on the intercepted channel + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 12); +} + class ClientInterceptorsCallbackEnd2endTest : public ::testing::Test { protected: ClientInterceptorsCallbackEnd2endTest() { @@ -898,151 +898,151 @@ class ClientInterceptorsCallbackEnd2endTest : public ::testing::Test { }; TEST_F(ClientInterceptorsCallbackEnd2endTest, - ClientInterceptorLoggingTestWithCallback) { - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( - new LoggingInterceptorFactory())); - // Add 20 dummy interceptors - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - auto channel = server_->experimental().InProcessChannelWithInterceptors( - args, std::move(creators)); - MakeCallbackCall(channel); - LoggingInterceptor::VerifyUnaryCall(); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - + ClientInterceptorLoggingTestWithCallback) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = server_->experimental().InProcessChannelWithInterceptors( + args, std::move(creators)); + MakeCallbackCall(channel); + LoggingInterceptor::VerifyUnaryCall(); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + TEST_F(ClientInterceptorsCallbackEnd2endTest, - ClientInterceptorFactoryAllowsNullptrReturn) { - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( - new LoggingInterceptorFactory())); - // Add 20 dummy interceptors and 20 null interceptors - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - creators.push_back( - std::unique_ptr<NullInterceptorFactory>(new NullInterceptorFactory())); - } - auto channel = server_->experimental().InProcessChannelWithInterceptors( - args, std::move(creators)); - MakeCallbackCall(channel); - LoggingInterceptor::VerifyUnaryCall(); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - -class ClientInterceptorsStreamingEnd2endTest : public ::testing::Test { - protected: - ClientInterceptorsStreamingEnd2endTest() { - int port = grpc_pick_unused_port_or_die(); - - ServerBuilder builder; + ClientInterceptorFactoryAllowsNullptrReturn) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors and 20 null interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + creators.push_back( + std::unique_ptr<NullInterceptorFactory>(new NullInterceptorFactory())); + } + auto channel = server_->experimental().InProcessChannelWithInterceptors( + args, std::move(creators)); + MakeCallbackCall(channel); + LoggingInterceptor::VerifyUnaryCall(); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +class ClientInterceptorsStreamingEnd2endTest : public ::testing::Test { + protected: + ClientInterceptorsStreamingEnd2endTest() { + int port = grpc_pick_unused_port_or_die(); + + ServerBuilder builder; server_address_ = "localhost:" + ToString(port); - builder.AddListeningPort(server_address_, InsecureServerCredentials()); - builder.RegisterService(&service_); - server_ = builder.BuildAndStart(); - } - - ~ClientInterceptorsStreamingEnd2endTest() { server_->Shutdown(); } - + builder.AddListeningPort(server_address_, InsecureServerCredentials()); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + + ~ClientInterceptorsStreamingEnd2endTest() { server_->Shutdown(); } + TString server_address_; - EchoTestServiceStreamingImpl service_; - std::unique_ptr<Server> server_; -}; - -TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( - new LoggingInterceptorFactory())); - // Add 20 dummy interceptors - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - MakeClientStreamingCall(channel); - LoggingInterceptor::VerifyClientStreamingCall(); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - -TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( - new LoggingInterceptorFactory())); - // Add 20 dummy interceptors - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - MakeServerStreamingCall(channel); - LoggingInterceptor::VerifyServerStreamingCall(); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - -TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingHijackingTest) { - ChannelArguments args; - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back( - std::unique_ptr<ClientStreamingRpcHijackingInterceptorFactory>( - new ClientStreamingRpcHijackingInterceptorFactory())); - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - - auto stub = grpc::testing::EchoTestService::NewStub(channel); - ClientContext ctx; - EchoRequest req; - EchoResponse resp; - req.mutable_param()->set_echo_metadata(true); - req.set_message("Hello"); - string expected_resp = ""; - auto writer = stub->RequestStream(&ctx, &resp); - for (int i = 0; i < 10; i++) { - EXPECT_TRUE(writer->Write(req)); - expected_resp += "Hello"; - } - // The interceptor will reject the 11th message - writer->Write(req); - Status s = writer->Finish(); - EXPECT_EQ(s.ok(), false); - EXPECT_TRUE(ClientStreamingRpcHijackingInterceptor::GotFailedSend()); -} - -TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingHijackingTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back( - std::unique_ptr<ServerStreamingRpcHijackingInterceptorFactory>( - new ServerStreamingRpcHijackingInterceptorFactory())); - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - MakeServerStreamingCall(channel); - EXPECT_TRUE(ServerStreamingRpcHijackingInterceptor::GotFailedMessage()); -} - + EchoTestServiceStreamingImpl service_; + std::unique_ptr<Server> server_; +}; + +TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeClientStreamingCall(channel); + LoggingInterceptor::VerifyClientStreamingCall(); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeServerStreamingCall(channel); + LoggingInterceptor::VerifyServerStreamingCall(); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingHijackingTest) { + ChannelArguments args; + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<ClientStreamingRpcHijackingInterceptorFactory>( + new ClientStreamingRpcHijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + EchoResponse resp; + req.mutable_param()->set_echo_metadata(true); + req.set_message("Hello"); + string expected_resp = ""; + auto writer = stub->RequestStream(&ctx, &resp); + for (int i = 0; i < 10; i++) { + EXPECT_TRUE(writer->Write(req)); + expected_resp += "Hello"; + } + // The interceptor will reject the 11th message + writer->Write(req); + Status s = writer->Finish(); + EXPECT_EQ(s.ok(), false); + EXPECT_TRUE(ClientStreamingRpcHijackingInterceptor::GotFailedSend()); +} + +TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingHijackingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<ServerStreamingRpcHijackingInterceptorFactory>( + new ServerStreamingRpcHijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeServerStreamingCall(channel); + EXPECT_TRUE(ServerStreamingRpcHijackingInterceptor::GotFailedMessage()); +} + TEST_F(ClientInterceptorsStreamingEnd2endTest, AsyncCQServerStreamingHijackingTest) { ChannelArguments args; @@ -1058,137 +1058,137 @@ TEST_F(ClientInterceptorsStreamingEnd2endTest, EXPECT_TRUE(ServerStreamingRpcHijackingInterceptor::GotFailedMessage()); } -TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingHijackingTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back( - std::unique_ptr<BidiStreamingRpcHijackingInterceptorFactory>( - new BidiStreamingRpcHijackingInterceptorFactory())); - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - MakeBidiStreamingCall(channel); -} - -TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( - new LoggingInterceptorFactory())); - // Add 20 dummy interceptors - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - MakeBidiStreamingCall(channel); - LoggingInterceptor::VerifyBidiStreamingCall(); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - -class ClientGlobalInterceptorEnd2endTest : public ::testing::Test { - protected: - ClientGlobalInterceptorEnd2endTest() { - int port = grpc_pick_unused_port_or_die(); - - ServerBuilder builder; +TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingHijackingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<BidiStreamingRpcHijackingInterceptorFactory>( + new BidiStreamingRpcHijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeBidiStreamingCall(channel); +} + +TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + creators.push_back(std::unique_ptr<LoggingInterceptorFactory>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptors + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeBidiStreamingCall(channel); + LoggingInterceptor::VerifyBidiStreamingCall(); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +class ClientGlobalInterceptorEnd2endTest : public ::testing::Test { + protected: + ClientGlobalInterceptorEnd2endTest() { + int port = grpc_pick_unused_port_or_die(); + + ServerBuilder builder; server_address_ = "localhost:" + ToString(port); - builder.AddListeningPort(server_address_, InsecureServerCredentials()); - builder.RegisterService(&service_); - server_ = builder.BuildAndStart(); - } - - ~ClientGlobalInterceptorEnd2endTest() { server_->Shutdown(); } - + builder.AddListeningPort(server_address_, InsecureServerCredentials()); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + + ~ClientGlobalInterceptorEnd2endTest() { server_->Shutdown(); } + TString server_address_; - TestServiceImpl service_; - std::unique_ptr<Server> server_; -}; - -TEST_F(ClientGlobalInterceptorEnd2endTest, DummyGlobalInterceptor) { - // We should ideally be registering a global interceptor only once per - // process, but for the purposes of testing, it should be fine to modify the - // registered global interceptor when there are no ongoing gRPC operations - DummyInterceptorFactory global_factory; - experimental::RegisterGlobalClientInterceptorFactory(&global_factory); - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - // Add 20 dummy interceptors - creators.reserve(20); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - MakeCall(channel); - // Make sure all 20 dummy interceptors were run with the global interceptor - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 21); - experimental::TestOnlyResetGlobalClientInterceptorFactory(); -} - -TEST_F(ClientGlobalInterceptorEnd2endTest, LoggingGlobalInterceptor) { - // We should ideally be registering a global interceptor only once per - // process, but for the purposes of testing, it should be fine to modify the - // registered global interceptor when there are no ongoing gRPC operations - LoggingInterceptorFactory global_factory; - experimental::RegisterGlobalClientInterceptorFactory(&global_factory); - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - // Add 20 dummy interceptors - creators.reserve(20); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - MakeCall(channel); - LoggingInterceptor::VerifyUnaryCall(); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); - experimental::TestOnlyResetGlobalClientInterceptorFactory(); -} - -TEST_F(ClientGlobalInterceptorEnd2endTest, HijackingGlobalInterceptor) { - // We should ideally be registering a global interceptor only once per - // process, but for the purposes of testing, it should be fine to modify the - // registered global interceptor when there are no ongoing gRPC operations - HijackingInterceptorFactory global_factory; - experimental::RegisterGlobalClientInterceptorFactory(&global_factory); - ChannelArguments args; - DummyInterceptor::Reset(); - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - // Add 20 dummy interceptors - creators.reserve(20); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - auto channel = experimental::CreateCustomChannelWithInterceptors( - server_address_, InsecureChannelCredentials(), args, std::move(creators)); - MakeCall(channel); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); - experimental::TestOnlyResetGlobalClientInterceptorFactory(); -} - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + TestServiceImpl service_; + std::unique_ptr<Server> server_; +}; + +TEST_F(ClientGlobalInterceptorEnd2endTest, DummyGlobalInterceptor) { + // We should ideally be registering a global interceptor only once per + // process, but for the purposes of testing, it should be fine to modify the + // registered global interceptor when there are no ongoing gRPC operations + DummyInterceptorFactory global_factory; + experimental::RegisterGlobalClientInterceptorFactory(&global_factory); + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 20 dummy interceptors + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeCall(channel); + // Make sure all 20 dummy interceptors were run with the global interceptor + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 21); + experimental::TestOnlyResetGlobalClientInterceptorFactory(); +} + +TEST_F(ClientGlobalInterceptorEnd2endTest, LoggingGlobalInterceptor) { + // We should ideally be registering a global interceptor only once per + // process, but for the purposes of testing, it should be fine to modify the + // registered global interceptor when there are no ongoing gRPC operations + LoggingInterceptorFactory global_factory; + experimental::RegisterGlobalClientInterceptorFactory(&global_factory); + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 20 dummy interceptors + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeCall(channel); + LoggingInterceptor::VerifyUnaryCall(); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + experimental::TestOnlyResetGlobalClientInterceptorFactory(); +} + +TEST_F(ClientGlobalInterceptorEnd2endTest, HijackingGlobalInterceptor) { + // We should ideally be registering a global interceptor only once per + // process, but for the purposes of testing, it should be fine to modify the + // registered global interceptor when there are no ongoing gRPC operations + HijackingInterceptorFactory global_factory; + experimental::RegisterGlobalClientInterceptorFactory(&global_factory); + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 20 dummy interceptors + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + experimental::TestOnlyResetGlobalClientInterceptorFactory(); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/client_lb_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/client_lb_end2end_test.cc index 30cfb444a1..fd08dd163d 100644 --- a/contrib/libs/grpc/test/cpp/end2end/client_lb_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/client_lb_end2end_test.cc @@ -1,1655 +1,1655 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * 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. - * - */ - -#include <algorithm> -#include <memory> -#include <mutex> -#include <random> -#include <set> +/* + * + * Copyright 2016 gRPC authors. + * + * 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. + * + */ + +#include <algorithm> +#include <memory> +#include <mutex> +#include <random> +#include <set> #include <util/generic/string.h> -#include <thread> - +#include <thread> + #include "y_absl/strings/str_cat.h" -#include <grpc/grpc.h> -#include <grpc/support/alloc.h> -#include <grpc/support/atm.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/health_check_service_interface.h> -#include <grpcpp/impl/codegen/sync.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> - -#include "src/core/ext/filters/client_channel/backup_poller.h" -#include "src/core/ext/filters/client_channel/global_subchannel_pool.h" -#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" -#include "src/core/ext/filters/client_channel/server_address.h" -#include "src/core/ext/filters/client_channel/service_config.h" -#include "src/core/lib/backoff/backoff.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/env.h" -#include "src/core/lib/gprpp/debug_location.h" -#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/atm.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/health_check_service_interface.h> +#include <grpcpp/impl/codegen/sync.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> + +#include "src/core/ext/filters/client_channel/backup_poller.h" +#include "src/core/ext/filters/client_channel/global_subchannel_pool.h" +#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" +#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/lib/backoff/backoff.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gprpp/debug_location.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/parse_address.h" -#include "src/core/lib/iomgr/tcp_client.h" -#include "src/core/lib/security/credentials/fake/fake_credentials.h" -#include "src/cpp/client/secure_credentials.h" -#include "src/cpp/server/secure_server_credentials.h" - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "src/proto/grpc/testing/xds/orca_load_report_for_test.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/core/util/test_lb_policies.h" -#include "test/cpp/end2end/test_service_impl.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; -using std::chrono::system_clock; - -// defined in tcp_client.cc -extern grpc_tcp_client_vtable* grpc_tcp_client_impl; - -static grpc_tcp_client_vtable* default_client_impl; - -namespace grpc { -namespace testing { -namespace { - -gpr_atm g_connection_delay_ms; - -void tcp_client_connect_with_delay(grpc_closure* closure, grpc_endpoint** ep, - grpc_pollset_set* interested_parties, - const grpc_channel_args* channel_args, - const grpc_resolved_address* addr, - grpc_millis deadline) { - const int delay_ms = gpr_atm_acq_load(&g_connection_delay_ms); - if (delay_ms > 0) { - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(delay_ms)); - } - default_client_impl->connect(closure, ep, interested_parties, channel_args, - addr, deadline + delay_ms); -} - -grpc_tcp_client_vtable delayed_connect = {tcp_client_connect_with_delay}; - -// Subclass of TestServiceImpl that increments a request counter for -// every call to the Echo RPC. -class MyTestServiceImpl : public TestServiceImpl { - public: - Status Echo(ServerContext* context, const EchoRequest* request, - EchoResponse* response) override { - const udpa::data::orca::v1::OrcaLoadReport* load_report = nullptr; - { - grpc::internal::MutexLock lock(&mu_); - ++request_count_; - load_report = load_report_; - } - AddClient(context->peer().c_str()); - if (load_report != nullptr) { - // TODO(roth): Once we provide a more standard server-side API for - // populating this data, use that API here. - context->AddTrailingMetadata("x-endpoint-load-metrics-bin", - load_report->SerializeAsString()); - } - return TestServiceImpl::Echo(context, request, response); - } - - int request_count() { - grpc::internal::MutexLock lock(&mu_); - return request_count_; - } - - void ResetCounters() { - grpc::internal::MutexLock lock(&mu_); - request_count_ = 0; - } - +#include "src/core/lib/iomgr/tcp_client.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "src/cpp/client/secure_credentials.h" +#include "src/cpp/server/secure_server_credentials.h" + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "src/proto/grpc/testing/xds/orca_load_report_for_test.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/core/util/test_lb_policies.h" +#include "test/cpp/end2end/test_service_impl.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; +using std::chrono::system_clock; + +// defined in tcp_client.cc +extern grpc_tcp_client_vtable* grpc_tcp_client_impl; + +static grpc_tcp_client_vtable* default_client_impl; + +namespace grpc { +namespace testing { +namespace { + +gpr_atm g_connection_delay_ms; + +void tcp_client_connect_with_delay(grpc_closure* closure, grpc_endpoint** ep, + grpc_pollset_set* interested_parties, + const grpc_channel_args* channel_args, + const grpc_resolved_address* addr, + grpc_millis deadline) { + const int delay_ms = gpr_atm_acq_load(&g_connection_delay_ms); + if (delay_ms > 0) { + gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(delay_ms)); + } + default_client_impl->connect(closure, ep, interested_parties, channel_args, + addr, deadline + delay_ms); +} + +grpc_tcp_client_vtable delayed_connect = {tcp_client_connect_with_delay}; + +// Subclass of TestServiceImpl that increments a request counter for +// every call to the Echo RPC. +class MyTestServiceImpl : public TestServiceImpl { + public: + Status Echo(ServerContext* context, const EchoRequest* request, + EchoResponse* response) override { + const udpa::data::orca::v1::OrcaLoadReport* load_report = nullptr; + { + grpc::internal::MutexLock lock(&mu_); + ++request_count_; + load_report = load_report_; + } + AddClient(context->peer().c_str()); + if (load_report != nullptr) { + // TODO(roth): Once we provide a more standard server-side API for + // populating this data, use that API here. + context->AddTrailingMetadata("x-endpoint-load-metrics-bin", + load_report->SerializeAsString()); + } + return TestServiceImpl::Echo(context, request, response); + } + + int request_count() { + grpc::internal::MutexLock lock(&mu_); + return request_count_; + } + + void ResetCounters() { + grpc::internal::MutexLock lock(&mu_); + request_count_ = 0; + } + std::set<TString> clients() { - grpc::internal::MutexLock lock(&clients_mu_); - return clients_; - } - - void set_load_report(udpa::data::orca::v1::OrcaLoadReport* load_report) { - grpc::internal::MutexLock lock(&mu_); - load_report_ = load_report; - } - - private: + grpc::internal::MutexLock lock(&clients_mu_); + return clients_; + } + + void set_load_report(udpa::data::orca::v1::OrcaLoadReport* load_report) { + grpc::internal::MutexLock lock(&mu_); + load_report_ = load_report; + } + + private: void AddClient(const TString& client) { - grpc::internal::MutexLock lock(&clients_mu_); - clients_.insert(client); - } - - grpc::internal::Mutex mu_; - int request_count_ = 0; - const udpa::data::orca::v1::OrcaLoadReport* load_report_ = nullptr; - grpc::internal::Mutex clients_mu_; + grpc::internal::MutexLock lock(&clients_mu_); + clients_.insert(client); + } + + grpc::internal::Mutex mu_; + int request_count_ = 0; + const udpa::data::orca::v1::OrcaLoadReport* load_report_ = nullptr; + grpc::internal::Mutex clients_mu_; std::set<TString> clients_; -}; - -class FakeResolverResponseGeneratorWrapper { - public: - FakeResolverResponseGeneratorWrapper() - : response_generator_(grpc_core::MakeRefCounted< - grpc_core::FakeResolverResponseGenerator>()) {} - - FakeResolverResponseGeneratorWrapper( +}; + +class FakeResolverResponseGeneratorWrapper { + public: + FakeResolverResponseGeneratorWrapper() + : response_generator_(grpc_core::MakeRefCounted< + grpc_core::FakeResolverResponseGenerator>()) {} + + FakeResolverResponseGeneratorWrapper( FakeResolverResponseGeneratorWrapper&& other) noexcept { - response_generator_ = std::move(other.response_generator_); - } - + response_generator_ = std::move(other.response_generator_); + } + void SetNextResolution( const std::vector<int>& ports, const char* service_config_json = nullptr, const char* attribute_key = nullptr, std::unique_ptr<grpc_core::ServerAddress::AttributeInterface> attribute = nullptr) { - grpc_core::ExecCtx exec_ctx; + grpc_core::ExecCtx exec_ctx; response_generator_->SetResponse(BuildFakeResults( ports, service_config_json, attribute_key, std::move(attribute))); - } - - void SetNextResolutionUponError(const std::vector<int>& ports) { - grpc_core::ExecCtx exec_ctx; - response_generator_->SetReresolutionResponse(BuildFakeResults(ports)); - } - - void SetFailureOnReresolution() { - grpc_core::ExecCtx exec_ctx; - response_generator_->SetFailureOnReresolution(); - } - - grpc_core::FakeResolverResponseGenerator* Get() const { - return response_generator_.get(); - } - - private: - static grpc_core::Resolver::Result BuildFakeResults( + } + + void SetNextResolutionUponError(const std::vector<int>& ports) { + grpc_core::ExecCtx exec_ctx; + response_generator_->SetReresolutionResponse(BuildFakeResults(ports)); + } + + void SetFailureOnReresolution() { + grpc_core::ExecCtx exec_ctx; + response_generator_->SetFailureOnReresolution(); + } + + grpc_core::FakeResolverResponseGenerator* Get() const { + return response_generator_.get(); + } + + private: + static grpc_core::Resolver::Result BuildFakeResults( const std::vector<int>& ports, const char* service_config_json = nullptr, const char* attribute_key = nullptr, std::unique_ptr<grpc_core::ServerAddress::AttributeInterface> attribute = nullptr) { - grpc_core::Resolver::Result result; - for (const int& port : ports) { + grpc_core::Resolver::Result result; + for (const int& port : ports) { TString lb_uri_str = y_absl::StrCat("ipv4:127.0.0.1:", port); grpc_uri* lb_uri = grpc_uri_parse(lb_uri_str.c_str(), true); - GPR_ASSERT(lb_uri != nullptr); - grpc_resolved_address address; - GPR_ASSERT(grpc_parse_uri(lb_uri, &address)); + GPR_ASSERT(lb_uri != nullptr); + grpc_resolved_address address; + GPR_ASSERT(grpc_parse_uri(lb_uri, &address)); std::map<const char*, std::unique_ptr<grpc_core::ServerAddress::AttributeInterface>> attributes; if (attribute != nullptr) { attributes[attribute_key] = attribute->Copy(); } - result.addresses.emplace_back(address.addr, address.len, + result.addresses.emplace_back(address.addr, address.len, nullptr /* args */, std::move(attributes)); - grpc_uri_destroy(lb_uri); - } - if (service_config_json != nullptr) { - result.service_config = grpc_core::ServiceConfig::Create( + grpc_uri_destroy(lb_uri); + } + if (service_config_json != nullptr) { + result.service_config = grpc_core::ServiceConfig::Create( nullptr, service_config_json, &result.service_config_error); - GPR_ASSERT(result.service_config != nullptr); - } - return result; - } - - grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator> - response_generator_; -}; - -class ClientLbEnd2endTest : public ::testing::Test { - protected: - ClientLbEnd2endTest() - : server_host_("localhost"), - kRequestMessage_("Live long and prosper."), - creds_(new SecureChannelCredentials( - grpc_fake_transport_security_credentials_create())) {} - - static void SetUpTestCase() { - // Make the backup poller poll very frequently in order to pick up - // updates from all the subchannels's FDs. - GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1); -#if TARGET_OS_IPHONE - // Workaround Apple CFStream bug - gpr_setenv("grpc_cfstream", "0"); -#endif - } - - void SetUp() override { grpc_init(); } - - void TearDown() override { - for (size_t i = 0; i < servers_.size(); ++i) { - servers_[i]->Shutdown(); - } - servers_.clear(); - creds_.reset(); - grpc_shutdown_blocking(); - } - - void CreateServers(size_t num_servers, - std::vector<int> ports = std::vector<int>()) { - servers_.clear(); - for (size_t i = 0; i < num_servers; ++i) { - int port = 0; - if (ports.size() == num_servers) port = ports[i]; - servers_.emplace_back(new ServerData(port)); - } - } - - void StartServer(size_t index) { servers_[index]->Start(server_host_); } - - void StartServers(size_t num_servers, - std::vector<int> ports = std::vector<int>()) { - CreateServers(num_servers, std::move(ports)); - for (size_t i = 0; i < num_servers; ++i) { - StartServer(i); - } - } - - std::vector<int> GetServersPorts(size_t start_index = 0) { - std::vector<int> ports; - for (size_t i = start_index; i < servers_.size(); ++i) { - ports.push_back(servers_[i]->port_); - } - return ports; - } - - FakeResolverResponseGeneratorWrapper BuildResolverResponseGenerator() { - return FakeResolverResponseGeneratorWrapper(); - } - - std::unique_ptr<grpc::testing::EchoTestService::Stub> BuildStub( - const std::shared_ptr<Channel>& channel) { - return grpc::testing::EchoTestService::NewStub(channel); - } - - std::shared_ptr<Channel> BuildChannel( + GPR_ASSERT(result.service_config != nullptr); + } + return result; + } + + grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator> + response_generator_; +}; + +class ClientLbEnd2endTest : public ::testing::Test { + protected: + ClientLbEnd2endTest() + : server_host_("localhost"), + kRequestMessage_("Live long and prosper."), + creds_(new SecureChannelCredentials( + grpc_fake_transport_security_credentials_create())) {} + + static void SetUpTestCase() { + // Make the backup poller poll very frequently in order to pick up + // updates from all the subchannels's FDs. + GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1); +#if TARGET_OS_IPHONE + // Workaround Apple CFStream bug + gpr_setenv("grpc_cfstream", "0"); +#endif + } + + void SetUp() override { grpc_init(); } + + void TearDown() override { + for (size_t i = 0; i < servers_.size(); ++i) { + servers_[i]->Shutdown(); + } + servers_.clear(); + creds_.reset(); + grpc_shutdown_blocking(); + } + + void CreateServers(size_t num_servers, + std::vector<int> ports = std::vector<int>()) { + servers_.clear(); + for (size_t i = 0; i < num_servers; ++i) { + int port = 0; + if (ports.size() == num_servers) port = ports[i]; + servers_.emplace_back(new ServerData(port)); + } + } + + void StartServer(size_t index) { servers_[index]->Start(server_host_); } + + void StartServers(size_t num_servers, + std::vector<int> ports = std::vector<int>()) { + CreateServers(num_servers, std::move(ports)); + for (size_t i = 0; i < num_servers; ++i) { + StartServer(i); + } + } + + std::vector<int> GetServersPorts(size_t start_index = 0) { + std::vector<int> ports; + for (size_t i = start_index; i < servers_.size(); ++i) { + ports.push_back(servers_[i]->port_); + } + return ports; + } + + FakeResolverResponseGeneratorWrapper BuildResolverResponseGenerator() { + return FakeResolverResponseGeneratorWrapper(); + } + + std::unique_ptr<grpc::testing::EchoTestService::Stub> BuildStub( + const std::shared_ptr<Channel>& channel) { + return grpc::testing::EchoTestService::NewStub(channel); + } + + std::shared_ptr<Channel> BuildChannel( const TString& lb_policy_name, - const FakeResolverResponseGeneratorWrapper& response_generator, - ChannelArguments args = ChannelArguments()) { - if (lb_policy_name.size() > 0) { - args.SetLoadBalancingPolicyName(lb_policy_name); - } // else, default to pick first - args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, - response_generator.Get()); - return ::grpc::CreateCustomChannel("fake:///", creds_, args); - } - - bool SendRpc( - const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub, - EchoResponse* response = nullptr, int timeout_ms = 1000, - Status* result = nullptr, bool wait_for_ready = false) { - const bool local_response = (response == nullptr); - if (local_response) response = new EchoResponse; - EchoRequest request; - request.set_message(kRequestMessage_); + const FakeResolverResponseGeneratorWrapper& response_generator, + ChannelArguments args = ChannelArguments()) { + if (lb_policy_name.size() > 0) { + args.SetLoadBalancingPolicyName(lb_policy_name); + } // else, default to pick first + args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, + response_generator.Get()); + return ::grpc::CreateCustomChannel("fake:///", creds_, args); + } + + bool SendRpc( + const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub, + EchoResponse* response = nullptr, int timeout_ms = 1000, + Status* result = nullptr, bool wait_for_ready = false) { + const bool local_response = (response == nullptr); + if (local_response) response = new EchoResponse; + EchoRequest request; + request.set_message(kRequestMessage_); request.mutable_param()->set_echo_metadata(true); - ClientContext context; - context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms)); - if (wait_for_ready) context.set_wait_for_ready(true); + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms)); + if (wait_for_ready) context.set_wait_for_ready(true); context.AddMetadata("foo", "1"); context.AddMetadata("bar", "2"); context.AddMetadata("baz", "3"); - Status status = stub->Echo(&context, request, response); - if (result != nullptr) *result = status; - if (local_response) delete response; - return status.ok(); - } - - void CheckRpcSendOk( - const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub, - const grpc_core::DebugLocation& location, bool wait_for_ready = false) { - EchoResponse response; - Status status; - const bool success = - SendRpc(stub, &response, 2000, &status, wait_for_ready); - ASSERT_TRUE(success) << "From " << location.file() << ":" << location.line() - << "\n" - << "Error: " << status.error_message() << " " - << status.error_details(); - ASSERT_EQ(response.message(), kRequestMessage_) - << "From " << location.file() << ":" << location.line(); - if (!success) abort(); - } - - void CheckRpcSendFailure( - const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub) { - const bool success = SendRpc(stub); - EXPECT_FALSE(success); - } - - struct ServerData { - int port_; - std::unique_ptr<Server> server_; - MyTestServiceImpl service_; - std::unique_ptr<std::thread> thread_; - bool server_ready_ = false; - bool started_ = false; - - explicit ServerData(int port = 0) { - port_ = port > 0 ? port : 5100; // grpc_pick_unused_port_or_die(); - } - + Status status = stub->Echo(&context, request, response); + if (result != nullptr) *result = status; + if (local_response) delete response; + return status.ok(); + } + + void CheckRpcSendOk( + const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub, + const grpc_core::DebugLocation& location, bool wait_for_ready = false) { + EchoResponse response; + Status status; + const bool success = + SendRpc(stub, &response, 2000, &status, wait_for_ready); + ASSERT_TRUE(success) << "From " << location.file() << ":" << location.line() + << "\n" + << "Error: " << status.error_message() << " " + << status.error_details(); + ASSERT_EQ(response.message(), kRequestMessage_) + << "From " << location.file() << ":" << location.line(); + if (!success) abort(); + } + + void CheckRpcSendFailure( + const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub) { + const bool success = SendRpc(stub); + EXPECT_FALSE(success); + } + + struct ServerData { + int port_; + std::unique_ptr<Server> server_; + MyTestServiceImpl service_; + std::unique_ptr<std::thread> thread_; + bool server_ready_ = false; + bool started_ = false; + + explicit ServerData(int port = 0) { + port_ = port > 0 ? port : 5100; // grpc_pick_unused_port_or_die(); + } + void Start(const TString& server_host) { - gpr_log(GPR_INFO, "starting server on port %d", port_); - started_ = true; - grpc::internal::Mutex mu; - grpc::internal::MutexLock lock(&mu); - grpc::internal::CondVar cond; - thread_.reset(new std::thread( - std::bind(&ServerData::Serve, this, server_host, &mu, &cond))); - cond.WaitUntil(&mu, [this] { return server_ready_; }); - server_ready_ = false; - gpr_log(GPR_INFO, "server startup complete"); - } - + gpr_log(GPR_INFO, "starting server on port %d", port_); + started_ = true; + grpc::internal::Mutex mu; + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; + thread_.reset(new std::thread( + std::bind(&ServerData::Serve, this, server_host, &mu, &cond))); + cond.WaitUntil(&mu, [this] { return server_ready_; }); + server_ready_ = false; + gpr_log(GPR_INFO, "server startup complete"); + } + void Serve(const TString& server_host, grpc::internal::Mutex* mu, - grpc::internal::CondVar* cond) { - std::ostringstream server_address; - server_address << server_host << ":" << port_; - ServerBuilder builder; - std::shared_ptr<ServerCredentials> creds(new SecureServerCredentials( - grpc_fake_transport_security_server_credentials_create())); - builder.AddListeningPort(server_address.str(), std::move(creds)); - builder.RegisterService(&service_); - server_ = builder.BuildAndStart(); - grpc::internal::MutexLock lock(mu); - server_ready_ = true; - cond->Signal(); - } - - void Shutdown() { - if (!started_) return; - server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0)); - thread_->join(); - started_ = false; - } - + grpc::internal::CondVar* cond) { + std::ostringstream server_address; + server_address << server_host << ":" << port_; + ServerBuilder builder; + std::shared_ptr<ServerCredentials> creds(new SecureServerCredentials( + grpc_fake_transport_security_server_credentials_create())); + builder.AddListeningPort(server_address.str(), std::move(creds)); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + grpc::internal::MutexLock lock(mu); + server_ready_ = true; + cond->Signal(); + } + + void Shutdown() { + if (!started_) return; + server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0)); + thread_->join(); + started_ = false; + } + void SetServingStatus(const TString& service, bool serving) { - server_->GetHealthCheckService()->SetServingStatus(service, serving); - } - }; - - void ResetCounters() { - for (const auto& server : servers_) server->service_.ResetCounters(); - } - - void WaitForServer( - const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub, - size_t server_idx, const grpc_core::DebugLocation& location, - bool ignore_failure = false) { - do { - if (ignore_failure) { - SendRpc(stub); - } else { - CheckRpcSendOk(stub, location, true); - } - } while (servers_[server_idx]->service_.request_count() == 0); - ResetCounters(); - } - - bool WaitForChannelState( - Channel* channel, std::function<bool(grpc_connectivity_state)> predicate, - bool try_to_connect = false, int timeout_seconds = 5) { - const gpr_timespec deadline = - grpc_timeout_seconds_to_deadline(timeout_seconds); - while (true) { - grpc_connectivity_state state = channel->GetState(try_to_connect); - if (predicate(state)) break; - if (!channel->WaitForStateChange(state, deadline)) return false; - } - return true; - } - - bool WaitForChannelNotReady(Channel* channel, int timeout_seconds = 5) { - auto predicate = [](grpc_connectivity_state state) { - return state != GRPC_CHANNEL_READY; - }; - return WaitForChannelState(channel, predicate, false, timeout_seconds); - } - - bool WaitForChannelReady(Channel* channel, int timeout_seconds = 5) { - auto predicate = [](grpc_connectivity_state state) { - return state == GRPC_CHANNEL_READY; - }; - return WaitForChannelState(channel, predicate, true, timeout_seconds); - } - - bool SeenAllServers() { - for (const auto& server : servers_) { - if (server->service_.request_count() == 0) return false; - } - return true; - } - - // Updates \a connection_order by appending to it the index of the newly - // connected server. Must be called after every single RPC. - void UpdateConnectionOrder( - const std::vector<std::unique_ptr<ServerData>>& servers, - std::vector<int>* connection_order) { - for (size_t i = 0; i < servers.size(); ++i) { - if (servers[i]->service_.request_count() == 1) { - // Was the server index known? If not, update connection_order. - const auto it = - std::find(connection_order->begin(), connection_order->end(), i); - if (it == connection_order->end()) { - connection_order->push_back(i); - return; - } - } - } - } - + server_->GetHealthCheckService()->SetServingStatus(service, serving); + } + }; + + void ResetCounters() { + for (const auto& server : servers_) server->service_.ResetCounters(); + } + + void WaitForServer( + const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub, + size_t server_idx, const grpc_core::DebugLocation& location, + bool ignore_failure = false) { + do { + if (ignore_failure) { + SendRpc(stub); + } else { + CheckRpcSendOk(stub, location, true); + } + } while (servers_[server_idx]->service_.request_count() == 0); + ResetCounters(); + } + + bool WaitForChannelState( + Channel* channel, std::function<bool(grpc_connectivity_state)> predicate, + bool try_to_connect = false, int timeout_seconds = 5) { + const gpr_timespec deadline = + grpc_timeout_seconds_to_deadline(timeout_seconds); + while (true) { + grpc_connectivity_state state = channel->GetState(try_to_connect); + if (predicate(state)) break; + if (!channel->WaitForStateChange(state, deadline)) return false; + } + return true; + } + + bool WaitForChannelNotReady(Channel* channel, int timeout_seconds = 5) { + auto predicate = [](grpc_connectivity_state state) { + return state != GRPC_CHANNEL_READY; + }; + return WaitForChannelState(channel, predicate, false, timeout_seconds); + } + + bool WaitForChannelReady(Channel* channel, int timeout_seconds = 5) { + auto predicate = [](grpc_connectivity_state state) { + return state == GRPC_CHANNEL_READY; + }; + return WaitForChannelState(channel, predicate, true, timeout_seconds); + } + + bool SeenAllServers() { + for (const auto& server : servers_) { + if (server->service_.request_count() == 0) return false; + } + return true; + } + + // Updates \a connection_order by appending to it the index of the newly + // connected server. Must be called after every single RPC. + void UpdateConnectionOrder( + const std::vector<std::unique_ptr<ServerData>>& servers, + std::vector<int>* connection_order) { + for (size_t i = 0; i < servers.size(); ++i) { + if (servers[i]->service_.request_count() == 1) { + // Was the server index known? If not, update connection_order. + const auto it = + std::find(connection_order->begin(), connection_order->end(), i); + if (it == connection_order->end()) { + connection_order->push_back(i); + return; + } + } + } + } + const TString server_host_; - std::vector<std::unique_ptr<ServerData>> servers_; + std::vector<std::unique_ptr<ServerData>> servers_; const TString kRequestMessage_; - std::shared_ptr<ChannelCredentials> creds_; -}; - -TEST_F(ClientLbEnd2endTest, ChannelStateConnectingWhenResolving) { - const int kNumServers = 3; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("", response_generator); - auto stub = BuildStub(channel); - // Initial state should be IDLE. - EXPECT_EQ(channel->GetState(false /* try_to_connect */), GRPC_CHANNEL_IDLE); - // Tell the channel to try to connect. - // Note that this call also returns IDLE, since the state change has - // not yet occurred; it just gets triggered by this call. - EXPECT_EQ(channel->GetState(true /* try_to_connect */), GRPC_CHANNEL_IDLE); - // Now that the channel is trying to connect, we should be in state - // CONNECTING. - EXPECT_EQ(channel->GetState(false /* try_to_connect */), - GRPC_CHANNEL_CONNECTING); - // Return a resolver result, which allows the connection attempt to proceed. - response_generator.SetNextResolution(GetServersPorts()); - // We should eventually transition into state READY. - EXPECT_TRUE(WaitForChannelReady(channel.get())); -} - -TEST_F(ClientLbEnd2endTest, PickFirst) { - // Start servers and send one RPC per server. - const int kNumServers = 3; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel( - "", response_generator); // test that pick first is the default. - auto stub = BuildStub(channel); - response_generator.SetNextResolution(GetServersPorts()); - for (size_t i = 0; i < servers_.size(); ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - } - // All requests should have gone to a single server. - bool found = false; - for (size_t i = 0; i < servers_.size(); ++i) { - const int request_count = servers_[i]->service_.request_count(); - if (request_count == kNumServers) { - found = true; - } else { - EXPECT_EQ(0, request_count); - } - } - EXPECT_TRUE(found); - // Check LB policy name for the channel. - EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName()); -} - -TEST_F(ClientLbEnd2endTest, PickFirstProcessPending) { - StartServers(1); // Single server - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel( - "", response_generator); // test that pick first is the default. - auto stub = BuildStub(channel); - response_generator.SetNextResolution({servers_[0]->port_}); - WaitForServer(stub, 0, DEBUG_LOCATION); - // Create a new channel and its corresponding PF LB policy, which will pick - // the subchannels in READY state from the previous RPC against the same - // target (even if it happened over a different channel, because subchannels - // are globally reused). Progress should happen without any transition from - // this READY state. - auto second_response_generator = BuildResolverResponseGenerator(); - auto second_channel = BuildChannel("", second_response_generator); - auto second_stub = BuildStub(second_channel); - second_response_generator.SetNextResolution({servers_[0]->port_}); - CheckRpcSendOk(second_stub, DEBUG_LOCATION); -} - -TEST_F(ClientLbEnd2endTest, PickFirstSelectsReadyAtStartup) { - ChannelArguments args; - constexpr int kInitialBackOffMs = 5000; - args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); - // Create 2 servers, but start only the second one. - std::vector<int> ports = { 5101, // grpc_pick_unused_port_or_die(), - 5102}; // grpc_pick_unused_port_or_die()}; - CreateServers(2, ports); - StartServer(1); - auto response_generator1 = BuildResolverResponseGenerator(); - auto channel1 = BuildChannel("pick_first", response_generator1, args); - auto stub1 = BuildStub(channel1); - response_generator1.SetNextResolution(ports); - // Wait for second server to be ready. - WaitForServer(stub1, 1, DEBUG_LOCATION); - // Create a second channel with the same addresses. Its PF instance - // should immediately pick the second subchannel, since it's already - // in READY state. - auto response_generator2 = BuildResolverResponseGenerator(); - auto channel2 = BuildChannel("pick_first", response_generator2, args); - response_generator2.SetNextResolution(ports); - // Check that the channel reports READY without waiting for the - // initial backoff. - EXPECT_TRUE(WaitForChannelReady(channel2.get(), 1 /* timeout_seconds */)); -} - -TEST_F(ClientLbEnd2endTest, PickFirstBackOffInitialReconnect) { - ChannelArguments args; - constexpr int kInitialBackOffMs = 100; - args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); - const std::vector<int> ports = {5103}; // {grpc_pick_unused_port_or_die()}; - const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("pick_first", response_generator, args); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(ports); - // The channel won't become connected (there's no server). - ASSERT_FALSE(channel->WaitForConnected( - grpc_timeout_milliseconds_to_deadline(kInitialBackOffMs * 2))); - // Bring up a server on the chosen port. - StartServers(1, ports); - // Now it will. - ASSERT_TRUE(channel->WaitForConnected( - grpc_timeout_milliseconds_to_deadline(kInitialBackOffMs * 2))); - const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC); - const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0)); - gpr_log(GPR_DEBUG, "Waited %" PRId64 " milliseconds", waited_ms); - // We should have waited at least kInitialBackOffMs. We substract one to - // account for test and precision accuracy drift. - EXPECT_GE(waited_ms, kInitialBackOffMs - 1); - // But not much more. - EXPECT_GT( - gpr_time_cmp( - grpc_timeout_milliseconds_to_deadline(kInitialBackOffMs * 1.10), t1), - 0); -} - -TEST_F(ClientLbEnd2endTest, PickFirstBackOffMinReconnect) { - ChannelArguments args; - constexpr int kMinReconnectBackOffMs = 1000; - args.SetInt(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, kMinReconnectBackOffMs); - const std::vector<int> ports = {5104}; // {grpc_pick_unused_port_or_die()}; - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("pick_first", response_generator, args); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(ports); - // Make connection delay a 10% longer than it's willing to in order to make - // sure we are hitting the codepath that waits for the min reconnect backoff. - gpr_atm_rel_store(&g_connection_delay_ms, kMinReconnectBackOffMs * 1.10); - default_client_impl = grpc_tcp_client_impl; - grpc_set_tcp_client_impl(&delayed_connect); - const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); - channel->WaitForConnected( - grpc_timeout_milliseconds_to_deadline(kMinReconnectBackOffMs * 2)); - const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC); - const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0)); - gpr_log(GPR_DEBUG, "Waited %" PRId64 " ms", waited_ms); - // We should have waited at least kMinReconnectBackOffMs. We substract one to - // account for test and precision accuracy drift. - EXPECT_GE(waited_ms, kMinReconnectBackOffMs - 1); - gpr_atm_rel_store(&g_connection_delay_ms, 0); -} - -TEST_F(ClientLbEnd2endTest, PickFirstResetConnectionBackoff) { - ChannelArguments args; - constexpr int kInitialBackOffMs = 1000; - args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); - const std::vector<int> ports = {5105}; // {grpc_pick_unused_port_or_die()}; - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("pick_first", response_generator, args); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(ports); - // The channel won't become connected (there's no server). - EXPECT_FALSE( - channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); - // Bring up a server on the chosen port. - StartServers(1, ports); - const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); - // Wait for connect, but not long enough. This proves that we're - // being throttled by initial backoff. - EXPECT_FALSE( - channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); - // Reset connection backoff. - experimental::ChannelResetConnectionBackoff(channel.get()); + std::shared_ptr<ChannelCredentials> creds_; +}; + +TEST_F(ClientLbEnd2endTest, ChannelStateConnectingWhenResolving) { + const int kNumServers = 3; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("", response_generator); + auto stub = BuildStub(channel); + // Initial state should be IDLE. + EXPECT_EQ(channel->GetState(false /* try_to_connect */), GRPC_CHANNEL_IDLE); + // Tell the channel to try to connect. + // Note that this call also returns IDLE, since the state change has + // not yet occurred; it just gets triggered by this call. + EXPECT_EQ(channel->GetState(true /* try_to_connect */), GRPC_CHANNEL_IDLE); + // Now that the channel is trying to connect, we should be in state + // CONNECTING. + EXPECT_EQ(channel->GetState(false /* try_to_connect */), + GRPC_CHANNEL_CONNECTING); + // Return a resolver result, which allows the connection attempt to proceed. + response_generator.SetNextResolution(GetServersPorts()); + // We should eventually transition into state READY. + EXPECT_TRUE(WaitForChannelReady(channel.get())); +} + +TEST_F(ClientLbEnd2endTest, PickFirst) { + // Start servers and send one RPC per server. + const int kNumServers = 3; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel( + "", response_generator); // test that pick first is the default. + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + for (size_t i = 0; i < servers_.size(); ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + } + // All requests should have gone to a single server. + bool found = false; + for (size_t i = 0; i < servers_.size(); ++i) { + const int request_count = servers_[i]->service_.request_count(); + if (request_count == kNumServers) { + found = true; + } else { + EXPECT_EQ(0, request_count); + } + } + EXPECT_TRUE(found); + // Check LB policy name for the channel. + EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName()); +} + +TEST_F(ClientLbEnd2endTest, PickFirstProcessPending) { + StartServers(1); // Single server + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel( + "", response_generator); // test that pick first is the default. + auto stub = BuildStub(channel); + response_generator.SetNextResolution({servers_[0]->port_}); + WaitForServer(stub, 0, DEBUG_LOCATION); + // Create a new channel and its corresponding PF LB policy, which will pick + // the subchannels in READY state from the previous RPC against the same + // target (even if it happened over a different channel, because subchannels + // are globally reused). Progress should happen without any transition from + // this READY state. + auto second_response_generator = BuildResolverResponseGenerator(); + auto second_channel = BuildChannel("", second_response_generator); + auto second_stub = BuildStub(second_channel); + second_response_generator.SetNextResolution({servers_[0]->port_}); + CheckRpcSendOk(second_stub, DEBUG_LOCATION); +} + +TEST_F(ClientLbEnd2endTest, PickFirstSelectsReadyAtStartup) { + ChannelArguments args; + constexpr int kInitialBackOffMs = 5000; + args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); + // Create 2 servers, but start only the second one. + std::vector<int> ports = { 5101, // grpc_pick_unused_port_or_die(), + 5102}; // grpc_pick_unused_port_or_die()}; + CreateServers(2, ports); + StartServer(1); + auto response_generator1 = BuildResolverResponseGenerator(); + auto channel1 = BuildChannel("pick_first", response_generator1, args); + auto stub1 = BuildStub(channel1); + response_generator1.SetNextResolution(ports); + // Wait for second server to be ready. + WaitForServer(stub1, 1, DEBUG_LOCATION); + // Create a second channel with the same addresses. Its PF instance + // should immediately pick the second subchannel, since it's already + // in READY state. + auto response_generator2 = BuildResolverResponseGenerator(); + auto channel2 = BuildChannel("pick_first", response_generator2, args); + response_generator2.SetNextResolution(ports); + // Check that the channel reports READY without waiting for the + // initial backoff. + EXPECT_TRUE(WaitForChannelReady(channel2.get(), 1 /* timeout_seconds */)); +} + +TEST_F(ClientLbEnd2endTest, PickFirstBackOffInitialReconnect) { + ChannelArguments args; + constexpr int kInitialBackOffMs = 100; + args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); + const std::vector<int> ports = {5103}; // {grpc_pick_unused_port_or_die()}; + const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("pick_first", response_generator, args); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(ports); + // The channel won't become connected (there's no server). + ASSERT_FALSE(channel->WaitForConnected( + grpc_timeout_milliseconds_to_deadline(kInitialBackOffMs * 2))); + // Bring up a server on the chosen port. + StartServers(1, ports); + // Now it will. + ASSERT_TRUE(channel->WaitForConnected( + grpc_timeout_milliseconds_to_deadline(kInitialBackOffMs * 2))); + const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC); + const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0)); + gpr_log(GPR_DEBUG, "Waited %" PRId64 " milliseconds", waited_ms); + // We should have waited at least kInitialBackOffMs. We substract one to + // account for test and precision accuracy drift. + EXPECT_GE(waited_ms, kInitialBackOffMs - 1); + // But not much more. + EXPECT_GT( + gpr_time_cmp( + grpc_timeout_milliseconds_to_deadline(kInitialBackOffMs * 1.10), t1), + 0); +} + +TEST_F(ClientLbEnd2endTest, PickFirstBackOffMinReconnect) { + ChannelArguments args; + constexpr int kMinReconnectBackOffMs = 1000; + args.SetInt(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, kMinReconnectBackOffMs); + const std::vector<int> ports = {5104}; // {grpc_pick_unused_port_or_die()}; + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("pick_first", response_generator, args); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(ports); + // Make connection delay a 10% longer than it's willing to in order to make + // sure we are hitting the codepath that waits for the min reconnect backoff. + gpr_atm_rel_store(&g_connection_delay_ms, kMinReconnectBackOffMs * 1.10); + default_client_impl = grpc_tcp_client_impl; + grpc_set_tcp_client_impl(&delayed_connect); + const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); + channel->WaitForConnected( + grpc_timeout_milliseconds_to_deadline(kMinReconnectBackOffMs * 2)); + const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC); + const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0)); + gpr_log(GPR_DEBUG, "Waited %" PRId64 " ms", waited_ms); + // We should have waited at least kMinReconnectBackOffMs. We substract one to + // account for test and precision accuracy drift. + EXPECT_GE(waited_ms, kMinReconnectBackOffMs - 1); + gpr_atm_rel_store(&g_connection_delay_ms, 0); +} + +TEST_F(ClientLbEnd2endTest, PickFirstResetConnectionBackoff) { + ChannelArguments args; + constexpr int kInitialBackOffMs = 1000; + args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); + const std::vector<int> ports = {5105}; // {grpc_pick_unused_port_or_die()}; + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("pick_first", response_generator, args); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(ports); + // The channel won't become connected (there's no server). + EXPECT_FALSE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); + // Bring up a server on the chosen port. + StartServers(1, ports); + const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); + // Wait for connect, but not long enough. This proves that we're + // being throttled by initial backoff. + EXPECT_FALSE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); + // Reset connection backoff. + experimental::ChannelResetConnectionBackoff(channel.get()); // Wait for connect. Should happen as soon as the client connects to // the newly started server, which should be before the initial // backoff timeout elapses. - EXPECT_TRUE( + EXPECT_TRUE( channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(20))); - const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC); - const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0)); - gpr_log(GPR_DEBUG, "Waited %" PRId64 " milliseconds", waited_ms); - // We should have waited less than kInitialBackOffMs. - EXPECT_LT(waited_ms, kInitialBackOffMs); -} - -TEST_F(ClientLbEnd2endTest, - PickFirstResetConnectionBackoffNextAttemptStartsImmediately) { - ChannelArguments args; - constexpr int kInitialBackOffMs = 1000; - args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); - const std::vector<int> ports = {5106}; // {grpc_pick_unused_port_or_die()}; - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("pick_first", response_generator, args); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(ports); - // Wait for connect, which should fail ~immediately, because the server - // is not up. - gpr_log(GPR_INFO, "=== INITIAL CONNECTION ATTEMPT"); - EXPECT_FALSE( - channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); - // Reset connection backoff. - // Note that the time at which the third attempt will be started is - // actually computed at this point, so we record the start time here. - gpr_log(GPR_INFO, "=== RESETTING BACKOFF"); - const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); - experimental::ChannelResetConnectionBackoff(channel.get()); - // Trigger a second connection attempt. This should also fail - // ~immediately, but the retry should be scheduled for - // kInitialBackOffMs instead of applying the multiplier. - gpr_log(GPR_INFO, "=== POLLING FOR SECOND CONNECTION ATTEMPT"); - EXPECT_FALSE( - channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); - // Bring up a server on the chosen port. - gpr_log(GPR_INFO, "=== STARTING BACKEND"); - StartServers(1, ports); - // Wait for connect. Should happen within kInitialBackOffMs. - // Give an extra 100ms to account for the time spent in the second and - // third connection attempts themselves (since what we really want to - // measure is the time between the two). As long as this is less than - // the 1.6x increase we would see if the backoff state was not reset - // properly, the test is still proving that the backoff was reset. - constexpr int kWaitMs = kInitialBackOffMs + 100; - gpr_log(GPR_INFO, "=== POLLING FOR THIRD CONNECTION ATTEMPT"); - EXPECT_TRUE(channel->WaitForConnected( - grpc_timeout_milliseconds_to_deadline(kWaitMs))); - const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC); - const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0)); - gpr_log(GPR_DEBUG, "Waited %" PRId64 " milliseconds", waited_ms); - EXPECT_LT(waited_ms, kWaitMs); -} - -TEST_F(ClientLbEnd2endTest, PickFirstUpdates) { - // Start servers and send one RPC per server. - const int kNumServers = 3; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("pick_first", response_generator); - auto stub = BuildStub(channel); - - std::vector<int> ports; - - // Perform one RPC against the first server. - ports.emplace_back(servers_[0]->port_); - response_generator.SetNextResolution(ports); - gpr_log(GPR_INFO, "****** SET [0] *******"); - CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(servers_[0]->service_.request_count(), 1); - - // An empty update will result in the channel going into TRANSIENT_FAILURE. - ports.clear(); - response_generator.SetNextResolution(ports); - gpr_log(GPR_INFO, "****** SET none *******"); - grpc_connectivity_state channel_state; - do { - channel_state = channel->GetState(true /* try to connect */); - } while (channel_state == GRPC_CHANNEL_READY); - ASSERT_NE(channel_state, GRPC_CHANNEL_READY); - servers_[0]->service_.ResetCounters(); - - // Next update introduces servers_[1], making the channel recover. - ports.clear(); - ports.emplace_back(servers_[1]->port_); - response_generator.SetNextResolution(ports); - gpr_log(GPR_INFO, "****** SET [1] *******"); - WaitForServer(stub, 1, DEBUG_LOCATION); - EXPECT_EQ(servers_[0]->service_.request_count(), 0); - - // And again for servers_[2] - ports.clear(); - ports.emplace_back(servers_[2]->port_); - response_generator.SetNextResolution(ports); - gpr_log(GPR_INFO, "****** SET [2] *******"); - WaitForServer(stub, 2, DEBUG_LOCATION); - EXPECT_EQ(servers_[0]->service_.request_count(), 0); - EXPECT_EQ(servers_[1]->service_.request_count(), 0); - - // Check LB policy name for the channel. - EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName()); -} - -TEST_F(ClientLbEnd2endTest, PickFirstUpdateSuperset) { - // Start servers and send one RPC per server. - const int kNumServers = 3; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("pick_first", response_generator); - auto stub = BuildStub(channel); - - std::vector<int> ports; - - // Perform one RPC against the first server. - ports.emplace_back(servers_[0]->port_); - response_generator.SetNextResolution(ports); - gpr_log(GPR_INFO, "****** SET [0] *******"); - CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(servers_[0]->service_.request_count(), 1); - servers_[0]->service_.ResetCounters(); - - // Send and superset update - ports.clear(); - ports.emplace_back(servers_[1]->port_); - ports.emplace_back(servers_[0]->port_); - response_generator.SetNextResolution(ports); - gpr_log(GPR_INFO, "****** SET superset *******"); - CheckRpcSendOk(stub, DEBUG_LOCATION); - // We stick to the previously connected server. - WaitForServer(stub, 0, DEBUG_LOCATION); - EXPECT_EQ(0, servers_[1]->service_.request_count()); - - // Check LB policy name for the channel. - EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName()); -} - -TEST_F(ClientLbEnd2endTest, PickFirstGlobalSubchannelPool) { - // Start one server. - const int kNumServers = 1; - StartServers(kNumServers); - std::vector<int> ports = GetServersPorts(); - // Create two channels that (by default) use the global subchannel pool. - auto response_generator1 = BuildResolverResponseGenerator(); - auto channel1 = BuildChannel("pick_first", response_generator1); - auto stub1 = BuildStub(channel1); - response_generator1.SetNextResolution(ports); - auto response_generator2 = BuildResolverResponseGenerator(); - auto channel2 = BuildChannel("pick_first", response_generator2); - auto stub2 = BuildStub(channel2); - response_generator2.SetNextResolution(ports); - WaitForServer(stub1, 0, DEBUG_LOCATION); - // Send one RPC on each channel. - CheckRpcSendOk(stub1, DEBUG_LOCATION); - CheckRpcSendOk(stub2, DEBUG_LOCATION); - // The server receives two requests. - EXPECT_EQ(2, servers_[0]->service_.request_count()); - // The two requests are from the same client port, because the two channels - // share subchannels via the global subchannel pool. - EXPECT_EQ(1UL, servers_[0]->service_.clients().size()); -} - -TEST_F(ClientLbEnd2endTest, PickFirstLocalSubchannelPool) { - // Start one server. - const int kNumServers = 1; - StartServers(kNumServers); - std::vector<int> ports = GetServersPorts(); - // Create two channels that use local subchannel pool. - ChannelArguments args; - args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1); - auto response_generator1 = BuildResolverResponseGenerator(); - auto channel1 = BuildChannel("pick_first", response_generator1, args); - auto stub1 = BuildStub(channel1); - response_generator1.SetNextResolution(ports); - auto response_generator2 = BuildResolverResponseGenerator(); - auto channel2 = BuildChannel("pick_first", response_generator2, args); - auto stub2 = BuildStub(channel2); - response_generator2.SetNextResolution(ports); - WaitForServer(stub1, 0, DEBUG_LOCATION); - // Send one RPC on each channel. - CheckRpcSendOk(stub1, DEBUG_LOCATION); - CheckRpcSendOk(stub2, DEBUG_LOCATION); - // The server receives two requests. - EXPECT_EQ(2, servers_[0]->service_.request_count()); - // The two requests are from two client ports, because the two channels didn't - // share subchannels with each other. - EXPECT_EQ(2UL, servers_[0]->service_.clients().size()); -} - -TEST_F(ClientLbEnd2endTest, PickFirstManyUpdates) { - const int kNumUpdates = 1000; - const int kNumServers = 3; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("pick_first", response_generator); - auto stub = BuildStub(channel); - std::vector<int> ports = GetServersPorts(); - for (size_t i = 0; i < kNumUpdates; ++i) { - std::shuffle(ports.begin(), ports.end(), - std::mt19937(std::random_device()())); - response_generator.SetNextResolution(ports); - // We should re-enter core at the end of the loop to give the resolution - // setting closure a chance to run. - if ((i + 1) % 10 == 0) CheckRpcSendOk(stub, DEBUG_LOCATION); - } - // Check LB policy name for the channel. - EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName()); -} - -TEST_F(ClientLbEnd2endTest, PickFirstReresolutionNoSelected) { - // Prepare the ports for up servers and down servers. - const int kNumServers = 3; - const int kNumAliveServers = 1; - StartServers(kNumAliveServers); - std::vector<int> alive_ports, dead_ports; - for (size_t i = 0; i < kNumServers; ++i) { - if (i < kNumAliveServers) { - alive_ports.emplace_back(servers_[i]->port_); - } else { - dead_ports.emplace_back(5107 + i); - // dead_ports.emplace_back(grpc_pick_unused_port_or_die()); - } - } - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("pick_first", response_generator); - auto stub = BuildStub(channel); - // The initial resolution only contains dead ports. There won't be any - // selected subchannel. Re-resolution will return the same result. - response_generator.SetNextResolution(dead_ports); - gpr_log(GPR_INFO, "****** INITIAL RESOLUTION SET *******"); - for (size_t i = 0; i < 10; ++i) CheckRpcSendFailure(stub); - // Set a re-resolution result that contains reachable ports, so that the - // pick_first LB policy can recover soon. - response_generator.SetNextResolutionUponError(alive_ports); - gpr_log(GPR_INFO, "****** RE-RESOLUTION SET *******"); - WaitForServer(stub, 0, DEBUG_LOCATION, true /* ignore_failure */); - CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(servers_[0]->service_.request_count(), 1); - // Check LB policy name for the channel. - EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName()); -} - -TEST_F(ClientLbEnd2endTest, PickFirstReconnectWithoutNewResolverResult) { - std::vector<int> ports = {5110}; // {grpc_pick_unused_port_or_die()}; - StartServers(1, ports); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("pick_first", response_generator); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(ports); - gpr_log(GPR_INFO, "****** INITIAL CONNECTION *******"); - WaitForServer(stub, 0, DEBUG_LOCATION); - gpr_log(GPR_INFO, "****** STOPPING SERVER ******"); - servers_[0]->Shutdown(); - EXPECT_TRUE(WaitForChannelNotReady(channel.get())); - gpr_log(GPR_INFO, "****** RESTARTING SERVER ******"); - StartServers(1, ports); - WaitForServer(stub, 0, DEBUG_LOCATION); -} - -TEST_F(ClientLbEnd2endTest, - PickFirstReconnectWithoutNewResolverResultStartsFromTopOfList) { - std::vector<int> ports = {5111, // grpc_pick_unused_port_or_die(), - 5112}; // grpc_pick_unused_port_or_die()}; - CreateServers(2, ports); - StartServer(1); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("pick_first", response_generator); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(ports); - gpr_log(GPR_INFO, "****** INITIAL CONNECTION *******"); - WaitForServer(stub, 1, DEBUG_LOCATION); - gpr_log(GPR_INFO, "****** STOPPING SERVER ******"); - servers_[1]->Shutdown(); - EXPECT_TRUE(WaitForChannelNotReady(channel.get())); - gpr_log(GPR_INFO, "****** STARTING BOTH SERVERS ******"); - StartServers(2, ports); - WaitForServer(stub, 0, DEBUG_LOCATION); -} - -TEST_F(ClientLbEnd2endTest, PickFirstCheckStateBeforeStartWatch) { - std::vector<int> ports = {5113}; // {grpc_pick_unused_port_or_die()}; - StartServers(1, ports); - auto response_generator = BuildResolverResponseGenerator(); - auto channel_1 = BuildChannel("pick_first", response_generator); - auto stub_1 = BuildStub(channel_1); - response_generator.SetNextResolution(ports); - gpr_log(GPR_INFO, "****** RESOLUTION SET FOR CHANNEL 1 *******"); - WaitForServer(stub_1, 0, DEBUG_LOCATION); - gpr_log(GPR_INFO, "****** CHANNEL 1 CONNECTED *******"); - servers_[0]->Shutdown(); - // Channel 1 will receive a re-resolution containing the same server. It will - // create a new subchannel and hold a ref to it. - StartServers(1, ports); - gpr_log(GPR_INFO, "****** SERVER RESTARTED *******"); - auto response_generator_2 = BuildResolverResponseGenerator(); - auto channel_2 = BuildChannel("pick_first", response_generator_2); - auto stub_2 = BuildStub(channel_2); - response_generator_2.SetNextResolution(ports); - gpr_log(GPR_INFO, "****** RESOLUTION SET FOR CHANNEL 2 *******"); - WaitForServer(stub_2, 0, DEBUG_LOCATION, true); - gpr_log(GPR_INFO, "****** CHANNEL 2 CONNECTED *******"); - servers_[0]->Shutdown(); - // Wait until the disconnection has triggered the connectivity notification. - // Otherwise, the subchannel may be picked for next call but will fail soon. - EXPECT_TRUE(WaitForChannelNotReady(channel_2.get())); - // Channel 2 will also receive a re-resolution containing the same server. - // Both channels will ref the same subchannel that failed. - StartServers(1, ports); - gpr_log(GPR_INFO, "****** SERVER RESTARTED AGAIN *******"); - gpr_log(GPR_INFO, "****** CHANNEL 2 STARTING A CALL *******"); - // The first call after the server restart will succeed. - CheckRpcSendOk(stub_2, DEBUG_LOCATION); - gpr_log(GPR_INFO, "****** CHANNEL 2 FINISHED A CALL *******"); - // Check LB policy name for the channel. - EXPECT_EQ("pick_first", channel_1->GetLoadBalancingPolicyName()); - // Check LB policy name for the channel. - EXPECT_EQ("pick_first", channel_2->GetLoadBalancingPolicyName()); -} - -TEST_F(ClientLbEnd2endTest, PickFirstIdleOnDisconnect) { - // Start server, send RPC, and make sure channel is READY. - const int kNumServers = 1; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = - BuildChannel("", response_generator); // pick_first is the default. - auto stub = BuildStub(channel); - response_generator.SetNextResolution(GetServersPorts()); - CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); - // Stop server. Channel should go into state IDLE. - response_generator.SetFailureOnReresolution(); - servers_[0]->Shutdown(); - EXPECT_TRUE(WaitForChannelNotReady(channel.get())); - EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); - servers_.clear(); -} - -TEST_F(ClientLbEnd2endTest, PickFirstPendingUpdateAndSelectedSubchannelFails) { - auto response_generator = BuildResolverResponseGenerator(); - auto channel = - BuildChannel("", response_generator); // pick_first is the default. - auto stub = BuildStub(channel); - // Create a number of servers, but only start 1 of them. - CreateServers(10); - StartServer(0); - // Initially resolve to first server and make sure it connects. - gpr_log(GPR_INFO, "Phase 1: Connect to first server."); - response_generator.SetNextResolution({servers_[0]->port_}); - CheckRpcSendOk(stub, DEBUG_LOCATION, true /* wait_for_ready */); - EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); - // Send a resolution update with the remaining servers, none of which are - // running yet, so the update will stay pending. Note that it's important - // to have multiple servers here, or else the test will be flaky; with only - // one server, the pending subchannel list has already gone into - // TRANSIENT_FAILURE due to hitting the end of the list by the time we - // check the state. - gpr_log(GPR_INFO, - "Phase 2: Resolver update pointing to remaining " - "(not started) servers."); - response_generator.SetNextResolution(GetServersPorts(1 /* start_index */)); - // RPCs will continue to be sent to the first server. - CheckRpcSendOk(stub, DEBUG_LOCATION); - // Now stop the first server, so that the current subchannel list - // fails. This should cause us to immediately swap over to the - // pending list, even though it's not yet connected. The state should - // be set to CONNECTING, since that's what the pending subchannel list - // was doing when we swapped over. - gpr_log(GPR_INFO, "Phase 3: Stopping first server."); - servers_[0]->Shutdown(); - WaitForChannelNotReady(channel.get()); - // TODO(roth): This should always return CONNECTING, but it's flaky - // between that and TRANSIENT_FAILURE. I suspect that this problem - // will go away once we move the backoff code out of the subchannel - // and into the LB policies. - EXPECT_THAT(channel->GetState(false), - ::testing::AnyOf(GRPC_CHANNEL_CONNECTING, - GRPC_CHANNEL_TRANSIENT_FAILURE)); - // Now start the second server. - gpr_log(GPR_INFO, "Phase 4: Starting second server."); - StartServer(1); - // The channel should go to READY state and RPCs should go to the - // second server. - WaitForChannelReady(channel.get()); - WaitForServer(stub, 1, DEBUG_LOCATION, true /* ignore_failure */); -} - -TEST_F(ClientLbEnd2endTest, PickFirstStaysIdleUponEmptyUpdate) { - // Start server, send RPC, and make sure channel is READY. - const int kNumServers = 1; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = - BuildChannel("", response_generator); // pick_first is the default. - auto stub = BuildStub(channel); - response_generator.SetNextResolution(GetServersPorts()); - CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); - // Stop server. Channel should go into state IDLE. - servers_[0]->Shutdown(); - EXPECT_TRUE(WaitForChannelNotReady(channel.get())); - EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); - // Now send resolver update that includes no addresses. Channel - // should stay in state IDLE. - response_generator.SetNextResolution({}); - EXPECT_FALSE(channel->WaitForStateChange( - GRPC_CHANNEL_IDLE, grpc_timeout_seconds_to_deadline(3))); - // Now bring the backend back up and send a non-empty resolver update, - // and then try to send an RPC. Channel should go back into state READY. - StartServer(0); - response_generator.SetNextResolution(GetServersPorts()); - CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); -} - -TEST_F(ClientLbEnd2endTest, RoundRobin) { - // Start servers and send one RPC per server. - const int kNumServers = 3; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(GetServersPorts()); - // Wait until all backends are ready. - do { - CheckRpcSendOk(stub, DEBUG_LOCATION); - } while (!SeenAllServers()); - ResetCounters(); - // "Sync" to the end of the list. Next sequence of picks will start at the - // first server (index 0). - WaitForServer(stub, servers_.size() - 1, DEBUG_LOCATION); - std::vector<int> connection_order; - for (size_t i = 0; i < servers_.size(); ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - UpdateConnectionOrder(servers_, &connection_order); - } - // Backends should be iterated over in the order in which the addresses were - // given. - const auto expected = std::vector<int>{0, 1, 2}; - EXPECT_EQ(expected, connection_order); - // Check LB policy name for the channel. - EXPECT_EQ("round_robin", channel->GetLoadBalancingPolicyName()); -} - -TEST_F(ClientLbEnd2endTest, RoundRobinProcessPending) { - StartServers(1); // Single server - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator); - auto stub = BuildStub(channel); - response_generator.SetNextResolution({servers_[0]->port_}); - WaitForServer(stub, 0, DEBUG_LOCATION); - // Create a new channel and its corresponding RR LB policy, which will pick - // the subchannels in READY state from the previous RPC against the same - // target (even if it happened over a different channel, because subchannels - // are globally reused). Progress should happen without any transition from - // this READY state. - auto second_response_generator = BuildResolverResponseGenerator(); - auto second_channel = BuildChannel("round_robin", second_response_generator); - auto second_stub = BuildStub(second_channel); - second_response_generator.SetNextResolution({servers_[0]->port_}); - CheckRpcSendOk(second_stub, DEBUG_LOCATION); -} - -TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) { - // Start servers and send one RPC per server. - const int kNumServers = 3; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator); - auto stub = BuildStub(channel); - std::vector<int> ports; - // Start with a single server. - gpr_log(GPR_INFO, "*** FIRST BACKEND ***"); - ports.emplace_back(servers_[0]->port_); - response_generator.SetNextResolution(ports); - WaitForServer(stub, 0, DEBUG_LOCATION); - // Send RPCs. They should all go servers_[0] - for (size_t i = 0; i < 10; ++i) CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(10, servers_[0]->service_.request_count()); - EXPECT_EQ(0, servers_[1]->service_.request_count()); - EXPECT_EQ(0, servers_[2]->service_.request_count()); - servers_[0]->service_.ResetCounters(); - // And now for the second server. - gpr_log(GPR_INFO, "*** SECOND BACKEND ***"); - ports.clear(); - ports.emplace_back(servers_[1]->port_); - response_generator.SetNextResolution(ports); - // Wait until update has been processed, as signaled by the second backend - // receiving a request. - EXPECT_EQ(0, servers_[1]->service_.request_count()); - WaitForServer(stub, 1, DEBUG_LOCATION); - for (size_t i = 0; i < 10; ++i) CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(0, servers_[0]->service_.request_count()); - EXPECT_EQ(10, servers_[1]->service_.request_count()); - EXPECT_EQ(0, servers_[2]->service_.request_count()); - servers_[1]->service_.ResetCounters(); - // ... and for the last server. - gpr_log(GPR_INFO, "*** THIRD BACKEND ***"); - ports.clear(); - ports.emplace_back(servers_[2]->port_); - response_generator.SetNextResolution(ports); - WaitForServer(stub, 2, DEBUG_LOCATION); - for (size_t i = 0; i < 10; ++i) CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(0, servers_[0]->service_.request_count()); - EXPECT_EQ(0, servers_[1]->service_.request_count()); - EXPECT_EQ(10, servers_[2]->service_.request_count()); - servers_[2]->service_.ResetCounters(); - // Back to all servers. - gpr_log(GPR_INFO, "*** ALL BACKENDS ***"); - ports.clear(); - ports.emplace_back(servers_[0]->port_); - ports.emplace_back(servers_[1]->port_); - ports.emplace_back(servers_[2]->port_); - response_generator.SetNextResolution(ports); - WaitForServer(stub, 0, DEBUG_LOCATION); - WaitForServer(stub, 1, DEBUG_LOCATION); - WaitForServer(stub, 2, DEBUG_LOCATION); - // Send three RPCs, one per server. - for (size_t i = 0; i < 3; ++i) CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(1, servers_[0]->service_.request_count()); - EXPECT_EQ(1, servers_[1]->service_.request_count()); - EXPECT_EQ(1, servers_[2]->service_.request_count()); - // An empty update will result in the channel going into TRANSIENT_FAILURE. - gpr_log(GPR_INFO, "*** NO BACKENDS ***"); - ports.clear(); - response_generator.SetNextResolution(ports); - grpc_connectivity_state channel_state; - do { - channel_state = channel->GetState(true /* try to connect */); - } while (channel_state == GRPC_CHANNEL_READY); - ASSERT_NE(channel_state, GRPC_CHANNEL_READY); - servers_[0]->service_.ResetCounters(); - // Next update introduces servers_[1], making the channel recover. - gpr_log(GPR_INFO, "*** BACK TO SECOND BACKEND ***"); - ports.clear(); - ports.emplace_back(servers_[1]->port_); - response_generator.SetNextResolution(ports); - WaitForServer(stub, 1, DEBUG_LOCATION); - channel_state = channel->GetState(false /* try to connect */); - ASSERT_EQ(channel_state, GRPC_CHANNEL_READY); - // Check LB policy name for the channel. - EXPECT_EQ("round_robin", channel->GetLoadBalancingPolicyName()); -} - -TEST_F(ClientLbEnd2endTest, RoundRobinUpdateInError) { - const int kNumServers = 3; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator); - auto stub = BuildStub(channel); - std::vector<int> ports; - // Start with a single server. - ports.emplace_back(servers_[0]->port_); - response_generator.SetNextResolution(ports); - WaitForServer(stub, 0, DEBUG_LOCATION); - // Send RPCs. They should all go to servers_[0] - for (size_t i = 0; i < 10; ++i) SendRpc(stub); - EXPECT_EQ(10, servers_[0]->service_.request_count()); - EXPECT_EQ(0, servers_[1]->service_.request_count()); - EXPECT_EQ(0, servers_[2]->service_.request_count()); - servers_[0]->service_.ResetCounters(); - // Shutdown one of the servers to be sent in the update. - servers_[1]->Shutdown(); - ports.emplace_back(servers_[1]->port_); - ports.emplace_back(servers_[2]->port_); - response_generator.SetNextResolution(ports); - WaitForServer(stub, 0, DEBUG_LOCATION); - WaitForServer(stub, 2, DEBUG_LOCATION); - // Send three RPCs, one per server. - for (size_t i = 0; i < kNumServers; ++i) SendRpc(stub); - // The server in shutdown shouldn't receive any. - EXPECT_EQ(0, servers_[1]->service_.request_count()); -} - -TEST_F(ClientLbEnd2endTest, RoundRobinManyUpdates) { - // Start servers and send one RPC per server. - const int kNumServers = 3; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator); - auto stub = BuildStub(channel); - std::vector<int> ports = GetServersPorts(); - for (size_t i = 0; i < 1000; ++i) { - std::shuffle(ports.begin(), ports.end(), - std::mt19937(std::random_device()())); - response_generator.SetNextResolution(ports); - if (i % 10 == 0) CheckRpcSendOk(stub, DEBUG_LOCATION); - } - // Check LB policy name for the channel. - EXPECT_EQ("round_robin", channel->GetLoadBalancingPolicyName()); -} - -TEST_F(ClientLbEnd2endTest, RoundRobinConcurrentUpdates) { - // TODO(dgq): replicate the way internal testing exercises the concurrent - // update provisions of RR. -} - -TEST_F(ClientLbEnd2endTest, RoundRobinReresolve) { - // Start servers and send one RPC per server. - const int kNumServers = 3; - std::vector<int> first_ports; - std::vector<int> second_ports; - first_ports.reserve(kNumServers); - for (int i = 0; i < kNumServers; ++i) { - // first_ports.push_back(grpc_pick_unused_port_or_die()); - first_ports.push_back(5114 + i); - } - second_ports.reserve(kNumServers); - for (int i = 0; i < kNumServers; ++i) { - // second_ports.push_back(grpc_pick_unused_port_or_die()); - second_ports.push_back(5117 + i); - } - StartServers(kNumServers, first_ports); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(first_ports); - // Send a number of RPCs, which succeed. - for (size_t i = 0; i < 100; ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - } - // Kill all servers - gpr_log(GPR_INFO, "****** ABOUT TO KILL SERVERS *******"); - for (size_t i = 0; i < servers_.size(); ++i) { - servers_[i]->Shutdown(); - } - gpr_log(GPR_INFO, "****** SERVERS KILLED *******"); - gpr_log(GPR_INFO, "****** SENDING DOOMED REQUESTS *******"); - // Client requests should fail. Send enough to tickle all subchannels. - for (size_t i = 0; i < servers_.size(); ++i) CheckRpcSendFailure(stub); - gpr_log(GPR_INFO, "****** DOOMED REQUESTS SENT *******"); - // Bring servers back up on a different set of ports. We need to do this to be - // sure that the eventual success is *not* due to subchannel reconnection - // attempts and that an actual re-resolution has happened as a result of the - // RR policy going into transient failure when all its subchannels become - // unavailable (in transient failure as well). - gpr_log(GPR_INFO, "****** RESTARTING SERVERS *******"); - StartServers(kNumServers, second_ports); - // Don't notify of the update. Wait for the LB policy's re-resolution to - // "pull" the new ports. - response_generator.SetNextResolutionUponError(second_ports); - gpr_log(GPR_INFO, "****** SERVERS RESTARTED *******"); - gpr_log(GPR_INFO, "****** SENDING REQUEST TO SUCCEED *******"); - // Client request should eventually (but still fairly soon) succeed. - const gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); - while (gpr_time_cmp(deadline, now) > 0) { - if (SendRpc(stub)) break; - now = gpr_now(GPR_CLOCK_MONOTONIC); - } - ASSERT_GT(gpr_time_cmp(deadline, now), 0); -} - -TEST_F(ClientLbEnd2endTest, RoundRobinTransientFailure) { - // Start servers and create channel. Channel should go to READY state. - const int kNumServers = 3; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(GetServersPorts()); - EXPECT_TRUE(WaitForChannelReady(channel.get())); - // Now kill the servers. The channel should transition to TRANSIENT_FAILURE. - // TODO(roth): This test should ideally check that even when the - // subchannels are in state CONNECTING for an extended period of time, - // we will still report TRANSIENT_FAILURE. Unfortunately, we don't - // currently have a good way to get a subchannel to report CONNECTING - // for a long period of time, since the servers in this test framework - // are on the loopback interface, which will immediately return a - // "Connection refused" error, so the subchannels will only be in - // CONNECTING state very briefly. When we have time, see if we can - // find a way to fix this. - for (size_t i = 0; i < servers_.size(); ++i) { - servers_[i]->Shutdown(); - } - auto predicate = [](grpc_connectivity_state state) { - return state == GRPC_CHANNEL_TRANSIENT_FAILURE; - }; - EXPECT_TRUE(WaitForChannelState(channel.get(), predicate)); -} - -TEST_F(ClientLbEnd2endTest, RoundRobinTransientFailureAtStartup) { - // Create channel and return servers that don't exist. Channel should - // quickly transition into TRANSIENT_FAILURE. - // TODO(roth): This test should ideally check that even when the - // subchannels are in state CONNECTING for an extended period of time, - // we will still report TRANSIENT_FAILURE. Unfortunately, we don't - // currently have a good way to get a subchannel to report CONNECTING - // for a long period of time, since the servers in this test framework - // are on the loopback interface, which will immediately return a - // "Connection refused" error, so the subchannels will only be in - // CONNECTING state very briefly. When we have time, see if we can - // find a way to fix this. - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator); - auto stub = BuildStub(channel); - response_generator.SetNextResolution({ - grpc_pick_unused_port_or_die(), - grpc_pick_unused_port_or_die(), - grpc_pick_unused_port_or_die(), - }); - for (size_t i = 0; i < servers_.size(); ++i) { - servers_[i]->Shutdown(); - } - auto predicate = [](grpc_connectivity_state state) { - return state == GRPC_CHANNEL_TRANSIENT_FAILURE; - }; - EXPECT_TRUE(WaitForChannelState(channel.get(), predicate, true)); -} - -TEST_F(ClientLbEnd2endTest, RoundRobinSingleReconnect) { - const int kNumServers = 3; - StartServers(kNumServers); - const auto ports = GetServersPorts(); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(ports); - for (size_t i = 0; i < kNumServers; ++i) { - WaitForServer(stub, i, DEBUG_LOCATION); - } - for (size_t i = 0; i < servers_.size(); ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(1, servers_[i]->service_.request_count()) << "for backend #" << i; - } - // One request should have gone to each server. - for (size_t i = 0; i < servers_.size(); ++i) { - EXPECT_EQ(1, servers_[i]->service_.request_count()); - } - const auto pre_death = servers_[0]->service_.request_count(); - // Kill the first server. - servers_[0]->Shutdown(); - // Client request still succeed. May need retrying if RR had returned a pick - // before noticing the change in the server's connectivity. - while (!SendRpc(stub)) { - } // Retry until success. - // Send a bunch of RPCs that should succeed. - for (int i = 0; i < 10 * kNumServers; ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - } - const auto post_death = servers_[0]->service_.request_count(); - // No requests have gone to the deceased server. - EXPECT_EQ(pre_death, post_death); - // Bring the first server back up. - StartServer(0); - // Requests should start arriving at the first server either right away (if - // the server managed to start before the RR policy retried the subchannel) or - // after the subchannel retry delay otherwise (RR's subchannel retried before - // the server was fully back up). - WaitForServer(stub, 0, DEBUG_LOCATION); -} - -// If health checking is required by client but health checking service -// is not running on the server, the channel should be treated as healthy. -TEST_F(ClientLbEnd2endTest, - RoundRobinServersHealthCheckingUnimplementedTreatedAsHealthy) { - StartServers(1); // Single server - ChannelArguments args; - args.SetServiceConfigJSON( - "{\"healthCheckConfig\": " - "{\"serviceName\": \"health_check_service_name\"}}"); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator, args); - auto stub = BuildStub(channel); - response_generator.SetNextResolution({servers_[0]->port_}); - EXPECT_TRUE(WaitForChannelReady(channel.get())); - CheckRpcSendOk(stub, DEBUG_LOCATION); -} - -TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthChecking) { - EnableDefaultHealthCheckService(true); - // Start servers. - const int kNumServers = 3; - StartServers(kNumServers); - ChannelArguments args; - args.SetServiceConfigJSON( - "{\"healthCheckConfig\": " - "{\"serviceName\": \"health_check_service_name\"}}"); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator, args); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(GetServersPorts()); - // Channel should not become READY, because health checks should be failing. - gpr_log(GPR_INFO, - "*** initial state: unknown health check service name for " - "all servers"); - EXPECT_FALSE(WaitForChannelReady(channel.get(), 1)); - // Now set one of the servers to be healthy. - // The channel should become healthy and all requests should go to - // the healthy server. - gpr_log(GPR_INFO, "*** server 0 healthy"); - servers_[0]->SetServingStatus("health_check_service_name", true); - EXPECT_TRUE(WaitForChannelReady(channel.get())); - for (int i = 0; i < 10; ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - } - EXPECT_EQ(10, servers_[0]->service_.request_count()); - EXPECT_EQ(0, servers_[1]->service_.request_count()); - EXPECT_EQ(0, servers_[2]->service_.request_count()); - // Now set a second server to be healthy. - gpr_log(GPR_INFO, "*** server 2 healthy"); - servers_[2]->SetServingStatus("health_check_service_name", true); - WaitForServer(stub, 2, DEBUG_LOCATION); - for (int i = 0; i < 10; ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - } - EXPECT_EQ(5, servers_[0]->service_.request_count()); - EXPECT_EQ(0, servers_[1]->service_.request_count()); - EXPECT_EQ(5, servers_[2]->service_.request_count()); - // Now set the remaining server to be healthy. - gpr_log(GPR_INFO, "*** server 1 healthy"); - servers_[1]->SetServingStatus("health_check_service_name", true); - WaitForServer(stub, 1, DEBUG_LOCATION); - for (int i = 0; i < 9; ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - } - EXPECT_EQ(3, servers_[0]->service_.request_count()); - EXPECT_EQ(3, servers_[1]->service_.request_count()); - EXPECT_EQ(3, servers_[2]->service_.request_count()); - // Now set one server to be unhealthy again. Then wait until the - // unhealthiness has hit the client. We know that the client will see - // this when we send kNumServers requests and one of the remaining servers - // sees two of the requests. - gpr_log(GPR_INFO, "*** server 0 unhealthy"); - servers_[0]->SetServingStatus("health_check_service_name", false); - do { - ResetCounters(); - for (int i = 0; i < kNumServers; ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - } - } while (servers_[1]->service_.request_count() != 2 && - servers_[2]->service_.request_count() != 2); - // Now set the remaining two servers to be unhealthy. Make sure the - // channel leaves READY state and that RPCs fail. - gpr_log(GPR_INFO, "*** all servers unhealthy"); - servers_[1]->SetServingStatus("health_check_service_name", false); - servers_[2]->SetServingStatus("health_check_service_name", false); - EXPECT_TRUE(WaitForChannelNotReady(channel.get())); - CheckRpcSendFailure(stub); - // Clean up. - EnableDefaultHealthCheckService(false); -} - -TEST_F(ClientLbEnd2endTest, - RoundRobinWithHealthCheckingHandlesSubchannelFailure) { - EnableDefaultHealthCheckService(true); - // Start servers. - const int kNumServers = 3; - StartServers(kNumServers); - servers_[0]->SetServingStatus("health_check_service_name", true); - servers_[1]->SetServingStatus("health_check_service_name", true); - servers_[2]->SetServingStatus("health_check_service_name", true); - ChannelArguments args; - args.SetServiceConfigJSON( - "{\"healthCheckConfig\": " - "{\"serviceName\": \"health_check_service_name\"}}"); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator, args); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(GetServersPorts()); - WaitForServer(stub, 0, DEBUG_LOCATION); - // Stop server 0 and send a new resolver result to ensure that RR - // checks each subchannel's state. - servers_[0]->Shutdown(); - response_generator.SetNextResolution(GetServersPorts()); - // Send a bunch more RPCs. - for (size_t i = 0; i < 100; i++) { - SendRpc(stub); - } -} - -TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingInhibitPerChannel) { - EnableDefaultHealthCheckService(true); - // Start server. - const int kNumServers = 1; - StartServers(kNumServers); - // Create a channel with health-checking enabled. - ChannelArguments args; - args.SetServiceConfigJSON( - "{\"healthCheckConfig\": " - "{\"serviceName\": \"health_check_service_name\"}}"); - auto response_generator1 = BuildResolverResponseGenerator(); - auto channel1 = BuildChannel("round_robin", response_generator1, args); - auto stub1 = BuildStub(channel1); - std::vector<int> ports = GetServersPorts(); - response_generator1.SetNextResolution(ports); - // Create a channel with health checking enabled but inhibited. - args.SetInt(GRPC_ARG_INHIBIT_HEALTH_CHECKING, 1); - auto response_generator2 = BuildResolverResponseGenerator(); - auto channel2 = BuildChannel("round_robin", response_generator2, args); - auto stub2 = BuildStub(channel2); - response_generator2.SetNextResolution(ports); - // First channel should not become READY, because health checks should be - // failing. - EXPECT_FALSE(WaitForChannelReady(channel1.get(), 1)); - CheckRpcSendFailure(stub1); - // Second channel should be READY. - EXPECT_TRUE(WaitForChannelReady(channel2.get(), 1)); - CheckRpcSendOk(stub2, DEBUG_LOCATION); - // Enable health checks on the backend and wait for channel 1 to succeed. - servers_[0]->SetServingStatus("health_check_service_name", true); - CheckRpcSendOk(stub1, DEBUG_LOCATION, true /* wait_for_ready */); - // Check that we created only one subchannel to the backend. - EXPECT_EQ(1UL, servers_[0]->service_.clients().size()); - // Clean up. - EnableDefaultHealthCheckService(false); -} - -TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingServiceNamePerChannel) { - EnableDefaultHealthCheckService(true); - // Start server. - const int kNumServers = 1; - StartServers(kNumServers); - // Create a channel with health-checking enabled. - ChannelArguments args; - args.SetServiceConfigJSON( - "{\"healthCheckConfig\": " - "{\"serviceName\": \"health_check_service_name\"}}"); - auto response_generator1 = BuildResolverResponseGenerator(); - auto channel1 = BuildChannel("round_robin", response_generator1, args); - auto stub1 = BuildStub(channel1); - std::vector<int> ports = GetServersPorts(); - response_generator1.SetNextResolution(ports); - // Create a channel with health-checking enabled with a different - // service name. - ChannelArguments args2; - args2.SetServiceConfigJSON( - "{\"healthCheckConfig\": " - "{\"serviceName\": \"health_check_service_name2\"}}"); - auto response_generator2 = BuildResolverResponseGenerator(); - auto channel2 = BuildChannel("round_robin", response_generator2, args2); - auto stub2 = BuildStub(channel2); - response_generator2.SetNextResolution(ports); - // Allow health checks from channel 2 to succeed. - servers_[0]->SetServingStatus("health_check_service_name2", true); - // First channel should not become READY, because health checks should be - // failing. - EXPECT_FALSE(WaitForChannelReady(channel1.get(), 1)); - CheckRpcSendFailure(stub1); - // Second channel should be READY. - EXPECT_TRUE(WaitForChannelReady(channel2.get(), 1)); - CheckRpcSendOk(stub2, DEBUG_LOCATION); - // Enable health checks for channel 1 and wait for it to succeed. - servers_[0]->SetServingStatus("health_check_service_name", true); - CheckRpcSendOk(stub1, DEBUG_LOCATION, true /* wait_for_ready */); - // Check that we created only one subchannel to the backend. - EXPECT_EQ(1UL, servers_[0]->service_.clients().size()); - // Clean up. - EnableDefaultHealthCheckService(false); -} - -TEST_F(ClientLbEnd2endTest, - RoundRobinWithHealthCheckingServiceNameChangesAfterSubchannelsCreated) { - EnableDefaultHealthCheckService(true); - // Start server. - const int kNumServers = 1; - StartServers(kNumServers); - // Create a channel with health-checking enabled. - const char* kServiceConfigJson = - "{\"healthCheckConfig\": " - "{\"serviceName\": \"health_check_service_name\"}}"; - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("round_robin", response_generator); - auto stub = BuildStub(channel); - std::vector<int> ports = GetServersPorts(); - response_generator.SetNextResolution(ports, kServiceConfigJson); - servers_[0]->SetServingStatus("health_check_service_name", true); - EXPECT_TRUE(WaitForChannelReady(channel.get(), 1 /* timeout_seconds */)); - // Send an update on the channel to change it to use a health checking - // service name that is not being reported as healthy. - const char* kServiceConfigJson2 = - "{\"healthCheckConfig\": " - "{\"serviceName\": \"health_check_service_name2\"}}"; - response_generator.SetNextResolution(ports, kServiceConfigJson2); - EXPECT_TRUE(WaitForChannelNotReady(channel.get())); - // Clean up. - EnableDefaultHealthCheckService(false); -} - -TEST_F(ClientLbEnd2endTest, ChannelIdleness) { - // Start server. - const int kNumServers = 1; - StartServers(kNumServers); - // Set max idle time and build the channel. - ChannelArguments args; - args.SetInt(GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS, 1000); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = BuildChannel("", response_generator, args); - auto stub = BuildStub(channel); - // The initial channel state should be IDLE. - EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); - // After sending RPC, channel state should be READY. - response_generator.SetNextResolution(GetServersPorts()); - CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); - // After a period time not using the channel, the channel state should switch - // to IDLE. - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(1200)); - EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); - // Sending a new RPC should awake the IDLE channel. - response_generator.SetNextResolution(GetServersPorts()); - CheckRpcSendOk(stub, DEBUG_LOCATION); - EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); -} - + const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC); + const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0)); + gpr_log(GPR_DEBUG, "Waited %" PRId64 " milliseconds", waited_ms); + // We should have waited less than kInitialBackOffMs. + EXPECT_LT(waited_ms, kInitialBackOffMs); +} + +TEST_F(ClientLbEnd2endTest, + PickFirstResetConnectionBackoffNextAttemptStartsImmediately) { + ChannelArguments args; + constexpr int kInitialBackOffMs = 1000; + args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); + const std::vector<int> ports = {5106}; // {grpc_pick_unused_port_or_die()}; + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("pick_first", response_generator, args); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(ports); + // Wait for connect, which should fail ~immediately, because the server + // is not up. + gpr_log(GPR_INFO, "=== INITIAL CONNECTION ATTEMPT"); + EXPECT_FALSE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); + // Reset connection backoff. + // Note that the time at which the third attempt will be started is + // actually computed at this point, so we record the start time here. + gpr_log(GPR_INFO, "=== RESETTING BACKOFF"); + const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); + experimental::ChannelResetConnectionBackoff(channel.get()); + // Trigger a second connection attempt. This should also fail + // ~immediately, but the retry should be scheduled for + // kInitialBackOffMs instead of applying the multiplier. + gpr_log(GPR_INFO, "=== POLLING FOR SECOND CONNECTION ATTEMPT"); + EXPECT_FALSE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); + // Bring up a server on the chosen port. + gpr_log(GPR_INFO, "=== STARTING BACKEND"); + StartServers(1, ports); + // Wait for connect. Should happen within kInitialBackOffMs. + // Give an extra 100ms to account for the time spent in the second and + // third connection attempts themselves (since what we really want to + // measure is the time between the two). As long as this is less than + // the 1.6x increase we would see if the backoff state was not reset + // properly, the test is still proving that the backoff was reset. + constexpr int kWaitMs = kInitialBackOffMs + 100; + gpr_log(GPR_INFO, "=== POLLING FOR THIRD CONNECTION ATTEMPT"); + EXPECT_TRUE(channel->WaitForConnected( + grpc_timeout_milliseconds_to_deadline(kWaitMs))); + const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC); + const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0)); + gpr_log(GPR_DEBUG, "Waited %" PRId64 " milliseconds", waited_ms); + EXPECT_LT(waited_ms, kWaitMs); +} + +TEST_F(ClientLbEnd2endTest, PickFirstUpdates) { + // Start servers and send one RPC per server. + const int kNumServers = 3; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("pick_first", response_generator); + auto stub = BuildStub(channel); + + std::vector<int> ports; + + // Perform one RPC against the first server. + ports.emplace_back(servers_[0]->port_); + response_generator.SetNextResolution(ports); + gpr_log(GPR_INFO, "****** SET [0] *******"); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(servers_[0]->service_.request_count(), 1); + + // An empty update will result in the channel going into TRANSIENT_FAILURE. + ports.clear(); + response_generator.SetNextResolution(ports); + gpr_log(GPR_INFO, "****** SET none *******"); + grpc_connectivity_state channel_state; + do { + channel_state = channel->GetState(true /* try to connect */); + } while (channel_state == GRPC_CHANNEL_READY); + ASSERT_NE(channel_state, GRPC_CHANNEL_READY); + servers_[0]->service_.ResetCounters(); + + // Next update introduces servers_[1], making the channel recover. + ports.clear(); + ports.emplace_back(servers_[1]->port_); + response_generator.SetNextResolution(ports); + gpr_log(GPR_INFO, "****** SET [1] *******"); + WaitForServer(stub, 1, DEBUG_LOCATION); + EXPECT_EQ(servers_[0]->service_.request_count(), 0); + + // And again for servers_[2] + ports.clear(); + ports.emplace_back(servers_[2]->port_); + response_generator.SetNextResolution(ports); + gpr_log(GPR_INFO, "****** SET [2] *******"); + WaitForServer(stub, 2, DEBUG_LOCATION); + EXPECT_EQ(servers_[0]->service_.request_count(), 0); + EXPECT_EQ(servers_[1]->service_.request_count(), 0); + + // Check LB policy name for the channel. + EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName()); +} + +TEST_F(ClientLbEnd2endTest, PickFirstUpdateSuperset) { + // Start servers and send one RPC per server. + const int kNumServers = 3; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("pick_first", response_generator); + auto stub = BuildStub(channel); + + std::vector<int> ports; + + // Perform one RPC against the first server. + ports.emplace_back(servers_[0]->port_); + response_generator.SetNextResolution(ports); + gpr_log(GPR_INFO, "****** SET [0] *******"); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(servers_[0]->service_.request_count(), 1); + servers_[0]->service_.ResetCounters(); + + // Send and superset update + ports.clear(); + ports.emplace_back(servers_[1]->port_); + ports.emplace_back(servers_[0]->port_); + response_generator.SetNextResolution(ports); + gpr_log(GPR_INFO, "****** SET superset *******"); + CheckRpcSendOk(stub, DEBUG_LOCATION); + // We stick to the previously connected server. + WaitForServer(stub, 0, DEBUG_LOCATION); + EXPECT_EQ(0, servers_[1]->service_.request_count()); + + // Check LB policy name for the channel. + EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName()); +} + +TEST_F(ClientLbEnd2endTest, PickFirstGlobalSubchannelPool) { + // Start one server. + const int kNumServers = 1; + StartServers(kNumServers); + std::vector<int> ports = GetServersPorts(); + // Create two channels that (by default) use the global subchannel pool. + auto response_generator1 = BuildResolverResponseGenerator(); + auto channel1 = BuildChannel("pick_first", response_generator1); + auto stub1 = BuildStub(channel1); + response_generator1.SetNextResolution(ports); + auto response_generator2 = BuildResolverResponseGenerator(); + auto channel2 = BuildChannel("pick_first", response_generator2); + auto stub2 = BuildStub(channel2); + response_generator2.SetNextResolution(ports); + WaitForServer(stub1, 0, DEBUG_LOCATION); + // Send one RPC on each channel. + CheckRpcSendOk(stub1, DEBUG_LOCATION); + CheckRpcSendOk(stub2, DEBUG_LOCATION); + // The server receives two requests. + EXPECT_EQ(2, servers_[0]->service_.request_count()); + // The two requests are from the same client port, because the two channels + // share subchannels via the global subchannel pool. + EXPECT_EQ(1UL, servers_[0]->service_.clients().size()); +} + +TEST_F(ClientLbEnd2endTest, PickFirstLocalSubchannelPool) { + // Start one server. + const int kNumServers = 1; + StartServers(kNumServers); + std::vector<int> ports = GetServersPorts(); + // Create two channels that use local subchannel pool. + ChannelArguments args; + args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1); + auto response_generator1 = BuildResolverResponseGenerator(); + auto channel1 = BuildChannel("pick_first", response_generator1, args); + auto stub1 = BuildStub(channel1); + response_generator1.SetNextResolution(ports); + auto response_generator2 = BuildResolverResponseGenerator(); + auto channel2 = BuildChannel("pick_first", response_generator2, args); + auto stub2 = BuildStub(channel2); + response_generator2.SetNextResolution(ports); + WaitForServer(stub1, 0, DEBUG_LOCATION); + // Send one RPC on each channel. + CheckRpcSendOk(stub1, DEBUG_LOCATION); + CheckRpcSendOk(stub2, DEBUG_LOCATION); + // The server receives two requests. + EXPECT_EQ(2, servers_[0]->service_.request_count()); + // The two requests are from two client ports, because the two channels didn't + // share subchannels with each other. + EXPECT_EQ(2UL, servers_[0]->service_.clients().size()); +} + +TEST_F(ClientLbEnd2endTest, PickFirstManyUpdates) { + const int kNumUpdates = 1000; + const int kNumServers = 3; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("pick_first", response_generator); + auto stub = BuildStub(channel); + std::vector<int> ports = GetServersPorts(); + for (size_t i = 0; i < kNumUpdates; ++i) { + std::shuffle(ports.begin(), ports.end(), + std::mt19937(std::random_device()())); + response_generator.SetNextResolution(ports); + // We should re-enter core at the end of the loop to give the resolution + // setting closure a chance to run. + if ((i + 1) % 10 == 0) CheckRpcSendOk(stub, DEBUG_LOCATION); + } + // Check LB policy name for the channel. + EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName()); +} + +TEST_F(ClientLbEnd2endTest, PickFirstReresolutionNoSelected) { + // Prepare the ports for up servers and down servers. + const int kNumServers = 3; + const int kNumAliveServers = 1; + StartServers(kNumAliveServers); + std::vector<int> alive_ports, dead_ports; + for (size_t i = 0; i < kNumServers; ++i) { + if (i < kNumAliveServers) { + alive_ports.emplace_back(servers_[i]->port_); + } else { + dead_ports.emplace_back(5107 + i); + // dead_ports.emplace_back(grpc_pick_unused_port_or_die()); + } + } + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("pick_first", response_generator); + auto stub = BuildStub(channel); + // The initial resolution only contains dead ports. There won't be any + // selected subchannel. Re-resolution will return the same result. + response_generator.SetNextResolution(dead_ports); + gpr_log(GPR_INFO, "****** INITIAL RESOLUTION SET *******"); + for (size_t i = 0; i < 10; ++i) CheckRpcSendFailure(stub); + // Set a re-resolution result that contains reachable ports, so that the + // pick_first LB policy can recover soon. + response_generator.SetNextResolutionUponError(alive_ports); + gpr_log(GPR_INFO, "****** RE-RESOLUTION SET *******"); + WaitForServer(stub, 0, DEBUG_LOCATION, true /* ignore_failure */); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(servers_[0]->service_.request_count(), 1); + // Check LB policy name for the channel. + EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName()); +} + +TEST_F(ClientLbEnd2endTest, PickFirstReconnectWithoutNewResolverResult) { + std::vector<int> ports = {5110}; // {grpc_pick_unused_port_or_die()}; + StartServers(1, ports); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("pick_first", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(ports); + gpr_log(GPR_INFO, "****** INITIAL CONNECTION *******"); + WaitForServer(stub, 0, DEBUG_LOCATION); + gpr_log(GPR_INFO, "****** STOPPING SERVER ******"); + servers_[0]->Shutdown(); + EXPECT_TRUE(WaitForChannelNotReady(channel.get())); + gpr_log(GPR_INFO, "****** RESTARTING SERVER ******"); + StartServers(1, ports); + WaitForServer(stub, 0, DEBUG_LOCATION); +} + +TEST_F(ClientLbEnd2endTest, + PickFirstReconnectWithoutNewResolverResultStartsFromTopOfList) { + std::vector<int> ports = {5111, // grpc_pick_unused_port_or_die(), + 5112}; // grpc_pick_unused_port_or_die()}; + CreateServers(2, ports); + StartServer(1); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("pick_first", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(ports); + gpr_log(GPR_INFO, "****** INITIAL CONNECTION *******"); + WaitForServer(stub, 1, DEBUG_LOCATION); + gpr_log(GPR_INFO, "****** STOPPING SERVER ******"); + servers_[1]->Shutdown(); + EXPECT_TRUE(WaitForChannelNotReady(channel.get())); + gpr_log(GPR_INFO, "****** STARTING BOTH SERVERS ******"); + StartServers(2, ports); + WaitForServer(stub, 0, DEBUG_LOCATION); +} + +TEST_F(ClientLbEnd2endTest, PickFirstCheckStateBeforeStartWatch) { + std::vector<int> ports = {5113}; // {grpc_pick_unused_port_or_die()}; + StartServers(1, ports); + auto response_generator = BuildResolverResponseGenerator(); + auto channel_1 = BuildChannel("pick_first", response_generator); + auto stub_1 = BuildStub(channel_1); + response_generator.SetNextResolution(ports); + gpr_log(GPR_INFO, "****** RESOLUTION SET FOR CHANNEL 1 *******"); + WaitForServer(stub_1, 0, DEBUG_LOCATION); + gpr_log(GPR_INFO, "****** CHANNEL 1 CONNECTED *******"); + servers_[0]->Shutdown(); + // Channel 1 will receive a re-resolution containing the same server. It will + // create a new subchannel and hold a ref to it. + StartServers(1, ports); + gpr_log(GPR_INFO, "****** SERVER RESTARTED *******"); + auto response_generator_2 = BuildResolverResponseGenerator(); + auto channel_2 = BuildChannel("pick_first", response_generator_2); + auto stub_2 = BuildStub(channel_2); + response_generator_2.SetNextResolution(ports); + gpr_log(GPR_INFO, "****** RESOLUTION SET FOR CHANNEL 2 *******"); + WaitForServer(stub_2, 0, DEBUG_LOCATION, true); + gpr_log(GPR_INFO, "****** CHANNEL 2 CONNECTED *******"); + servers_[0]->Shutdown(); + // Wait until the disconnection has triggered the connectivity notification. + // Otherwise, the subchannel may be picked for next call but will fail soon. + EXPECT_TRUE(WaitForChannelNotReady(channel_2.get())); + // Channel 2 will also receive a re-resolution containing the same server. + // Both channels will ref the same subchannel that failed. + StartServers(1, ports); + gpr_log(GPR_INFO, "****** SERVER RESTARTED AGAIN *******"); + gpr_log(GPR_INFO, "****** CHANNEL 2 STARTING A CALL *******"); + // The first call after the server restart will succeed. + CheckRpcSendOk(stub_2, DEBUG_LOCATION); + gpr_log(GPR_INFO, "****** CHANNEL 2 FINISHED A CALL *******"); + // Check LB policy name for the channel. + EXPECT_EQ("pick_first", channel_1->GetLoadBalancingPolicyName()); + // Check LB policy name for the channel. + EXPECT_EQ("pick_first", channel_2->GetLoadBalancingPolicyName()); +} + +TEST_F(ClientLbEnd2endTest, PickFirstIdleOnDisconnect) { + // Start server, send RPC, and make sure channel is READY. + const int kNumServers = 1; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = + BuildChannel("", response_generator); // pick_first is the default. + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); + // Stop server. Channel should go into state IDLE. + response_generator.SetFailureOnReresolution(); + servers_[0]->Shutdown(); + EXPECT_TRUE(WaitForChannelNotReady(channel.get())); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); + servers_.clear(); +} + +TEST_F(ClientLbEnd2endTest, PickFirstPendingUpdateAndSelectedSubchannelFails) { + auto response_generator = BuildResolverResponseGenerator(); + auto channel = + BuildChannel("", response_generator); // pick_first is the default. + auto stub = BuildStub(channel); + // Create a number of servers, but only start 1 of them. + CreateServers(10); + StartServer(0); + // Initially resolve to first server and make sure it connects. + gpr_log(GPR_INFO, "Phase 1: Connect to first server."); + response_generator.SetNextResolution({servers_[0]->port_}); + CheckRpcSendOk(stub, DEBUG_LOCATION, true /* wait_for_ready */); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); + // Send a resolution update with the remaining servers, none of which are + // running yet, so the update will stay pending. Note that it's important + // to have multiple servers here, or else the test will be flaky; with only + // one server, the pending subchannel list has already gone into + // TRANSIENT_FAILURE due to hitting the end of the list by the time we + // check the state. + gpr_log(GPR_INFO, + "Phase 2: Resolver update pointing to remaining " + "(not started) servers."); + response_generator.SetNextResolution(GetServersPorts(1 /* start_index */)); + // RPCs will continue to be sent to the first server. + CheckRpcSendOk(stub, DEBUG_LOCATION); + // Now stop the first server, so that the current subchannel list + // fails. This should cause us to immediately swap over to the + // pending list, even though it's not yet connected. The state should + // be set to CONNECTING, since that's what the pending subchannel list + // was doing when we swapped over. + gpr_log(GPR_INFO, "Phase 3: Stopping first server."); + servers_[0]->Shutdown(); + WaitForChannelNotReady(channel.get()); + // TODO(roth): This should always return CONNECTING, but it's flaky + // between that and TRANSIENT_FAILURE. I suspect that this problem + // will go away once we move the backoff code out of the subchannel + // and into the LB policies. + EXPECT_THAT(channel->GetState(false), + ::testing::AnyOf(GRPC_CHANNEL_CONNECTING, + GRPC_CHANNEL_TRANSIENT_FAILURE)); + // Now start the second server. + gpr_log(GPR_INFO, "Phase 4: Starting second server."); + StartServer(1); + // The channel should go to READY state and RPCs should go to the + // second server. + WaitForChannelReady(channel.get()); + WaitForServer(stub, 1, DEBUG_LOCATION, true /* ignore_failure */); +} + +TEST_F(ClientLbEnd2endTest, PickFirstStaysIdleUponEmptyUpdate) { + // Start server, send RPC, and make sure channel is READY. + const int kNumServers = 1; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = + BuildChannel("", response_generator); // pick_first is the default. + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); + // Stop server. Channel should go into state IDLE. + servers_[0]->Shutdown(); + EXPECT_TRUE(WaitForChannelNotReady(channel.get())); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); + // Now send resolver update that includes no addresses. Channel + // should stay in state IDLE. + response_generator.SetNextResolution({}); + EXPECT_FALSE(channel->WaitForStateChange( + GRPC_CHANNEL_IDLE, grpc_timeout_seconds_to_deadline(3))); + // Now bring the backend back up and send a non-empty resolver update, + // and then try to send an RPC. Channel should go back into state READY. + StartServer(0); + response_generator.SetNextResolution(GetServersPorts()); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); +} + +TEST_F(ClientLbEnd2endTest, RoundRobin) { + // Start servers and send one RPC per server. + const int kNumServers = 3; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + // Wait until all backends are ready. + do { + CheckRpcSendOk(stub, DEBUG_LOCATION); + } while (!SeenAllServers()); + ResetCounters(); + // "Sync" to the end of the list. Next sequence of picks will start at the + // first server (index 0). + WaitForServer(stub, servers_.size() - 1, DEBUG_LOCATION); + std::vector<int> connection_order; + for (size_t i = 0; i < servers_.size(); ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + UpdateConnectionOrder(servers_, &connection_order); + } + // Backends should be iterated over in the order in which the addresses were + // given. + const auto expected = std::vector<int>{0, 1, 2}; + EXPECT_EQ(expected, connection_order); + // Check LB policy name for the channel. + EXPECT_EQ("round_robin", channel->GetLoadBalancingPolicyName()); +} + +TEST_F(ClientLbEnd2endTest, RoundRobinProcessPending) { + StartServers(1); // Single server + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution({servers_[0]->port_}); + WaitForServer(stub, 0, DEBUG_LOCATION); + // Create a new channel and its corresponding RR LB policy, which will pick + // the subchannels in READY state from the previous RPC against the same + // target (even if it happened over a different channel, because subchannels + // are globally reused). Progress should happen without any transition from + // this READY state. + auto second_response_generator = BuildResolverResponseGenerator(); + auto second_channel = BuildChannel("round_robin", second_response_generator); + auto second_stub = BuildStub(second_channel); + second_response_generator.SetNextResolution({servers_[0]->port_}); + CheckRpcSendOk(second_stub, DEBUG_LOCATION); +} + +TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) { + // Start servers and send one RPC per server. + const int kNumServers = 3; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator); + auto stub = BuildStub(channel); + std::vector<int> ports; + // Start with a single server. + gpr_log(GPR_INFO, "*** FIRST BACKEND ***"); + ports.emplace_back(servers_[0]->port_); + response_generator.SetNextResolution(ports); + WaitForServer(stub, 0, DEBUG_LOCATION); + // Send RPCs. They should all go servers_[0] + for (size_t i = 0; i < 10; ++i) CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(10, servers_[0]->service_.request_count()); + EXPECT_EQ(0, servers_[1]->service_.request_count()); + EXPECT_EQ(0, servers_[2]->service_.request_count()); + servers_[0]->service_.ResetCounters(); + // And now for the second server. + gpr_log(GPR_INFO, "*** SECOND BACKEND ***"); + ports.clear(); + ports.emplace_back(servers_[1]->port_); + response_generator.SetNextResolution(ports); + // Wait until update has been processed, as signaled by the second backend + // receiving a request. + EXPECT_EQ(0, servers_[1]->service_.request_count()); + WaitForServer(stub, 1, DEBUG_LOCATION); + for (size_t i = 0; i < 10; ++i) CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(0, servers_[0]->service_.request_count()); + EXPECT_EQ(10, servers_[1]->service_.request_count()); + EXPECT_EQ(0, servers_[2]->service_.request_count()); + servers_[1]->service_.ResetCounters(); + // ... and for the last server. + gpr_log(GPR_INFO, "*** THIRD BACKEND ***"); + ports.clear(); + ports.emplace_back(servers_[2]->port_); + response_generator.SetNextResolution(ports); + WaitForServer(stub, 2, DEBUG_LOCATION); + for (size_t i = 0; i < 10; ++i) CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(0, servers_[0]->service_.request_count()); + EXPECT_EQ(0, servers_[1]->service_.request_count()); + EXPECT_EQ(10, servers_[2]->service_.request_count()); + servers_[2]->service_.ResetCounters(); + // Back to all servers. + gpr_log(GPR_INFO, "*** ALL BACKENDS ***"); + ports.clear(); + ports.emplace_back(servers_[0]->port_); + ports.emplace_back(servers_[1]->port_); + ports.emplace_back(servers_[2]->port_); + response_generator.SetNextResolution(ports); + WaitForServer(stub, 0, DEBUG_LOCATION); + WaitForServer(stub, 1, DEBUG_LOCATION); + WaitForServer(stub, 2, DEBUG_LOCATION); + // Send three RPCs, one per server. + for (size_t i = 0; i < 3; ++i) CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(1, servers_[0]->service_.request_count()); + EXPECT_EQ(1, servers_[1]->service_.request_count()); + EXPECT_EQ(1, servers_[2]->service_.request_count()); + // An empty update will result in the channel going into TRANSIENT_FAILURE. + gpr_log(GPR_INFO, "*** NO BACKENDS ***"); + ports.clear(); + response_generator.SetNextResolution(ports); + grpc_connectivity_state channel_state; + do { + channel_state = channel->GetState(true /* try to connect */); + } while (channel_state == GRPC_CHANNEL_READY); + ASSERT_NE(channel_state, GRPC_CHANNEL_READY); + servers_[0]->service_.ResetCounters(); + // Next update introduces servers_[1], making the channel recover. + gpr_log(GPR_INFO, "*** BACK TO SECOND BACKEND ***"); + ports.clear(); + ports.emplace_back(servers_[1]->port_); + response_generator.SetNextResolution(ports); + WaitForServer(stub, 1, DEBUG_LOCATION); + channel_state = channel->GetState(false /* try to connect */); + ASSERT_EQ(channel_state, GRPC_CHANNEL_READY); + // Check LB policy name for the channel. + EXPECT_EQ("round_robin", channel->GetLoadBalancingPolicyName()); +} + +TEST_F(ClientLbEnd2endTest, RoundRobinUpdateInError) { + const int kNumServers = 3; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator); + auto stub = BuildStub(channel); + std::vector<int> ports; + // Start with a single server. + ports.emplace_back(servers_[0]->port_); + response_generator.SetNextResolution(ports); + WaitForServer(stub, 0, DEBUG_LOCATION); + // Send RPCs. They should all go to servers_[0] + for (size_t i = 0; i < 10; ++i) SendRpc(stub); + EXPECT_EQ(10, servers_[0]->service_.request_count()); + EXPECT_EQ(0, servers_[1]->service_.request_count()); + EXPECT_EQ(0, servers_[2]->service_.request_count()); + servers_[0]->service_.ResetCounters(); + // Shutdown one of the servers to be sent in the update. + servers_[1]->Shutdown(); + ports.emplace_back(servers_[1]->port_); + ports.emplace_back(servers_[2]->port_); + response_generator.SetNextResolution(ports); + WaitForServer(stub, 0, DEBUG_LOCATION); + WaitForServer(stub, 2, DEBUG_LOCATION); + // Send three RPCs, one per server. + for (size_t i = 0; i < kNumServers; ++i) SendRpc(stub); + // The server in shutdown shouldn't receive any. + EXPECT_EQ(0, servers_[1]->service_.request_count()); +} + +TEST_F(ClientLbEnd2endTest, RoundRobinManyUpdates) { + // Start servers and send one RPC per server. + const int kNumServers = 3; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator); + auto stub = BuildStub(channel); + std::vector<int> ports = GetServersPorts(); + for (size_t i = 0; i < 1000; ++i) { + std::shuffle(ports.begin(), ports.end(), + std::mt19937(std::random_device()())); + response_generator.SetNextResolution(ports); + if (i % 10 == 0) CheckRpcSendOk(stub, DEBUG_LOCATION); + } + // Check LB policy name for the channel. + EXPECT_EQ("round_robin", channel->GetLoadBalancingPolicyName()); +} + +TEST_F(ClientLbEnd2endTest, RoundRobinConcurrentUpdates) { + // TODO(dgq): replicate the way internal testing exercises the concurrent + // update provisions of RR. +} + +TEST_F(ClientLbEnd2endTest, RoundRobinReresolve) { + // Start servers and send one RPC per server. + const int kNumServers = 3; + std::vector<int> first_ports; + std::vector<int> second_ports; + first_ports.reserve(kNumServers); + for (int i = 0; i < kNumServers; ++i) { + // first_ports.push_back(grpc_pick_unused_port_or_die()); + first_ports.push_back(5114 + i); + } + second_ports.reserve(kNumServers); + for (int i = 0; i < kNumServers; ++i) { + // second_ports.push_back(grpc_pick_unused_port_or_die()); + second_ports.push_back(5117 + i); + } + StartServers(kNumServers, first_ports); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(first_ports); + // Send a number of RPCs, which succeed. + for (size_t i = 0; i < 100; ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + } + // Kill all servers + gpr_log(GPR_INFO, "****** ABOUT TO KILL SERVERS *******"); + for (size_t i = 0; i < servers_.size(); ++i) { + servers_[i]->Shutdown(); + } + gpr_log(GPR_INFO, "****** SERVERS KILLED *******"); + gpr_log(GPR_INFO, "****** SENDING DOOMED REQUESTS *******"); + // Client requests should fail. Send enough to tickle all subchannels. + for (size_t i = 0; i < servers_.size(); ++i) CheckRpcSendFailure(stub); + gpr_log(GPR_INFO, "****** DOOMED REQUESTS SENT *******"); + // Bring servers back up on a different set of ports. We need to do this to be + // sure that the eventual success is *not* due to subchannel reconnection + // attempts and that an actual re-resolution has happened as a result of the + // RR policy going into transient failure when all its subchannels become + // unavailable (in transient failure as well). + gpr_log(GPR_INFO, "****** RESTARTING SERVERS *******"); + StartServers(kNumServers, second_ports); + // Don't notify of the update. Wait for the LB policy's re-resolution to + // "pull" the new ports. + response_generator.SetNextResolutionUponError(second_ports); + gpr_log(GPR_INFO, "****** SERVERS RESTARTED *******"); + gpr_log(GPR_INFO, "****** SENDING REQUEST TO SUCCEED *******"); + // Client request should eventually (but still fairly soon) succeed. + const gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + while (gpr_time_cmp(deadline, now) > 0) { + if (SendRpc(stub)) break; + now = gpr_now(GPR_CLOCK_MONOTONIC); + } + ASSERT_GT(gpr_time_cmp(deadline, now), 0); +} + +TEST_F(ClientLbEnd2endTest, RoundRobinTransientFailure) { + // Start servers and create channel. Channel should go to READY state. + const int kNumServers = 3; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + EXPECT_TRUE(WaitForChannelReady(channel.get())); + // Now kill the servers. The channel should transition to TRANSIENT_FAILURE. + // TODO(roth): This test should ideally check that even when the + // subchannels are in state CONNECTING for an extended period of time, + // we will still report TRANSIENT_FAILURE. Unfortunately, we don't + // currently have a good way to get a subchannel to report CONNECTING + // for a long period of time, since the servers in this test framework + // are on the loopback interface, which will immediately return a + // "Connection refused" error, so the subchannels will only be in + // CONNECTING state very briefly. When we have time, see if we can + // find a way to fix this. + for (size_t i = 0; i < servers_.size(); ++i) { + servers_[i]->Shutdown(); + } + auto predicate = [](grpc_connectivity_state state) { + return state == GRPC_CHANNEL_TRANSIENT_FAILURE; + }; + EXPECT_TRUE(WaitForChannelState(channel.get(), predicate)); +} + +TEST_F(ClientLbEnd2endTest, RoundRobinTransientFailureAtStartup) { + // Create channel and return servers that don't exist. Channel should + // quickly transition into TRANSIENT_FAILURE. + // TODO(roth): This test should ideally check that even when the + // subchannels are in state CONNECTING for an extended period of time, + // we will still report TRANSIENT_FAILURE. Unfortunately, we don't + // currently have a good way to get a subchannel to report CONNECTING + // for a long period of time, since the servers in this test framework + // are on the loopback interface, which will immediately return a + // "Connection refused" error, so the subchannels will only be in + // CONNECTING state very briefly. When we have time, see if we can + // find a way to fix this. + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution({ + grpc_pick_unused_port_or_die(), + grpc_pick_unused_port_or_die(), + grpc_pick_unused_port_or_die(), + }); + for (size_t i = 0; i < servers_.size(); ++i) { + servers_[i]->Shutdown(); + } + auto predicate = [](grpc_connectivity_state state) { + return state == GRPC_CHANNEL_TRANSIENT_FAILURE; + }; + EXPECT_TRUE(WaitForChannelState(channel.get(), predicate, true)); +} + +TEST_F(ClientLbEnd2endTest, RoundRobinSingleReconnect) { + const int kNumServers = 3; + StartServers(kNumServers); + const auto ports = GetServersPorts(); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(ports); + for (size_t i = 0; i < kNumServers; ++i) { + WaitForServer(stub, i, DEBUG_LOCATION); + } + for (size_t i = 0; i < servers_.size(); ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(1, servers_[i]->service_.request_count()) << "for backend #" << i; + } + // One request should have gone to each server. + for (size_t i = 0; i < servers_.size(); ++i) { + EXPECT_EQ(1, servers_[i]->service_.request_count()); + } + const auto pre_death = servers_[0]->service_.request_count(); + // Kill the first server. + servers_[0]->Shutdown(); + // Client request still succeed. May need retrying if RR had returned a pick + // before noticing the change in the server's connectivity. + while (!SendRpc(stub)) { + } // Retry until success. + // Send a bunch of RPCs that should succeed. + for (int i = 0; i < 10 * kNumServers; ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + } + const auto post_death = servers_[0]->service_.request_count(); + // No requests have gone to the deceased server. + EXPECT_EQ(pre_death, post_death); + // Bring the first server back up. + StartServer(0); + // Requests should start arriving at the first server either right away (if + // the server managed to start before the RR policy retried the subchannel) or + // after the subchannel retry delay otherwise (RR's subchannel retried before + // the server was fully back up). + WaitForServer(stub, 0, DEBUG_LOCATION); +} + +// If health checking is required by client but health checking service +// is not running on the server, the channel should be treated as healthy. +TEST_F(ClientLbEnd2endTest, + RoundRobinServersHealthCheckingUnimplementedTreatedAsHealthy) { + StartServers(1); // Single server + ChannelArguments args; + args.SetServiceConfigJSON( + "{\"healthCheckConfig\": " + "{\"serviceName\": \"health_check_service_name\"}}"); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator, args); + auto stub = BuildStub(channel); + response_generator.SetNextResolution({servers_[0]->port_}); + EXPECT_TRUE(WaitForChannelReady(channel.get())); + CheckRpcSendOk(stub, DEBUG_LOCATION); +} + +TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthChecking) { + EnableDefaultHealthCheckService(true); + // Start servers. + const int kNumServers = 3; + StartServers(kNumServers); + ChannelArguments args; + args.SetServiceConfigJSON( + "{\"healthCheckConfig\": " + "{\"serviceName\": \"health_check_service_name\"}}"); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator, args); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + // Channel should not become READY, because health checks should be failing. + gpr_log(GPR_INFO, + "*** initial state: unknown health check service name for " + "all servers"); + EXPECT_FALSE(WaitForChannelReady(channel.get(), 1)); + // Now set one of the servers to be healthy. + // The channel should become healthy and all requests should go to + // the healthy server. + gpr_log(GPR_INFO, "*** server 0 healthy"); + servers_[0]->SetServingStatus("health_check_service_name", true); + EXPECT_TRUE(WaitForChannelReady(channel.get())); + for (int i = 0; i < 10; ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + } + EXPECT_EQ(10, servers_[0]->service_.request_count()); + EXPECT_EQ(0, servers_[1]->service_.request_count()); + EXPECT_EQ(0, servers_[2]->service_.request_count()); + // Now set a second server to be healthy. + gpr_log(GPR_INFO, "*** server 2 healthy"); + servers_[2]->SetServingStatus("health_check_service_name", true); + WaitForServer(stub, 2, DEBUG_LOCATION); + for (int i = 0; i < 10; ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + } + EXPECT_EQ(5, servers_[0]->service_.request_count()); + EXPECT_EQ(0, servers_[1]->service_.request_count()); + EXPECT_EQ(5, servers_[2]->service_.request_count()); + // Now set the remaining server to be healthy. + gpr_log(GPR_INFO, "*** server 1 healthy"); + servers_[1]->SetServingStatus("health_check_service_name", true); + WaitForServer(stub, 1, DEBUG_LOCATION); + for (int i = 0; i < 9; ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + } + EXPECT_EQ(3, servers_[0]->service_.request_count()); + EXPECT_EQ(3, servers_[1]->service_.request_count()); + EXPECT_EQ(3, servers_[2]->service_.request_count()); + // Now set one server to be unhealthy again. Then wait until the + // unhealthiness has hit the client. We know that the client will see + // this when we send kNumServers requests and one of the remaining servers + // sees two of the requests. + gpr_log(GPR_INFO, "*** server 0 unhealthy"); + servers_[0]->SetServingStatus("health_check_service_name", false); + do { + ResetCounters(); + for (int i = 0; i < kNumServers; ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + } + } while (servers_[1]->service_.request_count() != 2 && + servers_[2]->service_.request_count() != 2); + // Now set the remaining two servers to be unhealthy. Make sure the + // channel leaves READY state and that RPCs fail. + gpr_log(GPR_INFO, "*** all servers unhealthy"); + servers_[1]->SetServingStatus("health_check_service_name", false); + servers_[2]->SetServingStatus("health_check_service_name", false); + EXPECT_TRUE(WaitForChannelNotReady(channel.get())); + CheckRpcSendFailure(stub); + // Clean up. + EnableDefaultHealthCheckService(false); +} + +TEST_F(ClientLbEnd2endTest, + RoundRobinWithHealthCheckingHandlesSubchannelFailure) { + EnableDefaultHealthCheckService(true); + // Start servers. + const int kNumServers = 3; + StartServers(kNumServers); + servers_[0]->SetServingStatus("health_check_service_name", true); + servers_[1]->SetServingStatus("health_check_service_name", true); + servers_[2]->SetServingStatus("health_check_service_name", true); + ChannelArguments args; + args.SetServiceConfigJSON( + "{\"healthCheckConfig\": " + "{\"serviceName\": \"health_check_service_name\"}}"); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator, args); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + WaitForServer(stub, 0, DEBUG_LOCATION); + // Stop server 0 and send a new resolver result to ensure that RR + // checks each subchannel's state. + servers_[0]->Shutdown(); + response_generator.SetNextResolution(GetServersPorts()); + // Send a bunch more RPCs. + for (size_t i = 0; i < 100; i++) { + SendRpc(stub); + } +} + +TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingInhibitPerChannel) { + EnableDefaultHealthCheckService(true); + // Start server. + const int kNumServers = 1; + StartServers(kNumServers); + // Create a channel with health-checking enabled. + ChannelArguments args; + args.SetServiceConfigJSON( + "{\"healthCheckConfig\": " + "{\"serviceName\": \"health_check_service_name\"}}"); + auto response_generator1 = BuildResolverResponseGenerator(); + auto channel1 = BuildChannel("round_robin", response_generator1, args); + auto stub1 = BuildStub(channel1); + std::vector<int> ports = GetServersPorts(); + response_generator1.SetNextResolution(ports); + // Create a channel with health checking enabled but inhibited. + args.SetInt(GRPC_ARG_INHIBIT_HEALTH_CHECKING, 1); + auto response_generator2 = BuildResolverResponseGenerator(); + auto channel2 = BuildChannel("round_robin", response_generator2, args); + auto stub2 = BuildStub(channel2); + response_generator2.SetNextResolution(ports); + // First channel should not become READY, because health checks should be + // failing. + EXPECT_FALSE(WaitForChannelReady(channel1.get(), 1)); + CheckRpcSendFailure(stub1); + // Second channel should be READY. + EXPECT_TRUE(WaitForChannelReady(channel2.get(), 1)); + CheckRpcSendOk(stub2, DEBUG_LOCATION); + // Enable health checks on the backend and wait for channel 1 to succeed. + servers_[0]->SetServingStatus("health_check_service_name", true); + CheckRpcSendOk(stub1, DEBUG_LOCATION, true /* wait_for_ready */); + // Check that we created only one subchannel to the backend. + EXPECT_EQ(1UL, servers_[0]->service_.clients().size()); + // Clean up. + EnableDefaultHealthCheckService(false); +} + +TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingServiceNamePerChannel) { + EnableDefaultHealthCheckService(true); + // Start server. + const int kNumServers = 1; + StartServers(kNumServers); + // Create a channel with health-checking enabled. + ChannelArguments args; + args.SetServiceConfigJSON( + "{\"healthCheckConfig\": " + "{\"serviceName\": \"health_check_service_name\"}}"); + auto response_generator1 = BuildResolverResponseGenerator(); + auto channel1 = BuildChannel("round_robin", response_generator1, args); + auto stub1 = BuildStub(channel1); + std::vector<int> ports = GetServersPorts(); + response_generator1.SetNextResolution(ports); + // Create a channel with health-checking enabled with a different + // service name. + ChannelArguments args2; + args2.SetServiceConfigJSON( + "{\"healthCheckConfig\": " + "{\"serviceName\": \"health_check_service_name2\"}}"); + auto response_generator2 = BuildResolverResponseGenerator(); + auto channel2 = BuildChannel("round_robin", response_generator2, args2); + auto stub2 = BuildStub(channel2); + response_generator2.SetNextResolution(ports); + // Allow health checks from channel 2 to succeed. + servers_[0]->SetServingStatus("health_check_service_name2", true); + // First channel should not become READY, because health checks should be + // failing. + EXPECT_FALSE(WaitForChannelReady(channel1.get(), 1)); + CheckRpcSendFailure(stub1); + // Second channel should be READY. + EXPECT_TRUE(WaitForChannelReady(channel2.get(), 1)); + CheckRpcSendOk(stub2, DEBUG_LOCATION); + // Enable health checks for channel 1 and wait for it to succeed. + servers_[0]->SetServingStatus("health_check_service_name", true); + CheckRpcSendOk(stub1, DEBUG_LOCATION, true /* wait_for_ready */); + // Check that we created only one subchannel to the backend. + EXPECT_EQ(1UL, servers_[0]->service_.clients().size()); + // Clean up. + EnableDefaultHealthCheckService(false); +} + +TEST_F(ClientLbEnd2endTest, + RoundRobinWithHealthCheckingServiceNameChangesAfterSubchannelsCreated) { + EnableDefaultHealthCheckService(true); + // Start server. + const int kNumServers = 1; + StartServers(kNumServers); + // Create a channel with health-checking enabled. + const char* kServiceConfigJson = + "{\"healthCheckConfig\": " + "{\"serviceName\": \"health_check_service_name\"}}"; + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("round_robin", response_generator); + auto stub = BuildStub(channel); + std::vector<int> ports = GetServersPorts(); + response_generator.SetNextResolution(ports, kServiceConfigJson); + servers_[0]->SetServingStatus("health_check_service_name", true); + EXPECT_TRUE(WaitForChannelReady(channel.get(), 1 /* timeout_seconds */)); + // Send an update on the channel to change it to use a health checking + // service name that is not being reported as healthy. + const char* kServiceConfigJson2 = + "{\"healthCheckConfig\": " + "{\"serviceName\": \"health_check_service_name2\"}}"; + response_generator.SetNextResolution(ports, kServiceConfigJson2); + EXPECT_TRUE(WaitForChannelNotReady(channel.get())); + // Clean up. + EnableDefaultHealthCheckService(false); +} + +TEST_F(ClientLbEnd2endTest, ChannelIdleness) { + // Start server. + const int kNumServers = 1; + StartServers(kNumServers); + // Set max idle time and build the channel. + ChannelArguments args; + args.SetInt(GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS, 1000); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = BuildChannel("", response_generator, args); + auto stub = BuildStub(channel); + // The initial channel state should be IDLE. + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); + // After sending RPC, channel state should be READY. + response_generator.SetNextResolution(GetServersPorts()); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); + // After a period time not using the channel, the channel state should switch + // to IDLE. + gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(1200)); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); + // Sending a new RPC should awake the IDLE channel. + response_generator.SetNextResolution(GetServersPorts()); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); +} + class ClientLbPickArgsTest : public ClientLbEnd2endTest { protected: void SetUp() override { @@ -1715,13 +1715,13 @@ TEST_F(ClientLbPickArgsTest, Basic) { ::testing::Pair("baz", "3")))))); } -class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { - protected: - void SetUp() override { - ClientLbEnd2endTest::SetUp(); +class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { + protected: + void SetUp() override { + ClientLbEnd2endTest::SetUp(); current_test_instance_ = this; - } - + } + static void SetUpTestCase() { grpc_init(); grpc_core::RegisterInterceptRecvTrailingMetadataLoadBalancingPolicy( @@ -1730,75 +1730,75 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { static void TearDownTestCase() { grpc_shutdown_blocking(); } - int trailers_intercepted() { - grpc::internal::MutexLock lock(&mu_); - return trailers_intercepted_; - } - + int trailers_intercepted() { + grpc::internal::MutexLock lock(&mu_); + return trailers_intercepted_; + } + const grpc_core::MetadataVector& trailing_metadata() { grpc::internal::MutexLock lock(&mu_); return trailing_metadata_; } - const udpa::data::orca::v1::OrcaLoadReport* backend_load_report() { - grpc::internal::MutexLock lock(&mu_); - return load_report_.get(); - } - - private: - static void ReportTrailerIntercepted( + const udpa::data::orca::v1::OrcaLoadReport* backend_load_report() { + grpc::internal::MutexLock lock(&mu_); + return load_report_.get(); + } + + private: + static void ReportTrailerIntercepted( const grpc_core::TrailingMetadataArgsSeen& args_seen) { const auto* backend_metric_data = args_seen.backend_metric_data; ClientLbInterceptTrailingMetadataTest* self = current_test_instance_; - grpc::internal::MutexLock lock(&self->mu_); - self->trailers_intercepted_++; + grpc::internal::MutexLock lock(&self->mu_); + self->trailers_intercepted_++; self->trailing_metadata_ = args_seen.metadata; - if (backend_metric_data != nullptr) { - self->load_report_.reset(new udpa::data::orca::v1::OrcaLoadReport); - self->load_report_->set_cpu_utilization( - backend_metric_data->cpu_utilization); - self->load_report_->set_mem_utilization( - backend_metric_data->mem_utilization); - self->load_report_->set_rps(backend_metric_data->requests_per_second); - for (const auto& p : backend_metric_data->request_cost) { + if (backend_metric_data != nullptr) { + self->load_report_.reset(new udpa::data::orca::v1::OrcaLoadReport); + self->load_report_->set_cpu_utilization( + backend_metric_data->cpu_utilization); + self->load_report_->set_mem_utilization( + backend_metric_data->mem_utilization); + self->load_report_->set_rps(backend_metric_data->requests_per_second); + for (const auto& p : backend_metric_data->request_cost) { TString name = TString(p.first); (*self->load_report_->mutable_request_cost())[std::move(name)] = p.second; - } - for (const auto& p : backend_metric_data->utilization) { + } + for (const auto& p : backend_metric_data->utilization) { TString name = TString(p.first); (*self->load_report_->mutable_utilization())[std::move(name)] = p.second; - } - } - } - + } + } + } + static ClientLbInterceptTrailingMetadataTest* current_test_instance_; - grpc::internal::Mutex mu_; - int trailers_intercepted_ = 0; + grpc::internal::Mutex mu_; + int trailers_intercepted_ = 0; grpc_core::MetadataVector trailing_metadata_; - std::unique_ptr<udpa::data::orca::v1::OrcaLoadReport> load_report_; -}; - + std::unique_ptr<udpa::data::orca::v1::OrcaLoadReport> load_report_; +}; + ClientLbInterceptTrailingMetadataTest* ClientLbInterceptTrailingMetadataTest::current_test_instance_ = nullptr; -TEST_F(ClientLbInterceptTrailingMetadataTest, InterceptsRetriesDisabled) { - const int kNumServers = 1; - const int kNumRpcs = 10; - StartServers(kNumServers); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = - BuildChannel("intercept_trailing_metadata_lb", response_generator); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(GetServersPorts()); - for (size_t i = 0; i < kNumRpcs; ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - } - // Check LB policy name for the channel. - EXPECT_EQ("intercept_trailing_metadata_lb", - channel->GetLoadBalancingPolicyName()); - EXPECT_EQ(kNumRpcs, trailers_intercepted()); +TEST_F(ClientLbInterceptTrailingMetadataTest, InterceptsRetriesDisabled) { + const int kNumServers = 1; + const int kNumRpcs = 10; + StartServers(kNumServers); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = + BuildChannel("intercept_trailing_metadata_lb", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + for (size_t i = 0; i < kNumRpcs; ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + } + // Check LB policy name for the channel. + EXPECT_EQ("intercept_trailing_metadata_lb", + channel->GetLoadBalancingPolicyName()); + EXPECT_EQ(kNumRpcs, trailers_intercepted()); EXPECT_THAT(trailing_metadata(), ::testing::UnorderedElementsAre( // TODO(roth): Should grpc-status be visible here? @@ -1806,41 +1806,41 @@ TEST_F(ClientLbInterceptTrailingMetadataTest, InterceptsRetriesDisabled) { ::testing::Pair("user-agent", ::testing::_), ::testing::Pair("foo", "1"), ::testing::Pair("bar", "2"), ::testing::Pair("baz", "3"))); - EXPECT_EQ(nullptr, backend_load_report()); -} - -TEST_F(ClientLbInterceptTrailingMetadataTest, InterceptsRetriesEnabled) { - const int kNumServers = 1; - const int kNumRpcs = 10; - StartServers(kNumServers); - ChannelArguments args; - args.SetServiceConfigJSON( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"grpc.testing.EchoTestService\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - auto response_generator = BuildResolverResponseGenerator(); - auto channel = - BuildChannel("intercept_trailing_metadata_lb", response_generator, args); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(GetServersPorts()); - for (size_t i = 0; i < kNumRpcs; ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - } - // Check LB policy name for the channel. - EXPECT_EQ("intercept_trailing_metadata_lb", - channel->GetLoadBalancingPolicyName()); - EXPECT_EQ(kNumRpcs, trailers_intercepted()); + EXPECT_EQ(nullptr, backend_load_report()); +} + +TEST_F(ClientLbInterceptTrailingMetadataTest, InterceptsRetriesEnabled) { + const int kNumServers = 1; + const int kNumRpcs = 10; + StartServers(kNumServers); + ChannelArguments args; + args.SetServiceConfigJSON( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"grpc.testing.EchoTestService\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}"); + auto response_generator = BuildResolverResponseGenerator(); + auto channel = + BuildChannel("intercept_trailing_metadata_lb", response_generator, args); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + for (size_t i = 0; i < kNumRpcs; ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + } + // Check LB policy name for the channel. + EXPECT_EQ("intercept_trailing_metadata_lb", + channel->GetLoadBalancingPolicyName()); + EXPECT_EQ(kNumRpcs, trailers_intercepted()); EXPECT_THAT(trailing_metadata(), ::testing::UnorderedElementsAre( // TODO(roth): Should grpc-status be visible here? @@ -1848,59 +1848,59 @@ TEST_F(ClientLbInterceptTrailingMetadataTest, InterceptsRetriesEnabled) { ::testing::Pair("user-agent", ::testing::_), ::testing::Pair("foo", "1"), ::testing::Pair("bar", "2"), ::testing::Pair("baz", "3"))); - EXPECT_EQ(nullptr, backend_load_report()); -} - -TEST_F(ClientLbInterceptTrailingMetadataTest, BackendMetricData) { - const int kNumServers = 1; - const int kNumRpcs = 10; - StartServers(kNumServers); - udpa::data::orca::v1::OrcaLoadReport load_report; - load_report.set_cpu_utilization(0.5); - load_report.set_mem_utilization(0.75); - load_report.set_rps(25); - auto* request_cost = load_report.mutable_request_cost(); - (*request_cost)["foo"] = 0.8; - (*request_cost)["bar"] = 1.4; - auto* utilization = load_report.mutable_utilization(); - (*utilization)["baz"] = 1.1; - (*utilization)["quux"] = 0.9; - for (const auto& server : servers_) { - server->service_.set_load_report(&load_report); - } - auto response_generator = BuildResolverResponseGenerator(); - auto channel = - BuildChannel("intercept_trailing_metadata_lb", response_generator); - auto stub = BuildStub(channel); - response_generator.SetNextResolution(GetServersPorts()); - for (size_t i = 0; i < kNumRpcs; ++i) { - CheckRpcSendOk(stub, DEBUG_LOCATION); - auto* actual = backend_load_report(); - ASSERT_NE(actual, nullptr); - // TODO(roth): Change this to use EqualsProto() once that becomes - // available in OSS. - EXPECT_EQ(actual->cpu_utilization(), load_report.cpu_utilization()); - EXPECT_EQ(actual->mem_utilization(), load_report.mem_utilization()); - EXPECT_EQ(actual->rps(), load_report.rps()); - EXPECT_EQ(actual->request_cost().size(), load_report.request_cost().size()); - for (const auto& p : actual->request_cost()) { - auto it = load_report.request_cost().find(p.first); - ASSERT_NE(it, load_report.request_cost().end()); - EXPECT_EQ(it->second, p.second); - } - EXPECT_EQ(actual->utilization().size(), load_report.utilization().size()); - for (const auto& p : actual->utilization()) { - auto it = load_report.utilization().find(p.first); - ASSERT_NE(it, load_report.utilization().end()); - EXPECT_EQ(it->second, p.second); - } - } - // Check LB policy name for the channel. - EXPECT_EQ("intercept_trailing_metadata_lb", - channel->GetLoadBalancingPolicyName()); - EXPECT_EQ(kNumRpcs, trailers_intercepted()); -} - + EXPECT_EQ(nullptr, backend_load_report()); +} + +TEST_F(ClientLbInterceptTrailingMetadataTest, BackendMetricData) { + const int kNumServers = 1; + const int kNumRpcs = 10; + StartServers(kNumServers); + udpa::data::orca::v1::OrcaLoadReport load_report; + load_report.set_cpu_utilization(0.5); + load_report.set_mem_utilization(0.75); + load_report.set_rps(25); + auto* request_cost = load_report.mutable_request_cost(); + (*request_cost)["foo"] = 0.8; + (*request_cost)["bar"] = 1.4; + auto* utilization = load_report.mutable_utilization(); + (*utilization)["baz"] = 1.1; + (*utilization)["quux"] = 0.9; + for (const auto& server : servers_) { + server->service_.set_load_report(&load_report); + } + auto response_generator = BuildResolverResponseGenerator(); + auto channel = + BuildChannel("intercept_trailing_metadata_lb", response_generator); + auto stub = BuildStub(channel); + response_generator.SetNextResolution(GetServersPorts()); + for (size_t i = 0; i < kNumRpcs; ++i) { + CheckRpcSendOk(stub, DEBUG_LOCATION); + auto* actual = backend_load_report(); + ASSERT_NE(actual, nullptr); + // TODO(roth): Change this to use EqualsProto() once that becomes + // available in OSS. + EXPECT_EQ(actual->cpu_utilization(), load_report.cpu_utilization()); + EXPECT_EQ(actual->mem_utilization(), load_report.mem_utilization()); + EXPECT_EQ(actual->rps(), load_report.rps()); + EXPECT_EQ(actual->request_cost().size(), load_report.request_cost().size()); + for (const auto& p : actual->request_cost()) { + auto it = load_report.request_cost().find(p.first); + ASSERT_NE(it, load_report.request_cost().end()); + EXPECT_EQ(it->second, p.second); + } + EXPECT_EQ(actual->utilization().size(), load_report.utilization().size()); + for (const auto& p : actual->utilization()) { + auto it = load_report.utilization().find(p.first); + ASSERT_NE(it, load_report.utilization().end()); + EXPECT_EQ(it->second, p.second); + } + } + // Check LB policy name for the channel. + EXPECT_EQ("intercept_trailing_metadata_lb", + channel->GetLoadBalancingPolicyName()); + EXPECT_EQ(kNumRpcs, trailers_intercepted()); +} + class ClientLbAddressTest : public ClientLbEnd2endTest { protected: static const char* kAttributeKey; @@ -1978,13 +1978,13 @@ TEST_F(ClientLbAddressTest, Basic) { EXPECT_EQ(addresses_seen(), expected); } -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - grpc::testing::TestEnvironment env(argc, argv); - const auto result = RUN_ALL_TESTS(); - return result; -} +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + grpc::testing::TestEnvironment env(argc, argv); + const auto result = RUN_ALL_TESTS(); + return result; +} diff --git a/contrib/libs/grpc/test/cpp/end2end/end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/end2end_test.cc index 9e1ae49b8d..ad2ddb7e84 100644 --- a/contrib/libs/grpc/test/cpp/end2end/end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/end2end_test.cc @@ -1,95 +1,95 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <grpc/grpc.h> -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/impl/codegen/status_code_enum.h> -#include <grpcpp/resource_quota.h> -#include <grpcpp/security/auth_metadata_processor.h> -#include <grpcpp/security/credentials.h> -#include <grpcpp/security/server_credentials.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/impl/codegen/status_code_enum.h> +#include <grpcpp/resource_quota.h> +#include <grpcpp/security/auth_metadata_processor.h> +#include <grpcpp/security/credentials.h> +#include <grpcpp/security/server_credentials.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> #include <grpcpp/support/string_ref.h> #include <grpcpp/test/channel_test_peer.h> - -#include <mutex> -#include <thread> - + +#include <mutex> +#include <thread> + #include "y_absl/strings/str_format.h" -#include "src/core/ext/filters/client_channel/backup_poller.h" -#include "src/core/lib/gpr/env.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/security/credentials/credentials.h" -#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/interceptors_util.h" -#include "test/cpp/end2end/test_service_impl.h" -#include "test/cpp/util/string_ref_helper.h" -#include "test/cpp/util/test_credentials_provider.h" - -#ifdef GRPC_POSIX_SOCKET_EV -#include "src/core/lib/iomgr/ev_posix.h" -#endif // GRPC_POSIX_SOCKET_EV - -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; -using grpc::testing::kTlsCredentialsType; -using std::chrono::system_clock; - -// MAYBE_SKIP_TEST is a macro to determine if this particular test configuration -// should be skipped based on a decision made at SetUp time. In particular, -// tests that use the callback server can only be run if the iomgr can run in -// the background or if the transport is in-process. -#define MAYBE_SKIP_TEST \ - do { \ - if (do_not_test_) { \ - return; \ - } \ - } while (0) - -namespace grpc { -namespace testing { -namespace { - +#include "src/core/ext/filters/client_channel/backup_poller.h" +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/interceptors_util.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/string_ref_helper.h" +#include "test/cpp/util/test_credentials_provider.h" + +#ifdef GRPC_POSIX_SOCKET_EV +#include "src/core/lib/iomgr/ev_posix.h" +#endif // GRPC_POSIX_SOCKET_EV + +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; +using grpc::testing::kTlsCredentialsType; +using std::chrono::system_clock; + +// MAYBE_SKIP_TEST is a macro to determine if this particular test configuration +// should be skipped based on a decision made at SetUp time. In particular, +// tests that use the callback server can only be run if the iomgr can run in +// the background or if the transport is in-process. +#define MAYBE_SKIP_TEST \ + do { \ + if (do_not_test_) { \ + return; \ + } \ + } while (0) + +namespace grpc { +namespace testing { +namespace { + bool CheckIsLocalhost(const TString& addr) { const TString kIpv6("ipv6:[::1]:"); const TString kIpv4MappedIpv6("ipv6:[::ffff:127.0.0.1]:"); const TString kIpv4("ipv4:127.0.0.1:"); - return addr.substr(0, kIpv4.size()) == kIpv4 || - addr.substr(0, kIpv4MappedIpv6.size()) == kIpv4MappedIpv6 || - addr.substr(0, kIpv6.size()) == kIpv6; -} - + return addr.substr(0, kIpv4.size()) == kIpv4 || + addr.substr(0, kIpv4MappedIpv6.size()) == kIpv4MappedIpv6 || + addr.substr(0, kIpv6.size()) == kIpv6; +} + const int kClientChannelBackupPollIntervalMs = 200; -const char kTestCredsPluginErrorMsg[] = "Could not find plugin metadata."; - +const char kTestCredsPluginErrorMsg[] = "Could not find plugin metadata."; + const char kFakeToken[] = "fake_token"; const char kFakeSelector[] = "fake_selector"; const char kExpectedFakeCredsDebugString[] = @@ -142,738 +142,738 @@ const char kExpectedCompositeCallCredsDebugString[] = "key:call-creds-key1,value:call-creds-val1},TestMetadataCredentials{key:" "call-creds-key2,value:call-creds-val2}}}"; -class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin { - public: - static const char kGoodMetadataKey[]; - static const char kBadMetadataKey[]; - - TestMetadataCredentialsPlugin(const grpc::string_ref& metadata_key, - const grpc::string_ref& metadata_value, - bool is_blocking, bool is_successful, - int delay_ms) - : metadata_key_(metadata_key.data(), metadata_key.length()), - metadata_value_(metadata_value.data(), metadata_value.length()), - is_blocking_(is_blocking), - is_successful_(is_successful), - delay_ms_(delay_ms) {} - - bool IsBlocking() const override { return is_blocking_; } - - Status GetMetadata( - grpc::string_ref service_url, grpc::string_ref method_name, - const grpc::AuthContext& channel_auth_context, +class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin { + public: + static const char kGoodMetadataKey[]; + static const char kBadMetadataKey[]; + + TestMetadataCredentialsPlugin(const grpc::string_ref& metadata_key, + const grpc::string_ref& metadata_value, + bool is_blocking, bool is_successful, + int delay_ms) + : metadata_key_(metadata_key.data(), metadata_key.length()), + metadata_value_(metadata_value.data(), metadata_value.length()), + is_blocking_(is_blocking), + is_successful_(is_successful), + delay_ms_(delay_ms) {} + + bool IsBlocking() const override { return is_blocking_; } + + Status GetMetadata( + grpc::string_ref service_url, grpc::string_ref method_name, + const grpc::AuthContext& channel_auth_context, std::multimap<TString, TString>* metadata) override { - if (delay_ms_ != 0) { - gpr_sleep_until( - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_millis(delay_ms_, GPR_TIMESPAN))); - } - EXPECT_GT(service_url.length(), 0UL); - EXPECT_GT(method_name.length(), 0UL); - EXPECT_TRUE(channel_auth_context.IsPeerAuthenticated()); - EXPECT_TRUE(metadata != nullptr); - if (is_successful_) { - metadata->insert(std::make_pair(metadata_key_, metadata_value_)); - return Status::OK; - } else { - return Status(StatusCode::NOT_FOUND, kTestCredsPluginErrorMsg); - } - } - + if (delay_ms_ != 0) { + gpr_sleep_until( + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(delay_ms_, GPR_TIMESPAN))); + } + EXPECT_GT(service_url.length(), 0UL); + EXPECT_GT(method_name.length(), 0UL); + EXPECT_TRUE(channel_auth_context.IsPeerAuthenticated()); + EXPECT_TRUE(metadata != nullptr); + if (is_successful_) { + metadata->insert(std::make_pair(metadata_key_, metadata_value_)); + return Status::OK; + } else { + return Status(StatusCode::NOT_FOUND, kTestCredsPluginErrorMsg); + } + } + TString DebugString() override { return y_absl::StrFormat("TestMetadataCredentials{key:%s,value:%s}", metadata_key_.c_str(), metadata_value_.c_str()); } - private: + private: TString metadata_key_; TString metadata_value_; - bool is_blocking_; - bool is_successful_; - int delay_ms_; -}; - -const char TestMetadataCredentialsPlugin::kBadMetadataKey[] = - "TestPluginMetadata"; -const char TestMetadataCredentialsPlugin::kGoodMetadataKey[] = - "test-plugin-metadata"; - -class TestAuthMetadataProcessor : public AuthMetadataProcessor { - public: - static const char kGoodGuy[]; - - TestAuthMetadataProcessor(bool is_blocking) : is_blocking_(is_blocking) {} - - std::shared_ptr<CallCredentials> GetCompatibleClientCreds() { - return grpc::MetadataCredentialsFromPlugin( - std::unique_ptr<MetadataCredentialsPlugin>( - new TestMetadataCredentialsPlugin( - TestMetadataCredentialsPlugin::kGoodMetadataKey, kGoodGuy, - is_blocking_, true, 0))); - } - - std::shared_ptr<CallCredentials> GetIncompatibleClientCreds() { - return grpc::MetadataCredentialsFromPlugin( - std::unique_ptr<MetadataCredentialsPlugin>( - new TestMetadataCredentialsPlugin( - TestMetadataCredentialsPlugin::kGoodMetadataKey, "Mr Hyde", - is_blocking_, true, 0))); - } - - // Interface implementation - bool IsBlocking() const override { return is_blocking_; } - - Status Process(const InputMetadata& auth_metadata, AuthContext* context, - OutputMetadata* consumed_auth_metadata, - OutputMetadata* response_metadata) override { - EXPECT_TRUE(consumed_auth_metadata != nullptr); - EXPECT_TRUE(context != nullptr); - EXPECT_TRUE(response_metadata != nullptr); - auto auth_md = - auth_metadata.find(TestMetadataCredentialsPlugin::kGoodMetadataKey); - EXPECT_NE(auth_md, auth_metadata.end()); - string_ref auth_md_value = auth_md->second; - if (auth_md_value == kGoodGuy) { - context->AddProperty(kIdentityPropName, kGoodGuy); - context->SetPeerIdentityPropertyName(kIdentityPropName); - consumed_auth_metadata->insert(std::make_pair( - string(auth_md->first.data(), auth_md->first.length()), - string(auth_md->second.data(), auth_md->second.length()))); - return Status::OK; - } else { - return Status(StatusCode::UNAUTHENTICATED, - string("Invalid principal: ") + - string(auth_md_value.data(), auth_md_value.length())); - } - } - - private: - static const char kIdentityPropName[]; - bool is_blocking_; -}; - -const char TestAuthMetadataProcessor::kGoodGuy[] = "Dr Jekyll"; -const char TestAuthMetadataProcessor::kIdentityPropName[] = "novel identity"; - -class Proxy : public ::grpc::testing::EchoTestService::Service { - public: - Proxy(const std::shared_ptr<Channel>& channel) - : stub_(grpc::testing::EchoTestService::NewStub(channel)) {} - - Status Echo(ServerContext* server_context, const EchoRequest* request, - EchoResponse* response) override { - std::unique_ptr<ClientContext> client_context = - ClientContext::FromServerContext(*server_context); - return stub_->Echo(client_context.get(), *request, response); - } - - private: - std::unique_ptr<::grpc::testing::EchoTestService::Stub> stub_; -}; - -class TestServiceImplDupPkg - : public ::grpc::testing::duplicate::EchoTestService::Service { - public: - Status Echo(ServerContext* /*context*/, const EchoRequest* /*request*/, - EchoResponse* response) override { - response->set_message("no package"); - return Status::OK; - } -}; - -class TestScenario { - public: - TestScenario(bool interceptors, bool proxy, bool inproc_stub, + bool is_blocking_; + bool is_successful_; + int delay_ms_; +}; + +const char TestMetadataCredentialsPlugin::kBadMetadataKey[] = + "TestPluginMetadata"; +const char TestMetadataCredentialsPlugin::kGoodMetadataKey[] = + "test-plugin-metadata"; + +class TestAuthMetadataProcessor : public AuthMetadataProcessor { + public: + static const char kGoodGuy[]; + + TestAuthMetadataProcessor(bool is_blocking) : is_blocking_(is_blocking) {} + + std::shared_ptr<CallCredentials> GetCompatibleClientCreds() { + return grpc::MetadataCredentialsFromPlugin( + std::unique_ptr<MetadataCredentialsPlugin>( + new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kGoodMetadataKey, kGoodGuy, + is_blocking_, true, 0))); + } + + std::shared_ptr<CallCredentials> GetIncompatibleClientCreds() { + return grpc::MetadataCredentialsFromPlugin( + std::unique_ptr<MetadataCredentialsPlugin>( + new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kGoodMetadataKey, "Mr Hyde", + is_blocking_, true, 0))); + } + + // Interface implementation + bool IsBlocking() const override { return is_blocking_; } + + Status Process(const InputMetadata& auth_metadata, AuthContext* context, + OutputMetadata* consumed_auth_metadata, + OutputMetadata* response_metadata) override { + EXPECT_TRUE(consumed_auth_metadata != nullptr); + EXPECT_TRUE(context != nullptr); + EXPECT_TRUE(response_metadata != nullptr); + auto auth_md = + auth_metadata.find(TestMetadataCredentialsPlugin::kGoodMetadataKey); + EXPECT_NE(auth_md, auth_metadata.end()); + string_ref auth_md_value = auth_md->second; + if (auth_md_value == kGoodGuy) { + context->AddProperty(kIdentityPropName, kGoodGuy); + context->SetPeerIdentityPropertyName(kIdentityPropName); + consumed_auth_metadata->insert(std::make_pair( + string(auth_md->first.data(), auth_md->first.length()), + string(auth_md->second.data(), auth_md->second.length()))); + return Status::OK; + } else { + return Status(StatusCode::UNAUTHENTICATED, + string("Invalid principal: ") + + string(auth_md_value.data(), auth_md_value.length())); + } + } + + private: + static const char kIdentityPropName[]; + bool is_blocking_; +}; + +const char TestAuthMetadataProcessor::kGoodGuy[] = "Dr Jekyll"; +const char TestAuthMetadataProcessor::kIdentityPropName[] = "novel identity"; + +class Proxy : public ::grpc::testing::EchoTestService::Service { + public: + Proxy(const std::shared_ptr<Channel>& channel) + : stub_(grpc::testing::EchoTestService::NewStub(channel)) {} + + Status Echo(ServerContext* server_context, const EchoRequest* request, + EchoResponse* response) override { + std::unique_ptr<ClientContext> client_context = + ClientContext::FromServerContext(*server_context); + return stub_->Echo(client_context.get(), *request, response); + } + + private: + std::unique_ptr<::grpc::testing::EchoTestService::Stub> stub_; +}; + +class TestServiceImplDupPkg + : public ::grpc::testing::duplicate::EchoTestService::Service { + public: + Status Echo(ServerContext* /*context*/, const EchoRequest* /*request*/, + EchoResponse* response) override { + response->set_message("no package"); + return Status::OK; + } +}; + +class TestScenario { + public: + TestScenario(bool interceptors, bool proxy, bool inproc_stub, const TString& creds_type, bool use_callback_server) - : use_interceptors(interceptors), - use_proxy(proxy), - inproc(inproc_stub), - credentials_type(creds_type), - callback_server(use_callback_server) {} - void Log() const; - bool use_interceptors; - bool use_proxy; - bool inproc; + : use_interceptors(interceptors), + use_proxy(proxy), + inproc(inproc_stub), + credentials_type(creds_type), + callback_server(use_callback_server) {} + void Log() const; + bool use_interceptors; + bool use_proxy; + bool inproc; const TString credentials_type; - bool callback_server; -}; - -static std::ostream& operator<<(std::ostream& out, - const TestScenario& scenario) { - return out << "TestScenario{use_interceptors=" - << (scenario.use_interceptors ? "true" : "false") - << ", use_proxy=" << (scenario.use_proxy ? "true" : "false") - << ", inproc=" << (scenario.inproc ? "true" : "false") - << ", server_type=" - << (scenario.callback_server ? "callback" : "sync") - << ", credentials='" << scenario.credentials_type << "'}"; -} - -void TestScenario::Log() const { - std::ostringstream out; - out << *this; - gpr_log(GPR_DEBUG, "%s", out.str().c_str()); -} - -class End2endTest : public ::testing::TestWithParam<TestScenario> { - protected: - static void SetUpTestCase() { grpc_init(); } - static void TearDownTestCase() { grpc_shutdown(); } - End2endTest() - : is_server_started_(false), - kMaxMessageSize_(8192), - special_service_("special"), - first_picked_port_(0) { - GetParam().Log(); - } - - void SetUp() override { - if (GetParam().callback_server && !GetParam().inproc && - !grpc_iomgr_run_in_background()) { - do_not_test_ = true; - return; - } - } - - void TearDown() override { - if (is_server_started_) { - server_->Shutdown(); - if (proxy_server_) proxy_server_->Shutdown(); - } - if (first_picked_port_ > 0) { - grpc_recycle_unused_port(first_picked_port_); - } - } - - void StartServer(const std::shared_ptr<AuthMetadataProcessor>& processor) { - int port = grpc_pick_unused_port_or_die(); - first_picked_port_ = port; - server_address_ << "127.0.0.1:" << port; - // Setup server - BuildAndStartServer(processor); - } - - void RestartServer(const std::shared_ptr<AuthMetadataProcessor>& processor) { - if (is_server_started_) { - server_->Shutdown(); - BuildAndStartServer(processor); - } - } - - void BuildAndStartServer( - const std::shared_ptr<AuthMetadataProcessor>& processor) { - ServerBuilder builder; - ConfigureServerBuilder(&builder); - auto server_creds = GetCredentialsProvider()->GetServerCredentials( - GetParam().credentials_type); - if (GetParam().credentials_type != kInsecureCredentialsType) { - server_creds->SetAuthMetadataProcessor(processor); - } - if (GetParam().use_interceptors) { - std::vector< - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> - creators; - // Add 20 dummy server interceptors - creators.reserve(20); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - builder.experimental().SetInterceptorCreators(std::move(creators)); - } - builder.AddListeningPort(server_address_.str(), server_creds); - if (!GetParam().callback_server) { - builder.RegisterService(&service_); - } else { - builder.RegisterService(&callback_service_); - } - builder.RegisterService("foo.test.youtube.com", &special_service_); - builder.RegisterService(&dup_pkg_service_); - - builder.SetSyncServerOption(ServerBuilder::SyncServerOption::NUM_CQS, 4); - builder.SetSyncServerOption( - ServerBuilder::SyncServerOption::CQ_TIMEOUT_MSEC, 10); - - server_ = builder.BuildAndStart(); - is_server_started_ = true; - } - - virtual void ConfigureServerBuilder(ServerBuilder* builder) { - builder->SetMaxMessageSize( - kMaxMessageSize_); // For testing max message size. - } - - void ResetChannel( - std::vector< - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators = {}) { - if (!is_server_started_) { - StartServer(std::shared_ptr<AuthMetadataProcessor>()); - } - EXPECT_TRUE(is_server_started_); - ChannelArguments args; - auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( - GetParam().credentials_type, &args); - if (!user_agent_prefix_.empty()) { - args.SetUserAgentPrefix(user_agent_prefix_); - } - args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test"); - - if (!GetParam().inproc) { - if (!GetParam().use_interceptors) { - channel_ = ::grpc::CreateCustomChannel(server_address_.str(), - channel_creds, args); - } else { - channel_ = CreateCustomChannelWithInterceptors( - server_address_.str(), channel_creds, args, - interceptor_creators.empty() ? CreateDummyClientInterceptors() - : std::move(interceptor_creators)); - } - } else { - if (!GetParam().use_interceptors) { - channel_ = server_->InProcessChannel(args); - } else { - channel_ = server_->experimental().InProcessChannelWithInterceptors( - args, interceptor_creators.empty() - ? CreateDummyClientInterceptors() - : std::move(interceptor_creators)); - } - } - } - - void ResetStub( - std::vector< - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators = {}) { - ResetChannel(std::move(interceptor_creators)); - if (GetParam().use_proxy) { - proxy_service_.reset(new Proxy(channel_)); - int port = grpc_pick_unused_port_or_die(); - std::ostringstream proxyaddr; - proxyaddr << "localhost:" << port; - ServerBuilder builder; - builder.AddListeningPort(proxyaddr.str(), InsecureServerCredentials()); - builder.RegisterService(proxy_service_.get()); - - builder.SetSyncServerOption(ServerBuilder::SyncServerOption::NUM_CQS, 4); - builder.SetSyncServerOption( - ServerBuilder::SyncServerOption::CQ_TIMEOUT_MSEC, 10); - - proxy_server_ = builder.BuildAndStart(); - - channel_ = - grpc::CreateChannel(proxyaddr.str(), InsecureChannelCredentials()); - } - - stub_ = grpc::testing::EchoTestService::NewStub(channel_); - DummyInterceptor::Reset(); - } - - bool do_not_test_{false}; - bool is_server_started_; - std::shared_ptr<Channel> channel_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - std::unique_ptr<Server> proxy_server_; - std::unique_ptr<Proxy> proxy_service_; - std::ostringstream server_address_; - const int kMaxMessageSize_; - TestServiceImpl service_; - CallbackTestServiceImpl callback_service_; - TestServiceImpl special_service_; - TestServiceImplDupPkg dup_pkg_service_; + bool callback_server; +}; + +static std::ostream& operator<<(std::ostream& out, + const TestScenario& scenario) { + return out << "TestScenario{use_interceptors=" + << (scenario.use_interceptors ? "true" : "false") + << ", use_proxy=" << (scenario.use_proxy ? "true" : "false") + << ", inproc=" << (scenario.inproc ? "true" : "false") + << ", server_type=" + << (scenario.callback_server ? "callback" : "sync") + << ", credentials='" << scenario.credentials_type << "'}"; +} + +void TestScenario::Log() const { + std::ostringstream out; + out << *this; + gpr_log(GPR_DEBUG, "%s", out.str().c_str()); +} + +class End2endTest : public ::testing::TestWithParam<TestScenario> { + protected: + static void SetUpTestCase() { grpc_init(); } + static void TearDownTestCase() { grpc_shutdown(); } + End2endTest() + : is_server_started_(false), + kMaxMessageSize_(8192), + special_service_("special"), + first_picked_port_(0) { + GetParam().Log(); + } + + void SetUp() override { + if (GetParam().callback_server && !GetParam().inproc && + !grpc_iomgr_run_in_background()) { + do_not_test_ = true; + return; + } + } + + void TearDown() override { + if (is_server_started_) { + server_->Shutdown(); + if (proxy_server_) proxy_server_->Shutdown(); + } + if (first_picked_port_ > 0) { + grpc_recycle_unused_port(first_picked_port_); + } + } + + void StartServer(const std::shared_ptr<AuthMetadataProcessor>& processor) { + int port = grpc_pick_unused_port_or_die(); + first_picked_port_ = port; + server_address_ << "127.0.0.1:" << port; + // Setup server + BuildAndStartServer(processor); + } + + void RestartServer(const std::shared_ptr<AuthMetadataProcessor>& processor) { + if (is_server_started_) { + server_->Shutdown(); + BuildAndStartServer(processor); + } + } + + void BuildAndStartServer( + const std::shared_ptr<AuthMetadataProcessor>& processor) { + ServerBuilder builder; + ConfigureServerBuilder(&builder); + auto server_creds = GetCredentialsProvider()->GetServerCredentials( + GetParam().credentials_type); + if (GetParam().credentials_type != kInsecureCredentialsType) { + server_creds->SetAuthMetadataProcessor(processor); + } + if (GetParam().use_interceptors) { + std::vector< + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + // Add 20 dummy server interceptors + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + } + builder.AddListeningPort(server_address_.str(), server_creds); + if (!GetParam().callback_server) { + builder.RegisterService(&service_); + } else { + builder.RegisterService(&callback_service_); + } + builder.RegisterService("foo.test.youtube.com", &special_service_); + builder.RegisterService(&dup_pkg_service_); + + builder.SetSyncServerOption(ServerBuilder::SyncServerOption::NUM_CQS, 4); + builder.SetSyncServerOption( + ServerBuilder::SyncServerOption::CQ_TIMEOUT_MSEC, 10); + + server_ = builder.BuildAndStart(); + is_server_started_ = true; + } + + virtual void ConfigureServerBuilder(ServerBuilder* builder) { + builder->SetMaxMessageSize( + kMaxMessageSize_); // For testing max message size. + } + + void ResetChannel( + std::vector< + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators = {}) { + if (!is_server_started_) { + StartServer(std::shared_ptr<AuthMetadataProcessor>()); + } + EXPECT_TRUE(is_server_started_); + ChannelArguments args; + auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); + if (!user_agent_prefix_.empty()) { + args.SetUserAgentPrefix(user_agent_prefix_); + } + args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test"); + + if (!GetParam().inproc) { + if (!GetParam().use_interceptors) { + channel_ = ::grpc::CreateCustomChannel(server_address_.str(), + channel_creds, args); + } else { + channel_ = CreateCustomChannelWithInterceptors( + server_address_.str(), channel_creds, args, + interceptor_creators.empty() ? CreateDummyClientInterceptors() + : std::move(interceptor_creators)); + } + } else { + if (!GetParam().use_interceptors) { + channel_ = server_->InProcessChannel(args); + } else { + channel_ = server_->experimental().InProcessChannelWithInterceptors( + args, interceptor_creators.empty() + ? CreateDummyClientInterceptors() + : std::move(interceptor_creators)); + } + } + } + + void ResetStub( + std::vector< + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators = {}) { + ResetChannel(std::move(interceptor_creators)); + if (GetParam().use_proxy) { + proxy_service_.reset(new Proxy(channel_)); + int port = grpc_pick_unused_port_or_die(); + std::ostringstream proxyaddr; + proxyaddr << "localhost:" << port; + ServerBuilder builder; + builder.AddListeningPort(proxyaddr.str(), InsecureServerCredentials()); + builder.RegisterService(proxy_service_.get()); + + builder.SetSyncServerOption(ServerBuilder::SyncServerOption::NUM_CQS, 4); + builder.SetSyncServerOption( + ServerBuilder::SyncServerOption::CQ_TIMEOUT_MSEC, 10); + + proxy_server_ = builder.BuildAndStart(); + + channel_ = + grpc::CreateChannel(proxyaddr.str(), InsecureChannelCredentials()); + } + + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + DummyInterceptor::Reset(); + } + + bool do_not_test_{false}; + bool is_server_started_; + std::shared_ptr<Channel> channel_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + std::unique_ptr<Server> proxy_server_; + std::unique_ptr<Proxy> proxy_service_; + std::ostringstream server_address_; + const int kMaxMessageSize_; + TestServiceImpl service_; + CallbackTestServiceImpl callback_service_; + TestServiceImpl special_service_; + TestServiceImplDupPkg dup_pkg_service_; TString user_agent_prefix_; - int first_picked_port_; -}; - -static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs, - bool with_binary_metadata) { - EchoRequest request; - EchoResponse response; - request.set_message("Hello hello hello hello"); - - for (int i = 0; i < num_rpcs; ++i) { - ClientContext context; - if (with_binary_metadata) { - char bytes[8] = {'\0', '\1', '\2', '\3', - '\4', '\5', '\6', static_cast<char>(i)}; + int first_picked_port_; +}; + +static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs, + bool with_binary_metadata) { + EchoRequest request; + EchoResponse response; + request.set_message("Hello hello hello hello"); + + for (int i = 0; i < num_rpcs; ++i) { + ClientContext context; + if (with_binary_metadata) { + char bytes[8] = {'\0', '\1', '\2', '\3', + '\4', '\5', '\6', static_cast<char>(i)}; context.AddMetadata("custom-bin", TString(bytes, 8)); - } - context.set_compression_algorithm(GRPC_COMPRESS_GZIP); - Status s = stub->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); - } -} - -// This class is for testing scenarios where RPCs are cancelled on the server -// by calling ServerContext::TryCancel() -class End2endServerTryCancelTest : public End2endTest { - protected: - // 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 - // the messages from the client - // - // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. - void TestRequestStreamServerCancel( - ServerTryCancelRequestPhase server_try_cancel, int num_msgs_to_send) { - MAYBE_SKIP_TEST; - RestartServer(std::shared_ptr<AuthMetadataProcessor>()); - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - - // Send server_try_cancel value in the client metadata - context.AddMetadata(kServerTryCancelRequest, + } + context.set_compression_algorithm(GRPC_COMPRESS_GZIP); + Status s = stub->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); + } +} + +// This class is for testing scenarios where RPCs are cancelled on the server +// by calling ServerContext::TryCancel() +class End2endServerTryCancelTest : public End2endTest { + protected: + // 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 + // the messages from the client + // + // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. + void TestRequestStreamServerCancel( + ServerTryCancelRequestPhase server_try_cancel, int num_msgs_to_send) { + MAYBE_SKIP_TEST; + RestartServer(std::shared_ptr<AuthMetadataProcessor>()); + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + // Send server_try_cancel value in the client metadata + context.AddMetadata(kServerTryCancelRequest, ToString(server_try_cancel)); - - auto stream = stub_->RequestStream(&context, &response); - - int num_msgs_sent = 0; - while (num_msgs_sent < num_msgs_to_send) { - request.set_message("hello"); - if (!stream->Write(request)) { - break; - } - num_msgs_sent++; - } - gpr_log(GPR_INFO, "Sent %d messages", num_msgs_sent); - - stream->WritesDone(); - Status s = stream->Finish(); - - // At this point, we know for sure that RPC was cancelled by the server - // since we passed server_try_cancel value in the metadata. Depending on the - // value of server_try_cancel, the RPC might have been cancelled by the - // server at different stages. The following validates our expectations of - // number of messages sent in various cancellation scenarios: - - switch (server_try_cancel) { - case CANCEL_BEFORE_PROCESSING: - case CANCEL_DURING_PROCESSING: - // If the RPC is cancelled by server before / during messages from the - // client, it means that the client most likely did not get a chance to - // send all the messages it wanted to send. i.e num_msgs_sent <= - // num_msgs_to_send - EXPECT_LE(num_msgs_sent, num_msgs_to_send); - break; - - case CANCEL_AFTER_PROCESSING: - // If the RPC was cancelled after all messages were read by the server, - // the client did get a chance to send all its messages - EXPECT_EQ(num_msgs_sent, num_msgs_to_send); - break; - - default: - gpr_log(GPR_ERROR, "Invalid server_try_cancel value: %d", - server_try_cancel); - EXPECT_TRUE(server_try_cancel > DO_NOT_CANCEL && - server_try_cancel <= CANCEL_AFTER_PROCESSING); - break; - } - - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } - } - - // 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 writing - // any messages to the client - // - // CANCEL_DURING_PROCESSING: Rpc is cancelled by the server while writing - // messages to the client - // - // CANCEL_AFTER PROCESSING: Rpc is cancelled by server after writing all - // the messages to the client - // - // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. - void TestResponseStreamServerCancel( - ServerTryCancelRequestPhase server_try_cancel) { - MAYBE_SKIP_TEST; - RestartServer(std::shared_ptr<AuthMetadataProcessor>()); - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - - // Send server_try_cancel in the client metadata - context.AddMetadata(kServerTryCancelRequest, + + auto stream = stub_->RequestStream(&context, &response); + + int num_msgs_sent = 0; + while (num_msgs_sent < num_msgs_to_send) { + request.set_message("hello"); + if (!stream->Write(request)) { + break; + } + num_msgs_sent++; + } + gpr_log(GPR_INFO, "Sent %d messages", num_msgs_sent); + + stream->WritesDone(); + Status s = stream->Finish(); + + // At this point, we know for sure that RPC was cancelled by the server + // since we passed server_try_cancel value in the metadata. Depending on the + // value of server_try_cancel, the RPC might have been cancelled by the + // server at different stages. The following validates our expectations of + // number of messages sent in various cancellation scenarios: + + switch (server_try_cancel) { + case CANCEL_BEFORE_PROCESSING: + case CANCEL_DURING_PROCESSING: + // If the RPC is cancelled by server before / during messages from the + // client, it means that the client most likely did not get a chance to + // send all the messages it wanted to send. i.e num_msgs_sent <= + // num_msgs_to_send + EXPECT_LE(num_msgs_sent, num_msgs_to_send); + break; + + case CANCEL_AFTER_PROCESSING: + // If the RPC was cancelled after all messages were read by the server, + // the client did get a chance to send all its messages + EXPECT_EQ(num_msgs_sent, num_msgs_to_send); + break; + + default: + gpr_log(GPR_ERROR, "Invalid server_try_cancel value: %d", + server_try_cancel); + EXPECT_TRUE(server_try_cancel > DO_NOT_CANCEL && + server_try_cancel <= CANCEL_AFTER_PROCESSING); + break; + } + + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } + } + + // 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 writing + // any messages to the client + // + // CANCEL_DURING_PROCESSING: Rpc is cancelled by the server while writing + // messages to the client + // + // CANCEL_AFTER PROCESSING: Rpc is cancelled by server after writing all + // the messages to the client + // + // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. + void TestResponseStreamServerCancel( + ServerTryCancelRequestPhase server_try_cancel) { + MAYBE_SKIP_TEST; + RestartServer(std::shared_ptr<AuthMetadataProcessor>()); + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + // Send server_try_cancel in the client metadata + context.AddMetadata(kServerTryCancelRequest, ToString(server_try_cancel)); - - request.set_message("hello"); - auto stream = stub_->ResponseStream(&context, request); - - int num_msgs_read = 0; - while (num_msgs_read < kServerDefaultResponseStreamsToSend) { - if (!stream->Read(&response)) { - break; - } - EXPECT_EQ(response.message(), + + request.set_message("hello"); + auto stream = stub_->ResponseStream(&context, request); + + int num_msgs_read = 0; + while (num_msgs_read < kServerDefaultResponseStreamsToSend) { + if (!stream->Read(&response)) { + break; + } + EXPECT_EQ(response.message(), request.message() + ToString(num_msgs_read)); - num_msgs_read++; - } - gpr_log(GPR_INFO, "Read %d messages", num_msgs_read); - - Status s = stream->Finish(); - - // Depending on the value of server_try_cancel, the RPC might have been - // cancelled by the server at different stages. The following validates our - // expectations of number of messages read in various cancellation - // scenarios: - switch (server_try_cancel) { - case CANCEL_BEFORE_PROCESSING: - // Server cancelled before sending any messages. Which means the client - // wouldn't have read any - EXPECT_EQ(num_msgs_read, 0); - break; - - case CANCEL_DURING_PROCESSING: - // Server cancelled while writing messages. Client must have read less - // than or equal to the expected number of messages - EXPECT_LE(num_msgs_read, kServerDefaultResponseStreamsToSend); - break; - - case CANCEL_AFTER_PROCESSING: - // Even though the Server cancelled after writing all messages, the RPC - // may be cancelled before the Client got a chance to read all the - // messages. - EXPECT_LE(num_msgs_read, kServerDefaultResponseStreamsToSend); - break; - - default: { - gpr_log(GPR_ERROR, "Invalid server_try_cancel value: %d", - server_try_cancel); - EXPECT_TRUE(server_try_cancel > DO_NOT_CANCEL && - server_try_cancel <= CANCEL_AFTER_PROCESSING); - break; - } - } - - EXPECT_FALSE(s.ok()); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } - } - - // Helper for testing bidirectional-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/ - // writing messages from/to the client - // - // CANCEL_AFTER PROCESSING: Rpc is cancelled by server after reading/writing - // all the messages from/to the client - // - // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. - void TestBidiStreamServerCancel(ServerTryCancelRequestPhase server_try_cancel, - int num_messages) { - MAYBE_SKIP_TEST; - RestartServer(std::shared_ptr<AuthMetadataProcessor>()); - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - - // Send server_try_cancel in the client metadata - context.AddMetadata(kServerTryCancelRequest, + num_msgs_read++; + } + gpr_log(GPR_INFO, "Read %d messages", num_msgs_read); + + Status s = stream->Finish(); + + // Depending on the value of server_try_cancel, the RPC might have been + // cancelled by the server at different stages. The following validates our + // expectations of number of messages read in various cancellation + // scenarios: + switch (server_try_cancel) { + case CANCEL_BEFORE_PROCESSING: + // Server cancelled before sending any messages. Which means the client + // wouldn't have read any + EXPECT_EQ(num_msgs_read, 0); + break; + + case CANCEL_DURING_PROCESSING: + // Server cancelled while writing messages. Client must have read less + // than or equal to the expected number of messages + EXPECT_LE(num_msgs_read, kServerDefaultResponseStreamsToSend); + break; + + case CANCEL_AFTER_PROCESSING: + // Even though the Server cancelled after writing all messages, the RPC + // may be cancelled before the Client got a chance to read all the + // messages. + EXPECT_LE(num_msgs_read, kServerDefaultResponseStreamsToSend); + break; + + default: { + gpr_log(GPR_ERROR, "Invalid server_try_cancel value: %d", + server_try_cancel); + EXPECT_TRUE(server_try_cancel > DO_NOT_CANCEL && + server_try_cancel <= CANCEL_AFTER_PROCESSING); + break; + } + } + + EXPECT_FALSE(s.ok()); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } + } + + // Helper for testing bidirectional-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/ + // writing messages from/to the client + // + // CANCEL_AFTER PROCESSING: Rpc is cancelled by server after reading/writing + // all the messages from/to the client + // + // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. + void TestBidiStreamServerCancel(ServerTryCancelRequestPhase server_try_cancel, + int num_messages) { + MAYBE_SKIP_TEST; + RestartServer(std::shared_ptr<AuthMetadataProcessor>()); + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + // Send server_try_cancel in the client metadata + context.AddMetadata(kServerTryCancelRequest, ToString(server_try_cancel)); - - auto stream = stub_->BidiStream(&context); - - int num_msgs_read = 0; - int num_msgs_sent = 0; - while (num_msgs_sent < num_messages) { + + auto stream = stub_->BidiStream(&context); + + int num_msgs_read = 0; + int num_msgs_sent = 0; + while (num_msgs_sent < num_messages) { request.set_message("hello " + ToString(num_msgs_sent)); - if (!stream->Write(request)) { - break; - } - num_msgs_sent++; - - if (!stream->Read(&response)) { - break; - } - num_msgs_read++; - - EXPECT_EQ(response.message(), request.message()); - } - gpr_log(GPR_INFO, "Sent %d messages", num_msgs_sent); - gpr_log(GPR_INFO, "Read %d messages", num_msgs_read); - - stream->WritesDone(); - Status s = stream->Finish(); - - // Depending on the value of server_try_cancel, the RPC might have been - // cancelled by the server at different stages. The following validates our - // expectations of number of messages read in various cancellation - // scenarios: - switch (server_try_cancel) { - case CANCEL_BEFORE_PROCESSING: - EXPECT_EQ(num_msgs_read, 0); - break; - - case CANCEL_DURING_PROCESSING: - EXPECT_LE(num_msgs_sent, num_messages); - EXPECT_LE(num_msgs_read, num_msgs_sent); - break; - - case CANCEL_AFTER_PROCESSING: - EXPECT_EQ(num_msgs_sent, num_messages); - - // The Server cancelled after reading the last message and after writing - // the message to the client. However, the RPC cancellation might have - // taken effect before the client actually read the response. - EXPECT_LE(num_msgs_read, num_msgs_sent); - break; - - default: - gpr_log(GPR_ERROR, "Invalid server_try_cancel value: %d", - server_try_cancel); - EXPECT_TRUE(server_try_cancel > DO_NOT_CANCEL && - server_try_cancel <= CANCEL_AFTER_PROCESSING); - break; - } - - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - // Make sure that the server interceptors were notified - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } - } -}; - -TEST_P(End2endServerTryCancelTest, RequestEchoServerCancel) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - - context.AddMetadata(kServerTryCancelRequest, + if (!stream->Write(request)) { + break; + } + num_msgs_sent++; + + if (!stream->Read(&response)) { + break; + } + num_msgs_read++; + + EXPECT_EQ(response.message(), request.message()); + } + gpr_log(GPR_INFO, "Sent %d messages", num_msgs_sent); + gpr_log(GPR_INFO, "Read %d messages", num_msgs_read); + + stream->WritesDone(); + Status s = stream->Finish(); + + // Depending on the value of server_try_cancel, the RPC might have been + // cancelled by the server at different stages. The following validates our + // expectations of number of messages read in various cancellation + // scenarios: + switch (server_try_cancel) { + case CANCEL_BEFORE_PROCESSING: + EXPECT_EQ(num_msgs_read, 0); + break; + + case CANCEL_DURING_PROCESSING: + EXPECT_LE(num_msgs_sent, num_messages); + EXPECT_LE(num_msgs_read, num_msgs_sent); + break; + + case CANCEL_AFTER_PROCESSING: + EXPECT_EQ(num_msgs_sent, num_messages); + + // The Server cancelled after reading the last message and after writing + // the message to the client. However, the RPC cancellation might have + // taken effect before the client actually read the response. + EXPECT_LE(num_msgs_read, num_msgs_sent); + break; + + default: + gpr_log(GPR_ERROR, "Invalid server_try_cancel value: %d", + server_try_cancel); + EXPECT_TRUE(server_try_cancel > DO_NOT_CANCEL && + server_try_cancel <= CANCEL_AFTER_PROCESSING); + break; + } + + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + // Make sure that the server interceptors were notified + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } + } +}; + +TEST_P(End2endServerTryCancelTest, RequestEchoServerCancel) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + context.AddMetadata(kServerTryCancelRequest, ToString(CANCEL_BEFORE_PROCESSING)); - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); -} - -// Server to cancel before doing reading the request -TEST_P(End2endServerTryCancelTest, RequestStreamServerCancelBeforeReads) { - TestRequestStreamServerCancel(CANCEL_BEFORE_PROCESSING, 1); -} - -// Server to cancel while reading a request from the stream in parallel -TEST_P(End2endServerTryCancelTest, RequestStreamServerCancelDuringRead) { - TestRequestStreamServerCancel(CANCEL_DURING_PROCESSING, 10); -} - -// Server to cancel after reading all the requests but before returning to the -// client -TEST_P(End2endServerTryCancelTest, RequestStreamServerCancelAfterReads) { - TestRequestStreamServerCancel(CANCEL_AFTER_PROCESSING, 4); -} - -// Server to cancel before sending any response messages -TEST_P(End2endServerTryCancelTest, ResponseStreamServerCancelBefore) { - TestResponseStreamServerCancel(CANCEL_BEFORE_PROCESSING); -} - -// Server to cancel while writing a response to the stream in parallel -TEST_P(End2endServerTryCancelTest, ResponseStreamServerCancelDuring) { - TestResponseStreamServerCancel(CANCEL_DURING_PROCESSING); -} - -// Server to cancel after writing all the respones to the stream but before -// returning to the client -TEST_P(End2endServerTryCancelTest, ResponseStreamServerCancelAfter) { - TestResponseStreamServerCancel(CANCEL_AFTER_PROCESSING); -} - -// Server to cancel before reading/writing any requests/responses on the stream -TEST_P(End2endServerTryCancelTest, BidiStreamServerCancelBefore) { - TestBidiStreamServerCancel(CANCEL_BEFORE_PROCESSING, 2); -} - -// Server to cancel while reading/writing requests/responses on the stream in -// parallel -TEST_P(End2endServerTryCancelTest, BidiStreamServerCancelDuring) { - TestBidiStreamServerCancel(CANCEL_DURING_PROCESSING, 10); -} - -// Server to cancel after reading/writing all requests/responses on the stream -// but before returning to the client -TEST_P(End2endServerTryCancelTest, BidiStreamServerCancelAfter) { - TestBidiStreamServerCancel(CANCEL_AFTER_PROCESSING, 5); -} - -TEST_P(End2endTest, SimpleRpcWithCustomUserAgentPrefix) { - MAYBE_SKIP_TEST; - // User-Agent is an HTTP header for HTTP transports only - if (GetParam().inproc) { - return; - } - user_agent_prefix_ = "custom_prefix"; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello hello hello hello"); - request.mutable_param()->set_echo_metadata(true); - - ClientContext context; - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); - const auto& trailing_metadata = context.GetServerTrailingMetadata(); - auto iter = trailing_metadata.find("user-agent"); - EXPECT_TRUE(iter != trailing_metadata.end()); + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); +} + +// Server to cancel before doing reading the request +TEST_P(End2endServerTryCancelTest, RequestStreamServerCancelBeforeReads) { + TestRequestStreamServerCancel(CANCEL_BEFORE_PROCESSING, 1); +} + +// Server to cancel while reading a request from the stream in parallel +TEST_P(End2endServerTryCancelTest, RequestStreamServerCancelDuringRead) { + TestRequestStreamServerCancel(CANCEL_DURING_PROCESSING, 10); +} + +// Server to cancel after reading all the requests but before returning to the +// client +TEST_P(End2endServerTryCancelTest, RequestStreamServerCancelAfterReads) { + TestRequestStreamServerCancel(CANCEL_AFTER_PROCESSING, 4); +} + +// Server to cancel before sending any response messages +TEST_P(End2endServerTryCancelTest, ResponseStreamServerCancelBefore) { + TestResponseStreamServerCancel(CANCEL_BEFORE_PROCESSING); +} + +// Server to cancel while writing a response to the stream in parallel +TEST_P(End2endServerTryCancelTest, ResponseStreamServerCancelDuring) { + TestResponseStreamServerCancel(CANCEL_DURING_PROCESSING); +} + +// Server to cancel after writing all the respones to the stream but before +// returning to the client +TEST_P(End2endServerTryCancelTest, ResponseStreamServerCancelAfter) { + TestResponseStreamServerCancel(CANCEL_AFTER_PROCESSING); +} + +// Server to cancel before reading/writing any requests/responses on the stream +TEST_P(End2endServerTryCancelTest, BidiStreamServerCancelBefore) { + TestBidiStreamServerCancel(CANCEL_BEFORE_PROCESSING, 2); +} + +// Server to cancel while reading/writing requests/responses on the stream in +// parallel +TEST_P(End2endServerTryCancelTest, BidiStreamServerCancelDuring) { + TestBidiStreamServerCancel(CANCEL_DURING_PROCESSING, 10); +} + +// Server to cancel after reading/writing all requests/responses on the stream +// but before returning to the client +TEST_P(End2endServerTryCancelTest, BidiStreamServerCancelAfter) { + TestBidiStreamServerCancel(CANCEL_AFTER_PROCESSING, 5); +} + +TEST_P(End2endTest, SimpleRpcWithCustomUserAgentPrefix) { + MAYBE_SKIP_TEST; + // User-Agent is an HTTP header for HTTP transports only + if (GetParam().inproc) { + return; + } + user_agent_prefix_ = "custom_prefix"; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello hello hello hello"); + request.mutable_param()->set_echo_metadata(true); + + ClientContext context; + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); + const auto& trailing_metadata = context.GetServerTrailingMetadata(); + auto iter = trailing_metadata.find("user-agent"); + EXPECT_TRUE(iter != trailing_metadata.end()); TString expected_prefix = user_agent_prefix_ + " grpc-c++/"; - EXPECT_TRUE(iter->second.starts_with(expected_prefix)) << iter->second; -} - -TEST_P(End2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { - MAYBE_SKIP_TEST; - ResetStub(); - std::vector<std::thread> threads; - threads.reserve(10); - for (int i = 0; i < 10; ++i) { - threads.emplace_back(SendRpc, stub_.get(), 10, true); - } - for (int i = 0; i < 10; ++i) { - threads[i].join(); - } -} - -TEST_P(End2endTest, MultipleRpcs) { - MAYBE_SKIP_TEST; - ResetStub(); - std::vector<std::thread> threads; - threads.reserve(10); - for (int i = 0; i < 10; ++i) { - threads.emplace_back(SendRpc, stub_.get(), 10, false); - } - for (int i = 0; i < 10; ++i) { - threads[i].join(); - } -} - + EXPECT_TRUE(iter->second.starts_with(expected_prefix)) << iter->second; +} + +TEST_P(End2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { + MAYBE_SKIP_TEST; + ResetStub(); + std::vector<std::thread> threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) { + threads.emplace_back(SendRpc, stub_.get(), 10, true); + } + for (int i = 0; i < 10; ++i) { + threads[i].join(); + } +} + +TEST_P(End2endTest, MultipleRpcs) { + MAYBE_SKIP_TEST; + ResetStub(); + std::vector<std::thread> threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) { + threads.emplace_back(SendRpc, stub_.get(), 10, false); + } + for (int i = 0; i < 10; ++i) { + threads[i].join(); + } +} + TEST_P(End2endTest, ManyStubs) { MAYBE_SKIP_TEST; ResetStub(); @@ -887,37 +887,37 @@ TEST_P(End2endTest, ManyStubs) { EXPECT_GT(peer.registration_attempts(), registration_attempts_pre); } -TEST_P(End2endTest, EmptyBinaryMetadata) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello hello hello hello"); - ClientContext context; - context.AddMetadata("custom-bin", ""); - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); -} - -TEST_P(End2endTest, ReconnectChannel) { - MAYBE_SKIP_TEST; - if (GetParam().inproc) { - return; - } - int poller_slowdown_factor = 1; - // It needs 2 pollset_works to reconnect the channel with polling engine - // "poll" -#ifdef GRPC_POSIX_SOCKET_EV - grpc_core::UniquePtr<char> poller = GPR_GLOBAL_CONFIG_GET(grpc_poll_strategy); - if (0 == strcmp(poller.get(), "poll")) { - poller_slowdown_factor = 2; - } -#endif // GRPC_POSIX_SOCKET_EV - ResetStub(); - SendRpc(stub_.get(), 1, false); - RestartServer(std::shared_ptr<AuthMetadataProcessor>()); - // It needs more than GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS time to +TEST_P(End2endTest, EmptyBinaryMetadata) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello hello hello hello"); + ClientContext context; + context.AddMetadata("custom-bin", ""); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); +} + +TEST_P(End2endTest, ReconnectChannel) { + MAYBE_SKIP_TEST; + if (GetParam().inproc) { + return; + } + int poller_slowdown_factor = 1; + // It needs 2 pollset_works to reconnect the channel with polling engine + // "poll" +#ifdef GRPC_POSIX_SOCKET_EV + grpc_core::UniquePtr<char> poller = GPR_GLOBAL_CONFIG_GET(grpc_poll_strategy); + if (0 == strcmp(poller.get(), "poll")) { + poller_slowdown_factor = 2; + } +#endif // GRPC_POSIX_SOCKET_EV + ResetStub(); + SendRpc(stub_.get(), 1, false); + RestartServer(std::shared_ptr<AuthMetadataProcessor>()); + // It needs more than GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS time to // reconnect the channel. Make it a factor of 5x gpr_sleep_until( gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), @@ -925,309 +925,309 @@ TEST_P(End2endTest, ReconnectChannel) { poller_slowdown_factor * grpc_test_slowdown_factor(), GPR_TIMESPAN))); - SendRpc(stub_.get(), 1, false); -} - -TEST_P(End2endTest, RequestStreamOneRequest) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - - auto stream = stub_->RequestStream(&context, &response); - request.set_message("hello"); - EXPECT_TRUE(stream->Write(request)); - stream->WritesDone(); - Status s = stream->Finish(); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); - EXPECT_TRUE(context.debug_error_string().empty()); -} - -TEST_P(End2endTest, RequestStreamOneRequestWithCoalescingApi) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - - context.set_initial_metadata_corked(true); - auto stream = stub_->RequestStream(&context, &response); - request.set_message("hello"); - stream->WriteLast(request, WriteOptions()); - Status s = stream->Finish(); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); -} - -TEST_P(End2endTest, RequestStreamTwoRequests) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - - auto stream = stub_->RequestStream(&context, &response); - request.set_message("hello"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Write(request)); - stream->WritesDone(); - Status s = stream->Finish(); - EXPECT_EQ(response.message(), "hellohello"); - EXPECT_TRUE(s.ok()); -} - -TEST_P(End2endTest, RequestStreamTwoRequestsWithWriteThrough) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - - auto stream = stub_->RequestStream(&context, &response); - request.set_message("hello"); - EXPECT_TRUE(stream->Write(request, WriteOptions().set_write_through())); - EXPECT_TRUE(stream->Write(request, WriteOptions().set_write_through())); - stream->WritesDone(); - Status s = stream->Finish(); - EXPECT_EQ(response.message(), "hellohello"); - EXPECT_TRUE(s.ok()); -} - -TEST_P(End2endTest, RequestStreamTwoRequestsWithCoalescingApi) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - - context.set_initial_metadata_corked(true); - auto stream = stub_->RequestStream(&context, &response); - request.set_message("hello"); - EXPECT_TRUE(stream->Write(request)); - stream->WriteLast(request, WriteOptions()); - Status s = stream->Finish(); - EXPECT_EQ(response.message(), "hellohello"); - EXPECT_TRUE(s.ok()); -} - -TEST_P(End2endTest, ResponseStream) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - request.set_message("hello"); - - auto stream = stub_->ResponseStream(&context, request); - for (int i = 0; i < kServerDefaultResponseStreamsToSend; ++i) { - EXPECT_TRUE(stream->Read(&response)); + SendRpc(stub_.get(), 1, false); +} + +TEST_P(End2endTest, RequestStreamOneRequest) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + auto stream = stub_->RequestStream(&context, &response); + request.set_message("hello"); + EXPECT_TRUE(stream->Write(request)); + stream->WritesDone(); + Status s = stream->Finish(); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); + EXPECT_TRUE(context.debug_error_string().empty()); +} + +TEST_P(End2endTest, RequestStreamOneRequestWithCoalescingApi) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + context.set_initial_metadata_corked(true); + auto stream = stub_->RequestStream(&context, &response); + request.set_message("hello"); + stream->WriteLast(request, WriteOptions()); + Status s = stream->Finish(); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); +} + +TEST_P(End2endTest, RequestStreamTwoRequests) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + auto stream = stub_->RequestStream(&context, &response); + request.set_message("hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Write(request)); + stream->WritesDone(); + Status s = stream->Finish(); + EXPECT_EQ(response.message(), "hellohello"); + EXPECT_TRUE(s.ok()); +} + +TEST_P(End2endTest, RequestStreamTwoRequestsWithWriteThrough) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + auto stream = stub_->RequestStream(&context, &response); + request.set_message("hello"); + EXPECT_TRUE(stream->Write(request, WriteOptions().set_write_through())); + EXPECT_TRUE(stream->Write(request, WriteOptions().set_write_through())); + stream->WritesDone(); + Status s = stream->Finish(); + EXPECT_EQ(response.message(), "hellohello"); + EXPECT_TRUE(s.ok()); +} + +TEST_P(End2endTest, RequestStreamTwoRequestsWithCoalescingApi) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + context.set_initial_metadata_corked(true); + auto stream = stub_->RequestStream(&context, &response); + request.set_message("hello"); + EXPECT_TRUE(stream->Write(request)); + stream->WriteLast(request, WriteOptions()); + Status s = stream->Finish(); + EXPECT_EQ(response.message(), "hellohello"); + EXPECT_TRUE(s.ok()); +} + +TEST_P(End2endTest, ResponseStream) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("hello"); + + auto stream = stub_->ResponseStream(&context, request); + for (int i = 0; i < kServerDefaultResponseStreamsToSend; ++i) { + EXPECT_TRUE(stream->Read(&response)); EXPECT_EQ(response.message(), request.message() + ToString(i)); - } - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); -} - -TEST_P(End2endTest, ResponseStreamWithCoalescingApi) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - request.set_message("hello"); - context.AddMetadata(kServerUseCoalescingApi, "1"); - - auto stream = stub_->ResponseStream(&context, request); - for (int i = 0; i < kServerDefaultResponseStreamsToSend; ++i) { - EXPECT_TRUE(stream->Read(&response)); + } + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); +} + +TEST_P(End2endTest, ResponseStreamWithCoalescingApi) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("hello"); + context.AddMetadata(kServerUseCoalescingApi, "1"); + + auto stream = stub_->ResponseStream(&context, request); + for (int i = 0; i < kServerDefaultResponseStreamsToSend; ++i) { + EXPECT_TRUE(stream->Read(&response)); EXPECT_EQ(response.message(), request.message() + ToString(i)); - } - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); -} - -// This was added to prevent regression from issue: -// https://github.com/grpc/grpc/issues/11546 -TEST_P(End2endTest, ResponseStreamWithEverythingCoalesced) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - request.set_message("hello"); - context.AddMetadata(kServerUseCoalescingApi, "1"); - // We will only send one message, forcing everything (init metadata, message, - // trailing) to be coalesced together. - context.AddMetadata(kServerResponseStreamsToSend, "1"); - - auto stream = stub_->ResponseStream(&context, request); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message() + "0"); - - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); -} - -TEST_P(End2endTest, BidiStream) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; + } + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); +} + +// This was added to prevent regression from issue: +// https://github.com/grpc/grpc/issues/11546 +TEST_P(End2endTest, ResponseStreamWithEverythingCoalesced) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("hello"); + context.AddMetadata(kServerUseCoalescingApi, "1"); + // We will only send one message, forcing everything (init metadata, message, + // trailing) to be coalesced together. + context.AddMetadata(kServerResponseStreamsToSend, "1"); + + auto stream = stub_->ResponseStream(&context, request); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "0"); + + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); +} + +TEST_P(End2endTest, BidiStream) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; TString msg("hello"); - - auto stream = stub_->BidiStream(&context); - - for (int i = 0; i < kServerDefaultResponseStreamsToSend; ++i) { + + auto stream = stub_->BidiStream(&context); + + for (int i = 0; i < kServerDefaultResponseStreamsToSend; ++i) { request.set_message(msg + ToString(i)); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - } - - stream->WritesDone(); - EXPECT_FALSE(stream->Read(&response)); - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); -} - -TEST_P(End2endTest, BidiStreamWithCoalescingApi) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.AddMetadata(kServerFinishAfterNReads, "3"); - context.set_initial_metadata_corked(true); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + } + + stream->WritesDone(); + EXPECT_FALSE(stream->Read(&response)); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); +} + +TEST_P(End2endTest, BidiStreamWithCoalescingApi) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.AddMetadata(kServerFinishAfterNReads, "3"); + context.set_initial_metadata_corked(true); TString msg("hello"); - - auto stream = stub_->BidiStream(&context); - - request.set_message(msg + "0"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - request.set_message(msg + "1"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - request.set_message(msg + "2"); - stream->WriteLast(request, WriteOptions()); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - EXPECT_FALSE(stream->Read(&response)); - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); -} - -// This was added to prevent regression from issue: -// https://github.com/grpc/grpc/issues/11546 -TEST_P(End2endTest, BidiStreamWithEverythingCoalesced) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.AddMetadata(kServerFinishAfterNReads, "1"); - context.set_initial_metadata_corked(true); + + auto stream = stub_->BidiStream(&context); + + request.set_message(msg + "0"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "1"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "2"); + stream->WriteLast(request, WriteOptions()); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + EXPECT_FALSE(stream->Read(&response)); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); +} + +// This was added to prevent regression from issue: +// https://github.com/grpc/grpc/issues/11546 +TEST_P(End2endTest, BidiStreamWithEverythingCoalesced) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.AddMetadata(kServerFinishAfterNReads, "1"); + context.set_initial_metadata_corked(true); TString msg("hello"); - - auto stream = stub_->BidiStream(&context); - - request.set_message(msg + "0"); - stream->WriteLast(request, WriteOptions()); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - EXPECT_FALSE(stream->Read(&response)); - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); -} - -// Talk to the two services with the same name but different package names. -// The two stubs are created on the same channel. -TEST_P(End2endTest, DiffPackageServices) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - - ClientContext context; - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); - - std::unique_ptr<grpc::testing::duplicate::EchoTestService::Stub> dup_pkg_stub( - grpc::testing::duplicate::EchoTestService::NewStub(channel_)); - ClientContext context2; - s = dup_pkg_stub->Echo(&context2, request, &response); - EXPECT_EQ("no package", response.message()); - EXPECT_TRUE(s.ok()); -} - -template <class ServiceType> -void CancelRpc(ClientContext* context, int delay_us, ServiceType* service) { - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(delay_us, GPR_TIMESPAN))); - while (!service->signal_client()) { - } - context->TryCancel(); -} - -TEST_P(End2endTest, CancelRpcBeforeStart) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - request.set_message("hello"); - context.TryCancel(); - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ("", response.message()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - + + auto stream = stub_->BidiStream(&context); + + request.set_message(msg + "0"); + stream->WriteLast(request, WriteOptions()); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + EXPECT_FALSE(stream->Read(&response)); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); +} + +// Talk to the two services with the same name but different package names. +// The two stubs are created on the same channel. +TEST_P(End2endTest, DiffPackageServices) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + + ClientContext context; + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); + + std::unique_ptr<grpc::testing::duplicate::EchoTestService::Stub> dup_pkg_stub( + grpc::testing::duplicate::EchoTestService::NewStub(channel_)); + ClientContext context2; + s = dup_pkg_stub->Echo(&context2, request, &response); + EXPECT_EQ("no package", response.message()); + EXPECT_TRUE(s.ok()); +} + +template <class ServiceType> +void CancelRpc(ClientContext* context, int delay_us, ServiceType* service) { + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(delay_us, GPR_TIMESPAN))); + while (!service->signal_client()) { + } + context->TryCancel(); +} + +TEST_P(End2endTest, CancelRpcBeforeStart) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("hello"); + context.TryCancel(); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ("", response.message()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + TEST_P(End2endTest, CancelRpcAfterStart) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - request.set_message("hello"); + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("hello"); request.mutable_param()->set_server_notify_client_when_started(true); - request.mutable_param()->set_skip_cancelled_check(true); - Status s; - std::thread echo_thread([this, &s, &context, &request, &response] { - s = stub_->Echo(&context, request, &response); - EXPECT_EQ(StatusCode::CANCELLED, s.error_code()); - }); + request.mutable_param()->set_skip_cancelled_check(true); + Status s; + std::thread echo_thread([this, &s, &context, &request, &response] { + s = stub_->Echo(&context, request, &response); + EXPECT_EQ(StatusCode::CANCELLED, s.error_code()); + }); if (!GetParam().callback_server) { service_.ClientWaitUntilRpcStarted(); } else { callback_service_.ClientWaitUntilRpcStarted(); } - context.TryCancel(); + context.TryCancel(); if (!GetParam().callback_server) { service_.SignalServerToContinue(); @@ -1235,1123 +1235,1123 @@ TEST_P(End2endTest, CancelRpcAfterStart) { callback_service_.SignalServerToContinue(); } - echo_thread.join(); - EXPECT_EQ("", response.message()); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Client cancels request stream after sending two messages -TEST_P(End2endTest, ClientCancelsRequestStream) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - request.set_message("hello"); - - auto stream = stub_->RequestStream(&context, &response); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Write(request)); - - context.TryCancel(); - - Status s = stream->Finish(); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - - EXPECT_EQ(response.message(), ""); - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Client cancels server stream after sending some messages -TEST_P(End2endTest, ClientCancelsResponseStream) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - request.set_message("hello"); - - auto stream = stub_->ResponseStream(&context, request); - - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message() + "0"); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message() + "1"); - - context.TryCancel(); - - // The cancellation races with responses, so there might be zero or - // one responses pending, read till failure - - if (stream->Read(&response)) { - EXPECT_EQ(response.message(), request.message() + "2"); - // Since we have cancelled, we expect the next attempt to read to fail - EXPECT_FALSE(stream->Read(&response)); - } - - Status s = stream->Finish(); - // The final status could be either of CANCELLED or OK depending on - // who won the race. - EXPECT_GE(grpc::StatusCode::CANCELLED, s.error_code()); - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -// Client cancels bidi stream after sending some messages -TEST_P(End2endTest, ClientCancelsBidi) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; + echo_thread.join(); + EXPECT_EQ("", response.message()); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Client cancels request stream after sending two messages +TEST_P(End2endTest, ClientCancelsRequestStream) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("hello"); + + auto stream = stub_->RequestStream(&context, &response); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Write(request)); + + context.TryCancel(); + + Status s = stream->Finish(); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + + EXPECT_EQ(response.message(), ""); + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Client cancels server stream after sending some messages +TEST_P(End2endTest, ClientCancelsResponseStream) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("hello"); + + auto stream = stub_->ResponseStream(&context, request); + + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "0"); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "1"); + + context.TryCancel(); + + // The cancellation races with responses, so there might be zero or + // one responses pending, read till failure + + if (stream->Read(&response)) { + EXPECT_EQ(response.message(), request.message() + "2"); + // Since we have cancelled, we expect the next attempt to read to fail + EXPECT_FALSE(stream->Read(&response)); + } + + Status s = stream->Finish(); + // The final status could be either of CANCELLED or OK depending on + // who won the race. + EXPECT_GE(grpc::StatusCode::CANCELLED, s.error_code()); + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +// Client cancels bidi stream after sending some messages +TEST_P(End2endTest, ClientCancelsBidi) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; TString msg("hello"); - - auto stream = stub_->BidiStream(&context); - - request.set_message(msg + "0"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - request.set_message(msg + "1"); - EXPECT_TRUE(stream->Write(request)); - - context.TryCancel(); - - // The cancellation races with responses, so there might be zero or - // one responses pending, read till failure - - if (stream->Read(&response)) { - EXPECT_EQ(response.message(), request.message()); - // Since we have cancelled, we expect the next attempt to read to fail - EXPECT_FALSE(stream->Read(&response)); - } - - Status s = stream->Finish(); - EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); - if (GetParam().use_interceptors) { - EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); - } -} - -TEST_P(End2endTest, RpcMaxMessageSize) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message(string(kMaxMessageSize_ * 2, 'a')); - request.mutable_param()->set_server_die(true); - - ClientContext context; - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); -} - -void ReaderThreadFunc(ClientReaderWriter<EchoRequest, EchoResponse>* stream, - gpr_event* ev) { - EchoResponse resp; - gpr_event_set(ev, (void*)1); - while (stream->Read(&resp)) { - gpr_log(GPR_INFO, "Read message"); - } -} - -// Run a Read and a WritesDone simultaneously. -TEST_P(End2endTest, SimultaneousReadWritesDone) { - MAYBE_SKIP_TEST; - ResetStub(); - ClientContext context; - gpr_event ev; - gpr_event_init(&ev); - auto stream = stub_->BidiStream(&context); - std::thread reader_thread(ReaderThreadFunc, stream.get(), &ev); - gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME)); - stream->WritesDone(); - reader_thread.join(); - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); -} - -TEST_P(End2endTest, ChannelState) { - MAYBE_SKIP_TEST; - if (GetParam().inproc) { - return; - } - - ResetStub(); - // Start IDLE - EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false)); - - // Did not ask to connect, no state change. - CompletionQueue cq; - std::chrono::system_clock::time_point deadline = - std::chrono::system_clock::now() + std::chrono::milliseconds(10); - channel_->NotifyOnStateChange(GRPC_CHANNEL_IDLE, deadline, &cq, nullptr); - void* tag; - bool ok = true; - cq.Next(&tag, &ok); - EXPECT_FALSE(ok); - - EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(true)); - EXPECT_TRUE(channel_->WaitForStateChange(GRPC_CHANNEL_IDLE, - gpr_inf_future(GPR_CLOCK_REALTIME))); - auto state = channel_->GetState(false); - EXPECT_TRUE(state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_READY); -} - -// Takes 10s. -TEST_P(End2endTest, ChannelStateTimeout) { - if ((GetParam().credentials_type != kInsecureCredentialsType) || - GetParam().inproc) { - return; - } - int port = grpc_pick_unused_port_or_die(); - std::ostringstream server_address; - server_address << "127.0.0.1:" << port; - // Channel to non-existing server - auto channel = - grpc::CreateChannel(server_address.str(), InsecureChannelCredentials()); - // Start IDLE - EXPECT_EQ(GRPC_CHANNEL_IDLE, channel->GetState(true)); - - auto state = GRPC_CHANNEL_IDLE; - for (int i = 0; i < 10; i++) { - channel->WaitForStateChange( - state, std::chrono::system_clock::now() + std::chrono::seconds(1)); - state = channel->GetState(false); - } -} - -// Talking to a non-existing service. -TEST_P(End2endTest, NonExistingService) { - MAYBE_SKIP_TEST; - ResetChannel(); - std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; - stub = grpc::testing::UnimplementedEchoService::NewStub(channel_); - - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - - ClientContext context; - Status s = stub->Unimplemented(&context, request, &response); - EXPECT_EQ(StatusCode::UNIMPLEMENTED, s.error_code()); - EXPECT_EQ("", s.error_message()); -} - -// Ask the server to send back a serialized proto in trailer. -// This is an example of setting error details. -TEST_P(End2endTest, BinaryTrailerTest) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - - request.mutable_param()->set_echo_metadata(true); - DebugInfo* info = request.mutable_param()->mutable_debug_info(); - info->add_stack_entries("stack_entry_1"); - info->add_stack_entries("stack_entry_2"); - info->add_stack_entries("stack_entry_3"); - info->set_detail("detailed debug info"); + + auto stream = stub_->BidiStream(&context); + + request.set_message(msg + "0"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "1"); + EXPECT_TRUE(stream->Write(request)); + + context.TryCancel(); + + // The cancellation races with responses, so there might be zero or + // one responses pending, read till failure + + if (stream->Read(&response)) { + EXPECT_EQ(response.message(), request.message()); + // Since we have cancelled, we expect the next attempt to read to fail + EXPECT_FALSE(stream->Read(&response)); + } + + Status s = stream->Finish(); + EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code()); + if (GetParam().use_interceptors) { + EXPECT_EQ(20, DummyInterceptor::GetNumTimesCancel()); + } +} + +TEST_P(End2endTest, RpcMaxMessageSize) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message(string(kMaxMessageSize_ * 2, 'a')); + request.mutable_param()->set_server_die(true); + + ClientContext context; + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); +} + +void ReaderThreadFunc(ClientReaderWriter<EchoRequest, EchoResponse>* stream, + gpr_event* ev) { + EchoResponse resp; + gpr_event_set(ev, (void*)1); + while (stream->Read(&resp)) { + gpr_log(GPR_INFO, "Read message"); + } +} + +// Run a Read and a WritesDone simultaneously. +TEST_P(End2endTest, SimultaneousReadWritesDone) { + MAYBE_SKIP_TEST; + ResetStub(); + ClientContext context; + gpr_event ev; + gpr_event_init(&ev); + auto stream = stub_->BidiStream(&context); + std::thread reader_thread(ReaderThreadFunc, stream.get(), &ev); + gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME)); + stream->WritesDone(); + reader_thread.join(); + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); +} + +TEST_P(End2endTest, ChannelState) { + MAYBE_SKIP_TEST; + if (GetParam().inproc) { + return; + } + + ResetStub(); + // Start IDLE + EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false)); + + // Did not ask to connect, no state change. + CompletionQueue cq; + std::chrono::system_clock::time_point deadline = + std::chrono::system_clock::now() + std::chrono::milliseconds(10); + channel_->NotifyOnStateChange(GRPC_CHANNEL_IDLE, deadline, &cq, nullptr); + void* tag; + bool ok = true; + cq.Next(&tag, &ok); + EXPECT_FALSE(ok); + + EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(true)); + EXPECT_TRUE(channel_->WaitForStateChange(GRPC_CHANNEL_IDLE, + gpr_inf_future(GPR_CLOCK_REALTIME))); + auto state = channel_->GetState(false); + EXPECT_TRUE(state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_READY); +} + +// Takes 10s. +TEST_P(End2endTest, ChannelStateTimeout) { + if ((GetParam().credentials_type != kInsecureCredentialsType) || + GetParam().inproc) { + return; + } + int port = grpc_pick_unused_port_or_die(); + std::ostringstream server_address; + server_address << "127.0.0.1:" << port; + // Channel to non-existing server + auto channel = + grpc::CreateChannel(server_address.str(), InsecureChannelCredentials()); + // Start IDLE + EXPECT_EQ(GRPC_CHANNEL_IDLE, channel->GetState(true)); + + auto state = GRPC_CHANNEL_IDLE; + for (int i = 0; i < 10; i++) { + channel->WaitForStateChange( + state, std::chrono::system_clock::now() + std::chrono::seconds(1)); + state = channel->GetState(false); + } +} + +// Talking to a non-existing service. +TEST_P(End2endTest, NonExistingService) { + MAYBE_SKIP_TEST; + ResetChannel(); + std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; + stub = grpc::testing::UnimplementedEchoService::NewStub(channel_); + + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + + ClientContext context; + Status s = stub->Unimplemented(&context, request, &response); + EXPECT_EQ(StatusCode::UNIMPLEMENTED, s.error_code()); + EXPECT_EQ("", s.error_message()); +} + +// Ask the server to send back a serialized proto in trailer. +// This is an example of setting error details. +TEST_P(End2endTest, BinaryTrailerTest) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + + request.mutable_param()->set_echo_metadata(true); + DebugInfo* info = request.mutable_param()->mutable_debug_info(); + info->add_stack_entries("stack_entry_1"); + info->add_stack_entries("stack_entry_2"); + info->add_stack_entries("stack_entry_3"); + info->set_detail("detailed debug info"); TString expected_string = info->SerializeAsString(); - request.set_message("Hello"); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - auto trailers = context.GetServerTrailingMetadata(); - EXPECT_EQ(1u, trailers.count(kDebugInfoTrailerKey)); - auto iter = trailers.find(kDebugInfoTrailerKey); - EXPECT_EQ(expected_string, iter->second); - // Parse the returned trailer into a DebugInfo proto. - DebugInfo returned_info; - EXPECT_TRUE(returned_info.ParseFromString(ToString(iter->second))); -} - -TEST_P(End2endTest, ExpectErrorTest) { - MAYBE_SKIP_TEST; - ResetStub(); - - std::vector<ErrorStatus> expected_status; - expected_status.emplace_back(); - expected_status.back().set_code(13); // INTERNAL - // No Error message or details - - expected_status.emplace_back(); - expected_status.back().set_code(13); // INTERNAL - expected_status.back().set_error_message("text error message"); - expected_status.back().set_binary_error_details("text error details"); - - expected_status.emplace_back(); - expected_status.back().set_code(13); // INTERNAL - expected_status.back().set_error_message("text error message"); - expected_status.back().set_binary_error_details( - "\x0\x1\x2\x3\x4\x5\x6\x8\x9\xA\xB"); - - for (auto iter = expected_status.begin(); iter != expected_status.end(); - ++iter) { - EchoRequest request; - EchoResponse response; - ClientContext context; - request.set_message("Hello"); - auto* error = request.mutable_param()->mutable_expected_error(); - error->set_code(iter->code()); - error->set_error_message(iter->error_message()); - error->set_binary_error_details(iter->binary_error_details()); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - EXPECT_EQ(iter->code(), s.error_code()); - EXPECT_EQ(iter->error_message(), s.error_message()); - EXPECT_EQ(iter->binary_error_details(), s.error_details()); - EXPECT_TRUE(context.debug_error_string().find("created") != + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + auto trailers = context.GetServerTrailingMetadata(); + EXPECT_EQ(1u, trailers.count(kDebugInfoTrailerKey)); + auto iter = trailers.find(kDebugInfoTrailerKey); + EXPECT_EQ(expected_string, iter->second); + // Parse the returned trailer into a DebugInfo proto. + DebugInfo returned_info; + EXPECT_TRUE(returned_info.ParseFromString(ToString(iter->second))); +} + +TEST_P(End2endTest, ExpectErrorTest) { + MAYBE_SKIP_TEST; + ResetStub(); + + std::vector<ErrorStatus> expected_status; + expected_status.emplace_back(); + expected_status.back().set_code(13); // INTERNAL + // No Error message or details + + expected_status.emplace_back(); + expected_status.back().set_code(13); // INTERNAL + expected_status.back().set_error_message("text error message"); + expected_status.back().set_binary_error_details("text error details"); + + expected_status.emplace_back(); + expected_status.back().set_code(13); // INTERNAL + expected_status.back().set_error_message("text error message"); + expected_status.back().set_binary_error_details( + "\x0\x1\x2\x3\x4\x5\x6\x8\x9\xA\xB"); + + for (auto iter = expected_status.begin(); iter != expected_status.end(); + ++iter) { + EchoRequest request; + EchoResponse response; + ClientContext context; + request.set_message("Hello"); + auto* error = request.mutable_param()->mutable_expected_error(); + error->set_code(iter->code()); + error->set_error_message(iter->error_message()); + error->set_binary_error_details(iter->binary_error_details()); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(iter->code(), s.error_code()); + EXPECT_EQ(iter->error_message(), s.error_message()); + EXPECT_EQ(iter->binary_error_details(), s.error_details()); + EXPECT_TRUE(context.debug_error_string().find("created") != TString::npos); EXPECT_TRUE(context.debug_error_string().find("file") != TString::npos); EXPECT_TRUE(context.debug_error_string().find("line") != TString::npos); - EXPECT_TRUE(context.debug_error_string().find("status") != + EXPECT_TRUE(context.debug_error_string().find("status") != TString::npos); EXPECT_TRUE(context.debug_error_string().find("13") != TString::npos); - } -} - -////////////////////////////////////////////////////////////////////////// -// Test with and without a proxy. -class ProxyEnd2endTest : public End2endTest { - protected: -}; - -TEST_P(ProxyEnd2endTest, SimpleRpc) { - MAYBE_SKIP_TEST; - ResetStub(); - SendRpc(stub_.get(), 1, false); -} - -TEST_P(ProxyEnd2endTest, SimpleRpcWithEmptyMessages) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - - ClientContext context; - Status s = stub_->Echo(&context, request, &response); - EXPECT_TRUE(s.ok()); -} - -TEST_P(ProxyEnd2endTest, MultipleRpcs) { - MAYBE_SKIP_TEST; - ResetStub(); - std::vector<std::thread> threads; - threads.reserve(10); - for (int i = 0; i < 10; ++i) { - threads.emplace_back(SendRpc, stub_.get(), 10, false); - } - for (int i = 0; i < 10; ++i) { - threads[i].join(); - } -} - -// Set a 10us deadline and make sure proper error is returned. -TEST_P(ProxyEnd2endTest, RpcDeadlineExpires) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - request.mutable_param()->set_skip_cancelled_check(true); - // Let server sleep for 40 ms first to guarantee expiry. - // 40 ms might seem a bit extreme but the timer manager would have been just - // initialized (when ResetStub() was called) and there are some warmup costs - // i.e the timer thread many not have even started. There might also be other - // delays in the timer manager thread (in acquiring locks, timer data - // structure manipulations, starting backup timer threads) that add to the - // delays. 40ms is still not enough in some cases but this significantly - // reduces the test flakes - request.mutable_param()->set_server_sleep_us(40 * 1000); - - ClientContext context; - std::chrono::system_clock::time_point deadline = - std::chrono::system_clock::now() + std::chrono::milliseconds(1); - context.set_deadline(deadline); - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, s.error_code()); -} - -// Set a long but finite deadline. -TEST_P(ProxyEnd2endTest, RpcLongDeadline) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - - ClientContext context; - std::chrono::system_clock::time_point deadline = - std::chrono::system_clock::now() + std::chrono::hours(1); - context.set_deadline(deadline); - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); -} - -// Ask server to echo back the deadline it sees. -TEST_P(ProxyEnd2endTest, EchoDeadline) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - request.mutable_param()->set_echo_deadline(true); - - ClientContext context; - std::chrono::system_clock::time_point deadline = - std::chrono::system_clock::now() + std::chrono::seconds(100); - context.set_deadline(deadline); - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); - gpr_timespec sent_deadline; - Timepoint2Timespec(deadline, &sent_deadline); - // We want to allow some reasonable error given: - // - request_deadline() only has 1sec resolution so the best we can do is +-1 - // - if sent_deadline.tv_nsec is very close to the next second's boundary we - // can end up being off by 2 in one direction. - EXPECT_LE(response.param().request_deadline() - sent_deadline.tv_sec, 2); - EXPECT_GE(response.param().request_deadline() - sent_deadline.tv_sec, -1); -} - -// Ask server to echo back the deadline it sees. The rpc has no deadline. -TEST_P(ProxyEnd2endTest, EchoDeadlineForNoDeadlineRpc) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - request.mutable_param()->set_echo_deadline(true); - - ClientContext context; - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); - EXPECT_EQ(response.param().request_deadline(), - gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec); -} - -TEST_P(ProxyEnd2endTest, UnimplementedRpc) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - - ClientContext context; - Status s = stub_->Unimplemented(&context, request, &response); - EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), grpc::StatusCode::UNIMPLEMENTED); - EXPECT_EQ(s.error_message(), ""); - EXPECT_EQ(response.message(), ""); -} - -// Client cancels rpc after 10ms -TEST_P(ProxyEnd2endTest, ClientCancelsRpc) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - const int kCancelDelayUs = 10 * 1000; - request.mutable_param()->set_client_cancel_after_us(kCancelDelayUs); - - ClientContext context; - std::thread cancel_thread; - if (!GetParam().callback_server) { - cancel_thread = std::thread( - [&context, this](int delay) { CancelRpc(&context, delay, &service_); }, - kCancelDelayUs); - // Note: the unusual pattern above (and below) is caused by a conflict - // between two sets of compiler expectations. clang allows const to be - // captured without mention, so there is no need to capture kCancelDelayUs - // (and indeed clang-tidy complains if you do so). OTOH, a Windows compiler - // in our tests requires an explicit capture even for const. We square this - // circle by passing the const value in as an argument to the lambda. - } else { - cancel_thread = std::thread( - [&context, this](int delay) { - CancelRpc(&context, delay, &callback_service_); - }, - kCancelDelayUs); - } - Status s = stub_->Echo(&context, request, &response); - cancel_thread.join(); - EXPECT_EQ(StatusCode::CANCELLED, s.error_code()); - EXPECT_EQ(s.error_message(), "Cancelled"); -} - -// Server cancels rpc after 1ms -TEST_P(ProxyEnd2endTest, ServerCancelsRpc) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - request.mutable_param()->set_server_cancel_after_us(1000); - - ClientContext context; - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(StatusCode::CANCELLED, s.error_code()); - EXPECT_TRUE(s.error_message().empty()); -} - -// Make the response larger than the flow control window. -TEST_P(ProxyEnd2endTest, HugeResponse) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("huge response"); - const size_t kResponseSize = 1024 * (1024 + 10); - request.mutable_param()->set_response_message_length(kResponseSize); - - ClientContext context; - std::chrono::system_clock::time_point deadline = - std::chrono::system_clock::now() + std::chrono::seconds(20); - context.set_deadline(deadline); - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(kResponseSize, response.message().size()); - EXPECT_TRUE(s.ok()); -} - -TEST_P(ProxyEnd2endTest, Peer) { - MAYBE_SKIP_TEST; - // Peer is not meaningful for inproc - if (GetParam().inproc) { - return; - } - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("hello"); - request.mutable_param()->set_echo_peer(true); - - ClientContext context; - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); - EXPECT_TRUE(CheckIsLocalhost(response.param().peer())); - EXPECT_TRUE(CheckIsLocalhost(context.peer())); -} - -////////////////////////////////////////////////////////////////////////// -class SecureEnd2endTest : public End2endTest { - protected: - SecureEnd2endTest() { - GPR_ASSERT(!GetParam().use_proxy); - GPR_ASSERT(GetParam().credentials_type != kInsecureCredentialsType); - } -}; - -TEST_P(SecureEnd2endTest, SimpleRpcWithHost) { - MAYBE_SKIP_TEST; - ResetStub(); - - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - - ClientContext context; - context.set_authority("foo.test.youtube.com"); - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(response.has_param()); - EXPECT_EQ("special", response.param().host()); - EXPECT_TRUE(s.ok()); -} - -bool MetadataContains( - const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, + } +} + +////////////////////////////////////////////////////////////////////////// +// Test with and without a proxy. +class ProxyEnd2endTest : public End2endTest { + protected: +}; + +TEST_P(ProxyEnd2endTest, SimpleRpc) { + MAYBE_SKIP_TEST; + ResetStub(); + SendRpc(stub_.get(), 1, false); +} + +TEST_P(ProxyEnd2endTest, SimpleRpcWithEmptyMessages) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + + ClientContext context; + Status s = stub_->Echo(&context, request, &response); + EXPECT_TRUE(s.ok()); +} + +TEST_P(ProxyEnd2endTest, MultipleRpcs) { + MAYBE_SKIP_TEST; + ResetStub(); + std::vector<std::thread> threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) { + threads.emplace_back(SendRpc, stub_.get(), 10, false); + } + for (int i = 0; i < 10; ++i) { + threads[i].join(); + } +} + +// Set a 10us deadline and make sure proper error is returned. +TEST_P(ProxyEnd2endTest, RpcDeadlineExpires) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + request.mutable_param()->set_skip_cancelled_check(true); + // Let server sleep for 40 ms first to guarantee expiry. + // 40 ms might seem a bit extreme but the timer manager would have been just + // initialized (when ResetStub() was called) and there are some warmup costs + // i.e the timer thread many not have even started. There might also be other + // delays in the timer manager thread (in acquiring locks, timer data + // structure manipulations, starting backup timer threads) that add to the + // delays. 40ms is still not enough in some cases but this significantly + // reduces the test flakes + request.mutable_param()->set_server_sleep_us(40 * 1000); + + ClientContext context; + std::chrono::system_clock::time_point deadline = + std::chrono::system_clock::now() + std::chrono::milliseconds(1); + context.set_deadline(deadline); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, s.error_code()); +} + +// Set a long but finite deadline. +TEST_P(ProxyEnd2endTest, RpcLongDeadline) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + + ClientContext context; + std::chrono::system_clock::time_point deadline = + std::chrono::system_clock::now() + std::chrono::hours(1); + context.set_deadline(deadline); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); +} + +// Ask server to echo back the deadline it sees. +TEST_P(ProxyEnd2endTest, EchoDeadline) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + request.mutable_param()->set_echo_deadline(true); + + ClientContext context; + std::chrono::system_clock::time_point deadline = + std::chrono::system_clock::now() + std::chrono::seconds(100); + context.set_deadline(deadline); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); + gpr_timespec sent_deadline; + Timepoint2Timespec(deadline, &sent_deadline); + // We want to allow some reasonable error given: + // - request_deadline() only has 1sec resolution so the best we can do is +-1 + // - if sent_deadline.tv_nsec is very close to the next second's boundary we + // can end up being off by 2 in one direction. + EXPECT_LE(response.param().request_deadline() - sent_deadline.tv_sec, 2); + EXPECT_GE(response.param().request_deadline() - sent_deadline.tv_sec, -1); +} + +// Ask server to echo back the deadline it sees. The rpc has no deadline. +TEST_P(ProxyEnd2endTest, EchoDeadlineForNoDeadlineRpc) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + request.mutable_param()->set_echo_deadline(true); + + ClientContext context; + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); + EXPECT_EQ(response.param().request_deadline(), + gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec); +} + +TEST_P(ProxyEnd2endTest, UnimplementedRpc) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + + ClientContext context; + Status s = stub_->Unimplemented(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), grpc::StatusCode::UNIMPLEMENTED); + EXPECT_EQ(s.error_message(), ""); + EXPECT_EQ(response.message(), ""); +} + +// Client cancels rpc after 10ms +TEST_P(ProxyEnd2endTest, ClientCancelsRpc) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + const int kCancelDelayUs = 10 * 1000; + request.mutable_param()->set_client_cancel_after_us(kCancelDelayUs); + + ClientContext context; + std::thread cancel_thread; + if (!GetParam().callback_server) { + cancel_thread = std::thread( + [&context, this](int delay) { CancelRpc(&context, delay, &service_); }, + kCancelDelayUs); + // Note: the unusual pattern above (and below) is caused by a conflict + // between two sets of compiler expectations. clang allows const to be + // captured without mention, so there is no need to capture kCancelDelayUs + // (and indeed clang-tidy complains if you do so). OTOH, a Windows compiler + // in our tests requires an explicit capture even for const. We square this + // circle by passing the const value in as an argument to the lambda. + } else { + cancel_thread = std::thread( + [&context, this](int delay) { + CancelRpc(&context, delay, &callback_service_); + }, + kCancelDelayUs); + } + Status s = stub_->Echo(&context, request, &response); + cancel_thread.join(); + EXPECT_EQ(StatusCode::CANCELLED, s.error_code()); + EXPECT_EQ(s.error_message(), "Cancelled"); +} + +// Server cancels rpc after 1ms +TEST_P(ProxyEnd2endTest, ServerCancelsRpc) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + request.mutable_param()->set_server_cancel_after_us(1000); + + ClientContext context; + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(StatusCode::CANCELLED, s.error_code()); + EXPECT_TRUE(s.error_message().empty()); +} + +// Make the response larger than the flow control window. +TEST_P(ProxyEnd2endTest, HugeResponse) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("huge response"); + const size_t kResponseSize = 1024 * (1024 + 10); + request.mutable_param()->set_response_message_length(kResponseSize); + + ClientContext context; + std::chrono::system_clock::time_point deadline = + std::chrono::system_clock::now() + std::chrono::seconds(20); + context.set_deadline(deadline); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(kResponseSize, response.message().size()); + EXPECT_TRUE(s.ok()); +} + +TEST_P(ProxyEnd2endTest, Peer) { + MAYBE_SKIP_TEST; + // Peer is not meaningful for inproc + if (GetParam().inproc) { + return; + } + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("hello"); + request.mutable_param()->set_echo_peer(true); + + ClientContext context; + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); + EXPECT_TRUE(CheckIsLocalhost(response.param().peer())); + EXPECT_TRUE(CheckIsLocalhost(context.peer())); +} + +////////////////////////////////////////////////////////////////////////// +class SecureEnd2endTest : public End2endTest { + protected: + SecureEnd2endTest() { + GPR_ASSERT(!GetParam().use_proxy); + GPR_ASSERT(GetParam().credentials_type != kInsecureCredentialsType); + } +}; + +TEST_P(SecureEnd2endTest, SimpleRpcWithHost) { + MAYBE_SKIP_TEST; + ResetStub(); + + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + + ClientContext context; + context.set_authority("foo.test.youtube.com"); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(response.has_param()); + EXPECT_EQ("special", response.param().host()); + EXPECT_TRUE(s.ok()); +} + +bool MetadataContains( + const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, const TString& key, const TString& value) { - int count = 0; - - for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator iter = - metadata.begin(); - iter != metadata.end(); ++iter) { - if (ToString(iter->first) == key && ToString(iter->second) == value) { - count++; - } - } - return count == 1; -} - -TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorSuccess) { - MAYBE_SKIP_TEST; - auto* processor = new TestAuthMetadataProcessor(true); - StartServer(std::shared_ptr<AuthMetadataProcessor>(processor)); - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_credentials(processor->GetCompatibleClientCreds()); - request.set_message("Hello"); - request.mutable_param()->set_echo_metadata(true); - request.mutable_param()->set_expected_client_identity( - TestAuthMetadataProcessor::kGoodGuy); - request.mutable_param()->set_expected_transport_security_type( - GetParam().credentials_type); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(request.message(), response.message()); - EXPECT_TRUE(s.ok()); - - // Metadata should have been consumed by the processor. - EXPECT_FALSE(MetadataContains( - context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY, + int count = 0; + + for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator iter = + metadata.begin(); + iter != metadata.end(); ++iter) { + if (ToString(iter->first) == key && ToString(iter->second) == value) { + count++; + } + } + return count == 1; +} + +TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorSuccess) { + MAYBE_SKIP_TEST; + auto* processor = new TestAuthMetadataProcessor(true); + StartServer(std::shared_ptr<AuthMetadataProcessor>(processor)); + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(processor->GetCompatibleClientCreds()); + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + request.mutable_param()->set_expected_client_identity( + TestAuthMetadataProcessor::kGoodGuy); + request.mutable_param()->set_expected_transport_security_type( + GetParam().credentials_type); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.ok()); + + // Metadata should have been consumed by the processor. + EXPECT_FALSE(MetadataContains( + context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY, TString("Bearer ") + TestAuthMetadataProcessor::kGoodGuy)); -} - -TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorFailure) { - MAYBE_SKIP_TEST; - auto* processor = new TestAuthMetadataProcessor(true); - StartServer(std::shared_ptr<AuthMetadataProcessor>(processor)); - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_credentials(processor->GetIncompatibleClientCreds()); - request.set_message("Hello"); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); -} - -TEST_P(SecureEnd2endTest, SetPerCallCredentials) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - std::shared_ptr<CallCredentials> creds = +} + +TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorFailure) { + MAYBE_SKIP_TEST; + auto* processor = new TestAuthMetadataProcessor(true); + StartServer(std::shared_ptr<AuthMetadataProcessor>(processor)); + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(processor->GetIncompatibleClientCreds()); + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); +} + +TEST_P(SecureEnd2endTest, SetPerCallCredentials) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + std::shared_ptr<CallCredentials> creds = GoogleIAMCredentials(kFakeToken, kFakeSelector); - context.set_credentials(creds); - request.set_message("Hello"); - request.mutable_param()->set_echo_metadata(true); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(request.message(), response.message()); - EXPECT_TRUE(s.ok()); - EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + context.set_credentials(creds); + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.ok()); + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, kFakeToken)); - EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, kFakeSelector)); EXPECT_EQ(context.credentials()->DebugString(), kExpectedFakeCredsDebugString); -} - -class CredentialsInterceptor : public experimental::Interceptor { - public: - CredentialsInterceptor(experimental::ClientRpcInfo* info) : info_(info) {} - - void Intercept(experimental::InterceptorBatchMethods* methods) { - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { - std::shared_ptr<CallCredentials> creds = +} + +class CredentialsInterceptor : public experimental::Interceptor { + public: + CredentialsInterceptor(experimental::ClientRpcInfo* info) : info_(info) {} + + void Intercept(experimental::InterceptorBatchMethods* methods) { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + std::shared_ptr<CallCredentials> creds = GoogleIAMCredentials(kFakeToken, kFakeSelector); - info_->client_context()->set_credentials(creds); - } - methods->Proceed(); - } - - private: - experimental::ClientRpcInfo* info_ = nullptr; -}; - -class CredentialsInterceptorFactory - : public experimental::ClientInterceptorFactoryInterface { - CredentialsInterceptor* CreateClientInterceptor( - experimental::ClientRpcInfo* info) { - return new CredentialsInterceptor(info); - } -}; - -TEST_P(SecureEnd2endTest, CallCredentialsInterception) { - MAYBE_SKIP_TEST; - if (!GetParam().use_interceptors) { - return; - } - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators; - interceptor_creators.push_back(std::unique_ptr<CredentialsInterceptorFactory>( - new CredentialsInterceptorFactory())); - ResetStub(std::move(interceptor_creators)); - EchoRequest request; - EchoResponse response; - ClientContext context; - - request.set_message("Hello"); - request.mutable_param()->set_echo_metadata(true); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(request.message(), response.message()); - EXPECT_TRUE(s.ok()); - EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + info_->client_context()->set_credentials(creds); + } + methods->Proceed(); + } + + private: + experimental::ClientRpcInfo* info_ = nullptr; +}; + +class CredentialsInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + CredentialsInterceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) { + return new CredentialsInterceptor(info); + } +}; + +TEST_P(SecureEnd2endTest, CallCredentialsInterception) { + MAYBE_SKIP_TEST; + if (!GetParam().use_interceptors) { + return; + } + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators; + interceptor_creators.push_back(std::unique_ptr<CredentialsInterceptorFactory>( + new CredentialsInterceptorFactory())); + ResetStub(std::move(interceptor_creators)); + EchoRequest request; + EchoResponse response; + ClientContext context; + + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.ok()); + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, kFakeToken)); - EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, kFakeSelector)); EXPECT_EQ(context.credentials()->DebugString(), kExpectedFakeCredsDebugString); -} - -TEST_P(SecureEnd2endTest, CallCredentialsInterceptionWithSetCredentials) { - MAYBE_SKIP_TEST; - if (!GetParam().use_interceptors) { - return; - } - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators; - interceptor_creators.push_back(std::unique_ptr<CredentialsInterceptorFactory>( - new CredentialsInterceptorFactory())); - ResetStub(std::move(interceptor_creators)); - EchoRequest request; - EchoResponse response; - ClientContext context; - std::shared_ptr<CallCredentials> creds1 = +} + +TEST_P(SecureEnd2endTest, CallCredentialsInterceptionWithSetCredentials) { + MAYBE_SKIP_TEST; + if (!GetParam().use_interceptors) { + return; + } + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators; + interceptor_creators.push_back(std::unique_ptr<CredentialsInterceptorFactory>( + new CredentialsInterceptorFactory())); + ResetStub(std::move(interceptor_creators)); + EchoRequest request; + EchoResponse response; + ClientContext context; + std::shared_ptr<CallCredentials> creds1 = GoogleIAMCredentials(kWrongToken, kWrongSelector); - context.set_credentials(creds1); - EXPECT_EQ(context.credentials(), creds1); + context.set_credentials(creds1); + EXPECT_EQ(context.credentials(), creds1); EXPECT_EQ(context.credentials()->DebugString(), kExpectedWrongCredsDebugString); - request.set_message("Hello"); - request.mutable_param()->set_echo_metadata(true); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(request.message(), response.message()); - EXPECT_TRUE(s.ok()); - EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.ok()); + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, kFakeToken)); - EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, kFakeSelector)); EXPECT_EQ(context.credentials()->DebugString(), kExpectedFakeCredsDebugString); -} - -TEST_P(SecureEnd2endTest, OverridePerCallCredentials) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - std::shared_ptr<CallCredentials> creds1 = +} + +TEST_P(SecureEnd2endTest, OverridePerCallCredentials) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + std::shared_ptr<CallCredentials> creds1 = GoogleIAMCredentials(kFakeToken1, kFakeSelector1); - context.set_credentials(creds1); - EXPECT_EQ(context.credentials(), creds1); + context.set_credentials(creds1); + EXPECT_EQ(context.credentials(), creds1); EXPECT_EQ(context.credentials()->DebugString(), kExpectedFakeCreds1DebugString); - std::shared_ptr<CallCredentials> creds2 = + std::shared_ptr<CallCredentials> creds2 = GoogleIAMCredentials(kFakeToken2, kFakeSelector2); - context.set_credentials(creds2); - EXPECT_EQ(context.credentials(), creds2); - request.set_message("Hello"); - request.mutable_param()->set_echo_metadata(true); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + context.set_credentials(creds2); + EXPECT_EQ(context.credentials(), creds2); + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, kFakeToken2)); - EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, kFakeSelector2)); - EXPECT_FALSE(MetadataContains(context.GetServerTrailingMetadata(), - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + EXPECT_FALSE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, kFakeToken1)); - EXPECT_FALSE(MetadataContains(context.GetServerTrailingMetadata(), - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + EXPECT_FALSE(MetadataContains(context.GetServerTrailingMetadata(), + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, kFakeSelector1)); EXPECT_EQ(context.credentials()->DebugString(), kExpectedFakeCreds2DebugString); - EXPECT_EQ(request.message(), response.message()); - EXPECT_TRUE(s.ok()); -} - -TEST_P(SecureEnd2endTest, AuthMetadataPluginKeyFailure) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_credentials(grpc::MetadataCredentialsFromPlugin( - std::unique_ptr<MetadataCredentialsPlugin>( - new TestMetadataCredentialsPlugin( - TestMetadataCredentialsPlugin::kBadMetadataKey, - "Does not matter, will fail the key is invalid.", false, true, - 0)))); - request.set_message("Hello"); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.ok()); +} + +TEST_P(SecureEnd2endTest, AuthMetadataPluginKeyFailure) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(grpc::MetadataCredentialsFromPlugin( + std::unique_ptr<MetadataCredentialsPlugin>( + new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kBadMetadataKey, + "Does not matter, will fail the key is invalid.", false, true, + 0)))); + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); EXPECT_EQ(context.credentials()->DebugString(), kExpectedAuthMetadataPluginKeyFailureCredsDebugString); -} - -TEST_P(SecureEnd2endTest, AuthMetadataPluginValueFailure) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_credentials(grpc::MetadataCredentialsFromPlugin( - std::unique_ptr<MetadataCredentialsPlugin>( - new TestMetadataCredentialsPlugin( - TestMetadataCredentialsPlugin::kGoodMetadataKey, - "With illegal \n value.", false, true, 0)))); - request.set_message("Hello"); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); +} + +TEST_P(SecureEnd2endTest, AuthMetadataPluginValueFailure) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(grpc::MetadataCredentialsFromPlugin( + std::unique_ptr<MetadataCredentialsPlugin>( + new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kGoodMetadataKey, + "With illegal \n value.", false, true, 0)))); + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); EXPECT_EQ(context.credentials()->DebugString(), kExpectedAuthMetadataPluginValueFailureCredsDebugString); -} - -TEST_P(SecureEnd2endTest, AuthMetadataPluginWithDeadline) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - request.mutable_param()->set_skip_cancelled_check(true); - EchoResponse response; - ClientContext context; - const int delay = 100; - std::chrono::system_clock::time_point deadline = - std::chrono::system_clock::now() + std::chrono::milliseconds(delay); - context.set_deadline(deadline); - context.set_credentials(grpc::MetadataCredentialsFromPlugin( - std::unique_ptr<MetadataCredentialsPlugin>( - new TestMetadataCredentialsPlugin("meta_key", "Does not matter", true, - true, delay)))); - request.set_message("Hello"); - - Status s = stub_->Echo(&context, request, &response); - if (!s.ok()) { - EXPECT_TRUE(s.error_code() == StatusCode::DEADLINE_EXCEEDED || - s.error_code() == StatusCode::UNAVAILABLE); - } +} + +TEST_P(SecureEnd2endTest, AuthMetadataPluginWithDeadline) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + request.mutable_param()->set_skip_cancelled_check(true); + EchoResponse response; + ClientContext context; + const int delay = 100; + std::chrono::system_clock::time_point deadline = + std::chrono::system_clock::now() + std::chrono::milliseconds(delay); + context.set_deadline(deadline); + context.set_credentials(grpc::MetadataCredentialsFromPlugin( + std::unique_ptr<MetadataCredentialsPlugin>( + new TestMetadataCredentialsPlugin("meta_key", "Does not matter", true, + true, delay)))); + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + if (!s.ok()) { + EXPECT_TRUE(s.error_code() == StatusCode::DEADLINE_EXCEEDED || + s.error_code() == StatusCode::UNAVAILABLE); + } EXPECT_EQ(context.credentials()->DebugString(), kExpectedAuthMetadataPluginWithDeadlineCredsDebugString); -} - -TEST_P(SecureEnd2endTest, AuthMetadataPluginWithCancel) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - request.mutable_param()->set_skip_cancelled_check(true); - EchoResponse response; - ClientContext context; - const int delay = 100; - context.set_credentials(grpc::MetadataCredentialsFromPlugin( - std::unique_ptr<MetadataCredentialsPlugin>( - new TestMetadataCredentialsPlugin("meta_key", "Does not matter", true, - true, delay)))); - request.set_message("Hello"); - - std::thread cancel_thread([&] { - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_millis(delay, GPR_TIMESPAN))); - context.TryCancel(); - }); - Status s = stub_->Echo(&context, request, &response); - if (!s.ok()) { - EXPECT_TRUE(s.error_code() == StatusCode::CANCELLED || - s.error_code() == StatusCode::UNAVAILABLE); - } - cancel_thread.join(); +} + +TEST_P(SecureEnd2endTest, AuthMetadataPluginWithCancel) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + request.mutable_param()->set_skip_cancelled_check(true); + EchoResponse response; + ClientContext context; + const int delay = 100; + context.set_credentials(grpc::MetadataCredentialsFromPlugin( + std::unique_ptr<MetadataCredentialsPlugin>( + new TestMetadataCredentialsPlugin("meta_key", "Does not matter", true, + true, delay)))); + request.set_message("Hello"); + + std::thread cancel_thread([&] { + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(delay, GPR_TIMESPAN))); + context.TryCancel(); + }); + Status s = stub_->Echo(&context, request, &response); + if (!s.ok()) { + EXPECT_TRUE(s.error_code() == StatusCode::CANCELLED || + s.error_code() == StatusCode::UNAVAILABLE); + } + cancel_thread.join(); EXPECT_EQ(context.credentials()->DebugString(), kExpectedAuthMetadataPluginWithDeadlineCredsDebugString); -} - -TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_credentials(grpc::MetadataCredentialsFromPlugin( - std::unique_ptr<MetadataCredentialsPlugin>( - new TestMetadataCredentialsPlugin( - TestMetadataCredentialsPlugin::kGoodMetadataKey, - "Does not matter, will fail anyway (see 3rd param)", false, false, - 0)))); - request.set_message("Hello"); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); - EXPECT_EQ(s.error_message(), +} + +TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(grpc::MetadataCredentialsFromPlugin( + std::unique_ptr<MetadataCredentialsPlugin>( + new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kGoodMetadataKey, + "Does not matter, will fail anyway (see 3rd param)", false, false, + 0)))); + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); + EXPECT_EQ(s.error_message(), TString("Getting metadata from plugin failed with error: ") + - kTestCredsPluginErrorMsg); + kTestCredsPluginErrorMsg); EXPECT_EQ(context.credentials()->DebugString(), kExpectedNonBlockingAuthMetadataPluginFailureCredsDebugString); -} - -TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) { - MAYBE_SKIP_TEST; - auto* processor = new TestAuthMetadataProcessor(false); - StartServer(std::shared_ptr<AuthMetadataProcessor>(processor)); - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_credentials(processor->GetCompatibleClientCreds()); - request.set_message("Hello"); - request.mutable_param()->set_echo_metadata(true); - request.mutable_param()->set_expected_client_identity( - TestAuthMetadataProcessor::kGoodGuy); - request.mutable_param()->set_expected_transport_security_type( - GetParam().credentials_type); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(request.message(), response.message()); - EXPECT_TRUE(s.ok()); - - // Metadata should have been consumed by the processor. - EXPECT_FALSE(MetadataContains( - context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY, +} + +TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) { + MAYBE_SKIP_TEST; + auto* processor = new TestAuthMetadataProcessor(false); + StartServer(std::shared_ptr<AuthMetadataProcessor>(processor)); + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(processor->GetCompatibleClientCreds()); + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + request.mutable_param()->set_expected_client_identity( + TestAuthMetadataProcessor::kGoodGuy); + request.mutable_param()->set_expected_transport_security_type( + GetParam().credentials_type); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.ok()); + + // Metadata should have been consumed by the processor. + EXPECT_FALSE(MetadataContains( + context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY, TString("Bearer ") + TestAuthMetadataProcessor::kGoodGuy)); EXPECT_EQ( context.credentials()->DebugString(), kExpectedNonBlockingAuthMetadataPluginAndProcessorSuccessCredsDebugString); -} - -TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorFailure) { - MAYBE_SKIP_TEST; - auto* processor = new TestAuthMetadataProcessor(false); - StartServer(std::shared_ptr<AuthMetadataProcessor>(processor)); - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_credentials(processor->GetIncompatibleClientCreds()); - request.set_message("Hello"); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); +} + +TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorFailure) { + MAYBE_SKIP_TEST; + auto* processor = new TestAuthMetadataProcessor(false); + StartServer(std::shared_ptr<AuthMetadataProcessor>(processor)); + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(processor->GetIncompatibleClientCreds()); + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); EXPECT_EQ( context.credentials()->DebugString(), kExpectedNonBlockingAuthMetadataPluginAndProcessorFailureCredsDebugString); -} - -TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginFailure) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_credentials(grpc::MetadataCredentialsFromPlugin( - std::unique_ptr<MetadataCredentialsPlugin>( - new TestMetadataCredentialsPlugin( - TestMetadataCredentialsPlugin::kGoodMetadataKey, - "Does not matter, will fail anyway (see 3rd param)", true, false, - 0)))); - request.set_message("Hello"); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); - EXPECT_EQ(s.error_message(), +} + +TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginFailure) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(grpc::MetadataCredentialsFromPlugin( + std::unique_ptr<MetadataCredentialsPlugin>( + new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kGoodMetadataKey, + "Does not matter, will fail anyway (see 3rd param)", true, false, + 0)))); + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNAVAILABLE); + EXPECT_EQ(s.error_message(), TString("Getting metadata from plugin failed with error: ") + - kTestCredsPluginErrorMsg); + kTestCredsPluginErrorMsg); EXPECT_EQ(context.credentials()->DebugString(), kExpectedBlockingAuthMetadataPluginFailureCredsDebugString); -} - -TEST_P(SecureEnd2endTest, CompositeCallCreds) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - ClientContext context; - const char kMetadataKey1[] = "call-creds-key1"; - const char kMetadataKey2[] = "call-creds-key2"; - const char kMetadataVal1[] = "call-creds-val1"; - const char kMetadataVal2[] = "call-creds-val2"; - - context.set_credentials(grpc::CompositeCallCredentials( - grpc::MetadataCredentialsFromPlugin( - std::unique_ptr<MetadataCredentialsPlugin>( - new TestMetadataCredentialsPlugin(kMetadataKey1, kMetadataVal1, - true, true, 0))), - grpc::MetadataCredentialsFromPlugin( - std::unique_ptr<MetadataCredentialsPlugin>( - new TestMetadataCredentialsPlugin(kMetadataKey2, kMetadataVal2, - true, true, 0))))); - request.set_message("Hello"); - request.mutable_param()->set_echo_metadata(true); - - Status s = stub_->Echo(&context, request, &response); - EXPECT_TRUE(s.ok()); - EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), - kMetadataKey1, kMetadataVal1)); - EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), - kMetadataKey2, kMetadataVal2)); +} + +TEST_P(SecureEnd2endTest, CompositeCallCreds) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + const char kMetadataKey1[] = "call-creds-key1"; + const char kMetadataKey2[] = "call-creds-key2"; + const char kMetadataVal1[] = "call-creds-val1"; + const char kMetadataVal2[] = "call-creds-val2"; + + context.set_credentials(grpc::CompositeCallCredentials( + grpc::MetadataCredentialsFromPlugin( + std::unique_ptr<MetadataCredentialsPlugin>( + new TestMetadataCredentialsPlugin(kMetadataKey1, kMetadataVal1, + true, true, 0))), + grpc::MetadataCredentialsFromPlugin( + std::unique_ptr<MetadataCredentialsPlugin>( + new TestMetadataCredentialsPlugin(kMetadataKey2, kMetadataVal2, + true, true, 0))))); + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_TRUE(s.ok()); + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + kMetadataKey1, kMetadataVal1)); + EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(), + kMetadataKey2, kMetadataVal2)); EXPECT_EQ(context.credentials()->DebugString(), kExpectedCompositeCallCredsDebugString); -} - -TEST_P(SecureEnd2endTest, ClientAuthContext) { - MAYBE_SKIP_TEST; - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - request.mutable_param()->set_check_auth_context(GetParam().credentials_type == - kTlsCredentialsType); - request.mutable_param()->set_expected_transport_security_type( - GetParam().credentials_type); - ClientContext context; - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); - - std::shared_ptr<const AuthContext> auth_ctx = context.auth_context(); - std::vector<grpc::string_ref> tst = - auth_ctx->FindPropertyValues("transport_security_type"); - ASSERT_EQ(1u, tst.size()); - EXPECT_EQ(GetParam().credentials_type, ToString(tst[0])); - if (GetParam().credentials_type == kTlsCredentialsType) { - EXPECT_EQ("x509_subject_alternative_name", - auth_ctx->GetPeerIdentityPropertyName()); - EXPECT_EQ(4u, auth_ctx->GetPeerIdentity().size()); - EXPECT_EQ("*.test.google.fr", ToString(auth_ctx->GetPeerIdentity()[0])); - EXPECT_EQ("waterzooi.test.google.be", - ToString(auth_ctx->GetPeerIdentity()[1])); - EXPECT_EQ("*.test.youtube.com", ToString(auth_ctx->GetPeerIdentity()[2])); - EXPECT_EQ("192.168.1.3", ToString(auth_ctx->GetPeerIdentity()[3])); - } -} - -class ResourceQuotaEnd2endTest : public End2endTest { - public: - ResourceQuotaEnd2endTest() - : server_resource_quota_("server_resource_quota") {} - - virtual void ConfigureServerBuilder(ServerBuilder* builder) override { - builder->SetResourceQuota(server_resource_quota_); - } - - private: - ResourceQuota server_resource_quota_; -}; - -TEST_P(ResourceQuotaEnd2endTest, SimpleRequest) { - MAYBE_SKIP_TEST; - ResetStub(); - - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - - ClientContext context; - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); -} - -// TODO(vjpai): refactor arguments into a struct if it makes sense -std::vector<TestScenario> CreateTestScenarios(bool use_proxy, - bool test_insecure, - bool test_secure, - bool test_inproc, - bool test_callback_server) { - std::vector<TestScenario> scenarios; +} + +TEST_P(SecureEnd2endTest, ClientAuthContext) { + MAYBE_SKIP_TEST; + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + request.mutable_param()->set_check_auth_context(GetParam().credentials_type == + kTlsCredentialsType); + request.mutable_param()->set_expected_transport_security_type( + GetParam().credentials_type); + ClientContext context; + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); + + std::shared_ptr<const AuthContext> auth_ctx = context.auth_context(); + std::vector<grpc::string_ref> tst = + auth_ctx->FindPropertyValues("transport_security_type"); + ASSERT_EQ(1u, tst.size()); + EXPECT_EQ(GetParam().credentials_type, ToString(tst[0])); + if (GetParam().credentials_type == kTlsCredentialsType) { + EXPECT_EQ("x509_subject_alternative_name", + auth_ctx->GetPeerIdentityPropertyName()); + EXPECT_EQ(4u, auth_ctx->GetPeerIdentity().size()); + EXPECT_EQ("*.test.google.fr", ToString(auth_ctx->GetPeerIdentity()[0])); + EXPECT_EQ("waterzooi.test.google.be", + ToString(auth_ctx->GetPeerIdentity()[1])); + EXPECT_EQ("*.test.youtube.com", ToString(auth_ctx->GetPeerIdentity()[2])); + EXPECT_EQ("192.168.1.3", ToString(auth_ctx->GetPeerIdentity()[3])); + } +} + +class ResourceQuotaEnd2endTest : public End2endTest { + public: + ResourceQuotaEnd2endTest() + : server_resource_quota_("server_resource_quota") {} + + virtual void ConfigureServerBuilder(ServerBuilder* builder) override { + builder->SetResourceQuota(server_resource_quota_); + } + + private: + ResourceQuota server_resource_quota_; +}; + +TEST_P(ResourceQuotaEnd2endTest, SimpleRequest) { + MAYBE_SKIP_TEST; + ResetStub(); + + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + + ClientContext context; + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); +} + +// TODO(vjpai): refactor arguments into a struct if it makes sense +std::vector<TestScenario> CreateTestScenarios(bool use_proxy, + bool test_insecure, + bool test_secure, + bool test_inproc, + bool test_callback_server) { + std::vector<TestScenario> scenarios; std::vector<TString> credentials_types; - + GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, kClientChannelBackupPollIntervalMs); -#if TARGET_OS_IPHONE - // Workaround Apple CFStream bug - gpr_setenv("grpc_cfstream", "0"); -#endif - - if (test_secure) { - credentials_types = - GetCredentialsProvider()->GetSecureCredentialsTypeList(); - } - auto insec_ok = [] { - // Only allow insecure credentials type when it is registered with the - // provider. User may create providers that do not have insecure. - return GetCredentialsProvider()->GetChannelCredentials( - kInsecureCredentialsType, nullptr) != nullptr; - }; - if (test_insecure && insec_ok()) { - credentials_types.push_back(kInsecureCredentialsType); - } - - // Test callback with inproc or if the event-engine allows it - GPR_ASSERT(!credentials_types.empty()); - for (const auto& cred : credentials_types) { - scenarios.emplace_back(false, false, false, cred, false); - scenarios.emplace_back(true, false, false, cred, false); - if (test_callback_server) { - // Note that these scenarios will be dynamically disabled if the event - // engine doesn't run in the background - scenarios.emplace_back(false, false, false, cred, true); - scenarios.emplace_back(true, false, false, cred, true); - } - if (use_proxy) { - scenarios.emplace_back(false, true, false, cred, false); - scenarios.emplace_back(true, true, false, cred, false); - } - } - if (test_inproc && insec_ok()) { - scenarios.emplace_back(false, false, true, kInsecureCredentialsType, false); - scenarios.emplace_back(true, false, true, kInsecureCredentialsType, false); - if (test_callback_server) { - scenarios.emplace_back(false, false, true, kInsecureCredentialsType, - true); - scenarios.emplace_back(true, false, true, kInsecureCredentialsType, true); - } - } - return scenarios; -} - -INSTANTIATE_TEST_SUITE_P( - End2end, End2endTest, - ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true))); - -INSTANTIATE_TEST_SUITE_P( - End2endServerTryCancel, End2endServerTryCancelTest, - ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true))); - -INSTANTIATE_TEST_SUITE_P( - ProxyEnd2end, ProxyEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(true, true, true, true, true))); - -INSTANTIATE_TEST_SUITE_P( - SecureEnd2end, SecureEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(false, false, true, false, true))); - -INSTANTIATE_TEST_SUITE_P( - ResourceQuotaEnd2end, ResourceQuotaEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true))); - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - int ret = RUN_ALL_TESTS(); - return ret; -} +#if TARGET_OS_IPHONE + // Workaround Apple CFStream bug + gpr_setenv("grpc_cfstream", "0"); +#endif + + if (test_secure) { + credentials_types = + GetCredentialsProvider()->GetSecureCredentialsTypeList(); + } + auto insec_ok = [] { + // Only allow insecure credentials type when it is registered with the + // provider. User may create providers that do not have insecure. + return GetCredentialsProvider()->GetChannelCredentials( + kInsecureCredentialsType, nullptr) != nullptr; + }; + if (test_insecure && insec_ok()) { + credentials_types.push_back(kInsecureCredentialsType); + } + + // Test callback with inproc or if the event-engine allows it + GPR_ASSERT(!credentials_types.empty()); + for (const auto& cred : credentials_types) { + scenarios.emplace_back(false, false, false, cred, false); + scenarios.emplace_back(true, false, false, cred, false); + if (test_callback_server) { + // Note that these scenarios will be dynamically disabled if the event + // engine doesn't run in the background + scenarios.emplace_back(false, false, false, cred, true); + scenarios.emplace_back(true, false, false, cred, true); + } + if (use_proxy) { + scenarios.emplace_back(false, true, false, cred, false); + scenarios.emplace_back(true, true, false, cred, false); + } + } + if (test_inproc && insec_ok()) { + scenarios.emplace_back(false, false, true, kInsecureCredentialsType, false); + scenarios.emplace_back(true, false, true, kInsecureCredentialsType, false); + if (test_callback_server) { + scenarios.emplace_back(false, false, true, kInsecureCredentialsType, + true); + scenarios.emplace_back(true, false, true, kInsecureCredentialsType, true); + } + } + return scenarios; +} + +INSTANTIATE_TEST_SUITE_P( + End2end, End2endTest, + ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true))); + +INSTANTIATE_TEST_SUITE_P( + End2endServerTryCancel, End2endServerTryCancelTest, + ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true))); + +INSTANTIATE_TEST_SUITE_P( + ProxyEnd2end, ProxyEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(true, true, true, true, true))); + +INSTANTIATE_TEST_SUITE_P( + SecureEnd2end, SecureEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(false, false, true, false, true))); + +INSTANTIATE_TEST_SUITE_P( + ResourceQuotaEnd2end, ResourceQuotaEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true))); + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + int ret = RUN_ALL_TESTS(); + return ret; +} diff --git a/contrib/libs/grpc/test/cpp/end2end/exception_test.cc b/contrib/libs/grpc/test/cpp/end2end/exception_test.cc index da342f1dfd..cd29eb8a10 100644 --- a/contrib/libs/grpc/test/cpp/end2end/exception_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/exception_test.cc @@ -1,123 +1,123 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * 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. - * - */ - -#include <exception> -#include <memory> - -#include <grpc/impl/codegen/port_platform.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/test_config.h" - -#include <gtest/gtest.h> - -namespace grpc { -namespace testing { - -const char* kErrorMessage = "This service caused an exception"; - -#if GRPC_ALLOW_EXCEPTIONS -class ExceptingServiceImpl : public ::grpc::testing::EchoTestService::Service { - public: - Status Echo(ServerContext* /*server_context*/, const EchoRequest* /*request*/, - EchoResponse* /*response*/) override { - throw - 1; - } - Status RequestStream(ServerContext* /*context*/, - ServerReader<EchoRequest>* /*reader*/, - EchoResponse* /*response*/) override { - throw ServiceException(); - } - - private: - class ServiceException final : public std::exception { - public: - ServiceException() {} - - private: - const char* what() const noexcept override { return kErrorMessage; } - }; -}; - -class ExceptionTest : public ::testing::Test { - protected: - ExceptionTest() {} - - void SetUp() override { - ServerBuilder builder; - builder.RegisterService(&service_); - server_ = builder.BuildAndStart(); - } - - void TearDown() override { server_->Shutdown(); } - - void ResetStub() { - channel_ = server_->InProcessChannel(ChannelArguments()); - stub_ = grpc::testing::EchoTestService::NewStub(channel_); - } - - std::shared_ptr<Channel> channel_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - ExceptingServiceImpl service_; -}; - -TEST_F(ExceptionTest, Unary) { - ResetStub(); - EchoRequest request; - EchoResponse response; - request.set_message("test"); - - for (int i = 0; i < 10; i++) { - ClientContext context; - Status s = stub_->Echo(&context, request, &response); - EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNKNOWN); - } -} - -TEST_F(ExceptionTest, RequestStream) { - ResetStub(); - EchoResponse response; - - for (int i = 0; i < 10; i++) { - ClientContext context; - auto stream = stub_->RequestStream(&context, &response); - stream->WritesDone(); - Status s = stream->Finish(); - - EXPECT_FALSE(s.ok()); - EXPECT_EQ(s.error_code(), StatusCode::UNKNOWN); - } -} - -#endif // GRPC_ALLOW_EXCEPTIONS - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} +/* + * + * Copyright 2017 gRPC authors. + * + * 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. + * + */ + +#include <exception> +#include <memory> + +#include <grpc/impl/codegen/port_platform.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/test_config.h" + +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { + +const char* kErrorMessage = "This service caused an exception"; + +#if GRPC_ALLOW_EXCEPTIONS +class ExceptingServiceImpl : public ::grpc::testing::EchoTestService::Service { + public: + Status Echo(ServerContext* /*server_context*/, const EchoRequest* /*request*/, + EchoResponse* /*response*/) override { + throw - 1; + } + Status RequestStream(ServerContext* /*context*/, + ServerReader<EchoRequest>* /*reader*/, + EchoResponse* /*response*/) override { + throw ServiceException(); + } + + private: + class ServiceException final : public std::exception { + public: + ServiceException() {} + + private: + const char* what() const noexcept override { return kErrorMessage; } + }; +}; + +class ExceptionTest : public ::testing::Test { + protected: + ExceptionTest() {} + + void SetUp() override { + ServerBuilder builder; + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + + void TearDown() override { server_->Shutdown(); } + + void ResetStub() { + channel_ = server_->InProcessChannel(ChannelArguments()); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + std::shared_ptr<Channel> channel_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + ExceptingServiceImpl service_; +}; + +TEST_F(ExceptionTest, Unary) { + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("test"); + + for (int i = 0; i < 10; i++) { + ClientContext context; + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNKNOWN); + } +} + +TEST_F(ExceptionTest, RequestStream) { + ResetStub(); + EchoResponse response; + + for (int i = 0; i < 10; i++) { + ClientContext context; + auto stream = stub_->RequestStream(&context, &response); + stream->WritesDone(); + Status s = stream->Finish(); + + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNKNOWN); + } +} + +#endif // GRPC_ALLOW_EXCEPTIONS + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/filter_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/filter_end2end_test.cc index d4724f4ce7..2f26d0716c 100644 --- a/contrib/libs/grpc/test/cpp/end2end/filter_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/filter_end2end_test.cc @@ -1,346 +1,346 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * 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. - * - */ - -#include <memory> -#include <mutex> +/* + * + * Copyright 2016 gRPC authors. + * + * 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. + * + */ + +#include <memory> +#include <mutex> #include <thread> - -#include <grpc/grpc.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/generic/async_generic_service.h> -#include <grpcpp/generic/generic_stub.h> -#include <grpcpp/impl/codegen/proto_utils.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> -#include <grpcpp/support/config.h> -#include <grpcpp/support/slice.h> - -#include "src/cpp/common/channel_filter.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/util/byte_buffer_proto_helper.h" - -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; -using std::chrono::system_clock; - -namespace grpc { -namespace testing { -namespace { - -void* tag(int i) { return (void*)static_cast<intptr_t>(i); } - -void verify_ok(CompletionQueue* cq, int i, bool expect_ok) { - bool ok; - void* got_tag; - EXPECT_TRUE(cq->Next(&got_tag, &ok)); - EXPECT_EQ(expect_ok, ok); - EXPECT_EQ(tag(i), got_tag); -} - -namespace { - -int global_num_connections = 0; -int global_num_calls = 0; -std::mutex global_mu; - -void IncrementConnectionCounter() { - std::unique_lock<std::mutex> lock(global_mu); - ++global_num_connections; -} - -void ResetConnectionCounter() { - std::unique_lock<std::mutex> lock(global_mu); - global_num_connections = 0; -} - -int GetConnectionCounterValue() { - std::unique_lock<std::mutex> lock(global_mu); - return global_num_connections; -} - -void IncrementCallCounter() { - std::unique_lock<std::mutex> lock(global_mu); - ++global_num_calls; -} - -void ResetCallCounter() { - std::unique_lock<std::mutex> lock(global_mu); - global_num_calls = 0; -} - -int GetCallCounterValue() { - std::unique_lock<std::mutex> lock(global_mu); - return global_num_calls; -} - -} // namespace - -class ChannelDataImpl : public ChannelData { - public: - grpc_error* Init(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { - IncrementConnectionCounter(); - return GRPC_ERROR_NONE; - } -}; - -class CallDataImpl : public CallData { - public: - void StartTransportStreamOpBatch(grpc_call_element* elem, - TransportStreamOpBatch* op) override { - // Incrementing the counter could be done from Init(), but we want - // to test that the individual methods are actually called correctly. - if (op->recv_initial_metadata() != nullptr) IncrementCallCounter(); - grpc_call_next_op(elem, op->op()); - } -}; - -class FilterEnd2endTest : public ::testing::Test { - protected: - FilterEnd2endTest() : server_host_("localhost") {} - - static void SetUpTestCase() { - // Workaround for - // https://github.com/google/google-toolbox-for-mac/issues/242 - static bool setup_done = false; - if (!setup_done) { - setup_done = true; - grpc::RegisterChannelFilter<ChannelDataImpl, CallDataImpl>( - "test-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr); - } - } - - void SetUp() override { - int port = grpc_pick_unused_port_or_die(); - server_address_ << server_host_ << ":" << port; - // Setup server - ServerBuilder builder; - builder.AddListeningPort(server_address_.str(), - InsecureServerCredentials()); - builder.RegisterAsyncGenericService(&generic_service_); - srv_cq_ = builder.AddCompletionQueue(); - server_ = builder.BuildAndStart(); - } - - void TearDown() override { - server_->Shutdown(); - void* ignored_tag; - bool ignored_ok; - cli_cq_.Shutdown(); - srv_cq_->Shutdown(); - while (cli_cq_.Next(&ignored_tag, &ignored_ok)) - ; - while (srv_cq_->Next(&ignored_tag, &ignored_ok)) - ; - } - - void ResetStub() { - std::shared_ptr<Channel> channel = grpc::CreateChannel( - server_address_.str(), InsecureChannelCredentials()); - generic_stub_.reset(new GenericStub(channel)); - ResetConnectionCounter(); - ResetCallCounter(); - } - - void server_ok(int i) { verify_ok(srv_cq_.get(), i, true); } - void client_ok(int i) { verify_ok(&cli_cq_, i, true); } - void server_fail(int i) { verify_ok(srv_cq_.get(), i, false); } - void client_fail(int i) { verify_ok(&cli_cq_, i, false); } - - void SendRpc(int num_rpcs) { + +#include <grpc/grpc.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/generic/async_generic_service.h> +#include <grpcpp/generic/generic_stub.h> +#include <grpcpp/impl/codegen/proto_utils.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> +#include <grpcpp/support/config.h> +#include <grpcpp/support/slice.h> + +#include "src/cpp/common/channel_filter.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" + +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; +using std::chrono::system_clock; + +namespace grpc { +namespace testing { +namespace { + +void* tag(int i) { return (void*)static_cast<intptr_t>(i); } + +void verify_ok(CompletionQueue* cq, int i, bool expect_ok) { + bool ok; + void* got_tag; + EXPECT_TRUE(cq->Next(&got_tag, &ok)); + EXPECT_EQ(expect_ok, ok); + EXPECT_EQ(tag(i), got_tag); +} + +namespace { + +int global_num_connections = 0; +int global_num_calls = 0; +std::mutex global_mu; + +void IncrementConnectionCounter() { + std::unique_lock<std::mutex> lock(global_mu); + ++global_num_connections; +} + +void ResetConnectionCounter() { + std::unique_lock<std::mutex> lock(global_mu); + global_num_connections = 0; +} + +int GetConnectionCounterValue() { + std::unique_lock<std::mutex> lock(global_mu); + return global_num_connections; +} + +void IncrementCallCounter() { + std::unique_lock<std::mutex> lock(global_mu); + ++global_num_calls; +} + +void ResetCallCounter() { + std::unique_lock<std::mutex> lock(global_mu); + global_num_calls = 0; +} + +int GetCallCounterValue() { + std::unique_lock<std::mutex> lock(global_mu); + return global_num_calls; +} + +} // namespace + +class ChannelDataImpl : public ChannelData { + public: + grpc_error* Init(grpc_channel_element* /*elem*/, + grpc_channel_element_args* /*args*/) { + IncrementConnectionCounter(); + return GRPC_ERROR_NONE; + } +}; + +class CallDataImpl : public CallData { + public: + void StartTransportStreamOpBatch(grpc_call_element* elem, + TransportStreamOpBatch* op) override { + // Incrementing the counter could be done from Init(), but we want + // to test that the individual methods are actually called correctly. + if (op->recv_initial_metadata() != nullptr) IncrementCallCounter(); + grpc_call_next_op(elem, op->op()); + } +}; + +class FilterEnd2endTest : public ::testing::Test { + protected: + FilterEnd2endTest() : server_host_("localhost") {} + + static void SetUpTestCase() { + // Workaround for + // https://github.com/google/google-toolbox-for-mac/issues/242 + static bool setup_done = false; + if (!setup_done) { + setup_done = true; + grpc::RegisterChannelFilter<ChannelDataImpl, CallDataImpl>( + "test-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr); + } + } + + void SetUp() override { + int port = grpc_pick_unused_port_or_die(); + server_address_ << server_host_ << ":" << port; + // Setup server + ServerBuilder builder; + builder.AddListeningPort(server_address_.str(), + InsecureServerCredentials()); + builder.RegisterAsyncGenericService(&generic_service_); + srv_cq_ = builder.AddCompletionQueue(); + server_ = builder.BuildAndStart(); + } + + void TearDown() override { + server_->Shutdown(); + void* ignored_tag; + bool ignored_ok; + cli_cq_.Shutdown(); + srv_cq_->Shutdown(); + while (cli_cq_.Next(&ignored_tag, &ignored_ok)) + ; + while (srv_cq_->Next(&ignored_tag, &ignored_ok)) + ; + } + + void ResetStub() { + std::shared_ptr<Channel> channel = grpc::CreateChannel( + server_address_.str(), InsecureChannelCredentials()); + generic_stub_.reset(new GenericStub(channel)); + ResetConnectionCounter(); + ResetCallCounter(); + } + + void server_ok(int i) { verify_ok(srv_cq_.get(), i, true); } + void client_ok(int i) { verify_ok(&cli_cq_, i, true); } + void server_fail(int i) { verify_ok(srv_cq_.get(), i, false); } + void client_fail(int i) { verify_ok(&cli_cq_, i, false); } + + void SendRpc(int num_rpcs) { const TString kMethodName("/grpc.cpp.test.util.EchoTestService/Echo"); - for (int i = 0; i < num_rpcs; i++) { - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - GenericServerContext srv_ctx; - GenericServerAsyncReaderWriter stream(&srv_ctx); - - // The string needs to be long enough to test heap-based slice. - send_request.set_message("Hello world. Hello world. Hello world."); + for (int i = 0; i < num_rpcs; i++) { + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + GenericServerContext srv_ctx; + GenericServerAsyncReaderWriter stream(&srv_ctx); + + // The string needs to be long enough to test heap-based slice. + send_request.set_message("Hello world. Hello world. Hello world."); std::thread request_call([this]() { server_ok(4); }); - std::unique_ptr<GenericClientAsyncReaderWriter> call = - generic_stub_->PrepareCall(&cli_ctx, kMethodName, &cli_cq_); - call->StartCall(tag(1)); - client_ok(1); - std::unique_ptr<ByteBuffer> send_buffer = - SerializeToByteBuffer(&send_request); - call->Write(*send_buffer, tag(2)); - // Send ByteBuffer can be destroyed after calling Write. - send_buffer.reset(); - client_ok(2); - call->WritesDone(tag(3)); - client_ok(3); - - generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), - srv_cq_.get(), tag(4)); - + std::unique_ptr<GenericClientAsyncReaderWriter> call = + generic_stub_->PrepareCall(&cli_ctx, kMethodName, &cli_cq_); + call->StartCall(tag(1)); + client_ok(1); + std::unique_ptr<ByteBuffer> send_buffer = + SerializeToByteBuffer(&send_request); + call->Write(*send_buffer, tag(2)); + // Send ByteBuffer can be destroyed after calling Write. + send_buffer.reset(); + client_ok(2); + call->WritesDone(tag(3)); + client_ok(3); + + generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), + srv_cq_.get(), tag(4)); + request_call.join(); - EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); - EXPECT_EQ(kMethodName, srv_ctx.method()); - ByteBuffer recv_buffer; - stream.Read(&recv_buffer, tag(5)); - server_ok(5); - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - send_buffer = SerializeToByteBuffer(&send_response); - stream.Write(*send_buffer, tag(6)); - send_buffer.reset(); - server_ok(6); - - stream.Finish(Status::OK, tag(7)); - server_ok(7); - - recv_buffer.Clear(); - call->Read(&recv_buffer, tag(8)); - client_ok(8); - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); - - call->Finish(&recv_status, tag(9)); - client_ok(9); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - } - } - - CompletionQueue cli_cq_; - std::unique_ptr<ServerCompletionQueue> srv_cq_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<grpc::GenericStub> generic_stub_; - std::unique_ptr<Server> server_; - AsyncGenericService generic_service_; + EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); + EXPECT_EQ(kMethodName, srv_ctx.method()); + ByteBuffer recv_buffer; + stream.Read(&recv_buffer, tag(5)); + server_ok(5); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + send_buffer = SerializeToByteBuffer(&send_response); + stream.Write(*send_buffer, tag(6)); + send_buffer.reset(); + server_ok(6); + + stream.Finish(Status::OK, tag(7)); + server_ok(7); + + recv_buffer.Clear(); + call->Read(&recv_buffer, tag(8)); + client_ok(8); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); + + call->Finish(&recv_status, tag(9)); + client_ok(9); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + } + } + + CompletionQueue cli_cq_; + std::unique_ptr<ServerCompletionQueue> srv_cq_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<grpc::GenericStub> generic_stub_; + std::unique_ptr<Server> server_; + AsyncGenericService generic_service_; const TString server_host_; - std::ostringstream server_address_; -}; - -TEST_F(FilterEnd2endTest, SimpleRpc) { - ResetStub(); - EXPECT_EQ(0, GetConnectionCounterValue()); - EXPECT_EQ(0, GetCallCounterValue()); - SendRpc(1); - EXPECT_EQ(1, GetConnectionCounterValue()); - EXPECT_EQ(1, GetCallCounterValue()); -} - -TEST_F(FilterEnd2endTest, SequentialRpcs) { - ResetStub(); - EXPECT_EQ(0, GetConnectionCounterValue()); - EXPECT_EQ(0, GetCallCounterValue()); - SendRpc(10); - EXPECT_EQ(1, GetConnectionCounterValue()); - EXPECT_EQ(10, GetCallCounterValue()); -} - -// One ping, one pong. -TEST_F(FilterEnd2endTest, SimpleBidiStreaming) { - ResetStub(); - EXPECT_EQ(0, GetConnectionCounterValue()); - EXPECT_EQ(0, GetCallCounterValue()); - + std::ostringstream server_address_; +}; + +TEST_F(FilterEnd2endTest, SimpleRpc) { + ResetStub(); + EXPECT_EQ(0, GetConnectionCounterValue()); + EXPECT_EQ(0, GetCallCounterValue()); + SendRpc(1); + EXPECT_EQ(1, GetConnectionCounterValue()); + EXPECT_EQ(1, GetCallCounterValue()); +} + +TEST_F(FilterEnd2endTest, SequentialRpcs) { + ResetStub(); + EXPECT_EQ(0, GetConnectionCounterValue()); + EXPECT_EQ(0, GetCallCounterValue()); + SendRpc(10); + EXPECT_EQ(1, GetConnectionCounterValue()); + EXPECT_EQ(10, GetCallCounterValue()); +} + +// One ping, one pong. +TEST_F(FilterEnd2endTest, SimpleBidiStreaming) { + ResetStub(); + EXPECT_EQ(0, GetConnectionCounterValue()); + EXPECT_EQ(0, GetCallCounterValue()); + const TString kMethodName( - "/grpc.cpp.test.util.EchoTestService/BidiStream"); - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - ClientContext cli_ctx; - GenericServerContext srv_ctx; - GenericServerAsyncReaderWriter srv_stream(&srv_ctx); - - cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP); - send_request.set_message("Hello"); + "/grpc.cpp.test.util.EchoTestService/BidiStream"); + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + ClientContext cli_ctx; + GenericServerContext srv_ctx; + GenericServerAsyncReaderWriter srv_stream(&srv_ctx); + + cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP); + send_request.set_message("Hello"); std::thread request_call([this]() { server_ok(2); }); - std::unique_ptr<GenericClientAsyncReaderWriter> cli_stream = - generic_stub_->PrepareCall(&cli_ctx, kMethodName, &cli_cq_); - cli_stream->StartCall(tag(1)); - client_ok(1); - - generic_service_.RequestCall(&srv_ctx, &srv_stream, srv_cq_.get(), - srv_cq_.get(), tag(2)); - + std::unique_ptr<GenericClientAsyncReaderWriter> cli_stream = + generic_stub_->PrepareCall(&cli_ctx, kMethodName, &cli_cq_); + cli_stream->StartCall(tag(1)); + client_ok(1); + + generic_service_.RequestCall(&srv_ctx, &srv_stream, srv_cq_.get(), + srv_cq_.get(), tag(2)); + request_call.join(); - EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); - EXPECT_EQ(kMethodName, srv_ctx.method()); - - std::unique_ptr<ByteBuffer> send_buffer = - SerializeToByteBuffer(&send_request); - cli_stream->Write(*send_buffer, tag(3)); - send_buffer.reset(); - client_ok(3); - - ByteBuffer recv_buffer; - srv_stream.Read(&recv_buffer, tag(4)); - server_ok(4); - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - send_buffer = SerializeToByteBuffer(&send_response); - srv_stream.Write(*send_buffer, tag(5)); - send_buffer.reset(); - server_ok(5); - - cli_stream->Read(&recv_buffer, tag(6)); - client_ok(6); - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); - EXPECT_EQ(send_response.message(), recv_response.message()); - - cli_stream->WritesDone(tag(7)); - client_ok(7); - - srv_stream.Read(&recv_buffer, tag(8)); - server_fail(8); - - srv_stream.Finish(Status::OK, tag(9)); - server_ok(9); - - cli_stream->Finish(&recv_status, tag(10)); - client_ok(10); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - - EXPECT_EQ(1, GetCallCounterValue()); - EXPECT_EQ(1, GetConnectionCounterValue()); -} - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); + EXPECT_EQ(kMethodName, srv_ctx.method()); + + std::unique_ptr<ByteBuffer> send_buffer = + SerializeToByteBuffer(&send_request); + cli_stream->Write(*send_buffer, tag(3)); + send_buffer.reset(); + client_ok(3); + + ByteBuffer recv_buffer; + srv_stream.Read(&recv_buffer, tag(4)); + server_ok(4); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + send_buffer = SerializeToByteBuffer(&send_response); + srv_stream.Write(*send_buffer, tag(5)); + send_buffer.reset(); + server_ok(5); + + cli_stream->Read(&recv_buffer, tag(6)); + client_ok(6); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->WritesDone(tag(7)); + client_ok(7); + + srv_stream.Read(&recv_buffer, tag(8)); + server_fail(8); + + srv_stream.Finish(Status::OK, tag(9)); + server_ok(9); + + cli_stream->Finish(&recv_status, tag(10)); + client_ok(10); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + + EXPECT_EQ(1, GetCallCounterValue()); + EXPECT_EQ(1, GetConnectionCounterValue()); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/generic_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/generic_end2end_test.cc index cbe9289302..59eec49fb2 100644 --- a/contrib/libs/grpc/test/cpp/end2end/generic_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/generic_end2end_test.cc @@ -1,430 +1,430 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <memory> -#include <thread> - -#include <grpc/grpc.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/generic/async_generic_service.h> -#include <grpcpp/generic/generic_stub.h> -#include <grpcpp/impl/codegen/proto_utils.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> -#include <grpcpp/support/slice.h> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/util/byte_buffer_proto_helper.h" - -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; -using std::chrono::system_clock; - -namespace grpc { -namespace testing { -namespace { - -void* tag(int i) { return (void*)static_cast<intptr_t>(i); } - -void verify_ok(CompletionQueue* cq, int i, bool expect_ok) { - bool ok; - void* got_tag; - EXPECT_TRUE(cq->Next(&got_tag, &ok)); - EXPECT_EQ(expect_ok, ok); - EXPECT_EQ(tag(i), got_tag); -} - -class GenericEnd2endTest : public ::testing::Test { - protected: - GenericEnd2endTest() : server_host_("localhost") {} - - void SetUp() override { - shut_down_ = false; - int port = grpc_pick_unused_port_or_die(); - server_address_ << server_host_ << ":" << port; - // Setup server - ServerBuilder builder; - builder.AddListeningPort(server_address_.str(), - InsecureServerCredentials()); - builder.RegisterAsyncGenericService(&generic_service_); - // Include a second call to RegisterAsyncGenericService to make sure that - // we get an error in the log, since it is not allowed to have 2 async - // generic services - builder.RegisterAsyncGenericService(&generic_service_); - srv_cq_ = builder.AddCompletionQueue(); - server_ = builder.BuildAndStart(); - } - - void ShutDownServerAndCQs() { - if (!shut_down_) { - server_->Shutdown(); - void* ignored_tag; - bool ignored_ok; - cli_cq_.Shutdown(); - srv_cq_->Shutdown(); - while (cli_cq_.Next(&ignored_tag, &ignored_ok)) - ; - while (srv_cq_->Next(&ignored_tag, &ignored_ok)) - ; - shut_down_ = true; - } - } - void TearDown() override { ShutDownServerAndCQs(); } - - void ResetStub() { - std::shared_ptr<Channel> channel = grpc::CreateChannel( - server_address_.str(), InsecureChannelCredentials()); - stub_ = grpc::testing::EchoTestService::NewStub(channel); - generic_stub_.reset(new GenericStub(channel)); - } - - void server_ok(int i) { verify_ok(srv_cq_.get(), i, true); } - void client_ok(int i) { verify_ok(&cli_cq_, i, true); } - void server_fail(int i) { verify_ok(srv_cq_.get(), i, false); } - void client_fail(int i) { verify_ok(&cli_cq_, i, false); } - - void SendRpc(int num_rpcs) { - SendRpc(num_rpcs, false, gpr_inf_future(GPR_CLOCK_MONOTONIC)); - } - - void SendRpc(int num_rpcs, bool check_deadline, gpr_timespec deadline) { +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <memory> +#include <thread> + +#include <grpc/grpc.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/generic/async_generic_service.h> +#include <grpcpp/generic/generic_stub.h> +#include <grpcpp/impl/codegen/proto_utils.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> +#include <grpcpp/support/slice.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" + +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; +using std::chrono::system_clock; + +namespace grpc { +namespace testing { +namespace { + +void* tag(int i) { return (void*)static_cast<intptr_t>(i); } + +void verify_ok(CompletionQueue* cq, int i, bool expect_ok) { + bool ok; + void* got_tag; + EXPECT_TRUE(cq->Next(&got_tag, &ok)); + EXPECT_EQ(expect_ok, ok); + EXPECT_EQ(tag(i), got_tag); +} + +class GenericEnd2endTest : public ::testing::Test { + protected: + GenericEnd2endTest() : server_host_("localhost") {} + + void SetUp() override { + shut_down_ = false; + int port = grpc_pick_unused_port_or_die(); + server_address_ << server_host_ << ":" << port; + // Setup server + ServerBuilder builder; + builder.AddListeningPort(server_address_.str(), + InsecureServerCredentials()); + builder.RegisterAsyncGenericService(&generic_service_); + // Include a second call to RegisterAsyncGenericService to make sure that + // we get an error in the log, since it is not allowed to have 2 async + // generic services + builder.RegisterAsyncGenericService(&generic_service_); + srv_cq_ = builder.AddCompletionQueue(); + server_ = builder.BuildAndStart(); + } + + void ShutDownServerAndCQs() { + if (!shut_down_) { + server_->Shutdown(); + void* ignored_tag; + bool ignored_ok; + cli_cq_.Shutdown(); + srv_cq_->Shutdown(); + while (cli_cq_.Next(&ignored_tag, &ignored_ok)) + ; + while (srv_cq_->Next(&ignored_tag, &ignored_ok)) + ; + shut_down_ = true; + } + } + void TearDown() override { ShutDownServerAndCQs(); } + + void ResetStub() { + std::shared_ptr<Channel> channel = grpc::CreateChannel( + server_address_.str(), InsecureChannelCredentials()); + stub_ = grpc::testing::EchoTestService::NewStub(channel); + generic_stub_.reset(new GenericStub(channel)); + } + + void server_ok(int i) { verify_ok(srv_cq_.get(), i, true); } + void client_ok(int i) { verify_ok(&cli_cq_, i, true); } + void server_fail(int i) { verify_ok(srv_cq_.get(), i, false); } + void client_fail(int i) { verify_ok(&cli_cq_, i, false); } + + void SendRpc(int num_rpcs) { + SendRpc(num_rpcs, false, gpr_inf_future(GPR_CLOCK_MONOTONIC)); + } + + void SendRpc(int num_rpcs, bool check_deadline, gpr_timespec deadline) { const TString kMethodName("/grpc.cpp.test.util.EchoTestService/Echo"); - for (int i = 0; i < num_rpcs; i++) { - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - GenericServerContext srv_ctx; - GenericServerAsyncReaderWriter stream(&srv_ctx); - - // The string needs to be long enough to test heap-based slice. - send_request.set_message("Hello world. Hello world. Hello world."); - - if (check_deadline) { - cli_ctx.set_deadline(deadline); - } - - // Rather than using the original kMethodName, make a short-lived - // copy to also confirm that we don't refer to this object beyond - // the initial call preparation + for (int i = 0; i < num_rpcs; i++) { + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + GenericServerContext srv_ctx; + GenericServerAsyncReaderWriter stream(&srv_ctx); + + // The string needs to be long enough to test heap-based slice. + send_request.set_message("Hello world. Hello world. Hello world."); + + if (check_deadline) { + cli_ctx.set_deadline(deadline); + } + + // Rather than using the original kMethodName, make a short-lived + // copy to also confirm that we don't refer to this object beyond + // the initial call preparation const TString* method_name = new TString(kMethodName); - - std::unique_ptr<GenericClientAsyncReaderWriter> call = - generic_stub_->PrepareCall(&cli_ctx, *method_name, &cli_cq_); - - delete method_name; // Make sure that this is not needed after invocation - + + std::unique_ptr<GenericClientAsyncReaderWriter> call = + generic_stub_->PrepareCall(&cli_ctx, *method_name, &cli_cq_); + + delete method_name; // Make sure that this is not needed after invocation + std::thread request_call([this]() { server_ok(4); }); - call->StartCall(tag(1)); - client_ok(1); - std::unique_ptr<ByteBuffer> send_buffer = - SerializeToByteBuffer(&send_request); - call->Write(*send_buffer, tag(2)); - // Send ByteBuffer can be destroyed after calling Write. - send_buffer.reset(); - client_ok(2); - call->WritesDone(tag(3)); - client_ok(3); - - generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), - srv_cq_.get(), tag(4)); - + call->StartCall(tag(1)); + client_ok(1); + std::unique_ptr<ByteBuffer> send_buffer = + SerializeToByteBuffer(&send_request); + call->Write(*send_buffer, tag(2)); + // Send ByteBuffer can be destroyed after calling Write. + send_buffer.reset(); + client_ok(2); + call->WritesDone(tag(3)); + client_ok(3); + + generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), + srv_cq_.get(), tag(4)); + request_call.join(); - EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); - EXPECT_EQ(kMethodName, srv_ctx.method()); - - if (check_deadline) { - EXPECT_TRUE(gpr_time_similar(deadline, srv_ctx.raw_deadline(), - gpr_time_from_millis(1000, GPR_TIMESPAN))); - } - - ByteBuffer recv_buffer; - stream.Read(&recv_buffer, tag(5)); - server_ok(5); - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - send_buffer = SerializeToByteBuffer(&send_response); - stream.Write(*send_buffer, tag(6)); - send_buffer.reset(); - server_ok(6); - - stream.Finish(Status::OK, tag(7)); - server_ok(7); - - recv_buffer.Clear(); - call->Read(&recv_buffer, tag(8)); - client_ok(8); - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); - - call->Finish(&recv_status, tag(9)); - client_ok(9); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - } - } - - // Return errors to up to one call that comes in on the supplied completion - // queue, until the CQ is being shut down (and therefore we can no longer - // enqueue further events). - void DriveCompletionQueue() { - enum class Event : uintptr_t { - kCallReceived, - kResponseSent, - }; - // Request the call, but only if the main thread hasn't beaten us to - // shutting down the CQ. - grpc::GenericServerContext server_context; - grpc::GenericServerAsyncReaderWriter reader_writer(&server_context); - - { - std::lock_guard<std::mutex> lock(shutting_down_mu_); - if (!shutting_down_) { - generic_service_.RequestCall( - &server_context, &reader_writer, srv_cq_.get(), srv_cq_.get(), - reinterpret_cast<void*>(Event::kCallReceived)); - } - } - // Process events. - { - Event event; - bool ok; - while (srv_cq_->Next(reinterpret_cast<void**>(&event), &ok)) { - std::lock_guard<std::mutex> lock(shutting_down_mu_); - if (shutting_down_) { - // The main thread has started shutting down. Simply continue to drain - // events. - continue; - } - - switch (event) { - case Event::kCallReceived: - reader_writer.Finish( - ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "go away"), - reinterpret_cast<void*>(Event::kResponseSent)); - break; - - case Event::kResponseSent: - // We are done. - break; - } - } - } - } - - CompletionQueue cli_cq_; - std::unique_ptr<ServerCompletionQueue> srv_cq_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<grpc::GenericStub> generic_stub_; - std::unique_ptr<Server> server_; - AsyncGenericService generic_service_; + EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); + EXPECT_EQ(kMethodName, srv_ctx.method()); + + if (check_deadline) { + EXPECT_TRUE(gpr_time_similar(deadline, srv_ctx.raw_deadline(), + gpr_time_from_millis(1000, GPR_TIMESPAN))); + } + + ByteBuffer recv_buffer; + stream.Read(&recv_buffer, tag(5)); + server_ok(5); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + send_buffer = SerializeToByteBuffer(&send_response); + stream.Write(*send_buffer, tag(6)); + send_buffer.reset(); + server_ok(6); + + stream.Finish(Status::OK, tag(7)); + server_ok(7); + + recv_buffer.Clear(); + call->Read(&recv_buffer, tag(8)); + client_ok(8); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); + + call->Finish(&recv_status, tag(9)); + client_ok(9); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + } + } + + // Return errors to up to one call that comes in on the supplied completion + // queue, until the CQ is being shut down (and therefore we can no longer + // enqueue further events). + void DriveCompletionQueue() { + enum class Event : uintptr_t { + kCallReceived, + kResponseSent, + }; + // Request the call, but only if the main thread hasn't beaten us to + // shutting down the CQ. + grpc::GenericServerContext server_context; + grpc::GenericServerAsyncReaderWriter reader_writer(&server_context); + + { + std::lock_guard<std::mutex> lock(shutting_down_mu_); + if (!shutting_down_) { + generic_service_.RequestCall( + &server_context, &reader_writer, srv_cq_.get(), srv_cq_.get(), + reinterpret_cast<void*>(Event::kCallReceived)); + } + } + // Process events. + { + Event event; + bool ok; + while (srv_cq_->Next(reinterpret_cast<void**>(&event), &ok)) { + std::lock_guard<std::mutex> lock(shutting_down_mu_); + if (shutting_down_) { + // The main thread has started shutting down. Simply continue to drain + // events. + continue; + } + + switch (event) { + case Event::kCallReceived: + reader_writer.Finish( + ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "go away"), + reinterpret_cast<void*>(Event::kResponseSent)); + break; + + case Event::kResponseSent: + // We are done. + break; + } + } + } + } + + CompletionQueue cli_cq_; + std::unique_ptr<ServerCompletionQueue> srv_cq_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<grpc::GenericStub> generic_stub_; + std::unique_ptr<Server> server_; + AsyncGenericService generic_service_; const TString server_host_; - std::ostringstream server_address_; - bool shutting_down_; - bool shut_down_; - std::mutex shutting_down_mu_; -}; - -TEST_F(GenericEnd2endTest, SimpleRpc) { - ResetStub(); - SendRpc(1); -} - -TEST_F(GenericEnd2endTest, SequentialRpcs) { - ResetStub(); - SendRpc(10); -} - -TEST_F(GenericEnd2endTest, SequentialUnaryRpcs) { - ResetStub(); - const int num_rpcs = 10; + std::ostringstream server_address_; + bool shutting_down_; + bool shut_down_; + std::mutex shutting_down_mu_; +}; + +TEST_F(GenericEnd2endTest, SimpleRpc) { + ResetStub(); + SendRpc(1); +} + +TEST_F(GenericEnd2endTest, SequentialRpcs) { + ResetStub(); + SendRpc(10); +} + +TEST_F(GenericEnd2endTest, SequentialUnaryRpcs) { + ResetStub(); + const int num_rpcs = 10; const TString kMethodName("/grpc.cpp.test.util.EchoTestService/Echo"); - for (int i = 0; i < num_rpcs; i++) { - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - GenericServerContext srv_ctx; - GenericServerAsyncReaderWriter stream(&srv_ctx); - - // The string needs to be long enough to test heap-based slice. - send_request.set_message("Hello world. Hello world. Hello world."); - - std::unique_ptr<ByteBuffer> cli_send_buffer = - SerializeToByteBuffer(&send_request); + for (int i = 0; i < num_rpcs; i++) { + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + GenericServerContext srv_ctx; + GenericServerAsyncReaderWriter stream(&srv_ctx); + + // The string needs to be long enough to test heap-based slice. + send_request.set_message("Hello world. Hello world. Hello world."); + + std::unique_ptr<ByteBuffer> cli_send_buffer = + SerializeToByteBuffer(&send_request); std::thread request_call([this]() { server_ok(4); }); - std::unique_ptr<GenericClientAsyncResponseReader> call = - generic_stub_->PrepareUnaryCall(&cli_ctx, kMethodName, - *cli_send_buffer.get(), &cli_cq_); - call->StartCall(); - ByteBuffer cli_recv_buffer; - call->Finish(&cli_recv_buffer, &recv_status, tag(1)); - std::thread client_check([this] { client_ok(1); }); - - generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), - srv_cq_.get(), tag(4)); + std::unique_ptr<GenericClientAsyncResponseReader> call = + generic_stub_->PrepareUnaryCall(&cli_ctx, kMethodName, + *cli_send_buffer.get(), &cli_cq_); + call->StartCall(); + ByteBuffer cli_recv_buffer; + call->Finish(&cli_recv_buffer, &recv_status, tag(1)); + std::thread client_check([this] { client_ok(1); }); + + generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), + srv_cq_.get(), tag(4)); request_call.join(); - EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); - EXPECT_EQ(kMethodName, srv_ctx.method()); - - ByteBuffer srv_recv_buffer; - stream.Read(&srv_recv_buffer, tag(5)); - server_ok(5); - EXPECT_TRUE(ParseFromByteBuffer(&srv_recv_buffer, &recv_request)); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - std::unique_ptr<ByteBuffer> srv_send_buffer = - SerializeToByteBuffer(&send_response); - stream.Write(*srv_send_buffer, tag(6)); - server_ok(6); - - stream.Finish(Status::OK, tag(7)); - server_ok(7); - - client_check.join(); - EXPECT_TRUE(ParseFromByteBuffer(&cli_recv_buffer, &recv_response)); - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - } -} - -// One ping, one pong. -TEST_F(GenericEnd2endTest, SimpleBidiStreaming) { - ResetStub(); - + EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); + EXPECT_EQ(kMethodName, srv_ctx.method()); + + ByteBuffer srv_recv_buffer; + stream.Read(&srv_recv_buffer, tag(5)); + server_ok(5); + EXPECT_TRUE(ParseFromByteBuffer(&srv_recv_buffer, &recv_request)); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + std::unique_ptr<ByteBuffer> srv_send_buffer = + SerializeToByteBuffer(&send_response); + stream.Write(*srv_send_buffer, tag(6)); + server_ok(6); + + stream.Finish(Status::OK, tag(7)); + server_ok(7); + + client_check.join(); + EXPECT_TRUE(ParseFromByteBuffer(&cli_recv_buffer, &recv_response)); + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + } +} + +// One ping, one pong. +TEST_F(GenericEnd2endTest, SimpleBidiStreaming) { + ResetStub(); + const TString kMethodName( - "/grpc.cpp.test.util.EchoTestService/BidiStream"); - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - ClientContext cli_ctx; - GenericServerContext srv_ctx; - GenericServerAsyncReaderWriter srv_stream(&srv_ctx); - - cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP); - send_request.set_message("Hello"); + "/grpc.cpp.test.util.EchoTestService/BidiStream"); + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + ClientContext cli_ctx; + GenericServerContext srv_ctx; + GenericServerAsyncReaderWriter srv_stream(&srv_ctx); + + cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP); + send_request.set_message("Hello"); std::thread request_call([this]() { server_ok(2); }); - std::unique_ptr<GenericClientAsyncReaderWriter> cli_stream = - generic_stub_->PrepareCall(&cli_ctx, kMethodName, &cli_cq_); - cli_stream->StartCall(tag(1)); - client_ok(1); - - generic_service_.RequestCall(&srv_ctx, &srv_stream, srv_cq_.get(), - srv_cq_.get(), tag(2)); + std::unique_ptr<GenericClientAsyncReaderWriter> cli_stream = + generic_stub_->PrepareCall(&cli_ctx, kMethodName, &cli_cq_); + cli_stream->StartCall(tag(1)); + client_ok(1); + + generic_service_.RequestCall(&srv_ctx, &srv_stream, srv_cq_.get(), + srv_cq_.get(), tag(2)); request_call.join(); - - EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); - EXPECT_EQ(kMethodName, srv_ctx.method()); - - std::unique_ptr<ByteBuffer> send_buffer = - SerializeToByteBuffer(&send_request); - cli_stream->Write(*send_buffer, tag(3)); - send_buffer.reset(); - client_ok(3); - - ByteBuffer recv_buffer; - srv_stream.Read(&recv_buffer, tag(4)); - server_ok(4); - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - send_buffer = SerializeToByteBuffer(&send_response); - srv_stream.Write(*send_buffer, tag(5)); - send_buffer.reset(); - server_ok(5); - - cli_stream->Read(&recv_buffer, tag(6)); - client_ok(6); - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); - EXPECT_EQ(send_response.message(), recv_response.message()); - - cli_stream->WritesDone(tag(7)); - client_ok(7); - - srv_stream.Read(&recv_buffer, tag(8)); - server_fail(8); - - srv_stream.Finish(Status::OK, tag(9)); - server_ok(9); - - cli_stream->Finish(&recv_status, tag(10)); - client_ok(10); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); -} - -TEST_F(GenericEnd2endTest, Deadline) { - ResetStub(); - SendRpc(1, true, - gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_seconds(10, GPR_TIMESPAN))); -} - -TEST_F(GenericEnd2endTest, ShortDeadline) { - ResetStub(); - - ClientContext cli_ctx; - EchoRequest request; - EchoResponse response; - - shutting_down_ = false; - std::thread driver([this] { DriveCompletionQueue(); }); - - request.set_message(""); - cli_ctx.set_deadline(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_micros(500, GPR_TIMESPAN))); - Status s = stub_->Echo(&cli_ctx, request, &response); - EXPECT_FALSE(s.ok()); - { - std::lock_guard<std::mutex> lock(shutting_down_mu_); - shutting_down_ = true; - } - ShutDownServerAndCQs(); - driver.join(); -} - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + + EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); + EXPECT_EQ(kMethodName, srv_ctx.method()); + + std::unique_ptr<ByteBuffer> send_buffer = + SerializeToByteBuffer(&send_request); + cli_stream->Write(*send_buffer, tag(3)); + send_buffer.reset(); + client_ok(3); + + ByteBuffer recv_buffer; + srv_stream.Read(&recv_buffer, tag(4)); + server_ok(4); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + send_buffer = SerializeToByteBuffer(&send_response); + srv_stream.Write(*send_buffer, tag(5)); + send_buffer.reset(); + server_ok(5); + + cli_stream->Read(&recv_buffer, tag(6)); + client_ok(6); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->WritesDone(tag(7)); + client_ok(7); + + srv_stream.Read(&recv_buffer, tag(8)); + server_fail(8); + + srv_stream.Finish(Status::OK, tag(9)); + server_ok(9); + + cli_stream->Finish(&recv_status, tag(10)); + client_ok(10); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); +} + +TEST_F(GenericEnd2endTest, Deadline) { + ResetStub(); + SendRpc(1, true, + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_seconds(10, GPR_TIMESPAN))); +} + +TEST_F(GenericEnd2endTest, ShortDeadline) { + ResetStub(); + + ClientContext cli_ctx; + EchoRequest request; + EchoResponse response; + + shutting_down_ = false; + std::thread driver([this] { DriveCompletionQueue(); }); + + request.set_message(""); + cli_ctx.set_deadline(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_micros(500, GPR_TIMESPAN))); + Status s = stub_->Echo(&cli_ctx, request, &response); + EXPECT_FALSE(s.ok()); + { + std::lock_guard<std::mutex> lock(shutting_down_mu_); + shutting_down_ = true; + } + ShutDownServerAndCQs(); + driver.join(); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/grpclb_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/grpclb_end2end_test.cc index 9111899785..6208dc2535 100644 --- a/contrib/libs/grpc/test/cpp/end2end/grpclb_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/grpclb_end2end_test.cc @@ -1,94 +1,94 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * 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. - * - */ - +/* + * + * Copyright 2017 gRPC authors. + * + * 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. + * + */ + #include <deque> -#include <memory> -#include <mutex> -#include <set> -#include <sstream> +#include <memory> +#include <mutex> +#include <set> +#include <sstream> #include <util/generic/string.h> -#include <thread> - +#include <thread> + #include "y_absl/strings/str_cat.h" #include "y_absl/strings/str_format.h" -#include <grpc/grpc.h> -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/impl/codegen/sync.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> - -#include "src/core/ext/filters/client_channel/backup_poller.h" +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/impl/codegen/sync.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> + +#include "src/core/ext/filters/client_channel/backup_poller.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h" -#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" -#include "src/core/ext/filters/client_channel/server_address.h" -#include "src/core/ext/filters/client_channel/service_config.h" -#include "src/core/lib/gpr/env.h" -#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" +#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/parse_address.h" -#include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/transport/authority_override.h" -#include "src/cpp/client/secure_credentials.h" -#include "src/cpp/server/secure_server_credentials.h" - -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/test_service_impl.h" - -#include "src/proto/grpc/lb/v1/load_balancer.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -// TODO(dgq): Other scenarios in need of testing: -// - Send a serverlist with faulty ip:port addresses (port > 2^16, etc). -// - Test reception of invalid serverlist -// - Test against a non-LB server. -// - Random LB server closing the stream unexpectedly. -// -// Findings from end to end testing to be covered here: -// - Handling of LB servers restart, including reconnection after backing-off -// retries. -// - Destruction of load balanced channel (and therefore of grpclb instance) -// while: -// 1) the internal LB call is still active. This should work by virtue -// of the weak reference the LB call holds. The call should be terminated as -// part of the grpclb shutdown process. -// 2) the retry timer is active. Again, the weak reference it holds should -// prevent a premature call to \a glb_destroy. - -using std::chrono::system_clock; - +#include "src/cpp/client/secure_credentials.h" +#include "src/cpp/server/secure_server_credentials.h" + +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" + +#include "src/proto/grpc/lb/v1/load_balancer.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +// TODO(dgq): Other scenarios in need of testing: +// - Send a serverlist with faulty ip:port addresses (port > 2^16, etc). +// - Test reception of invalid serverlist +// - Test against a non-LB server. +// - Random LB server closing the stream unexpectedly. +// +// Findings from end to end testing to be covered here: +// - Handling of LB servers restart, including reconnection after backing-off +// retries. +// - Destruction of load balanced channel (and therefore of grpclb instance) +// while: +// 1) the internal LB call is still active. This should work by virtue +// of the weak reference the LB call holds. The call should be terminated as +// part of the grpclb shutdown process. +// 2) the retry timer is active. Again, the weak reference it holds should +// prevent a premature call to \a glb_destroy. + +using std::chrono::system_clock; + using grpc::lb::v1::LoadBalancer; -using grpc::lb::v1::LoadBalanceRequest; -using grpc::lb::v1::LoadBalanceResponse; - -namespace grpc { -namespace testing { -namespace { - +using grpc::lb::v1::LoadBalanceRequest; +using grpc::lb::v1::LoadBalanceResponse; + +namespace grpc { +namespace testing { +namespace { + constexpr char kDefaultServiceConfig[] = "{\n" " \"loadBalancingConfig\":[\n" @@ -96,255 +96,255 @@ constexpr char kDefaultServiceConfig[] = " ]\n" "}"; -template <typename ServiceType> -class CountedService : public ServiceType { - public: - size_t request_count() { - grpc::internal::MutexLock lock(&mu_); - return request_count_; - } - - size_t response_count() { - grpc::internal::MutexLock lock(&mu_); - return response_count_; - } - - void IncreaseResponseCount() { - grpc::internal::MutexLock lock(&mu_); - ++response_count_; - } - void IncreaseRequestCount() { - grpc::internal::MutexLock lock(&mu_); - ++request_count_; - } - - void ResetCounters() { - grpc::internal::MutexLock lock(&mu_); - request_count_ = 0; - response_count_ = 0; - } - - protected: - grpc::internal::Mutex mu_; - - private: - size_t request_count_ = 0; - size_t response_count_ = 0; -}; - -using BackendService = CountedService<TestServiceImpl>; -using BalancerService = CountedService<LoadBalancer::Service>; - -const char g_kCallCredsMdKey[] = "Balancer should not ..."; -const char g_kCallCredsMdValue[] = "... receive me"; - -class BackendServiceImpl : public BackendService { - public: - BackendServiceImpl() {} - - Status Echo(ServerContext* context, const EchoRequest* request, - EchoResponse* response) override { - // Backend should receive the call credentials metadata. - auto call_credentials_entry = - context->client_metadata().find(g_kCallCredsMdKey); - EXPECT_NE(call_credentials_entry, context->client_metadata().end()); - if (call_credentials_entry != context->client_metadata().end()) { - EXPECT_EQ(call_credentials_entry->second, g_kCallCredsMdValue); - } - IncreaseRequestCount(); - const auto status = TestServiceImpl::Echo(context, request, response); - IncreaseResponseCount(); - AddClient(context->peer().c_str()); - return status; - } - - void Start() {} - - void Shutdown() {} - +template <typename ServiceType> +class CountedService : public ServiceType { + public: + size_t request_count() { + grpc::internal::MutexLock lock(&mu_); + return request_count_; + } + + size_t response_count() { + grpc::internal::MutexLock lock(&mu_); + return response_count_; + } + + void IncreaseResponseCount() { + grpc::internal::MutexLock lock(&mu_); + ++response_count_; + } + void IncreaseRequestCount() { + grpc::internal::MutexLock lock(&mu_); + ++request_count_; + } + + void ResetCounters() { + grpc::internal::MutexLock lock(&mu_); + request_count_ = 0; + response_count_ = 0; + } + + protected: + grpc::internal::Mutex mu_; + + private: + size_t request_count_ = 0; + size_t response_count_ = 0; +}; + +using BackendService = CountedService<TestServiceImpl>; +using BalancerService = CountedService<LoadBalancer::Service>; + +const char g_kCallCredsMdKey[] = "Balancer should not ..."; +const char g_kCallCredsMdValue[] = "... receive me"; + +class BackendServiceImpl : public BackendService { + public: + BackendServiceImpl() {} + + Status Echo(ServerContext* context, const EchoRequest* request, + EchoResponse* response) override { + // Backend should receive the call credentials metadata. + auto call_credentials_entry = + context->client_metadata().find(g_kCallCredsMdKey); + EXPECT_NE(call_credentials_entry, context->client_metadata().end()); + if (call_credentials_entry != context->client_metadata().end()) { + EXPECT_EQ(call_credentials_entry->second, g_kCallCredsMdValue); + } + IncreaseRequestCount(); + const auto status = TestServiceImpl::Echo(context, request, response); + IncreaseResponseCount(); + AddClient(context->peer().c_str()); + return status; + } + + void Start() {} + + void Shutdown() {} + std::set<TString> clients() { - grpc::internal::MutexLock lock(&clients_mu_); - return clients_; - } - - private: + grpc::internal::MutexLock lock(&clients_mu_); + return clients_; + } + + private: void AddClient(const TString& client) { - grpc::internal::MutexLock lock(&clients_mu_); - clients_.insert(client); - } - - grpc::internal::Mutex mu_; - grpc::internal::Mutex clients_mu_; + grpc::internal::MutexLock lock(&clients_mu_); + clients_.insert(client); + } + + grpc::internal::Mutex mu_; + grpc::internal::Mutex clients_mu_; std::set<TString> clients_; -}; - +}; + TString Ip4ToPackedString(const char* ip_str) { - struct in_addr ip4; - GPR_ASSERT(inet_pton(AF_INET, ip_str, &ip4) == 1); + struct in_addr ip4; + GPR_ASSERT(inet_pton(AF_INET, ip_str, &ip4) == 1); return TString(reinterpret_cast<const char*>(&ip4), sizeof(ip4)); -} - -struct ClientStats { - size_t num_calls_started = 0; - size_t num_calls_finished = 0; - size_t num_calls_finished_with_client_failed_to_send = 0; - size_t num_calls_finished_known_received = 0; +} + +struct ClientStats { + size_t num_calls_started = 0; + size_t num_calls_finished = 0; + size_t num_calls_finished_with_client_failed_to_send = 0; + size_t num_calls_finished_known_received = 0; std::map<TString, size_t> drop_token_counts; - - ClientStats& operator+=(const ClientStats& other) { - num_calls_started += other.num_calls_started; - num_calls_finished += other.num_calls_finished; - num_calls_finished_with_client_failed_to_send += - other.num_calls_finished_with_client_failed_to_send; - num_calls_finished_known_received += - other.num_calls_finished_known_received; - for (const auto& p : other.drop_token_counts) { - drop_token_counts[p.first] += p.second; - } - return *this; - } - - void Reset() { - num_calls_started = 0; - num_calls_finished = 0; - num_calls_finished_with_client_failed_to_send = 0; - num_calls_finished_known_received = 0; - drop_token_counts.clear(); - } -}; - -class BalancerServiceImpl : public BalancerService { - public: - using Stream = ServerReaderWriter<LoadBalanceResponse, LoadBalanceRequest>; - using ResponseDelayPair = std::pair<LoadBalanceResponse, int>; - - explicit BalancerServiceImpl(int client_load_reporting_interval_seconds) - : client_load_reporting_interval_seconds_( - client_load_reporting_interval_seconds) {} - - Status BalanceLoad(ServerContext* context, Stream* stream) override { - gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); - { - grpc::internal::MutexLock lock(&mu_); - if (serverlist_done_) goto done; - } - { - // Balancer shouldn't receive the call credentials metadata. - EXPECT_EQ(context->client_metadata().find(g_kCallCredsMdKey), - context->client_metadata().end()); - LoadBalanceRequest request; - std::vector<ResponseDelayPair> responses_and_delays; - - if (!stream->Read(&request)) { - goto done; + + ClientStats& operator+=(const ClientStats& other) { + num_calls_started += other.num_calls_started; + num_calls_finished += other.num_calls_finished; + num_calls_finished_with_client_failed_to_send += + other.num_calls_finished_with_client_failed_to_send; + num_calls_finished_known_received += + other.num_calls_finished_known_received; + for (const auto& p : other.drop_token_counts) { + drop_token_counts[p.first] += p.second; + } + return *this; + } + + void Reset() { + num_calls_started = 0; + num_calls_finished = 0; + num_calls_finished_with_client_failed_to_send = 0; + num_calls_finished_known_received = 0; + drop_token_counts.clear(); + } +}; + +class BalancerServiceImpl : public BalancerService { + public: + using Stream = ServerReaderWriter<LoadBalanceResponse, LoadBalanceRequest>; + using ResponseDelayPair = std::pair<LoadBalanceResponse, int>; + + explicit BalancerServiceImpl(int client_load_reporting_interval_seconds) + : client_load_reporting_interval_seconds_( + client_load_reporting_interval_seconds) {} + + Status BalanceLoad(ServerContext* context, Stream* stream) override { + gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); + { + grpc::internal::MutexLock lock(&mu_); + if (serverlist_done_) goto done; + } + { + // Balancer shouldn't receive the call credentials metadata. + EXPECT_EQ(context->client_metadata().find(g_kCallCredsMdKey), + context->client_metadata().end()); + LoadBalanceRequest request; + std::vector<ResponseDelayPair> responses_and_delays; + + if (!stream->Read(&request)) { + goto done; } else { if (request.has_initial_request()) { grpc::internal::MutexLock lock(&mu_); service_names_.push_back(request.initial_request().name()); } - } - IncreaseRequestCount(); - gpr_log(GPR_INFO, "LB[%p]: received initial message '%s'", this, - request.DebugString().c_str()); - - // TODO(juanlishen): Initial response should always be the first response. - if (client_load_reporting_interval_seconds_ > 0) { - LoadBalanceResponse initial_response; - initial_response.mutable_initial_response() - ->mutable_client_stats_report_interval() - ->set_seconds(client_load_reporting_interval_seconds_); - stream->Write(initial_response); - } - - { - grpc::internal::MutexLock lock(&mu_); - responses_and_delays = responses_and_delays_; - } - for (const auto& response_and_delay : responses_and_delays) { - SendResponse(stream, response_and_delay.first, - response_and_delay.second); - } - { - grpc::internal::MutexLock lock(&mu_); - serverlist_cond_.WaitUntil(&mu_, [this] { return serverlist_done_; }); - } - - if (client_load_reporting_interval_seconds_ > 0) { - request.Clear(); + } + IncreaseRequestCount(); + gpr_log(GPR_INFO, "LB[%p]: received initial message '%s'", this, + request.DebugString().c_str()); + + // TODO(juanlishen): Initial response should always be the first response. + if (client_load_reporting_interval_seconds_ > 0) { + LoadBalanceResponse initial_response; + initial_response.mutable_initial_response() + ->mutable_client_stats_report_interval() + ->set_seconds(client_load_reporting_interval_seconds_); + stream->Write(initial_response); + } + + { + grpc::internal::MutexLock lock(&mu_); + responses_and_delays = responses_and_delays_; + } + for (const auto& response_and_delay : responses_and_delays) { + SendResponse(stream, response_and_delay.first, + response_and_delay.second); + } + { + grpc::internal::MutexLock lock(&mu_); + serverlist_cond_.WaitUntil(&mu_, [this] { return serverlist_done_; }); + } + + if (client_load_reporting_interval_seconds_ > 0) { + request.Clear(); while (stream->Read(&request)) { - gpr_log(GPR_INFO, "LB[%p]: received client load report message '%s'", - this, request.DebugString().c_str()); - GPR_ASSERT(request.has_client_stats()); + gpr_log(GPR_INFO, "LB[%p]: received client load report message '%s'", + this, request.DebugString().c_str()); + GPR_ASSERT(request.has_client_stats()); ClientStats load_report; load_report.num_calls_started = - request.client_stats().num_calls_started(); + request.client_stats().num_calls_started(); load_report.num_calls_finished = - request.client_stats().num_calls_finished(); + request.client_stats().num_calls_finished(); load_report.num_calls_finished_with_client_failed_to_send = - request.client_stats() - .num_calls_finished_with_client_failed_to_send(); + request.client_stats() + .num_calls_finished_with_client_failed_to_send(); load_report.num_calls_finished_known_received = - request.client_stats().num_calls_finished_known_received(); - for (const auto& drop_token_count : - request.client_stats().calls_finished_with_drop()) { + request.client_stats().num_calls_finished_known_received(); + for (const auto& drop_token_count : + request.client_stats().calls_finished_with_drop()) { load_report .drop_token_counts[drop_token_count.load_balance_token()] = - drop_token_count.num_calls(); - } + drop_token_count.num_calls(); + } // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. grpc::internal::MutexLock lock(&mu_); load_report_queue_.emplace_back(std::move(load_report)); if (load_report_cond_ != nullptr) load_report_cond_->Signal(); - } - } - } - done: - gpr_log(GPR_INFO, "LB[%p]: done", this); - return Status::OK; - } - - void add_response(const LoadBalanceResponse& response, int send_after_ms) { - grpc::internal::MutexLock lock(&mu_); - responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); - } - - void Start() { - grpc::internal::MutexLock lock(&mu_); - serverlist_done_ = false; - responses_and_delays_.clear(); + } + } + } + done: + gpr_log(GPR_INFO, "LB[%p]: done", this); + return Status::OK; + } + + void add_response(const LoadBalanceResponse& response, int send_after_ms) { + grpc::internal::MutexLock lock(&mu_); + responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); + } + + void Start() { + grpc::internal::MutexLock lock(&mu_); + serverlist_done_ = false; + responses_and_delays_.clear(); load_report_queue_.clear(); - } - - void Shutdown() { - NotifyDoneWithServerlists(); - gpr_log(GPR_INFO, "LB[%p]: shut down", this); - } - - static LoadBalanceResponse BuildResponseForBackends( - const std::vector<int>& backend_ports, + } + + void Shutdown() { + NotifyDoneWithServerlists(); + gpr_log(GPR_INFO, "LB[%p]: shut down", this); + } + + static LoadBalanceResponse BuildResponseForBackends( + const std::vector<int>& backend_ports, const std::map<TString, size_t>& drop_token_counts) { - LoadBalanceResponse response; - for (const auto& drop_token_count : drop_token_counts) { - for (size_t i = 0; i < drop_token_count.second; ++i) { - auto* server = response.mutable_server_list()->add_servers(); - server->set_drop(true); - server->set_load_balance_token(drop_token_count.first); - } - } - for (const int& backend_port : backend_ports) { - auto* server = response.mutable_server_list()->add_servers(); - server->set_ip_address(Ip4ToPackedString("127.0.0.1")); - server->set_port(backend_port); - static int token_count = 0; + LoadBalanceResponse response; + for (const auto& drop_token_count : drop_token_counts) { + for (size_t i = 0; i < drop_token_count.second; ++i) { + auto* server = response.mutable_server_list()->add_servers(); + server->set_drop(true); + server->set_load_balance_token(drop_token_count.first); + } + } + for (const int& backend_port : backend_ports) { + auto* server = response.mutable_server_list()->add_servers(); + server->set_ip_address(Ip4ToPackedString("127.0.0.1")); + server->set_port(backend_port); + static int token_count = 0; server->set_load_balance_token( y_absl::StrFormat("token%03d", ++token_count)); - } - return response; - } - + } + return response; + } + ClientStats WaitForLoadReport() { - grpc::internal::MutexLock lock(&mu_); + grpc::internal::MutexLock lock(&mu_); grpc::internal::CondVar cv; if (load_report_queue_.empty()) { load_report_cond_ = &cv; @@ -355,216 +355,216 @@ class BalancerServiceImpl : public BalancerService { ClientStats load_report = std::move(load_report_queue_.front()); load_report_queue_.pop_front(); return load_report; - } - - void NotifyDoneWithServerlists() { - grpc::internal::MutexLock lock(&mu_); - if (!serverlist_done_) { - serverlist_done_ = true; - serverlist_cond_.Broadcast(); - } - } - + } + + void NotifyDoneWithServerlists() { + grpc::internal::MutexLock lock(&mu_); + if (!serverlist_done_) { + serverlist_done_ = true; + serverlist_cond_.Broadcast(); + } + } + std::vector<TString> service_names() { grpc::internal::MutexLock lock(&mu_); return service_names_; } - private: - void SendResponse(Stream* stream, const LoadBalanceResponse& response, - int delay_ms) { - gpr_log(GPR_INFO, "LB[%p]: sleeping for %d ms...", this, delay_ms); - if (delay_ms > 0) { - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(delay_ms)); - } - gpr_log(GPR_INFO, "LB[%p]: Woke up! Sending response '%s'", this, - response.DebugString().c_str()); - IncreaseResponseCount(); - stream->Write(response); - } - - const int client_load_reporting_interval_seconds_; - std::vector<ResponseDelayPair> responses_and_delays_; + private: + void SendResponse(Stream* stream, const LoadBalanceResponse& response, + int delay_ms) { + gpr_log(GPR_INFO, "LB[%p]: sleeping for %d ms...", this, delay_ms); + if (delay_ms > 0) { + gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(delay_ms)); + } + gpr_log(GPR_INFO, "LB[%p]: Woke up! Sending response '%s'", this, + response.DebugString().c_str()); + IncreaseResponseCount(); + stream->Write(response); + } + + const int client_load_reporting_interval_seconds_; + std::vector<ResponseDelayPair> responses_and_delays_; std::vector<TString> service_names_; - grpc::internal::Mutex mu_; - grpc::internal::CondVar serverlist_cond_; - bool serverlist_done_ = false; + grpc::internal::Mutex mu_; + grpc::internal::CondVar serverlist_cond_; + bool serverlist_done_ = false; grpc::internal::CondVar* load_report_cond_ = nullptr; std::deque<ClientStats> load_report_queue_; -}; - -class GrpclbEnd2endTest : public ::testing::Test { - protected: - GrpclbEnd2endTest(size_t num_backends, size_t num_balancers, - int client_load_reporting_interval_seconds) - : server_host_("localhost"), - num_backends_(num_backends), - num_balancers_(num_balancers), - client_load_reporting_interval_seconds_( - client_load_reporting_interval_seconds) {} - - static void SetUpTestCase() { - // Make the backup poller poll very frequently in order to pick up - // updates from all the subchannels's FDs. - GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1); -#if TARGET_OS_IPHONE - // Workaround Apple CFStream bug - gpr_setenv("grpc_cfstream", "0"); -#endif - grpc_init(); - } - - static void TearDownTestCase() { grpc_shutdown(); } - - void SetUp() override { - response_generator_ = - grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>(); - // Start the backends. - for (size_t i = 0; i < num_backends_; ++i) { - backends_.emplace_back(new ServerThread<BackendServiceImpl>("backend")); - backends_.back()->Start(server_host_); - } - // Start the load balancers. - for (size_t i = 0; i < num_balancers_; ++i) { - balancers_.emplace_back(new ServerThread<BalancerServiceImpl>( - "balancer", client_load_reporting_interval_seconds_)); - balancers_.back()->Start(server_host_); - } - ResetStub(); - } - - void TearDown() override { - ShutdownAllBackends(); - for (auto& balancer : balancers_) balancer->Shutdown(); - } - - void StartAllBackends() { - for (auto& backend : backends_) backend->Start(server_host_); - } - - void StartBackend(size_t index) { backends_[index]->Start(server_host_); } - - void ShutdownAllBackends() { - for (auto& backend : backends_) backend->Shutdown(); - } - - void ShutdownBackend(size_t index) { backends_[index]->Shutdown(); } - - void ResetStub(int fallback_timeout = 0, +}; + +class GrpclbEnd2endTest : public ::testing::Test { + protected: + GrpclbEnd2endTest(size_t num_backends, size_t num_balancers, + int client_load_reporting_interval_seconds) + : server_host_("localhost"), + num_backends_(num_backends), + num_balancers_(num_balancers), + client_load_reporting_interval_seconds_( + client_load_reporting_interval_seconds) {} + + static void SetUpTestCase() { + // Make the backup poller poll very frequently in order to pick up + // updates from all the subchannels's FDs. + GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1); +#if TARGET_OS_IPHONE + // Workaround Apple CFStream bug + gpr_setenv("grpc_cfstream", "0"); +#endif + grpc_init(); + } + + static void TearDownTestCase() { grpc_shutdown(); } + + void SetUp() override { + response_generator_ = + grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>(); + // Start the backends. + for (size_t i = 0; i < num_backends_; ++i) { + backends_.emplace_back(new ServerThread<BackendServiceImpl>("backend")); + backends_.back()->Start(server_host_); + } + // Start the load balancers. + for (size_t i = 0; i < num_balancers_; ++i) { + balancers_.emplace_back(new ServerThread<BalancerServiceImpl>( + "balancer", client_load_reporting_interval_seconds_)); + balancers_.back()->Start(server_host_); + } + ResetStub(); + } + + void TearDown() override { + ShutdownAllBackends(); + for (auto& balancer : balancers_) balancer->Shutdown(); + } + + void StartAllBackends() { + for (auto& backend : backends_) backend->Start(server_host_); + } + + void StartBackend(size_t index) { backends_[index]->Start(server_host_); } + + void ShutdownAllBackends() { + for (auto& backend : backends_) backend->Shutdown(); + } + + void ShutdownBackend(size_t index) { backends_[index]->Shutdown(); } + + void ResetStub(int fallback_timeout = 0, const TString& expected_targets = "") { - ChannelArguments args; - if (fallback_timeout > 0) args.SetGrpclbFallbackTimeout(fallback_timeout); - args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, - response_generator_.get()); - if (!expected_targets.empty()) { - args.SetString(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS, expected_targets); - } - std::ostringstream uri; - uri << "fake:///" << kApplicationTargetName_; - // TODO(dgq): templatize tests to run everything using both secure and - // insecure channel credentials. - grpc_channel_credentials* channel_creds = - grpc_fake_transport_security_credentials_create(); - grpc_call_credentials* call_creds = grpc_md_only_test_credentials_create( - g_kCallCredsMdKey, g_kCallCredsMdValue, false); - std::shared_ptr<ChannelCredentials> creds( - new SecureChannelCredentials(grpc_composite_channel_credentials_create( - channel_creds, call_creds, nullptr))); - call_creds->Unref(); - channel_creds->Unref(); - channel_ = ::grpc::CreateCustomChannel(uri.str(), creds, args); - stub_ = grpc::testing::EchoTestService::NewStub(channel_); - } - - void ResetBackendCounters() { - for (auto& backend : backends_) backend->service_.ResetCounters(); - } - - ClientStats WaitForLoadReports() { - ClientStats client_stats; - for (auto& balancer : balancers_) { - client_stats += balancer->service_.WaitForLoadReport(); - } - return client_stats; - } - - bool SeenAllBackends(size_t start_index = 0, size_t stop_index = 0) { - if (stop_index == 0) stop_index = backends_.size(); - for (size_t i = start_index; i < stop_index; ++i) { - if (backends_[i]->service_.request_count() == 0) return false; - } - return true; - } - - void SendRpcAndCount(int* num_total, int* num_ok, int* num_failure, - int* num_drops) { - const Status status = SendRpc(); - if (status.ok()) { - ++*num_ok; - } else { - if (status.error_message() == "Call dropped by load balancing policy") { - ++*num_drops; - } else { - ++*num_failure; - } - } - ++*num_total; - } - - std::tuple<int, int, int> WaitForAllBackends(int num_requests_multiple_of = 1, - size_t start_index = 0, - size_t stop_index = 0) { - int num_ok = 0; - int num_failure = 0; - int num_drops = 0; - int num_total = 0; - while (!SeenAllBackends(start_index, stop_index)) { - SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_drops); - } - while (num_total % num_requests_multiple_of != 0) { - SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_drops); - } - ResetBackendCounters(); - gpr_log(GPR_INFO, - "Performed %d warm up requests (a multiple of %d) against the " - "backends. %d succeeded, %d failed, %d dropped.", - num_total, num_requests_multiple_of, num_ok, num_failure, - num_drops); - return std::make_tuple(num_ok, num_failure, num_drops); - } - - void WaitForBackend(size_t backend_idx) { - do { - (void)SendRpc(); - } while (backends_[backend_idx]->service_.request_count() == 0); - ResetBackendCounters(); - } - - struct AddressData { - int port; + ChannelArguments args; + if (fallback_timeout > 0) args.SetGrpclbFallbackTimeout(fallback_timeout); + args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, + response_generator_.get()); + if (!expected_targets.empty()) { + args.SetString(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS, expected_targets); + } + std::ostringstream uri; + uri << "fake:///" << kApplicationTargetName_; + // TODO(dgq): templatize tests to run everything using both secure and + // insecure channel credentials. + grpc_channel_credentials* channel_creds = + grpc_fake_transport_security_credentials_create(); + grpc_call_credentials* call_creds = grpc_md_only_test_credentials_create( + g_kCallCredsMdKey, g_kCallCredsMdValue, false); + std::shared_ptr<ChannelCredentials> creds( + new SecureChannelCredentials(grpc_composite_channel_credentials_create( + channel_creds, call_creds, nullptr))); + call_creds->Unref(); + channel_creds->Unref(); + channel_ = ::grpc::CreateCustomChannel(uri.str(), creds, args); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + void ResetBackendCounters() { + for (auto& backend : backends_) backend->service_.ResetCounters(); + } + + ClientStats WaitForLoadReports() { + ClientStats client_stats; + for (auto& balancer : balancers_) { + client_stats += balancer->service_.WaitForLoadReport(); + } + return client_stats; + } + + bool SeenAllBackends(size_t start_index = 0, size_t stop_index = 0) { + if (stop_index == 0) stop_index = backends_.size(); + for (size_t i = start_index; i < stop_index; ++i) { + if (backends_[i]->service_.request_count() == 0) return false; + } + return true; + } + + void SendRpcAndCount(int* num_total, int* num_ok, int* num_failure, + int* num_drops) { + const Status status = SendRpc(); + if (status.ok()) { + ++*num_ok; + } else { + if (status.error_message() == "Call dropped by load balancing policy") { + ++*num_drops; + } else { + ++*num_failure; + } + } + ++*num_total; + } + + std::tuple<int, int, int> WaitForAllBackends(int num_requests_multiple_of = 1, + size_t start_index = 0, + size_t stop_index = 0) { + int num_ok = 0; + int num_failure = 0; + int num_drops = 0; + int num_total = 0; + while (!SeenAllBackends(start_index, stop_index)) { + SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_drops); + } + while (num_total % num_requests_multiple_of != 0) { + SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_drops); + } + ResetBackendCounters(); + gpr_log(GPR_INFO, + "Performed %d warm up requests (a multiple of %d) against the " + "backends. %d succeeded, %d failed, %d dropped.", + num_total, num_requests_multiple_of, num_ok, num_failure, + num_drops); + return std::make_tuple(num_ok, num_failure, num_drops); + } + + void WaitForBackend(size_t backend_idx) { + do { + (void)SendRpc(); + } while (backends_[backend_idx]->service_.request_count() == 0); + ResetBackendCounters(); + } + + struct AddressData { + int port; TString balancer_name; - }; - + }; + static grpc_core::ServerAddressList CreateLbAddressesFromAddressDataList( - const std::vector<AddressData>& address_data) { - grpc_core::ServerAddressList addresses; - for (const auto& addr : address_data) { + const std::vector<AddressData>& address_data) { + grpc_core::ServerAddressList addresses; + for (const auto& addr : address_data) { TString lb_uri_str = y_absl::StrCat("ipv4:127.0.0.1:", addr.port); grpc_uri* lb_uri = grpc_uri_parse(lb_uri_str.c_str(), true); - GPR_ASSERT(lb_uri != nullptr); - grpc_resolved_address address; - GPR_ASSERT(grpc_parse_uri(lb_uri, &address)); + GPR_ASSERT(lb_uri != nullptr); + grpc_resolved_address address; + GPR_ASSERT(grpc_parse_uri(lb_uri, &address)); grpc_arg arg = grpc_core::CreateAuthorityOverrideChannelArg( addr.balancer_name.c_str()); grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); - addresses.emplace_back(address.addr, address.len, args); - grpc_uri_destroy(lb_uri); - } - return addresses; - } - + addresses.emplace_back(address.addr, address.len, args); + grpc_uri_destroy(lb_uri); + } + return addresses; + } + static grpc_core::Resolver::Result MakeResolverResult( const std::vector<AddressData>& balancer_address_data, const std::vector<AddressData>& backend_address_data = {}, @@ -583,191 +583,191 @@ class GrpclbEnd2endTest : public ::testing::Test { return result; } - void SetNextResolutionAllBalancers( + void SetNextResolutionAllBalancers( const char* service_config_json = kDefaultServiceConfig) { - std::vector<AddressData> addresses; - for (size_t i = 0; i < balancers_.size(); ++i) { + std::vector<AddressData> addresses; + for (size_t i = 0; i < balancers_.size(); ++i) { addresses.emplace_back(AddressData{balancers_[i]->port_, ""}); - } + } SetNextResolution(addresses, {}, service_config_json); - } - + } + void SetNextResolution( const std::vector<AddressData>& balancer_address_data, const std::vector<AddressData>& backend_address_data = {}, const char* service_config_json = kDefaultServiceConfig) { - grpc_core::ExecCtx exec_ctx; + grpc_core::ExecCtx exec_ctx; grpc_core::Resolver::Result result = MakeResolverResult( balancer_address_data, backend_address_data, service_config_json); - response_generator_->SetResponse(std::move(result)); - } - - void SetNextReresolutionResponse( + response_generator_->SetResponse(std::move(result)); + } + + void SetNextReresolutionResponse( const std::vector<AddressData>& balancer_address_data, const std::vector<AddressData>& backend_address_data = {}, const char* service_config_json = kDefaultServiceConfig) { - grpc_core::ExecCtx exec_ctx; + grpc_core::ExecCtx exec_ctx; grpc_core::Resolver::Result result = MakeResolverResult( balancer_address_data, backend_address_data, service_config_json); - response_generator_->SetReresolutionResponse(std::move(result)); - } - - const std::vector<int> GetBackendPorts(size_t start_index = 0, - size_t stop_index = 0) const { - if (stop_index == 0) stop_index = backends_.size(); - std::vector<int> backend_ports; - for (size_t i = start_index; i < stop_index; ++i) { - backend_ports.push_back(backends_[i]->port_); - } - return backend_ports; - } - - void ScheduleResponseForBalancer(size_t i, - const LoadBalanceResponse& response, - int delay_ms) { - balancers_[i]->service_.add_response(response, delay_ms); - } - - Status SendRpc(EchoResponse* response = nullptr, int timeout_ms = 1000, + response_generator_->SetReresolutionResponse(std::move(result)); + } + + const std::vector<int> GetBackendPorts(size_t start_index = 0, + size_t stop_index = 0) const { + if (stop_index == 0) stop_index = backends_.size(); + std::vector<int> backend_ports; + for (size_t i = start_index; i < stop_index; ++i) { + backend_ports.push_back(backends_[i]->port_); + } + return backend_ports; + } + + void ScheduleResponseForBalancer(size_t i, + const LoadBalanceResponse& response, + int delay_ms) { + balancers_[i]->service_.add_response(response, delay_ms); + } + + Status SendRpc(EchoResponse* response = nullptr, int timeout_ms = 1000, bool wait_for_ready = false, const Status& expected_status = Status::OK) { - const bool local_response = (response == nullptr); - if (local_response) response = new EchoResponse; - EchoRequest request; - request.set_message(kRequestMessage_); + const bool local_response = (response == nullptr); + if (local_response) response = new EchoResponse; + EchoRequest request; + request.set_message(kRequestMessage_); if (!expected_status.ok()) { auto* error = request.mutable_param()->mutable_expected_error(); error->set_code(expected_status.error_code()); error->set_error_message(expected_status.error_message()); } - ClientContext context; - context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms)); - if (wait_for_ready) context.set_wait_for_ready(true); - Status status = stub_->Echo(&context, request, response); - if (local_response) delete response; - return status; - } - - void CheckRpcSendOk(const size_t times = 1, const int timeout_ms = 1000, - bool wait_for_ready = false) { - for (size_t i = 0; i < times; ++i) { - EchoResponse response; - const Status status = SendRpc(&response, timeout_ms, wait_for_ready); - EXPECT_TRUE(status.ok()) << "code=" << status.error_code() - << " message=" << status.error_message(); - EXPECT_EQ(response.message(), kRequestMessage_); - } - } - - void CheckRpcSendFailure() { - const Status status = SendRpc(); - EXPECT_FALSE(status.ok()); - } - - template <typename T> - struct ServerThread { - template <typename... Args> + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms)); + if (wait_for_ready) context.set_wait_for_ready(true); + Status status = stub_->Echo(&context, request, response); + if (local_response) delete response; + return status; + } + + void CheckRpcSendOk(const size_t times = 1, const int timeout_ms = 1000, + bool wait_for_ready = false) { + for (size_t i = 0; i < times; ++i) { + EchoResponse response; + const Status status = SendRpc(&response, timeout_ms, wait_for_ready); + EXPECT_TRUE(status.ok()) << "code=" << status.error_code() + << " message=" << status.error_message(); + EXPECT_EQ(response.message(), kRequestMessage_); + } + } + + void CheckRpcSendFailure() { + const Status status = SendRpc(); + EXPECT_FALSE(status.ok()); + } + + template <typename T> + struct ServerThread { + template <typename... Args> explicit ServerThread(const TString& type, Args&&... args) - : port_(grpc_pick_unused_port_or_die()), - type_(type), - service_(std::forward<Args>(args)...) {} - + : port_(grpc_pick_unused_port_or_die()), + type_(type), + service_(std::forward<Args>(args)...) {} + void Start(const TString& server_host) { - gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); - GPR_ASSERT(!running_); - running_ = true; - service_.Start(); - grpc::internal::Mutex mu; - // We need to acquire the lock here in order to prevent the notify_one - // by ServerThread::Serve from firing before the wait below is hit. - grpc::internal::MutexLock lock(&mu); - grpc::internal::CondVar cond; - thread_.reset(new std::thread( - std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); - cond.Wait(&mu); - gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); - } - + gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); + GPR_ASSERT(!running_); + running_ = true; + service_.Start(); + grpc::internal::Mutex mu; + // We need to acquire the lock here in order to prevent the notify_one + // by ServerThread::Serve from firing before the wait below is hit. + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; + thread_.reset(new std::thread( + std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); + cond.Wait(&mu); + gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); + } + void Serve(const TString& server_host, grpc::internal::Mutex* mu, - grpc::internal::CondVar* cond) { - // We need to acquire the lock here in order to prevent the notify_one - // below from firing before its corresponding wait is executed. - grpc::internal::MutexLock lock(mu); - std::ostringstream server_address; - server_address << server_host << ":" << port_; - ServerBuilder builder; - std::shared_ptr<ServerCredentials> creds(new SecureServerCredentials( - grpc_fake_transport_security_server_credentials_create())); - builder.AddListeningPort(server_address.str(), creds); - builder.RegisterService(&service_); - server_ = builder.BuildAndStart(); - cond->Signal(); - } - - void Shutdown() { - if (!running_) return; - gpr_log(GPR_INFO, "%s about to shutdown", type_.c_str()); - service_.Shutdown(); - server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0)); - thread_->join(); - gpr_log(GPR_INFO, "%s shutdown completed", type_.c_str()); - running_ = false; - } - - const int port_; + grpc::internal::CondVar* cond) { + // We need to acquire the lock here in order to prevent the notify_one + // below from firing before its corresponding wait is executed. + grpc::internal::MutexLock lock(mu); + std::ostringstream server_address; + server_address << server_host << ":" << port_; + ServerBuilder builder; + std::shared_ptr<ServerCredentials> creds(new SecureServerCredentials( + grpc_fake_transport_security_server_credentials_create())); + builder.AddListeningPort(server_address.str(), creds); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + cond->Signal(); + } + + void Shutdown() { + if (!running_) return; + gpr_log(GPR_INFO, "%s about to shutdown", type_.c_str()); + service_.Shutdown(); + server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0)); + thread_->join(); + gpr_log(GPR_INFO, "%s shutdown completed", type_.c_str()); + running_ = false; + } + + const int port_; TString type_; - T service_; - std::unique_ptr<Server> server_; - std::unique_ptr<std::thread> thread_; - bool running_ = false; - }; - + T service_; + std::unique_ptr<Server> server_; + std::unique_ptr<std::thread> thread_; + bool running_ = false; + }; + const TString server_host_; - const size_t num_backends_; - const size_t num_balancers_; - const int client_load_reporting_interval_seconds_; - std::shared_ptr<Channel> channel_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::vector<std::unique_ptr<ServerThread<BackendServiceImpl>>> backends_; - std::vector<std::unique_ptr<ServerThread<BalancerServiceImpl>>> balancers_; - grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator> - response_generator_; + const size_t num_backends_; + const size_t num_balancers_; + const int client_load_reporting_interval_seconds_; + std::shared_ptr<Channel> channel_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::vector<std::unique_ptr<ServerThread<BackendServiceImpl>>> backends_; + std::vector<std::unique_ptr<ServerThread<BalancerServiceImpl>>> balancers_; + grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator> + response_generator_; const TString kRequestMessage_ = "Live long and prosper."; const TString kApplicationTargetName_ = "application_target_name"; -}; - -class SingleBalancerTest : public GrpclbEnd2endTest { - public: - SingleBalancerTest() : GrpclbEnd2endTest(4, 1, 0) {} -}; - -TEST_F(SingleBalancerTest, Vanilla) { - SetNextResolutionAllBalancers(); - const size_t kNumRpcsPerAddress = 100; - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), - 0); - // Make sure that trying to connect works without a call. - channel_->GetState(true /* try_to_connect */); - // We need to wait for all backends to come online. - WaitForAllBackends(); - // Send kNumRpcsPerAddress RPCs per server. - CheckRpcSendOk(kNumRpcsPerAddress * num_backends_); - - // Each backend should have gotten 100 requests. - for (size_t i = 0; i < backends_.size(); ++i) { - EXPECT_EQ(kNumRpcsPerAddress, backends_[i]->service_.request_count()); - } - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - - // Check LB policy name for the channel. - EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); -} - +}; + +class SingleBalancerTest : public GrpclbEnd2endTest { + public: + SingleBalancerTest() : GrpclbEnd2endTest(4, 1, 0) {} +}; + +TEST_F(SingleBalancerTest, Vanilla) { + SetNextResolutionAllBalancers(); + const size_t kNumRpcsPerAddress = 100; + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), + 0); + // Make sure that trying to connect works without a call. + channel_->GetState(true /* try_to_connect */); + // We need to wait for all backends to come online. + WaitForAllBackends(); + // Send kNumRpcsPerAddress RPCs per server. + CheckRpcSendOk(kNumRpcsPerAddress * num_backends_); + + // Each backend should have gotten 100 requests. + for (size_t i = 0; i < backends_.size(); ++i) { + EXPECT_EQ(kNumRpcsPerAddress, backends_[i]->service_.request_count()); + } + balancers_[0]->service_.NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + + // Check LB policy name for the channel. + EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); +} + TEST_F(SingleBalancerTest, ReturnServerStatus) { SetNextResolutionAllBalancers(); ScheduleResponseForBalancer( @@ -784,550 +784,550 @@ TEST_F(SingleBalancerTest, ReturnServerStatus) { EXPECT_EQ(actual.error_message(), expected.error_message()); } -TEST_F(SingleBalancerTest, SelectGrpclbWithMigrationServiceConfig) { - SetNextResolutionAllBalancers( - "{\n" - " \"loadBalancingConfig\":[\n" - " { \"does_not_exist\":{} },\n" - " { \"grpclb\":{} }\n" - " ]\n" - "}"); - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), - 0); - CheckRpcSendOk(1, 1000 /* timeout_ms */, true /* wait_for_ready */); - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - // Check LB policy name for the channel. - EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); -} - -TEST_F(SingleBalancerTest, - SelectGrpclbWithMigrationServiceConfigAndNoAddresses) { - const int kFallbackTimeoutMs = 200 * grpc_test_slowdown_factor(); - ResetStub(kFallbackTimeoutMs); +TEST_F(SingleBalancerTest, SelectGrpclbWithMigrationServiceConfig) { + SetNextResolutionAllBalancers( + "{\n" + " \"loadBalancingConfig\":[\n" + " { \"does_not_exist\":{} },\n" + " { \"grpclb\":{} }\n" + " ]\n" + "}"); + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), + 0); + CheckRpcSendOk(1, 1000 /* timeout_ms */, true /* wait_for_ready */); + balancers_[0]->service_.NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + // Check LB policy name for the channel. + EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); +} + +TEST_F(SingleBalancerTest, + SelectGrpclbWithMigrationServiceConfigAndNoAddresses) { + const int kFallbackTimeoutMs = 200 * grpc_test_slowdown_factor(); + ResetStub(kFallbackTimeoutMs); SetNextResolution({}, {}, - "{\n" - " \"loadBalancingConfig\":[\n" - " { \"does_not_exist\":{} },\n" - " { \"grpclb\":{} }\n" - " ]\n" - "}"); - // Try to connect. - EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(true)); - // Should go into state TRANSIENT_FAILURE when we enter fallback mode. - const gpr_timespec deadline = grpc_timeout_seconds_to_deadline(1); - grpc_connectivity_state state; - while ((state = channel_->GetState(false)) != - GRPC_CHANNEL_TRANSIENT_FAILURE) { - ASSERT_TRUE(channel_->WaitForStateChange(state, deadline)); - } - // Check LB policy name for the channel. - EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); -} - -TEST_F(SingleBalancerTest, UsePickFirstChildPolicy) { - SetNextResolutionAllBalancers( - "{\n" - " \"loadBalancingConfig\":[\n" - " { \"grpclb\":{\n" - " \"childPolicy\":[\n" - " { \"pick_first\":{} }\n" - " ]\n" - " } }\n" - " ]\n" - "}"); - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), - 0); - const size_t kNumRpcs = num_backends_ * 2; - CheckRpcSendOk(kNumRpcs, 1000 /* timeout_ms */, true /* wait_for_ready */); - balancers_[0]->service_.NotifyDoneWithServerlists(); - // Check that all requests went to the first backend. This verifies - // that we used pick_first instead of round_robin as the child policy. - EXPECT_EQ(backends_[0]->service_.request_count(), kNumRpcs); - for (size_t i = 1; i < backends_.size(); ++i) { - EXPECT_EQ(backends_[i]->service_.request_count(), 0UL); - } - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - // Check LB policy name for the channel. - EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); -} - -TEST_F(SingleBalancerTest, SwapChildPolicy) { - SetNextResolutionAllBalancers( - "{\n" - " \"loadBalancingConfig\":[\n" - " { \"grpclb\":{\n" - " \"childPolicy\":[\n" - " { \"pick_first\":{} }\n" - " ]\n" - " } }\n" - " ]\n" - "}"); - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), - 0); - const size_t kNumRpcs = num_backends_ * 2; - CheckRpcSendOk(kNumRpcs, 1000 /* timeout_ms */, true /* wait_for_ready */); - // Check that all requests went to the first backend. This verifies - // that we used pick_first instead of round_robin as the child policy. - EXPECT_EQ(backends_[0]->service_.request_count(), kNumRpcs); - for (size_t i = 1; i < backends_.size(); ++i) { - EXPECT_EQ(backends_[i]->service_.request_count(), 0UL); - } - // Send new resolution that removes child policy from service config. + "{\n" + " \"loadBalancingConfig\":[\n" + " { \"does_not_exist\":{} },\n" + " { \"grpclb\":{} }\n" + " ]\n" + "}"); + // Try to connect. + EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(true)); + // Should go into state TRANSIENT_FAILURE when we enter fallback mode. + const gpr_timespec deadline = grpc_timeout_seconds_to_deadline(1); + grpc_connectivity_state state; + while ((state = channel_->GetState(false)) != + GRPC_CHANNEL_TRANSIENT_FAILURE) { + ASSERT_TRUE(channel_->WaitForStateChange(state, deadline)); + } + // Check LB policy name for the channel. + EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); +} + +TEST_F(SingleBalancerTest, UsePickFirstChildPolicy) { + SetNextResolutionAllBalancers( + "{\n" + " \"loadBalancingConfig\":[\n" + " { \"grpclb\":{\n" + " \"childPolicy\":[\n" + " { \"pick_first\":{} }\n" + " ]\n" + " } }\n" + " ]\n" + "}"); + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), + 0); + const size_t kNumRpcs = num_backends_ * 2; + CheckRpcSendOk(kNumRpcs, 1000 /* timeout_ms */, true /* wait_for_ready */); + balancers_[0]->service_.NotifyDoneWithServerlists(); + // Check that all requests went to the first backend. This verifies + // that we used pick_first instead of round_robin as the child policy. + EXPECT_EQ(backends_[0]->service_.request_count(), kNumRpcs); + for (size_t i = 1; i < backends_.size(); ++i) { + EXPECT_EQ(backends_[i]->service_.request_count(), 0UL); + } + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + // Check LB policy name for the channel. + EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); +} + +TEST_F(SingleBalancerTest, SwapChildPolicy) { + SetNextResolutionAllBalancers( + "{\n" + " \"loadBalancingConfig\":[\n" + " { \"grpclb\":{\n" + " \"childPolicy\":[\n" + " { \"pick_first\":{} }\n" + " ]\n" + " } }\n" + " ]\n" + "}"); + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), + 0); + const size_t kNumRpcs = num_backends_ * 2; + CheckRpcSendOk(kNumRpcs, 1000 /* timeout_ms */, true /* wait_for_ready */); + // Check that all requests went to the first backend. This verifies + // that we used pick_first instead of round_robin as the child policy. + EXPECT_EQ(backends_[0]->service_.request_count(), kNumRpcs); + for (size_t i = 1; i < backends_.size(); ++i) { + EXPECT_EQ(backends_[i]->service_.request_count(), 0UL); + } + // Send new resolution that removes child policy from service config. SetNextResolutionAllBalancers(); - WaitForAllBackends(); - CheckRpcSendOk(kNumRpcs, 1000 /* timeout_ms */, true /* wait_for_ready */); - // Check that every backend saw the same number of requests. This verifies - // that we used round_robin. - for (size_t i = 0; i < backends_.size(); ++i) { - EXPECT_EQ(backends_[i]->service_.request_count(), 2UL); - } - // Done. - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - // Check LB policy name for the channel. - EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); -} - -TEST_F(SingleBalancerTest, SameBackendListedMultipleTimes) { - SetNextResolutionAllBalancers(); - // Same backend listed twice. - std::vector<int> ports; - ports.push_back(backends_[0]->port_); - ports.push_back(backends_[0]->port_); - const size_t kNumRpcsPerAddress = 10; - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(ports, {}), 0); - // We need to wait for the backend to come online. - WaitForBackend(0); - // Send kNumRpcsPerAddress RPCs per server. - CheckRpcSendOk(kNumRpcsPerAddress * ports.size()); - // Backend should have gotten 20 requests. - EXPECT_EQ(kNumRpcsPerAddress * 2, backends_[0]->service_.request_count()); - // And they should have come from a single client port, because of - // subchannel sharing. - EXPECT_EQ(1UL, backends_[0]->service_.clients().size()); - balancers_[0]->service_.NotifyDoneWithServerlists(); -} - -TEST_F(SingleBalancerTest, SecureNaming) { - ResetStub(0, kApplicationTargetName_ + ";lb"); + WaitForAllBackends(); + CheckRpcSendOk(kNumRpcs, 1000 /* timeout_ms */, true /* wait_for_ready */); + // Check that every backend saw the same number of requests. This verifies + // that we used round_robin. + for (size_t i = 0; i < backends_.size(); ++i) { + EXPECT_EQ(backends_[i]->service_.request_count(), 2UL); + } + // Done. + balancers_[0]->service_.NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + // Check LB policy name for the channel. + EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); +} + +TEST_F(SingleBalancerTest, SameBackendListedMultipleTimes) { + SetNextResolutionAllBalancers(); + // Same backend listed twice. + std::vector<int> ports; + ports.push_back(backends_[0]->port_); + ports.push_back(backends_[0]->port_); + const size_t kNumRpcsPerAddress = 10; + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(ports, {}), 0); + // We need to wait for the backend to come online. + WaitForBackend(0); + // Send kNumRpcsPerAddress RPCs per server. + CheckRpcSendOk(kNumRpcsPerAddress * ports.size()); + // Backend should have gotten 20 requests. + EXPECT_EQ(kNumRpcsPerAddress * 2, backends_[0]->service_.request_count()); + // And they should have come from a single client port, because of + // subchannel sharing. + EXPECT_EQ(1UL, backends_[0]->service_.clients().size()); + balancers_[0]->service_.NotifyDoneWithServerlists(); +} + +TEST_F(SingleBalancerTest, SecureNaming) { + ResetStub(0, kApplicationTargetName_ + ";lb"); SetNextResolution({AddressData{balancers_[0]->port_, "lb"}}); - const size_t kNumRpcsPerAddress = 100; - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), - 0); - // Make sure that trying to connect works without a call. - channel_->GetState(true /* try_to_connect */); - // We need to wait for all backends to come online. - WaitForAllBackends(); - // Send kNumRpcsPerAddress RPCs per server. - CheckRpcSendOk(kNumRpcsPerAddress * num_backends_); - - // Each backend should have gotten 100 requests. - for (size_t i = 0; i < backends_.size(); ++i) { - EXPECT_EQ(kNumRpcsPerAddress, backends_[i]->service_.request_count()); - } - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - // Check LB policy name for the channel. - EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); -} - -TEST_F(SingleBalancerTest, SecureNamingDeathTest) { - ::testing::FLAGS_gtest_death_test_style = "threadsafe"; - // Make sure that we blow up (via abort() from the security connector) when - // the name from the balancer doesn't match expectations. - ASSERT_DEATH_IF_SUPPORTED( - { - ResetStub(0, kApplicationTargetName_ + ";lb"); + const size_t kNumRpcsPerAddress = 100; + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), + 0); + // Make sure that trying to connect works without a call. + channel_->GetState(true /* try_to_connect */); + // We need to wait for all backends to come online. + WaitForAllBackends(); + // Send kNumRpcsPerAddress RPCs per server. + CheckRpcSendOk(kNumRpcsPerAddress * num_backends_); + + // Each backend should have gotten 100 requests. + for (size_t i = 0; i < backends_.size(); ++i) { + EXPECT_EQ(kNumRpcsPerAddress, backends_[i]->service_.request_count()); + } + balancers_[0]->service_.NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + // Check LB policy name for the channel. + EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); +} + +TEST_F(SingleBalancerTest, SecureNamingDeathTest) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + // Make sure that we blow up (via abort() from the security connector) when + // the name from the balancer doesn't match expectations. + ASSERT_DEATH_IF_SUPPORTED( + { + ResetStub(0, kApplicationTargetName_ + ";lb"); SetNextResolution({AddressData{balancers_[0]->port_, "woops"}}); - channel_->WaitForConnected(grpc_timeout_seconds_to_deadline(1)); - }, - ""); -} - -TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) { - SetNextResolutionAllBalancers(); - const int kServerlistDelayMs = 500 * grpc_test_slowdown_factor(); - const int kCallDeadlineMs = kServerlistDelayMs * 2; - // First response is an empty serverlist, sent right away. - ScheduleResponseForBalancer(0, LoadBalanceResponse(), 0); - // Send non-empty serverlist only after kServerlistDelayMs - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), - kServerlistDelayMs); - const auto t0 = system_clock::now(); - // Client will block: LB will initially send empty serverlist. - CheckRpcSendOk(1, kCallDeadlineMs, true /* wait_for_ready */); - const auto ellapsed_ms = - std::chrono::duration_cast<std::chrono::milliseconds>( - system_clock::now() - t0); - // but eventually, the LB sends a serverlist update that allows the call to - // proceed. The call delay must be larger than the delay in sending the - // populated serverlist but under the call's deadline (which is enforced by - // the call's deadline). - EXPECT_GT(ellapsed_ms.count(), kServerlistDelayMs); - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent two responses. - EXPECT_EQ(2U, balancers_[0]->service_.response_count()); -} - -TEST_F(SingleBalancerTest, AllServersUnreachableFailFast) { - SetNextResolutionAllBalancers(); - const size_t kNumUnreachableServers = 5; - std::vector<int> ports; - for (size_t i = 0; i < kNumUnreachableServers; ++i) { - ports.push_back(grpc_pick_unused_port_or_die()); - } - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(ports, {}), 0); - const Status status = SendRpc(); - // The error shouldn't be DEADLINE_EXCEEDED. - EXPECT_EQ(StatusCode::UNAVAILABLE, status.error_code()); - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); -} - -TEST_F(SingleBalancerTest, Fallback) { - SetNextResolutionAllBalancers(); - const int kFallbackTimeoutMs = 200 * grpc_test_slowdown_factor(); - const int kServerlistDelayMs = 500 * grpc_test_slowdown_factor(); - const size_t kNumBackendsInResolution = backends_.size() / 2; - - ResetStub(kFallbackTimeoutMs); + channel_->WaitForConnected(grpc_timeout_seconds_to_deadline(1)); + }, + ""); +} + +TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) { + SetNextResolutionAllBalancers(); + const int kServerlistDelayMs = 500 * grpc_test_slowdown_factor(); + const int kCallDeadlineMs = kServerlistDelayMs * 2; + // First response is an empty serverlist, sent right away. + ScheduleResponseForBalancer(0, LoadBalanceResponse(), 0); + // Send non-empty serverlist only after kServerlistDelayMs + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), + kServerlistDelayMs); + const auto t0 = system_clock::now(); + // Client will block: LB will initially send empty serverlist. + CheckRpcSendOk(1, kCallDeadlineMs, true /* wait_for_ready */); + const auto ellapsed_ms = + std::chrono::duration_cast<std::chrono::milliseconds>( + system_clock::now() - t0); + // but eventually, the LB sends a serverlist update that allows the call to + // proceed. The call delay must be larger than the delay in sending the + // populated serverlist but under the call's deadline (which is enforced by + // the call's deadline). + EXPECT_GT(ellapsed_ms.count(), kServerlistDelayMs); + balancers_[0]->service_.NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent two responses. + EXPECT_EQ(2U, balancers_[0]->service_.response_count()); +} + +TEST_F(SingleBalancerTest, AllServersUnreachableFailFast) { + SetNextResolutionAllBalancers(); + const size_t kNumUnreachableServers = 5; + std::vector<int> ports; + for (size_t i = 0; i < kNumUnreachableServers; ++i) { + ports.push_back(grpc_pick_unused_port_or_die()); + } + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(ports, {}), 0); + const Status status = SendRpc(); + // The error shouldn't be DEADLINE_EXCEEDED. + EXPECT_EQ(StatusCode::UNAVAILABLE, status.error_code()); + balancers_[0]->service_.NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); +} + +TEST_F(SingleBalancerTest, Fallback) { + SetNextResolutionAllBalancers(); + const int kFallbackTimeoutMs = 200 * grpc_test_slowdown_factor(); + const int kServerlistDelayMs = 500 * grpc_test_slowdown_factor(); + const size_t kNumBackendsInResolution = backends_.size() / 2; + + ResetStub(kFallbackTimeoutMs); std::vector<AddressData> balancer_addresses; balancer_addresses.emplace_back(AddressData{balancers_[0]->port_, ""}); std::vector<AddressData> backend_addresses; - for (size_t i = 0; i < kNumBackendsInResolution; ++i) { + for (size_t i = 0; i < kNumBackendsInResolution; ++i) { backend_addresses.emplace_back(AddressData{backends_[i]->port_, ""}); - } + } SetNextResolution(balancer_addresses, backend_addresses); - - // Send non-empty serverlist only after kServerlistDelayMs. - ScheduleResponseForBalancer( - 0, - BalancerServiceImpl::BuildResponseForBackends( - GetBackendPorts(kNumBackendsInResolution /* start_index */), {}), - kServerlistDelayMs); - - // Wait until all the fallback backends are reachable. - for (size_t i = 0; i < kNumBackendsInResolution; ++i) { - WaitForBackend(i); - } - - // The first request. - gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); - CheckRpcSendOk(kNumBackendsInResolution); - gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); - - // Fallback is used: each backend returned by the resolver should have - // gotten one request. - for (size_t i = 0; i < kNumBackendsInResolution; ++i) { - EXPECT_EQ(1U, backends_[i]->service_.request_count()); - } - for (size_t i = kNumBackendsInResolution; i < backends_.size(); ++i) { - EXPECT_EQ(0U, backends_[i]->service_.request_count()); - } - - // Wait until the serverlist reception has been processed and all backends - // in the serverlist are reachable. - for (size_t i = kNumBackendsInResolution; i < backends_.size(); ++i) { - WaitForBackend(i); - } - - // Send out the second request. - gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); - CheckRpcSendOk(backends_.size() - kNumBackendsInResolution); - gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); - - // Serverlist is used: each backend returned by the balancer should - // have gotten one request. - for (size_t i = 0; i < kNumBackendsInResolution; ++i) { - EXPECT_EQ(0U, backends_[i]->service_.request_count()); - } - for (size_t i = kNumBackendsInResolution; i < backends_.size(); ++i) { - EXPECT_EQ(1U, backends_[i]->service_.request_count()); - } - - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); -} - -TEST_F(SingleBalancerTest, FallbackUpdate) { - SetNextResolutionAllBalancers(); - const int kFallbackTimeoutMs = 200 * grpc_test_slowdown_factor(); - const int kServerlistDelayMs = 500 * grpc_test_slowdown_factor(); - const size_t kNumBackendsInResolution = backends_.size() / 3; - const size_t kNumBackendsInResolutionUpdate = backends_.size() / 3; - - ResetStub(kFallbackTimeoutMs); + + // Send non-empty serverlist only after kServerlistDelayMs. + ScheduleResponseForBalancer( + 0, + BalancerServiceImpl::BuildResponseForBackends( + GetBackendPorts(kNumBackendsInResolution /* start_index */), {}), + kServerlistDelayMs); + + // Wait until all the fallback backends are reachable. + for (size_t i = 0; i < kNumBackendsInResolution; ++i) { + WaitForBackend(i); + } + + // The first request. + gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); + CheckRpcSendOk(kNumBackendsInResolution); + gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); + + // Fallback is used: each backend returned by the resolver should have + // gotten one request. + for (size_t i = 0; i < kNumBackendsInResolution; ++i) { + EXPECT_EQ(1U, backends_[i]->service_.request_count()); + } + for (size_t i = kNumBackendsInResolution; i < backends_.size(); ++i) { + EXPECT_EQ(0U, backends_[i]->service_.request_count()); + } + + // Wait until the serverlist reception has been processed and all backends + // in the serverlist are reachable. + for (size_t i = kNumBackendsInResolution; i < backends_.size(); ++i) { + WaitForBackend(i); + } + + // Send out the second request. + gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); + CheckRpcSendOk(backends_.size() - kNumBackendsInResolution); + gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); + + // Serverlist is used: each backend returned by the balancer should + // have gotten one request. + for (size_t i = 0; i < kNumBackendsInResolution; ++i) { + EXPECT_EQ(0U, backends_[i]->service_.request_count()); + } + for (size_t i = kNumBackendsInResolution; i < backends_.size(); ++i) { + EXPECT_EQ(1U, backends_[i]->service_.request_count()); + } + + balancers_[0]->service_.NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); +} + +TEST_F(SingleBalancerTest, FallbackUpdate) { + SetNextResolutionAllBalancers(); + const int kFallbackTimeoutMs = 200 * grpc_test_slowdown_factor(); + const int kServerlistDelayMs = 500 * grpc_test_slowdown_factor(); + const size_t kNumBackendsInResolution = backends_.size() / 3; + const size_t kNumBackendsInResolutionUpdate = backends_.size() / 3; + + ResetStub(kFallbackTimeoutMs); std::vector<AddressData> balancer_addresses; balancer_addresses.emplace_back(AddressData{balancers_[0]->port_, ""}); std::vector<AddressData> backend_addresses; - for (size_t i = 0; i < kNumBackendsInResolution; ++i) { + for (size_t i = 0; i < kNumBackendsInResolution; ++i) { backend_addresses.emplace_back(AddressData{backends_[i]->port_, ""}); - } + } SetNextResolution(balancer_addresses, backend_addresses); - - // Send non-empty serverlist only after kServerlistDelayMs. - ScheduleResponseForBalancer( - 0, - BalancerServiceImpl::BuildResponseForBackends( - GetBackendPorts(kNumBackendsInResolution + - kNumBackendsInResolutionUpdate /* start_index */), - {}), - kServerlistDelayMs); - - // Wait until all the fallback backends are reachable. - for (size_t i = 0; i < kNumBackendsInResolution; ++i) { - WaitForBackend(i); - } - - // The first request. - gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); - CheckRpcSendOk(kNumBackendsInResolution); - gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); - - // Fallback is used: each backend returned by the resolver should have - // gotten one request. - for (size_t i = 0; i < kNumBackendsInResolution; ++i) { - EXPECT_EQ(1U, backends_[i]->service_.request_count()); - } - for (size_t i = kNumBackendsInResolution; i < backends_.size(); ++i) { - EXPECT_EQ(0U, backends_[i]->service_.request_count()); - } - + + // Send non-empty serverlist only after kServerlistDelayMs. + ScheduleResponseForBalancer( + 0, + BalancerServiceImpl::BuildResponseForBackends( + GetBackendPorts(kNumBackendsInResolution + + kNumBackendsInResolutionUpdate /* start_index */), + {}), + kServerlistDelayMs); + + // Wait until all the fallback backends are reachable. + for (size_t i = 0; i < kNumBackendsInResolution; ++i) { + WaitForBackend(i); + } + + // The first request. + gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); + CheckRpcSendOk(kNumBackendsInResolution); + gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); + + // Fallback is used: each backend returned by the resolver should have + // gotten one request. + for (size_t i = 0; i < kNumBackendsInResolution; ++i) { + EXPECT_EQ(1U, backends_[i]->service_.request_count()); + } + for (size_t i = kNumBackendsInResolution; i < backends_.size(); ++i) { + EXPECT_EQ(0U, backends_[i]->service_.request_count()); + } + balancer_addresses.clear(); balancer_addresses.emplace_back(AddressData{balancers_[0]->port_, ""}); backend_addresses.clear(); - for (size_t i = kNumBackendsInResolution; - i < kNumBackendsInResolution + kNumBackendsInResolutionUpdate; ++i) { + for (size_t i = kNumBackendsInResolution; + i < kNumBackendsInResolution + kNumBackendsInResolutionUpdate; ++i) { backend_addresses.emplace_back(AddressData{backends_[i]->port_, ""}); - } + } SetNextResolution(balancer_addresses, backend_addresses); - - // Wait until the resolution update has been processed and all the new - // fallback backends are reachable. - for (size_t i = kNumBackendsInResolution; - i < kNumBackendsInResolution + kNumBackendsInResolutionUpdate; ++i) { - WaitForBackend(i); - } - - // Send out the second request. - gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); - CheckRpcSendOk(kNumBackendsInResolutionUpdate); - gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); - - // The resolution update is used: each backend in the resolution update should - // have gotten one request. - for (size_t i = 0; i < kNumBackendsInResolution; ++i) { - EXPECT_EQ(0U, backends_[i]->service_.request_count()); - } - for (size_t i = kNumBackendsInResolution; - i < kNumBackendsInResolution + kNumBackendsInResolutionUpdate; ++i) { - EXPECT_EQ(1U, backends_[i]->service_.request_count()); - } - for (size_t i = kNumBackendsInResolution + kNumBackendsInResolutionUpdate; - i < backends_.size(); ++i) { - EXPECT_EQ(0U, backends_[i]->service_.request_count()); - } - - // Wait until the serverlist reception has been processed and all backends - // in the serverlist are reachable. - for (size_t i = kNumBackendsInResolution + kNumBackendsInResolutionUpdate; - i < backends_.size(); ++i) { - WaitForBackend(i); - } - - // Send out the third request. - gpr_log(GPR_INFO, "========= BEFORE THIRD BATCH =========="); - CheckRpcSendOk(backends_.size() - kNumBackendsInResolution - - kNumBackendsInResolutionUpdate); - gpr_log(GPR_INFO, "========= DONE WITH THIRD BATCH =========="); - - // Serverlist is used: each backend returned by the balancer should - // have gotten one request. - for (size_t i = 0; - i < kNumBackendsInResolution + kNumBackendsInResolutionUpdate; ++i) { - EXPECT_EQ(0U, backends_[i]->service_.request_count()); - } - for (size_t i = kNumBackendsInResolution + kNumBackendsInResolutionUpdate; - i < backends_.size(); ++i) { - EXPECT_EQ(1U, backends_[i]->service_.request_count()); - } - - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); -} - -TEST_F(SingleBalancerTest, - FallbackAfterStartup_LoseContactWithBalancerThenBackends) { - // First two backends are fallback, last two are pointed to by balancer. - const size_t kNumFallbackBackends = 2; - const size_t kNumBalancerBackends = backends_.size() - kNumFallbackBackends; + + // Wait until the resolution update has been processed and all the new + // fallback backends are reachable. + for (size_t i = kNumBackendsInResolution; + i < kNumBackendsInResolution + kNumBackendsInResolutionUpdate; ++i) { + WaitForBackend(i); + } + + // Send out the second request. + gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); + CheckRpcSendOk(kNumBackendsInResolutionUpdate); + gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); + + // The resolution update is used: each backend in the resolution update should + // have gotten one request. + for (size_t i = 0; i < kNumBackendsInResolution; ++i) { + EXPECT_EQ(0U, backends_[i]->service_.request_count()); + } + for (size_t i = kNumBackendsInResolution; + i < kNumBackendsInResolution + kNumBackendsInResolutionUpdate; ++i) { + EXPECT_EQ(1U, backends_[i]->service_.request_count()); + } + for (size_t i = kNumBackendsInResolution + kNumBackendsInResolutionUpdate; + i < backends_.size(); ++i) { + EXPECT_EQ(0U, backends_[i]->service_.request_count()); + } + + // Wait until the serverlist reception has been processed and all backends + // in the serverlist are reachable. + for (size_t i = kNumBackendsInResolution + kNumBackendsInResolutionUpdate; + i < backends_.size(); ++i) { + WaitForBackend(i); + } + + // Send out the third request. + gpr_log(GPR_INFO, "========= BEFORE THIRD BATCH =========="); + CheckRpcSendOk(backends_.size() - kNumBackendsInResolution - + kNumBackendsInResolutionUpdate); + gpr_log(GPR_INFO, "========= DONE WITH THIRD BATCH =========="); + + // Serverlist is used: each backend returned by the balancer should + // have gotten one request. + for (size_t i = 0; + i < kNumBackendsInResolution + kNumBackendsInResolutionUpdate; ++i) { + EXPECT_EQ(0U, backends_[i]->service_.request_count()); + } + for (size_t i = kNumBackendsInResolution + kNumBackendsInResolutionUpdate; + i < backends_.size(); ++i) { + EXPECT_EQ(1U, backends_[i]->service_.request_count()); + } + + balancers_[0]->service_.NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); +} + +TEST_F(SingleBalancerTest, + FallbackAfterStartup_LoseContactWithBalancerThenBackends) { + // First two backends are fallback, last two are pointed to by balancer. + const size_t kNumFallbackBackends = 2; + const size_t kNumBalancerBackends = backends_.size() - kNumFallbackBackends; std::vector<AddressData> backend_addresses; - for (size_t i = 0; i < kNumFallbackBackends; ++i) { + for (size_t i = 0; i < kNumFallbackBackends; ++i) { backend_addresses.emplace_back(AddressData{backends_[i]->port_, ""}); - } + } std::vector<AddressData> balancer_addresses; - for (size_t i = 0; i < balancers_.size(); ++i) { + for (size_t i = 0; i < balancers_.size(); ++i) { balancer_addresses.emplace_back(AddressData{balancers_[i]->port_, ""}); - } + } SetNextResolution(balancer_addresses, backend_addresses); - ScheduleResponseForBalancer(0, - BalancerServiceImpl::BuildResponseForBackends( - GetBackendPorts(kNumFallbackBackends), {}), - 0); - // Try to connect. - channel_->GetState(true /* try_to_connect */); - WaitForAllBackends(1 /* num_requests_multiple_of */, - kNumFallbackBackends /* start_index */); - // Stop balancer. RPCs should continue going to backends from balancer. - balancers_[0]->Shutdown(); - CheckRpcSendOk(100 * kNumBalancerBackends); - for (size_t i = kNumFallbackBackends; i < backends_.size(); ++i) { - EXPECT_EQ(100UL, backends_[i]->service_.request_count()); - } - // Stop backends from balancer. This should put us in fallback mode. - for (size_t i = kNumFallbackBackends; i < backends_.size(); ++i) { - ShutdownBackend(i); - } - WaitForAllBackends(1 /* num_requests_multiple_of */, 0 /* start_index */, - kNumFallbackBackends /* stop_index */); - // Restart the backends from the balancer. We should *not* start - // sending traffic back to them at this point (although the behavior - // in xds may be different). - for (size_t i = kNumFallbackBackends; i < backends_.size(); ++i) { - StartBackend(i); - } - CheckRpcSendOk(100 * kNumBalancerBackends); - for (size_t i = 0; i < kNumFallbackBackends; ++i) { - EXPECT_EQ(100UL, backends_[i]->service_.request_count()); - } - // Now start the balancer again. This should cause us to exit - // fallback mode. - balancers_[0]->Start(server_host_); - ScheduleResponseForBalancer(0, - BalancerServiceImpl::BuildResponseForBackends( - GetBackendPorts(kNumFallbackBackends), {}), - 0); - WaitForAllBackends(1 /* num_requests_multiple_of */, - kNumFallbackBackends /* start_index */); -} - -TEST_F(SingleBalancerTest, - FallbackAfterStartup_LoseContactWithBackendsThenBalancer) { - // First two backends are fallback, last two are pointed to by balancer. - const size_t kNumFallbackBackends = 2; - const size_t kNumBalancerBackends = backends_.size() - kNumFallbackBackends; + ScheduleResponseForBalancer(0, + BalancerServiceImpl::BuildResponseForBackends( + GetBackendPorts(kNumFallbackBackends), {}), + 0); + // Try to connect. + channel_->GetState(true /* try_to_connect */); + WaitForAllBackends(1 /* num_requests_multiple_of */, + kNumFallbackBackends /* start_index */); + // Stop balancer. RPCs should continue going to backends from balancer. + balancers_[0]->Shutdown(); + CheckRpcSendOk(100 * kNumBalancerBackends); + for (size_t i = kNumFallbackBackends; i < backends_.size(); ++i) { + EXPECT_EQ(100UL, backends_[i]->service_.request_count()); + } + // Stop backends from balancer. This should put us in fallback mode. + for (size_t i = kNumFallbackBackends; i < backends_.size(); ++i) { + ShutdownBackend(i); + } + WaitForAllBackends(1 /* num_requests_multiple_of */, 0 /* start_index */, + kNumFallbackBackends /* stop_index */); + // Restart the backends from the balancer. We should *not* start + // sending traffic back to them at this point (although the behavior + // in xds may be different). + for (size_t i = kNumFallbackBackends; i < backends_.size(); ++i) { + StartBackend(i); + } + CheckRpcSendOk(100 * kNumBalancerBackends); + for (size_t i = 0; i < kNumFallbackBackends; ++i) { + EXPECT_EQ(100UL, backends_[i]->service_.request_count()); + } + // Now start the balancer again. This should cause us to exit + // fallback mode. + balancers_[0]->Start(server_host_); + ScheduleResponseForBalancer(0, + BalancerServiceImpl::BuildResponseForBackends( + GetBackendPorts(kNumFallbackBackends), {}), + 0); + WaitForAllBackends(1 /* num_requests_multiple_of */, + kNumFallbackBackends /* start_index */); +} + +TEST_F(SingleBalancerTest, + FallbackAfterStartup_LoseContactWithBackendsThenBalancer) { + // First two backends are fallback, last two are pointed to by balancer. + const size_t kNumFallbackBackends = 2; + const size_t kNumBalancerBackends = backends_.size() - kNumFallbackBackends; std::vector<AddressData> backend_addresses; - for (size_t i = 0; i < kNumFallbackBackends; ++i) { + for (size_t i = 0; i < kNumFallbackBackends; ++i) { backend_addresses.emplace_back(AddressData{backends_[i]->port_, ""}); - } + } std::vector<AddressData> balancer_addresses; - for (size_t i = 0; i < balancers_.size(); ++i) { + for (size_t i = 0; i < balancers_.size(); ++i) { balancer_addresses.emplace_back(AddressData{balancers_[i]->port_, ""}); - } + } SetNextResolution(balancer_addresses, backend_addresses); - ScheduleResponseForBalancer(0, - BalancerServiceImpl::BuildResponseForBackends( - GetBackendPorts(kNumFallbackBackends), {}), - 0); - // Try to connect. - channel_->GetState(true /* try_to_connect */); - WaitForAllBackends(1 /* num_requests_multiple_of */, - kNumFallbackBackends /* start_index */); - // Stop backends from balancer. Since we are still in contact with - // the balancer at this point, RPCs should be failing. - for (size_t i = kNumFallbackBackends; i < backends_.size(); ++i) { - ShutdownBackend(i); - } - CheckRpcSendFailure(); - // Stop balancer. This should put us in fallback mode. - balancers_[0]->Shutdown(); - WaitForAllBackends(1 /* num_requests_multiple_of */, 0 /* start_index */, - kNumFallbackBackends /* stop_index */); - // Restart the backends from the balancer. We should *not* start - // sending traffic back to them at this point (although the behavior - // in xds may be different). - for (size_t i = kNumFallbackBackends; i < backends_.size(); ++i) { - StartBackend(i); - } - CheckRpcSendOk(100 * kNumBalancerBackends); - for (size_t i = 0; i < kNumFallbackBackends; ++i) { - EXPECT_EQ(100UL, backends_[i]->service_.request_count()); - } - // Now start the balancer again. This should cause us to exit - // fallback mode. - balancers_[0]->Start(server_host_); - ScheduleResponseForBalancer(0, - BalancerServiceImpl::BuildResponseForBackends( - GetBackendPorts(kNumFallbackBackends), {}), - 0); - WaitForAllBackends(1 /* num_requests_multiple_of */, - kNumFallbackBackends /* start_index */); -} - -TEST_F(SingleBalancerTest, FallbackEarlyWhenBalancerChannelFails) { - const int kFallbackTimeoutMs = 10000 * grpc_test_slowdown_factor(); - ResetStub(kFallbackTimeoutMs); - // Return an unreachable balancer and one fallback backend. + ScheduleResponseForBalancer(0, + BalancerServiceImpl::BuildResponseForBackends( + GetBackendPorts(kNumFallbackBackends), {}), + 0); + // Try to connect. + channel_->GetState(true /* try_to_connect */); + WaitForAllBackends(1 /* num_requests_multiple_of */, + kNumFallbackBackends /* start_index */); + // Stop backends from balancer. Since we are still in contact with + // the balancer at this point, RPCs should be failing. + for (size_t i = kNumFallbackBackends; i < backends_.size(); ++i) { + ShutdownBackend(i); + } + CheckRpcSendFailure(); + // Stop balancer. This should put us in fallback mode. + balancers_[0]->Shutdown(); + WaitForAllBackends(1 /* num_requests_multiple_of */, 0 /* start_index */, + kNumFallbackBackends /* stop_index */); + // Restart the backends from the balancer. We should *not* start + // sending traffic back to them at this point (although the behavior + // in xds may be different). + for (size_t i = kNumFallbackBackends; i < backends_.size(); ++i) { + StartBackend(i); + } + CheckRpcSendOk(100 * kNumBalancerBackends); + for (size_t i = 0; i < kNumFallbackBackends; ++i) { + EXPECT_EQ(100UL, backends_[i]->service_.request_count()); + } + // Now start the balancer again. This should cause us to exit + // fallback mode. + balancers_[0]->Start(server_host_); + ScheduleResponseForBalancer(0, + BalancerServiceImpl::BuildResponseForBackends( + GetBackendPorts(kNumFallbackBackends), {}), + 0); + WaitForAllBackends(1 /* num_requests_multiple_of */, + kNumFallbackBackends /* start_index */); +} + +TEST_F(SingleBalancerTest, FallbackEarlyWhenBalancerChannelFails) { + const int kFallbackTimeoutMs = 10000 * grpc_test_slowdown_factor(); + ResetStub(kFallbackTimeoutMs); + // Return an unreachable balancer and one fallback backend. std::vector<AddressData> balancer_addresses; balancer_addresses.emplace_back( AddressData{grpc_pick_unused_port_or_die(), ""}); std::vector<AddressData> backend_addresses; backend_addresses.emplace_back(AddressData{backends_[0]->port_, ""}); SetNextResolution(balancer_addresses, backend_addresses); - // Send RPC with deadline less than the fallback timeout and make sure it - // succeeds. - CheckRpcSendOk(/* times */ 1, /* timeout_ms */ 1000, - /* wait_for_ready */ false); -} - -TEST_F(SingleBalancerTest, FallbackEarlyWhenBalancerCallFails) { - const int kFallbackTimeoutMs = 10000 * grpc_test_slowdown_factor(); - ResetStub(kFallbackTimeoutMs); + // Send RPC with deadline less than the fallback timeout and make sure it + // succeeds. + CheckRpcSendOk(/* times */ 1, /* timeout_ms */ 1000, + /* wait_for_ready */ false); +} + +TEST_F(SingleBalancerTest, FallbackEarlyWhenBalancerCallFails) { + const int kFallbackTimeoutMs = 10000 * grpc_test_slowdown_factor(); + ResetStub(kFallbackTimeoutMs); // Return one balancer and one fallback backend. std::vector<AddressData> balancer_addresses; balancer_addresses.emplace_back(AddressData{balancers_[0]->port_, ""}); std::vector<AddressData> backend_addresses; backend_addresses.emplace_back(AddressData{backends_[0]->port_, ""}); SetNextResolution(balancer_addresses, backend_addresses); - // Balancer drops call without sending a serverlist. - balancers_[0]->service_.NotifyDoneWithServerlists(); - // Send RPC with deadline less than the fallback timeout and make sure it - // succeeds. - CheckRpcSendOk(/* times */ 1, /* timeout_ms */ 1000, - /* wait_for_ready */ false); -} - + // Balancer drops call without sending a serverlist. + balancers_[0]->service_.NotifyDoneWithServerlists(); + // Send RPC with deadline less than the fallback timeout and make sure it + // succeeds. + CheckRpcSendOk(/* times */ 1, /* timeout_ms */ 1000, + /* wait_for_ready */ false); +} + TEST_F(SingleBalancerTest, FallbackControlledByBalancer_BeforeFirstServerlist) { const int kFallbackTimeoutMs = 10000 * grpc_test_slowdown_factor(); ResetStub(kFallbackTimeoutMs); @@ -1371,29 +1371,29 @@ TEST_F(SingleBalancerTest, FallbackControlledByBalancer_AfterFirstServerlist) { WaitForBackend(1); } -TEST_F(SingleBalancerTest, BackendsRestart) { - SetNextResolutionAllBalancers(); - const size_t kNumRpcsPerAddress = 100; - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), - 0); - // Make sure that trying to connect works without a call. - channel_->GetState(true /* try_to_connect */); - // Send kNumRpcsPerAddress RPCs per server. - CheckRpcSendOk(kNumRpcsPerAddress * num_backends_); - // Stop backends. RPCs should fail. - ShutdownAllBackends(); - CheckRpcSendFailure(); - // Restart backends. RPCs should start succeeding again. - StartAllBackends(); - CheckRpcSendOk(1 /* times */, 2000 /* timeout_ms */, - true /* wait_for_ready */); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); -} - +TEST_F(SingleBalancerTest, BackendsRestart) { + SetNextResolutionAllBalancers(); + const size_t kNumRpcsPerAddress = 100; + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), + 0); + // Make sure that trying to connect works without a call. + channel_->GetState(true /* try_to_connect */); + // Send kNumRpcsPerAddress RPCs per server. + CheckRpcSendOk(kNumRpcsPerAddress * num_backends_); + // Stop backends. RPCs should fail. + ShutdownAllBackends(); + CheckRpcSendFailure(); + // Restart backends. RPCs should start succeeding again. + StartAllBackends(); + CheckRpcSendOk(1 /* times */, 2000 /* timeout_ms */, + true /* wait_for_ready */); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); +} + TEST_F(SingleBalancerTest, ServiceNameFromLbPolicyConfig) { constexpr char kServiceConfigWithTarget[] = "{\n" @@ -1415,277 +1415,277 @@ TEST_F(SingleBalancerTest, ServiceNameFromLbPolicyConfig) { EXPECT_EQ(balancers_[0]->service_.service_names().back(), "test_service"); } -class UpdatesTest : public GrpclbEnd2endTest { - public: - UpdatesTest() : GrpclbEnd2endTest(4, 3, 0) {} -}; - -TEST_F(UpdatesTest, UpdateBalancersButKeepUsingOriginalBalancer) { - SetNextResolutionAllBalancers(); - const std::vector<int> first_backend{GetBackendPorts()[0]}; - const std::vector<int> second_backend{GetBackendPorts()[1]}; - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(first_backend, {}), 0); - ScheduleResponseForBalancer( - 1, BalancerServiceImpl::BuildResponseForBackends(second_backend, {}), 0); - - // Wait until the first backend is ready. - WaitForBackend(0); - - // Send 10 requests. - gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); - - // All 10 requests should have gone to the first backend. - EXPECT_EQ(10U, backends_[0]->service_.request_count()); - - // Balancer 0 got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - EXPECT_EQ(0U, balancers_[1]->service_.request_count()); - EXPECT_EQ(0U, balancers_[1]->service_.response_count()); - EXPECT_EQ(0U, balancers_[2]->service_.request_count()); - EXPECT_EQ(0U, balancers_[2]->service_.response_count()); - - std::vector<AddressData> addresses; +class UpdatesTest : public GrpclbEnd2endTest { + public: + UpdatesTest() : GrpclbEnd2endTest(4, 3, 0) {} +}; + +TEST_F(UpdatesTest, UpdateBalancersButKeepUsingOriginalBalancer) { + SetNextResolutionAllBalancers(); + const std::vector<int> first_backend{GetBackendPorts()[0]}; + const std::vector<int> second_backend{GetBackendPorts()[1]}; + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(first_backend, {}), 0); + ScheduleResponseForBalancer( + 1, BalancerServiceImpl::BuildResponseForBackends(second_backend, {}), 0); + + // Wait until the first backend is ready. + WaitForBackend(0); + + // Send 10 requests. + gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); + CheckRpcSendOk(10); + gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); + + // All 10 requests should have gone to the first backend. + EXPECT_EQ(10U, backends_[0]->service_.request_count()); + + // Balancer 0 got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + EXPECT_EQ(0U, balancers_[1]->service_.request_count()); + EXPECT_EQ(0U, balancers_[1]->service_.response_count()); + EXPECT_EQ(0U, balancers_[2]->service_.request_count()); + EXPECT_EQ(0U, balancers_[2]->service_.response_count()); + + std::vector<AddressData> addresses; addresses.emplace_back(AddressData{balancers_[1]->port_, ""}); - gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 =========="); - SetNextResolution(addresses); - gpr_log(GPR_INFO, "========= UPDATE 1 DONE =========="); - - EXPECT_EQ(0U, backends_[1]->service_.request_count()); - gpr_timespec deadline = gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN)); - // Send 10 seconds worth of RPCs - do { - CheckRpcSendOk(); - } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); - // The current LB call is still working, so grpclb continued using it to the - // first balancer, which doesn't assign the second backend. - EXPECT_EQ(0U, backends_[1]->service_.request_count()); - - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - EXPECT_EQ(0U, balancers_[1]->service_.request_count()); - EXPECT_EQ(0U, balancers_[1]->service_.response_count()); - EXPECT_EQ(0U, balancers_[2]->service_.request_count()); - EXPECT_EQ(0U, balancers_[2]->service_.response_count()); -} - -// Send an update with the same set of LBs as the one in SetUp() in order to -// verify that the LB channel inside grpclb keeps the initial connection (which -// by definition is also present in the update). -TEST_F(UpdatesTest, UpdateBalancersRepeated) { - SetNextResolutionAllBalancers(); - const std::vector<int> first_backend{GetBackendPorts()[0]}; - const std::vector<int> second_backend{GetBackendPorts()[0]}; - - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(first_backend, {}), 0); - ScheduleResponseForBalancer( - 1, BalancerServiceImpl::BuildResponseForBackends(second_backend, {}), 0); - - // Wait until the first backend is ready. - WaitForBackend(0); - - // Send 10 requests. - gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); - - // All 10 requests should have gone to the first backend. - EXPECT_EQ(10U, backends_[0]->service_.request_count()); - - balancers_[0]->service_.NotifyDoneWithServerlists(); - // Balancer 0 got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - EXPECT_EQ(0U, balancers_[1]->service_.request_count()); - EXPECT_EQ(0U, balancers_[1]->service_.response_count()); - EXPECT_EQ(0U, balancers_[2]->service_.request_count()); - EXPECT_EQ(0U, balancers_[2]->service_.response_count()); - - std::vector<AddressData> addresses; + gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 =========="); + SetNextResolution(addresses); + gpr_log(GPR_INFO, "========= UPDATE 1 DONE =========="); + + EXPECT_EQ(0U, backends_[1]->service_.request_count()); + gpr_timespec deadline = gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN)); + // Send 10 seconds worth of RPCs + do { + CheckRpcSendOk(); + } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); + // The current LB call is still working, so grpclb continued using it to the + // first balancer, which doesn't assign the second backend. + EXPECT_EQ(0U, backends_[1]->service_.request_count()); + + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + EXPECT_EQ(0U, balancers_[1]->service_.request_count()); + EXPECT_EQ(0U, balancers_[1]->service_.response_count()); + EXPECT_EQ(0U, balancers_[2]->service_.request_count()); + EXPECT_EQ(0U, balancers_[2]->service_.response_count()); +} + +// Send an update with the same set of LBs as the one in SetUp() in order to +// verify that the LB channel inside grpclb keeps the initial connection (which +// by definition is also present in the update). +TEST_F(UpdatesTest, UpdateBalancersRepeated) { + SetNextResolutionAllBalancers(); + const std::vector<int> first_backend{GetBackendPorts()[0]}; + const std::vector<int> second_backend{GetBackendPorts()[0]}; + + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(first_backend, {}), 0); + ScheduleResponseForBalancer( + 1, BalancerServiceImpl::BuildResponseForBackends(second_backend, {}), 0); + + // Wait until the first backend is ready. + WaitForBackend(0); + + // Send 10 requests. + gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); + CheckRpcSendOk(10); + gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); + + // All 10 requests should have gone to the first backend. + EXPECT_EQ(10U, backends_[0]->service_.request_count()); + + balancers_[0]->service_.NotifyDoneWithServerlists(); + // Balancer 0 got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + EXPECT_EQ(0U, balancers_[1]->service_.request_count()); + EXPECT_EQ(0U, balancers_[1]->service_.response_count()); + EXPECT_EQ(0U, balancers_[2]->service_.request_count()); + EXPECT_EQ(0U, balancers_[2]->service_.response_count()); + + std::vector<AddressData> addresses; addresses.emplace_back(AddressData{balancers_[0]->port_, ""}); addresses.emplace_back(AddressData{balancers_[1]->port_, ""}); addresses.emplace_back(AddressData{balancers_[2]->port_, ""}); - gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 =========="); - SetNextResolution(addresses); - gpr_log(GPR_INFO, "========= UPDATE 1 DONE =========="); - - EXPECT_EQ(0U, backends_[1]->service_.request_count()); - gpr_timespec deadline = gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN)); - // Send 10 seconds worth of RPCs - do { - CheckRpcSendOk(); - } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); - // grpclb continued using the original LB call to the first balancer, which - // doesn't assign the second backend. - EXPECT_EQ(0U, backends_[1]->service_.request_count()); - balancers_[0]->service_.NotifyDoneWithServerlists(); - - addresses.clear(); + gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 =========="); + SetNextResolution(addresses); + gpr_log(GPR_INFO, "========= UPDATE 1 DONE =========="); + + EXPECT_EQ(0U, backends_[1]->service_.request_count()); + gpr_timespec deadline = gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN)); + // Send 10 seconds worth of RPCs + do { + CheckRpcSendOk(); + } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); + // grpclb continued using the original LB call to the first balancer, which + // doesn't assign the second backend. + EXPECT_EQ(0U, backends_[1]->service_.request_count()); + balancers_[0]->service_.NotifyDoneWithServerlists(); + + addresses.clear(); addresses.emplace_back(AddressData{balancers_[0]->port_, ""}); addresses.emplace_back(AddressData{balancers_[1]->port_, ""}); - gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 2 =========="); - SetNextResolution(addresses); - gpr_log(GPR_INFO, "========= UPDATE 2 DONE =========="); - - EXPECT_EQ(0U, backends_[1]->service_.request_count()); - deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_millis(10000, GPR_TIMESPAN)); - // Send 10 seconds worth of RPCs - do { - CheckRpcSendOk(); - } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); - // grpclb continued using the original LB call to the first balancer, which - // doesn't assign the second backend. - EXPECT_EQ(0U, backends_[1]->service_.request_count()); - balancers_[0]->service_.NotifyDoneWithServerlists(); -} - -TEST_F(UpdatesTest, UpdateBalancersDeadUpdate) { - std::vector<AddressData> addresses; + gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 2 =========="); + SetNextResolution(addresses); + gpr_log(GPR_INFO, "========= UPDATE 2 DONE =========="); + + EXPECT_EQ(0U, backends_[1]->service_.request_count()); + deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(10000, GPR_TIMESPAN)); + // Send 10 seconds worth of RPCs + do { + CheckRpcSendOk(); + } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); + // grpclb continued using the original LB call to the first balancer, which + // doesn't assign the second backend. + EXPECT_EQ(0U, backends_[1]->service_.request_count()); + balancers_[0]->service_.NotifyDoneWithServerlists(); +} + +TEST_F(UpdatesTest, UpdateBalancersDeadUpdate) { + std::vector<AddressData> addresses; addresses.emplace_back(AddressData{balancers_[0]->port_, ""}); - SetNextResolution(addresses); - const std::vector<int> first_backend{GetBackendPorts()[0]}; - const std::vector<int> second_backend{GetBackendPorts()[1]}; - - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(first_backend, {}), 0); - ScheduleResponseForBalancer( - 1, BalancerServiceImpl::BuildResponseForBackends(second_backend, {}), 0); - - // Start servers and send 10 RPCs per server. - gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); - // All 10 requests should have gone to the first backend. - EXPECT_EQ(10U, backends_[0]->service_.request_count()); - - // Kill balancer 0 - gpr_log(GPR_INFO, "********** ABOUT TO KILL BALANCER 0 *************"); - balancers_[0]->Shutdown(); - gpr_log(GPR_INFO, "********** KILLED BALANCER 0 *************"); - - // This is serviced by the existing RR policy - gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); - // All 10 requests should again have gone to the first backend. - EXPECT_EQ(20U, backends_[0]->service_.request_count()); - EXPECT_EQ(0U, backends_[1]->service_.request_count()); - - // Balancer 0 got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - EXPECT_EQ(0U, balancers_[1]->service_.request_count()); - EXPECT_EQ(0U, balancers_[1]->service_.response_count()); - EXPECT_EQ(0U, balancers_[2]->service_.request_count()); - EXPECT_EQ(0U, balancers_[2]->service_.response_count()); - - addresses.clear(); + SetNextResolution(addresses); + const std::vector<int> first_backend{GetBackendPorts()[0]}; + const std::vector<int> second_backend{GetBackendPorts()[1]}; + + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(first_backend, {}), 0); + ScheduleResponseForBalancer( + 1, BalancerServiceImpl::BuildResponseForBackends(second_backend, {}), 0); + + // Start servers and send 10 RPCs per server. + gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); + CheckRpcSendOk(10); + gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); + // All 10 requests should have gone to the first backend. + EXPECT_EQ(10U, backends_[0]->service_.request_count()); + + // Kill balancer 0 + gpr_log(GPR_INFO, "********** ABOUT TO KILL BALANCER 0 *************"); + balancers_[0]->Shutdown(); + gpr_log(GPR_INFO, "********** KILLED BALANCER 0 *************"); + + // This is serviced by the existing RR policy + gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); + CheckRpcSendOk(10); + gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); + // All 10 requests should again have gone to the first backend. + EXPECT_EQ(20U, backends_[0]->service_.request_count()); + EXPECT_EQ(0U, backends_[1]->service_.request_count()); + + // Balancer 0 got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + EXPECT_EQ(0U, balancers_[1]->service_.request_count()); + EXPECT_EQ(0U, balancers_[1]->service_.response_count()); + EXPECT_EQ(0U, balancers_[2]->service_.request_count()); + EXPECT_EQ(0U, balancers_[2]->service_.response_count()); + + addresses.clear(); addresses.emplace_back(AddressData{balancers_[1]->port_, ""}); - gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 =========="); - SetNextResolution(addresses); - gpr_log(GPR_INFO, "========= UPDATE 1 DONE =========="); - - // Wait until update has been processed, as signaled by the second backend - // receiving a request. In the meantime, the client continues to be serviced - // (by the first backend) without interruption. - EXPECT_EQ(0U, backends_[1]->service_.request_count()); - WaitForBackend(1); - - // This is serviced by the updated RR policy - backends_[1]->service_.ResetCounters(); - gpr_log(GPR_INFO, "========= BEFORE THIRD BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH THIRD BATCH =========="); - // All 10 requests should have gone to the second backend. - EXPECT_EQ(10U, backends_[1]->service_.request_count()); - - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - // The second balancer, published as part of the first update, may end up - // getting two requests (that is, 1 <= #req <= 2) if the LB call retry timer - // firing races with the arrival of the update containing the second - // balancer. - EXPECT_GE(balancers_[1]->service_.request_count(), 1U); - EXPECT_GE(balancers_[1]->service_.response_count(), 1U); - EXPECT_LE(balancers_[1]->service_.request_count(), 2U); - EXPECT_LE(balancers_[1]->service_.response_count(), 2U); - EXPECT_EQ(0U, balancers_[2]->service_.request_count()); - EXPECT_EQ(0U, balancers_[2]->service_.response_count()); -} - -TEST_F(UpdatesTest, ReresolveDeadBackend) { - ResetStub(500); - // The first resolution contains the addresses of a balancer that never - // responds, and a fallback backend. + gpr_log(GPR_INFO, "========= ABOUT TO UPDATE 1 =========="); + SetNextResolution(addresses); + gpr_log(GPR_INFO, "========= UPDATE 1 DONE =========="); + + // Wait until update has been processed, as signaled by the second backend + // receiving a request. In the meantime, the client continues to be serviced + // (by the first backend) without interruption. + EXPECT_EQ(0U, backends_[1]->service_.request_count()); + WaitForBackend(1); + + // This is serviced by the updated RR policy + backends_[1]->service_.ResetCounters(); + gpr_log(GPR_INFO, "========= BEFORE THIRD BATCH =========="); + CheckRpcSendOk(10); + gpr_log(GPR_INFO, "========= DONE WITH THIRD BATCH =========="); + // All 10 requests should have gone to the second backend. + EXPECT_EQ(10U, backends_[1]->service_.request_count()); + + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + // The second balancer, published as part of the first update, may end up + // getting two requests (that is, 1 <= #req <= 2) if the LB call retry timer + // firing races with the arrival of the update containing the second + // balancer. + EXPECT_GE(balancers_[1]->service_.request_count(), 1U); + EXPECT_GE(balancers_[1]->service_.response_count(), 1U); + EXPECT_LE(balancers_[1]->service_.request_count(), 2U); + EXPECT_LE(balancers_[1]->service_.response_count(), 2U); + EXPECT_EQ(0U, balancers_[2]->service_.request_count()); + EXPECT_EQ(0U, balancers_[2]->service_.response_count()); +} + +TEST_F(UpdatesTest, ReresolveDeadBackend) { + ResetStub(500); + // The first resolution contains the addresses of a balancer that never + // responds, and a fallback backend. std::vector<AddressData> balancer_addresses; balancer_addresses.emplace_back(AddressData{balancers_[0]->port_, ""}); std::vector<AddressData> backend_addresses; backend_addresses.emplace_back(AddressData{backends_[0]->port_, ""}); SetNextResolution(balancer_addresses, backend_addresses); - // Ask channel to connect to trigger resolver creation. - channel_->GetState(true); - // The re-resolution result will contain the addresses of the same balancer - // and a new fallback backend. + // Ask channel to connect to trigger resolver creation. + channel_->GetState(true); + // The re-resolution result will contain the addresses of the same balancer + // and a new fallback backend. balancer_addresses.clear(); balancer_addresses.emplace_back(AddressData{balancers_[0]->port_, ""}); backend_addresses.clear(); backend_addresses.emplace_back(AddressData{backends_[1]->port_, ""}); SetNextReresolutionResponse(balancer_addresses, backend_addresses); - - // Start servers and send 10 RPCs per server. - gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); - // All 10 requests should have gone to the fallback backend. - EXPECT_EQ(10U, backends_[0]->service_.request_count()); - - // Kill backend 0. - gpr_log(GPR_INFO, "********** ABOUT TO KILL BACKEND 0 *************"); - backends_[0]->Shutdown(); - gpr_log(GPR_INFO, "********** KILLED BACKEND 0 *************"); - - // Wait until re-resolution has finished, as signaled by the second backend - // receiving a request. - WaitForBackend(1); - - gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); - // All 10 requests should have gone to the second backend. - EXPECT_EQ(10U, backends_[1]->service_.request_count()); - - balancers_[0]->service_.NotifyDoneWithServerlists(); - balancers_[1]->service_.NotifyDoneWithServerlists(); - balancers_[2]->service_.NotifyDoneWithServerlists(); - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - EXPECT_EQ(0U, balancers_[0]->service_.response_count()); - EXPECT_EQ(0U, balancers_[1]->service_.request_count()); - EXPECT_EQ(0U, balancers_[1]->service_.response_count()); - EXPECT_EQ(0U, balancers_[2]->service_.request_count()); - EXPECT_EQ(0U, balancers_[2]->service_.response_count()); -} - -// TODO(juanlishen): Should be removed when the first response is always the -// initial response. Currently, if client load reporting is not enabled, the -// balancer doesn't send initial response. When the backend shuts down, an -// unexpected re-resolution will happen. This test configuration is a workaround -// for test ReresolveDeadBalancer. -class UpdatesWithClientLoadReportingTest : public GrpclbEnd2endTest { - public: - UpdatesWithClientLoadReportingTest() : GrpclbEnd2endTest(4, 3, 2) {} -}; - -TEST_F(UpdatesWithClientLoadReportingTest, ReresolveDeadBalancer) { + + // Start servers and send 10 RPCs per server. + gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); + CheckRpcSendOk(10); + gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); + // All 10 requests should have gone to the fallback backend. + EXPECT_EQ(10U, backends_[0]->service_.request_count()); + + // Kill backend 0. + gpr_log(GPR_INFO, "********** ABOUT TO KILL BACKEND 0 *************"); + backends_[0]->Shutdown(); + gpr_log(GPR_INFO, "********** KILLED BACKEND 0 *************"); + + // Wait until re-resolution has finished, as signaled by the second backend + // receiving a request. + WaitForBackend(1); + + gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); + CheckRpcSendOk(10); + gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); + // All 10 requests should have gone to the second backend. + EXPECT_EQ(10U, backends_[1]->service_.request_count()); + + balancers_[0]->service_.NotifyDoneWithServerlists(); + balancers_[1]->service_.NotifyDoneWithServerlists(); + balancers_[2]->service_.NotifyDoneWithServerlists(); + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + EXPECT_EQ(0U, balancers_[0]->service_.response_count()); + EXPECT_EQ(0U, balancers_[1]->service_.request_count()); + EXPECT_EQ(0U, balancers_[1]->service_.response_count()); + EXPECT_EQ(0U, balancers_[2]->service_.request_count()); + EXPECT_EQ(0U, balancers_[2]->service_.response_count()); +} + +// TODO(juanlishen): Should be removed when the first response is always the +// initial response. Currently, if client load reporting is not enabled, the +// balancer doesn't send initial response. When the backend shuts down, an +// unexpected re-resolution will happen. This test configuration is a workaround +// for test ReresolveDeadBalancer. +class UpdatesWithClientLoadReportingTest : public GrpclbEnd2endTest { + public: + UpdatesWithClientLoadReportingTest() : GrpclbEnd2endTest(4, 3, 2) {} +}; + +TEST_F(UpdatesWithClientLoadReportingTest, ReresolveDeadBalancer) { const std::vector<int> first_backend{GetBackendPorts()[0]}; const std::vector<int> second_backend{GetBackendPorts()[1]}; ScheduleResponseForBalancer( @@ -1693,337 +1693,337 @@ TEST_F(UpdatesWithClientLoadReportingTest, ReresolveDeadBalancer) { ScheduleResponseForBalancer( 1, BalancerServiceImpl::BuildResponseForBackends(second_backend, {}), 0); - // Ask channel to connect to trigger resolver creation. - channel_->GetState(true); - std::vector<AddressData> addresses; + // Ask channel to connect to trigger resolver creation. + channel_->GetState(true); + std::vector<AddressData> addresses; addresses.emplace_back(AddressData{balancers_[0]->port_, ""}); - SetNextResolution(addresses); - addresses.clear(); + SetNextResolution(addresses); + addresses.clear(); addresses.emplace_back(AddressData{balancers_[1]->port_, ""}); - SetNextReresolutionResponse(addresses); - - // Start servers and send 10 RPCs per server. - gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); - // All 10 requests should have gone to the first backend. - EXPECT_EQ(10U, backends_[0]->service_.request_count()); - - // Kill backend 0. - gpr_log(GPR_INFO, "********** ABOUT TO KILL BACKEND 0 *************"); - backends_[0]->Shutdown(); - gpr_log(GPR_INFO, "********** KILLED BACKEND 0 *************"); - - CheckRpcSendFailure(); - - // Balancer 0 got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - EXPECT_EQ(0U, balancers_[1]->service_.request_count()); - EXPECT_EQ(0U, balancers_[1]->service_.response_count()); - EXPECT_EQ(0U, balancers_[2]->service_.request_count()); - EXPECT_EQ(0U, balancers_[2]->service_.response_count()); - - // Kill balancer 0. - gpr_log(GPR_INFO, "********** ABOUT TO KILL BALANCER 0 *************"); - balancers_[0]->Shutdown(); - gpr_log(GPR_INFO, "********** KILLED BALANCER 0 *************"); - - // Wait until re-resolution has finished, as signaled by the second backend - // receiving a request. - WaitForBackend(1); - - // This is serviced by the new serverlist. - gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); - // All 10 requests should have gone to the second backend. - EXPECT_EQ(10U, backends_[1]->service_.request_count()); - - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - // After balancer 0 is killed, we restart an LB call immediately (because we - // disconnect to a previously connected balancer). Although we will cancel - // this call when the re-resolution update is done and another LB call restart - // is needed, this old call may still succeed reaching the LB server if - // re-resolution is slow. So balancer 1 may have received 2 requests and sent - // 2 responses. - EXPECT_GE(balancers_[1]->service_.request_count(), 1U); - EXPECT_GE(balancers_[1]->service_.response_count(), 1U); - EXPECT_LE(balancers_[1]->service_.request_count(), 2U); - EXPECT_LE(balancers_[1]->service_.response_count(), 2U); - EXPECT_EQ(0U, balancers_[2]->service_.request_count()); - EXPECT_EQ(0U, balancers_[2]->service_.response_count()); -} - -TEST_F(SingleBalancerTest, Drop) { - SetNextResolutionAllBalancers(); - const size_t kNumRpcsPerAddress = 100; - const int num_of_drop_by_rate_limiting_addresses = 1; - const int num_of_drop_by_load_balancing_addresses = 2; - const int num_of_drop_addresses = num_of_drop_by_rate_limiting_addresses + - num_of_drop_by_load_balancing_addresses; - const int num_total_addresses = num_backends_ + num_of_drop_addresses; - ScheduleResponseForBalancer( - 0, - BalancerServiceImpl::BuildResponseForBackends( - GetBackendPorts(), - {{"rate_limiting", num_of_drop_by_rate_limiting_addresses}, - {"load_balancing", num_of_drop_by_load_balancing_addresses}}), - 0); - // Wait until all backends are ready. - WaitForAllBackends(); - // Send kNumRpcsPerAddress RPCs for each server and drop address. - size_t num_drops = 0; - for (size_t i = 0; i < kNumRpcsPerAddress * num_total_addresses; ++i) { - EchoResponse response; - const Status status = SendRpc(&response); - if (!status.ok() && - status.error_message() == "Call dropped by load balancing policy") { - ++num_drops; - } else { - EXPECT_TRUE(status.ok()) << "code=" << status.error_code() - << " message=" << status.error_message(); - EXPECT_EQ(response.message(), kRequestMessage_); - } - } - EXPECT_EQ(kNumRpcsPerAddress * num_of_drop_addresses, num_drops); - // Each backend should have gotten 100 requests. - for (size_t i = 0; i < backends_.size(); ++i) { - EXPECT_EQ(kNumRpcsPerAddress, backends_[i]->service_.request_count()); - } - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); -} - -TEST_F(SingleBalancerTest, DropAllFirst) { - SetNextResolutionAllBalancers(); - // All registered addresses are marked as "drop". - const int num_of_drop_by_rate_limiting_addresses = 1; - const int num_of_drop_by_load_balancing_addresses = 1; - ScheduleResponseForBalancer( - 0, - BalancerServiceImpl::BuildResponseForBackends( - {}, {{"rate_limiting", num_of_drop_by_rate_limiting_addresses}, - {"load_balancing", num_of_drop_by_load_balancing_addresses}}), - 0); - const Status status = SendRpc(nullptr, 1000, true); - EXPECT_FALSE(status.ok()); - EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy"); -} - -TEST_F(SingleBalancerTest, DropAll) { - SetNextResolutionAllBalancers(); - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), - 0); - const int num_of_drop_by_rate_limiting_addresses = 1; - const int num_of_drop_by_load_balancing_addresses = 1; - ScheduleResponseForBalancer( - 0, - BalancerServiceImpl::BuildResponseForBackends( - {}, {{"rate_limiting", num_of_drop_by_rate_limiting_addresses}, - {"load_balancing", num_of_drop_by_load_balancing_addresses}}), - 1000); - - // First call succeeds. - CheckRpcSendOk(); - // But eventually, the update with only dropped servers is processed and calls - // fail. - Status status; - do { - status = SendRpc(nullptr, 1000, true); - } while (status.ok()); - EXPECT_FALSE(status.ok()); - EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy"); -} - -class SingleBalancerWithClientLoadReportingTest : public GrpclbEnd2endTest { - public: - SingleBalancerWithClientLoadReportingTest() : GrpclbEnd2endTest(4, 1, 3) {} -}; - -TEST_F(SingleBalancerWithClientLoadReportingTest, Vanilla) { - SetNextResolutionAllBalancers(); - const size_t kNumRpcsPerAddress = 100; - ScheduleResponseForBalancer( - 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), - 0); - // Wait until all backends are ready. - int num_ok = 0; - int num_failure = 0; - int num_drops = 0; - std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends(); - // Send kNumRpcsPerAddress RPCs per server. - CheckRpcSendOk(kNumRpcsPerAddress * num_backends_); - // Each backend should have gotten 100 requests. - for (size_t i = 0; i < backends_.size(); ++i) { - EXPECT_EQ(kNumRpcsPerAddress, backends_[i]->service_.request_count()); - } - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - + SetNextReresolutionResponse(addresses); + + // Start servers and send 10 RPCs per server. + gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); + CheckRpcSendOk(10); + gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); + // All 10 requests should have gone to the first backend. + EXPECT_EQ(10U, backends_[0]->service_.request_count()); + + // Kill backend 0. + gpr_log(GPR_INFO, "********** ABOUT TO KILL BACKEND 0 *************"); + backends_[0]->Shutdown(); + gpr_log(GPR_INFO, "********** KILLED BACKEND 0 *************"); + + CheckRpcSendFailure(); + + // Balancer 0 got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + EXPECT_EQ(0U, balancers_[1]->service_.request_count()); + EXPECT_EQ(0U, balancers_[1]->service_.response_count()); + EXPECT_EQ(0U, balancers_[2]->service_.request_count()); + EXPECT_EQ(0U, balancers_[2]->service_.response_count()); + + // Kill balancer 0. + gpr_log(GPR_INFO, "********** ABOUT TO KILL BALANCER 0 *************"); + balancers_[0]->Shutdown(); + gpr_log(GPR_INFO, "********** KILLED BALANCER 0 *************"); + + // Wait until re-resolution has finished, as signaled by the second backend + // receiving a request. + WaitForBackend(1); + + // This is serviced by the new serverlist. + gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); + CheckRpcSendOk(10); + gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); + // All 10 requests should have gone to the second backend. + EXPECT_EQ(10U, backends_[1]->service_.request_count()); + + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + // After balancer 0 is killed, we restart an LB call immediately (because we + // disconnect to a previously connected balancer). Although we will cancel + // this call when the re-resolution update is done and another LB call restart + // is needed, this old call may still succeed reaching the LB server if + // re-resolution is slow. So balancer 1 may have received 2 requests and sent + // 2 responses. + EXPECT_GE(balancers_[1]->service_.request_count(), 1U); + EXPECT_GE(balancers_[1]->service_.response_count(), 1U); + EXPECT_LE(balancers_[1]->service_.request_count(), 2U); + EXPECT_LE(balancers_[1]->service_.response_count(), 2U); + EXPECT_EQ(0U, balancers_[2]->service_.request_count()); + EXPECT_EQ(0U, balancers_[2]->service_.response_count()); +} + +TEST_F(SingleBalancerTest, Drop) { + SetNextResolutionAllBalancers(); + const size_t kNumRpcsPerAddress = 100; + const int num_of_drop_by_rate_limiting_addresses = 1; + const int num_of_drop_by_load_balancing_addresses = 2; + const int num_of_drop_addresses = num_of_drop_by_rate_limiting_addresses + + num_of_drop_by_load_balancing_addresses; + const int num_total_addresses = num_backends_ + num_of_drop_addresses; + ScheduleResponseForBalancer( + 0, + BalancerServiceImpl::BuildResponseForBackends( + GetBackendPorts(), + {{"rate_limiting", num_of_drop_by_rate_limiting_addresses}, + {"load_balancing", num_of_drop_by_load_balancing_addresses}}), + 0); + // Wait until all backends are ready. + WaitForAllBackends(); + // Send kNumRpcsPerAddress RPCs for each server and drop address. + size_t num_drops = 0; + for (size_t i = 0; i < kNumRpcsPerAddress * num_total_addresses; ++i) { + EchoResponse response; + const Status status = SendRpc(&response); + if (!status.ok() && + status.error_message() == "Call dropped by load balancing policy") { + ++num_drops; + } else { + EXPECT_TRUE(status.ok()) << "code=" << status.error_code() + << " message=" << status.error_message(); + EXPECT_EQ(response.message(), kRequestMessage_); + } + } + EXPECT_EQ(kNumRpcsPerAddress * num_of_drop_addresses, num_drops); + // Each backend should have gotten 100 requests. + for (size_t i = 0; i < backends_.size(); ++i) { + EXPECT_EQ(kNumRpcsPerAddress, backends_[i]->service_.request_count()); + } + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); +} + +TEST_F(SingleBalancerTest, DropAllFirst) { + SetNextResolutionAllBalancers(); + // All registered addresses are marked as "drop". + const int num_of_drop_by_rate_limiting_addresses = 1; + const int num_of_drop_by_load_balancing_addresses = 1; + ScheduleResponseForBalancer( + 0, + BalancerServiceImpl::BuildResponseForBackends( + {}, {{"rate_limiting", num_of_drop_by_rate_limiting_addresses}, + {"load_balancing", num_of_drop_by_load_balancing_addresses}}), + 0); + const Status status = SendRpc(nullptr, 1000, true); + EXPECT_FALSE(status.ok()); + EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy"); +} + +TEST_F(SingleBalancerTest, DropAll) { + SetNextResolutionAllBalancers(); + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), + 0); + const int num_of_drop_by_rate_limiting_addresses = 1; + const int num_of_drop_by_load_balancing_addresses = 1; + ScheduleResponseForBalancer( + 0, + BalancerServiceImpl::BuildResponseForBackends( + {}, {{"rate_limiting", num_of_drop_by_rate_limiting_addresses}, + {"load_balancing", num_of_drop_by_load_balancing_addresses}}), + 1000); + + // First call succeeds. + CheckRpcSendOk(); + // But eventually, the update with only dropped servers is processed and calls + // fail. + Status status; + do { + status = SendRpc(nullptr, 1000, true); + } while (status.ok()); + EXPECT_FALSE(status.ok()); + EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy"); +} + +class SingleBalancerWithClientLoadReportingTest : public GrpclbEnd2endTest { + public: + SingleBalancerWithClientLoadReportingTest() : GrpclbEnd2endTest(4, 1, 3) {} +}; + +TEST_F(SingleBalancerWithClientLoadReportingTest, Vanilla) { + SetNextResolutionAllBalancers(); + const size_t kNumRpcsPerAddress = 100; + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), + 0); + // Wait until all backends are ready. + int num_ok = 0; + int num_failure = 0; + int num_drops = 0; + std::tie(num_ok, num_failure, num_drops) = WaitForAllBackends(); + // Send kNumRpcsPerAddress RPCs per server. + CheckRpcSendOk(kNumRpcsPerAddress * num_backends_); + // Each backend should have gotten 100 requests. + for (size_t i = 0; i < backends_.size(); ++i) { + EXPECT_EQ(kNumRpcsPerAddress, backends_[i]->service_.request_count()); + } + balancers_[0]->service_.NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + ClientStats client_stats; do { client_stats += WaitForLoadReports(); } while (client_stats.num_calls_finished != kNumRpcsPerAddress * num_backends_ + num_ok); - EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_ok, - client_stats.num_calls_started); - EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_ok, - client_stats.num_calls_finished); - EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send); - EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + (num_ok + num_drops), - client_stats.num_calls_finished_known_received); - EXPECT_THAT(client_stats.drop_token_counts, ::testing::ElementsAre()); -} - -TEST_F(SingleBalancerWithClientLoadReportingTest, BalancerRestart) { - SetNextResolutionAllBalancers(); - const size_t kNumBackendsFirstPass = 2; - const size_t kNumBackendsSecondPass = - backends_.size() - kNumBackendsFirstPass; - // Balancer returns backends starting at index 1. - ScheduleResponseForBalancer( - 0, - BalancerServiceImpl::BuildResponseForBackends( - GetBackendPorts(0, kNumBackendsFirstPass), {}), - 0); - // Wait until all backends returned by the balancer are ready. - int num_ok = 0; - int num_failure = 0; - int num_drops = 0; - std::tie(num_ok, num_failure, num_drops) = - WaitForAllBackends(/* num_requests_multiple_of */ 1, /* start_index */ 0, - /* stop_index */ kNumBackendsFirstPass); - balancers_[0]->service_.NotifyDoneWithServerlists(); - ClientStats client_stats = WaitForLoadReports(); - EXPECT_EQ(static_cast<size_t>(num_ok), client_stats.num_calls_started); - EXPECT_EQ(static_cast<size_t>(num_ok), client_stats.num_calls_finished); - EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send); - EXPECT_EQ(static_cast<size_t>(num_ok), - client_stats.num_calls_finished_known_received); - EXPECT_THAT(client_stats.drop_token_counts, ::testing::ElementsAre()); - // Shut down the balancer. - balancers_[0]->Shutdown(); - // Send 10 more requests per backend. This will continue using the - // last serverlist we received from the balancer before it was shut down. - ResetBackendCounters(); - CheckRpcSendOk(kNumBackendsFirstPass); - // Each backend should have gotten 1 request. - for (size_t i = 0; i < kNumBackendsFirstPass; ++i) { - EXPECT_EQ(1UL, backends_[i]->service_.request_count()); - } - // Now restart the balancer, this time pointing to all backends. - balancers_[0]->Start(server_host_); - ScheduleResponseForBalancer(0, - BalancerServiceImpl::BuildResponseForBackends( - GetBackendPorts(kNumBackendsFirstPass), {}), - 0); - // Wait for queries to start going to one of the new backends. - // This tells us that we're now using the new serverlist. - do { - CheckRpcSendOk(); - } while (backends_[2]->service_.request_count() == 0 && - backends_[3]->service_.request_count() == 0); - // Send one RPC per backend. - CheckRpcSendOk(kNumBackendsSecondPass); - balancers_[0]->service_.NotifyDoneWithServerlists(); - // Check client stats. - client_stats = WaitForLoadReports(); - EXPECT_EQ(kNumBackendsSecondPass + 1, client_stats.num_calls_started); - EXPECT_EQ(kNumBackendsSecondPass + 1, client_stats.num_calls_finished); - EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send); - EXPECT_EQ(kNumBackendsSecondPass + 1, - client_stats.num_calls_finished_known_received); - EXPECT_THAT(client_stats.drop_token_counts, ::testing::ElementsAre()); -} - -TEST_F(SingleBalancerWithClientLoadReportingTest, Drop) { - SetNextResolutionAllBalancers(); - const size_t kNumRpcsPerAddress = 3; - const int num_of_drop_by_rate_limiting_addresses = 2; - const int num_of_drop_by_load_balancing_addresses = 1; - const int num_of_drop_addresses = num_of_drop_by_rate_limiting_addresses + - num_of_drop_by_load_balancing_addresses; - const int num_total_addresses = num_backends_ + num_of_drop_addresses; - ScheduleResponseForBalancer( - 0, - BalancerServiceImpl::BuildResponseForBackends( - GetBackendPorts(), - {{"rate_limiting", num_of_drop_by_rate_limiting_addresses}, - {"load_balancing", num_of_drop_by_load_balancing_addresses}}), - 0); - // Wait until all backends are ready. - int num_warmup_ok = 0; - int num_warmup_failure = 0; - int num_warmup_drops = 0; - std::tie(num_warmup_ok, num_warmup_failure, num_warmup_drops) = - WaitForAllBackends(num_total_addresses /* num_requests_multiple_of */); - const int num_total_warmup_requests = - num_warmup_ok + num_warmup_failure + num_warmup_drops; - size_t num_drops = 0; - for (size_t i = 0; i < kNumRpcsPerAddress * num_total_addresses; ++i) { - EchoResponse response; - const Status status = SendRpc(&response); - if (!status.ok() && - status.error_message() == "Call dropped by load balancing policy") { - ++num_drops; - } else { - EXPECT_TRUE(status.ok()) << "code=" << status.error_code() - << " message=" << status.error_message(); - EXPECT_EQ(response.message(), kRequestMessage_); - } - } - EXPECT_EQ(kNumRpcsPerAddress * num_of_drop_addresses, num_drops); - // Each backend should have gotten 100 requests. - for (size_t i = 0; i < backends_.size(); ++i) { - EXPECT_EQ(kNumRpcsPerAddress, backends_[i]->service_.request_count()); - } - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - - const ClientStats client_stats = WaitForLoadReports(); - EXPECT_EQ( - kNumRpcsPerAddress * num_total_addresses + num_total_warmup_requests, - client_stats.num_calls_started); - EXPECT_EQ( - kNumRpcsPerAddress * num_total_addresses + num_total_warmup_requests, - client_stats.num_calls_finished); - EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send); - EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_warmup_ok, - client_stats.num_calls_finished_known_received); - // The number of warmup request is a multiple of the number of addresses. - // Therefore, all addresses in the scheduled balancer response are hit the - // same number of times. - const int num_times_drop_addresses_hit = - num_warmup_drops / num_of_drop_addresses; - EXPECT_THAT( - client_stats.drop_token_counts, - ::testing::ElementsAre( - ::testing::Pair("load_balancing", - (kNumRpcsPerAddress + num_times_drop_addresses_hit)), - ::testing::Pair( - "rate_limiting", - (kNumRpcsPerAddress + num_times_drop_addresses_hit) * 2))); -} - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - const auto result = RUN_ALL_TESTS(); - return result; -} + EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_ok, + client_stats.num_calls_started); + EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_ok, + client_stats.num_calls_finished); + EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send); + EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + (num_ok + num_drops), + client_stats.num_calls_finished_known_received); + EXPECT_THAT(client_stats.drop_token_counts, ::testing::ElementsAre()); +} + +TEST_F(SingleBalancerWithClientLoadReportingTest, BalancerRestart) { + SetNextResolutionAllBalancers(); + const size_t kNumBackendsFirstPass = 2; + const size_t kNumBackendsSecondPass = + backends_.size() - kNumBackendsFirstPass; + // Balancer returns backends starting at index 1. + ScheduleResponseForBalancer( + 0, + BalancerServiceImpl::BuildResponseForBackends( + GetBackendPorts(0, kNumBackendsFirstPass), {}), + 0); + // Wait until all backends returned by the balancer are ready. + int num_ok = 0; + int num_failure = 0; + int num_drops = 0; + std::tie(num_ok, num_failure, num_drops) = + WaitForAllBackends(/* num_requests_multiple_of */ 1, /* start_index */ 0, + /* stop_index */ kNumBackendsFirstPass); + balancers_[0]->service_.NotifyDoneWithServerlists(); + ClientStats client_stats = WaitForLoadReports(); + EXPECT_EQ(static_cast<size_t>(num_ok), client_stats.num_calls_started); + EXPECT_EQ(static_cast<size_t>(num_ok), client_stats.num_calls_finished); + EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send); + EXPECT_EQ(static_cast<size_t>(num_ok), + client_stats.num_calls_finished_known_received); + EXPECT_THAT(client_stats.drop_token_counts, ::testing::ElementsAre()); + // Shut down the balancer. + balancers_[0]->Shutdown(); + // Send 10 more requests per backend. This will continue using the + // last serverlist we received from the balancer before it was shut down. + ResetBackendCounters(); + CheckRpcSendOk(kNumBackendsFirstPass); + // Each backend should have gotten 1 request. + for (size_t i = 0; i < kNumBackendsFirstPass; ++i) { + EXPECT_EQ(1UL, backends_[i]->service_.request_count()); + } + // Now restart the balancer, this time pointing to all backends. + balancers_[0]->Start(server_host_); + ScheduleResponseForBalancer(0, + BalancerServiceImpl::BuildResponseForBackends( + GetBackendPorts(kNumBackendsFirstPass), {}), + 0); + // Wait for queries to start going to one of the new backends. + // This tells us that we're now using the new serverlist. + do { + CheckRpcSendOk(); + } while (backends_[2]->service_.request_count() == 0 && + backends_[3]->service_.request_count() == 0); + // Send one RPC per backend. + CheckRpcSendOk(kNumBackendsSecondPass); + balancers_[0]->service_.NotifyDoneWithServerlists(); + // Check client stats. + client_stats = WaitForLoadReports(); + EXPECT_EQ(kNumBackendsSecondPass + 1, client_stats.num_calls_started); + EXPECT_EQ(kNumBackendsSecondPass + 1, client_stats.num_calls_finished); + EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send); + EXPECT_EQ(kNumBackendsSecondPass + 1, + client_stats.num_calls_finished_known_received); + EXPECT_THAT(client_stats.drop_token_counts, ::testing::ElementsAre()); +} + +TEST_F(SingleBalancerWithClientLoadReportingTest, Drop) { + SetNextResolutionAllBalancers(); + const size_t kNumRpcsPerAddress = 3; + const int num_of_drop_by_rate_limiting_addresses = 2; + const int num_of_drop_by_load_balancing_addresses = 1; + const int num_of_drop_addresses = num_of_drop_by_rate_limiting_addresses + + num_of_drop_by_load_balancing_addresses; + const int num_total_addresses = num_backends_ + num_of_drop_addresses; + ScheduleResponseForBalancer( + 0, + BalancerServiceImpl::BuildResponseForBackends( + GetBackendPorts(), + {{"rate_limiting", num_of_drop_by_rate_limiting_addresses}, + {"load_balancing", num_of_drop_by_load_balancing_addresses}}), + 0); + // Wait until all backends are ready. + int num_warmup_ok = 0; + int num_warmup_failure = 0; + int num_warmup_drops = 0; + std::tie(num_warmup_ok, num_warmup_failure, num_warmup_drops) = + WaitForAllBackends(num_total_addresses /* num_requests_multiple_of */); + const int num_total_warmup_requests = + num_warmup_ok + num_warmup_failure + num_warmup_drops; + size_t num_drops = 0; + for (size_t i = 0; i < kNumRpcsPerAddress * num_total_addresses; ++i) { + EchoResponse response; + const Status status = SendRpc(&response); + if (!status.ok() && + status.error_message() == "Call dropped by load balancing policy") { + ++num_drops; + } else { + EXPECT_TRUE(status.ok()) << "code=" << status.error_code() + << " message=" << status.error_message(); + EXPECT_EQ(response.message(), kRequestMessage_); + } + } + EXPECT_EQ(kNumRpcsPerAddress * num_of_drop_addresses, num_drops); + // Each backend should have gotten 100 requests. + for (size_t i = 0; i < backends_.size(); ++i) { + EXPECT_EQ(kNumRpcsPerAddress, backends_[i]->service_.request_count()); + } + balancers_[0]->service_.NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancers_[0]->service_.request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + + const ClientStats client_stats = WaitForLoadReports(); + EXPECT_EQ( + kNumRpcsPerAddress * num_total_addresses + num_total_warmup_requests, + client_stats.num_calls_started); + EXPECT_EQ( + kNumRpcsPerAddress * num_total_addresses + num_total_warmup_requests, + client_stats.num_calls_finished); + EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send); + EXPECT_EQ(kNumRpcsPerAddress * num_backends_ + num_warmup_ok, + client_stats.num_calls_finished_known_received); + // The number of warmup request is a multiple of the number of addresses. + // Therefore, all addresses in the scheduled balancer response are hit the + // same number of times. + const int num_times_drop_addresses_hit = + num_warmup_drops / num_of_drop_addresses; + EXPECT_THAT( + client_stats.drop_token_counts, + ::testing::ElementsAre( + ::testing::Pair("load_balancing", + (kNumRpcsPerAddress + num_times_drop_addresses_hit)), + ::testing::Pair( + "rate_limiting", + (kNumRpcsPerAddress + num_times_drop_addresses_hit) * 2))); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + const auto result = RUN_ALL_TESTS(); + return result; +} diff --git a/contrib/libs/grpc/test/cpp/end2end/health/ya.make b/contrib/libs/grpc/test/cpp/end2end/health/ya.make index 0eda6bab65..7330129b73 100644 --- a/contrib/libs/grpc/test/cpp/end2end/health/ya.make +++ b/contrib/libs/grpc/test/cpp/end2end/health/ya.make @@ -1,33 +1,33 @@ GTEST_UGLY() - -OWNER( - dvshkurko - g:ymake -) - -ADDINCL( + +OWNER( + dvshkurko + g:ymake +) + +ADDINCL( ${ARCADIA_BUILD_ROOT}/contrib/libs/grpc - ${ARCADIA_ROOT}/contrib/libs/grpc -) - -PEERDIR( - contrib/libs/grpc/src/proto/grpc/health/v1 - contrib/libs/grpc/src/proto/grpc/core - contrib/libs/grpc/src/proto/grpc/testing - contrib/libs/grpc/src/proto/grpc/testing/duplicate - contrib/libs/grpc/test/core/util - contrib/libs/grpc/test/cpp/end2end - contrib/libs/grpc/test/cpp/util -) - -NO_COMPILER_WARNINGS() - -SRCDIR( - contrib/libs/grpc/test/cpp/end2end -) - -SRCS( - health_service_end2end_test.cc -) - -END() + ${ARCADIA_ROOT}/contrib/libs/grpc +) + +PEERDIR( + contrib/libs/grpc/src/proto/grpc/health/v1 + contrib/libs/grpc/src/proto/grpc/core + contrib/libs/grpc/src/proto/grpc/testing + contrib/libs/grpc/src/proto/grpc/testing/duplicate + contrib/libs/grpc/test/core/util + contrib/libs/grpc/test/cpp/end2end + contrib/libs/grpc/test/cpp/util +) + +NO_COMPILER_WARNINGS() + +SRCDIR( + contrib/libs/grpc/test/cpp/end2end +) + +SRCS( + health_service_end2end_test.cc +) + +END() diff --git a/contrib/libs/grpc/test/cpp/end2end/health_service_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/health_service_end2end_test.cc index 628917274b..516b3a4c81 100644 --- a/contrib/libs/grpc/test/cpp/end2end/health_service_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/health_service_end2end_test.cc @@ -1,374 +1,374 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * 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. - * - */ - -#include <memory> -#include <mutex> -#include <thread> -#include <vector> - -#include <grpc/grpc.h> -#include <grpc/support/log.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/ext/health_check_service_server_builder_option.h> -#include <grpcpp/health_check_service_interface.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/proto/grpc/health/v1/health.grpc.pb.h" -#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/test_health_check_service_impl.h" -#include "test/cpp/end2end/test_service_impl.h" - -#include <gtest/gtest.h> - -using grpc::health::v1::Health; -using grpc::health::v1::HealthCheckRequest; -using grpc::health::v1::HealthCheckResponse; - -namespace grpc { -namespace testing { -namespace { - -// A custom implementation of the health checking service interface. This is -// used to test that it prevents the server from creating a default service and -// also serves as an example of how to override the default service. -class CustomHealthCheckService : public HealthCheckServiceInterface { - public: - explicit CustomHealthCheckService(HealthCheckServiceImpl* impl) - : impl_(impl) { - impl_->SetStatus("", HealthCheckResponse::SERVING); - } +/* + * + * Copyright 2016 gRPC authors. + * + * 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. + * + */ + +#include <memory> +#include <mutex> +#include <thread> +#include <vector> + +#include <grpc/grpc.h> +#include <grpc/support/log.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/ext/health_check_service_server_builder_option.h> +#include <grpcpp/health_check_service_interface.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/health/v1/health.grpc.pb.h" +#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_health_check_service_impl.h" +#include "test/cpp/end2end/test_service_impl.h" + +#include <gtest/gtest.h> + +using grpc::health::v1::Health; +using grpc::health::v1::HealthCheckRequest; +using grpc::health::v1::HealthCheckResponse; + +namespace grpc { +namespace testing { +namespace { + +// A custom implementation of the health checking service interface. This is +// used to test that it prevents the server from creating a default service and +// also serves as an example of how to override the default service. +class CustomHealthCheckService : public HealthCheckServiceInterface { + public: + explicit CustomHealthCheckService(HealthCheckServiceImpl* impl) + : impl_(impl) { + impl_->SetStatus("", HealthCheckResponse::SERVING); + } void SetServingStatus(const TString& service_name, - bool serving) override { - impl_->SetStatus(service_name, serving ? HealthCheckResponse::SERVING - : HealthCheckResponse::NOT_SERVING); - } - - void SetServingStatus(bool serving) override { - impl_->SetAll(serving ? HealthCheckResponse::SERVING - : HealthCheckResponse::NOT_SERVING); - } - - void Shutdown() override { impl_->Shutdown(); } - - private: - HealthCheckServiceImpl* impl_; // not owned -}; - -class HealthServiceEnd2endTest : public ::testing::Test { - protected: - HealthServiceEnd2endTest() {} - - void SetUpServer(bool register_sync_test_service, bool add_async_cq, - bool explicit_health_service, - std::unique_ptr<HealthCheckServiceInterface> service) { - int port = 5001; // grpc_pick_unused_port_or_die(); - server_address_ << "localhost:" << port; - - bool register_sync_health_service_impl = - explicit_health_service && service != nullptr; - - // Setup server - ServerBuilder builder; - if (explicit_health_service) { - std::unique_ptr<ServerBuilderOption> option( - new HealthCheckServiceServerBuilderOption(std::move(service))); - builder.SetOption(std::move(option)); - } - builder.AddListeningPort(server_address_.str(), - grpc::InsecureServerCredentials()); - if (register_sync_test_service) { - // Register a sync service. - builder.RegisterService(&echo_test_service_); - } - if (register_sync_health_service_impl) { - builder.RegisterService(&health_check_service_impl_); - } - if (add_async_cq) { - cq_ = builder.AddCompletionQueue(); - } - server_ = builder.BuildAndStart(); - } - - void TearDown() override { - if (server_) { - server_->Shutdown(); - if (cq_ != nullptr) { - cq_->Shutdown(); - } - if (cq_thread_.joinable()) { - cq_thread_.join(); - } - } - } - - void ResetStubs() { - std::shared_ptr<Channel> channel = grpc::CreateChannel( - server_address_.str(), InsecureChannelCredentials()); - hc_stub_ = grpc::health::v1::Health::NewStub(channel); - } - - // When the expected_status is NOT OK, we do not care about the response. + bool serving) override { + impl_->SetStatus(service_name, serving ? HealthCheckResponse::SERVING + : HealthCheckResponse::NOT_SERVING); + } + + void SetServingStatus(bool serving) override { + impl_->SetAll(serving ? HealthCheckResponse::SERVING + : HealthCheckResponse::NOT_SERVING); + } + + void Shutdown() override { impl_->Shutdown(); } + + private: + HealthCheckServiceImpl* impl_; // not owned +}; + +class HealthServiceEnd2endTest : public ::testing::Test { + protected: + HealthServiceEnd2endTest() {} + + void SetUpServer(bool register_sync_test_service, bool add_async_cq, + bool explicit_health_service, + std::unique_ptr<HealthCheckServiceInterface> service) { + int port = 5001; // grpc_pick_unused_port_or_die(); + server_address_ << "localhost:" << port; + + bool register_sync_health_service_impl = + explicit_health_service && service != nullptr; + + // Setup server + ServerBuilder builder; + if (explicit_health_service) { + std::unique_ptr<ServerBuilderOption> option( + new HealthCheckServiceServerBuilderOption(std::move(service))); + builder.SetOption(std::move(option)); + } + builder.AddListeningPort(server_address_.str(), + grpc::InsecureServerCredentials()); + if (register_sync_test_service) { + // Register a sync service. + builder.RegisterService(&echo_test_service_); + } + if (register_sync_health_service_impl) { + builder.RegisterService(&health_check_service_impl_); + } + if (add_async_cq) { + cq_ = builder.AddCompletionQueue(); + } + server_ = builder.BuildAndStart(); + } + + void TearDown() override { + if (server_) { + server_->Shutdown(); + if (cq_ != nullptr) { + cq_->Shutdown(); + } + if (cq_thread_.joinable()) { + cq_thread_.join(); + } + } + } + + void ResetStubs() { + std::shared_ptr<Channel> channel = grpc::CreateChannel( + server_address_.str(), InsecureChannelCredentials()); + hc_stub_ = grpc::health::v1::Health::NewStub(channel); + } + + // When the expected_status is NOT OK, we do not care about the response. void SendHealthCheckRpc(const TString& service_name, - const Status& expected_status) { - EXPECT_FALSE(expected_status.ok()); - SendHealthCheckRpc(service_name, expected_status, - HealthCheckResponse::UNKNOWN); - } - - void SendHealthCheckRpc( + const Status& expected_status) { + EXPECT_FALSE(expected_status.ok()); + SendHealthCheckRpc(service_name, expected_status, + HealthCheckResponse::UNKNOWN); + } + + void SendHealthCheckRpc( const TString& service_name, const Status& expected_status, - HealthCheckResponse::ServingStatus expected_serving_status) { - HealthCheckRequest request; - request.set_service(service_name); - HealthCheckResponse response; - ClientContext context; - Status s = hc_stub_->Check(&context, request, &response); - EXPECT_EQ(expected_status.error_code(), s.error_code()); - if (s.ok()) { - EXPECT_EQ(expected_serving_status, response.status()); - } - } - - void VerifyHealthCheckService() { - HealthCheckServiceInterface* service = server_->GetHealthCheckService(); - EXPECT_TRUE(service != nullptr); + HealthCheckResponse::ServingStatus expected_serving_status) { + HealthCheckRequest request; + request.set_service(service_name); + HealthCheckResponse response; + ClientContext context; + Status s = hc_stub_->Check(&context, request, &response); + EXPECT_EQ(expected_status.error_code(), s.error_code()); + if (s.ok()) { + EXPECT_EQ(expected_serving_status, response.status()); + } + } + + void VerifyHealthCheckService() { + HealthCheckServiceInterface* service = server_->GetHealthCheckService(); + EXPECT_TRUE(service != nullptr); const TString kHealthyService("healthy_service"); const TString kUnhealthyService("unhealthy_service"); const TString kNotRegisteredService("not_registered"); - service->SetServingStatus(kHealthyService, true); - service->SetServingStatus(kUnhealthyService, false); - - ResetStubs(); - - SendHealthCheckRpc("", Status::OK, HealthCheckResponse::SERVING); - SendHealthCheckRpc(kHealthyService, Status::OK, - HealthCheckResponse::SERVING); - SendHealthCheckRpc(kUnhealthyService, Status::OK, - HealthCheckResponse::NOT_SERVING); - SendHealthCheckRpc(kNotRegisteredService, - Status(StatusCode::NOT_FOUND, "")); - - service->SetServingStatus(false); - SendHealthCheckRpc("", Status::OK, HealthCheckResponse::NOT_SERVING); - SendHealthCheckRpc(kHealthyService, Status::OK, - HealthCheckResponse::NOT_SERVING); - SendHealthCheckRpc(kUnhealthyService, Status::OK, - HealthCheckResponse::NOT_SERVING); - SendHealthCheckRpc(kNotRegisteredService, - Status(StatusCode::NOT_FOUND, "")); - } - - void VerifyHealthCheckServiceStreaming() { + service->SetServingStatus(kHealthyService, true); + service->SetServingStatus(kUnhealthyService, false); + + ResetStubs(); + + SendHealthCheckRpc("", Status::OK, HealthCheckResponse::SERVING); + SendHealthCheckRpc(kHealthyService, Status::OK, + HealthCheckResponse::SERVING); + SendHealthCheckRpc(kUnhealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kNotRegisteredService, + Status(StatusCode::NOT_FOUND, "")); + + service->SetServingStatus(false); + SendHealthCheckRpc("", Status::OK, HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kHealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kUnhealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kNotRegisteredService, + Status(StatusCode::NOT_FOUND, "")); + } + + void VerifyHealthCheckServiceStreaming() { const TString kServiceName("service_name"); - HealthCheckServiceInterface* service = server_->GetHealthCheckService(); - // Start Watch for service. - ClientContext context; - HealthCheckRequest request; - request.set_service(kServiceName); - std::unique_ptr<::grpc::ClientReaderInterface<HealthCheckResponse>> reader = - hc_stub_->Watch(&context, request); - // Initial response will be SERVICE_UNKNOWN. - HealthCheckResponse response; - EXPECT_TRUE(reader->Read(&response)); - EXPECT_EQ(response.SERVICE_UNKNOWN, response.status()); - response.Clear(); - // Now set service to NOT_SERVING and make sure we get an update. - service->SetServingStatus(kServiceName, false); - EXPECT_TRUE(reader->Read(&response)); - EXPECT_EQ(response.NOT_SERVING, response.status()); - response.Clear(); - // Now set service to SERVING and make sure we get another update. - service->SetServingStatus(kServiceName, true); - EXPECT_TRUE(reader->Read(&response)); - EXPECT_EQ(response.SERVING, response.status()); - // Finish call. - context.TryCancel(); - } - - // Verify that after HealthCheckServiceInterface::Shutdown is called - // 1. unary client will see NOT_SERVING. - // 2. unary client still sees NOT_SERVING after a SetServing(true) is called. - // 3. streaming (Watch) client will see an update. - // 4. setting a new service to serving after shutdown will add the service - // name but return NOT_SERVING to client. - // This has to be called last. - void VerifyHealthCheckServiceShutdown() { - HealthCheckServiceInterface* service = server_->GetHealthCheckService(); - EXPECT_TRUE(service != nullptr); + HealthCheckServiceInterface* service = server_->GetHealthCheckService(); + // Start Watch for service. + ClientContext context; + HealthCheckRequest request; + request.set_service(kServiceName); + std::unique_ptr<::grpc::ClientReaderInterface<HealthCheckResponse>> reader = + hc_stub_->Watch(&context, request); + // Initial response will be SERVICE_UNKNOWN. + HealthCheckResponse response; + EXPECT_TRUE(reader->Read(&response)); + EXPECT_EQ(response.SERVICE_UNKNOWN, response.status()); + response.Clear(); + // Now set service to NOT_SERVING and make sure we get an update. + service->SetServingStatus(kServiceName, false); + EXPECT_TRUE(reader->Read(&response)); + EXPECT_EQ(response.NOT_SERVING, response.status()); + response.Clear(); + // Now set service to SERVING and make sure we get another update. + service->SetServingStatus(kServiceName, true); + EXPECT_TRUE(reader->Read(&response)); + EXPECT_EQ(response.SERVING, response.status()); + // Finish call. + context.TryCancel(); + } + + // Verify that after HealthCheckServiceInterface::Shutdown is called + // 1. unary client will see NOT_SERVING. + // 2. unary client still sees NOT_SERVING after a SetServing(true) is called. + // 3. streaming (Watch) client will see an update. + // 4. setting a new service to serving after shutdown will add the service + // name but return NOT_SERVING to client. + // This has to be called last. + void VerifyHealthCheckServiceShutdown() { + HealthCheckServiceInterface* service = server_->GetHealthCheckService(); + EXPECT_TRUE(service != nullptr); const TString kHealthyService("healthy_service"); const TString kUnhealthyService("unhealthy_service"); const TString kNotRegisteredService("not_registered"); const TString kNewService("add_after_shutdown"); - service->SetServingStatus(kHealthyService, true); - service->SetServingStatus(kUnhealthyService, false); - - ResetStubs(); - - // Start Watch for service. - ClientContext context; - HealthCheckRequest request; - request.set_service(kHealthyService); - std::unique_ptr<::grpc::ClientReaderInterface<HealthCheckResponse>> reader = - hc_stub_->Watch(&context, request); - - HealthCheckResponse response; - EXPECT_TRUE(reader->Read(&response)); - EXPECT_EQ(response.SERVING, response.status()); - - SendHealthCheckRpc("", Status::OK, HealthCheckResponse::SERVING); - SendHealthCheckRpc(kHealthyService, Status::OK, - HealthCheckResponse::SERVING); - SendHealthCheckRpc(kUnhealthyService, Status::OK, - HealthCheckResponse::NOT_SERVING); - SendHealthCheckRpc(kNotRegisteredService, - Status(StatusCode::NOT_FOUND, "")); - SendHealthCheckRpc(kNewService, Status(StatusCode::NOT_FOUND, "")); - - // Shutdown health check service. - service->Shutdown(); - - // Watch client gets another update. - EXPECT_TRUE(reader->Read(&response)); - EXPECT_EQ(response.NOT_SERVING, response.status()); - // Finish Watch call. - context.TryCancel(); - - SendHealthCheckRpc("", Status::OK, HealthCheckResponse::NOT_SERVING); - SendHealthCheckRpc(kHealthyService, Status::OK, - HealthCheckResponse::NOT_SERVING); - SendHealthCheckRpc(kUnhealthyService, Status::OK, - HealthCheckResponse::NOT_SERVING); - SendHealthCheckRpc(kNotRegisteredService, - Status(StatusCode::NOT_FOUND, "")); - - // Setting status after Shutdown has no effect. - service->SetServingStatus(kHealthyService, true); - SendHealthCheckRpc(kHealthyService, Status::OK, - HealthCheckResponse::NOT_SERVING); - - // Adding serving status for a new service after shutdown will return - // NOT_SERVING. - service->SetServingStatus(kNewService, true); - SendHealthCheckRpc(kNewService, Status::OK, - HealthCheckResponse::NOT_SERVING); - } - - TestServiceImpl echo_test_service_; - HealthCheckServiceImpl health_check_service_impl_; - std::unique_ptr<Health::Stub> hc_stub_; - std::unique_ptr<ServerCompletionQueue> cq_; - std::unique_ptr<Server> server_; - std::ostringstream server_address_; - std::thread cq_thread_; -}; - -TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceDisabled) { - EnableDefaultHealthCheckService(false); - EXPECT_FALSE(DefaultHealthCheckServiceEnabled()); - SetUpServer(true, false, false, nullptr); - HealthCheckServiceInterface* default_service = - server_->GetHealthCheckService(); - EXPECT_TRUE(default_service == nullptr); - - ResetStubs(); - - SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, "")); -} - -TEST_F(HealthServiceEnd2endTest, DefaultHealthService) { - EnableDefaultHealthCheckService(true); - EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); - SetUpServer(true, false, false, nullptr); - VerifyHealthCheckService(); - VerifyHealthCheckServiceStreaming(); - - // The default service has a size limit of the service name. + service->SetServingStatus(kHealthyService, true); + service->SetServingStatus(kUnhealthyService, false); + + ResetStubs(); + + // Start Watch for service. + ClientContext context; + HealthCheckRequest request; + request.set_service(kHealthyService); + std::unique_ptr<::grpc::ClientReaderInterface<HealthCheckResponse>> reader = + hc_stub_->Watch(&context, request); + + HealthCheckResponse response; + EXPECT_TRUE(reader->Read(&response)); + EXPECT_EQ(response.SERVING, response.status()); + + SendHealthCheckRpc("", Status::OK, HealthCheckResponse::SERVING); + SendHealthCheckRpc(kHealthyService, Status::OK, + HealthCheckResponse::SERVING); + SendHealthCheckRpc(kUnhealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kNotRegisteredService, + Status(StatusCode::NOT_FOUND, "")); + SendHealthCheckRpc(kNewService, Status(StatusCode::NOT_FOUND, "")); + + // Shutdown health check service. + service->Shutdown(); + + // Watch client gets another update. + EXPECT_TRUE(reader->Read(&response)); + EXPECT_EQ(response.NOT_SERVING, response.status()); + // Finish Watch call. + context.TryCancel(); + + SendHealthCheckRpc("", Status::OK, HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kHealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kUnhealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + SendHealthCheckRpc(kNotRegisteredService, + Status(StatusCode::NOT_FOUND, "")); + + // Setting status after Shutdown has no effect. + service->SetServingStatus(kHealthyService, true); + SendHealthCheckRpc(kHealthyService, Status::OK, + HealthCheckResponse::NOT_SERVING); + + // Adding serving status for a new service after shutdown will return + // NOT_SERVING. + service->SetServingStatus(kNewService, true); + SendHealthCheckRpc(kNewService, Status::OK, + HealthCheckResponse::NOT_SERVING); + } + + TestServiceImpl echo_test_service_; + HealthCheckServiceImpl health_check_service_impl_; + std::unique_ptr<Health::Stub> hc_stub_; + std::unique_ptr<ServerCompletionQueue> cq_; + std::unique_ptr<Server> server_; + std::ostringstream server_address_; + std::thread cq_thread_; +}; + +TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceDisabled) { + EnableDefaultHealthCheckService(false); + EXPECT_FALSE(DefaultHealthCheckServiceEnabled()); + SetUpServer(true, false, false, nullptr); + HealthCheckServiceInterface* default_service = + server_->GetHealthCheckService(); + EXPECT_TRUE(default_service == nullptr); + + ResetStubs(); + + SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, "")); +} + +TEST_F(HealthServiceEnd2endTest, DefaultHealthService) { + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + SetUpServer(true, false, false, nullptr); + VerifyHealthCheckService(); + VerifyHealthCheckServiceStreaming(); + + // The default service has a size limit of the service name. const TString kTooLongServiceName(201, 'x'); - SendHealthCheckRpc(kTooLongServiceName, - Status(StatusCode::INVALID_ARGUMENT, "")); -} - -TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceShutdown) { - EnableDefaultHealthCheckService(true); - EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); - SetUpServer(true, false, false, nullptr); - VerifyHealthCheckServiceShutdown(); -} - -// Provide an empty service to disable the default service. -TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) { - EnableDefaultHealthCheckService(true); - EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); - std::unique_ptr<HealthCheckServiceInterface> empty_service; - SetUpServer(true, false, true, std::move(empty_service)); - HealthCheckServiceInterface* service = server_->GetHealthCheckService(); - EXPECT_TRUE(service == nullptr); - - ResetStubs(); - - SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, "")); -} - -// Provide an explicit override of health checking service interface. -TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) { - EnableDefaultHealthCheckService(true); - EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); - std::unique_ptr<HealthCheckServiceInterface> override_service( - new CustomHealthCheckService(&health_check_service_impl_)); - HealthCheckServiceInterface* underlying_service = override_service.get(); - SetUpServer(false, false, true, std::move(override_service)); - HealthCheckServiceInterface* service = server_->GetHealthCheckService(); - EXPECT_TRUE(service == underlying_service); - - ResetStubs(); - - VerifyHealthCheckService(); - VerifyHealthCheckServiceStreaming(); -} - -TEST_F(HealthServiceEnd2endTest, ExplicitlyHealthServiceShutdown) { - EnableDefaultHealthCheckService(true); - EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); - std::unique_ptr<HealthCheckServiceInterface> override_service( - new CustomHealthCheckService(&health_check_service_impl_)); - HealthCheckServiceInterface* underlying_service = override_service.get(); - SetUpServer(false, false, true, std::move(override_service)); - HealthCheckServiceInterface* service = server_->GetHealthCheckService(); - EXPECT_TRUE(service == underlying_service); - - ResetStubs(); - - VerifyHealthCheckServiceShutdown(); -} - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + SendHealthCheckRpc(kTooLongServiceName, + Status(StatusCode::INVALID_ARGUMENT, "")); +} + +TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceShutdown) { + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + SetUpServer(true, false, false, nullptr); + VerifyHealthCheckServiceShutdown(); +} + +// Provide an empty service to disable the default service. +TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) { + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + std::unique_ptr<HealthCheckServiceInterface> empty_service; + SetUpServer(true, false, true, std::move(empty_service)); + HealthCheckServiceInterface* service = server_->GetHealthCheckService(); + EXPECT_TRUE(service == nullptr); + + ResetStubs(); + + SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, "")); +} + +// Provide an explicit override of health checking service interface. +TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) { + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + std::unique_ptr<HealthCheckServiceInterface> override_service( + new CustomHealthCheckService(&health_check_service_impl_)); + HealthCheckServiceInterface* underlying_service = override_service.get(); + SetUpServer(false, false, true, std::move(override_service)); + HealthCheckServiceInterface* service = server_->GetHealthCheckService(); + EXPECT_TRUE(service == underlying_service); + + ResetStubs(); + + VerifyHealthCheckService(); + VerifyHealthCheckServiceStreaming(); +} + +TEST_F(HealthServiceEnd2endTest, ExplicitlyHealthServiceShutdown) { + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + std::unique_ptr<HealthCheckServiceInterface> override_service( + new CustomHealthCheckService(&health_check_service_impl_)); + HealthCheckServiceInterface* underlying_service = override_service.get(); + SetUpServer(false, false, true, std::move(override_service)); + HealthCheckServiceInterface* service = server_->GetHealthCheckService(); + EXPECT_TRUE(service == underlying_service); + + ResetStubs(); + + VerifyHealthCheckServiceShutdown(); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/hybrid_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/hybrid_end2end_test.cc index 9fc5cc1ba7..e4ebee8e93 100644 --- a/contrib/libs/grpc/test/cpp/end2end/hybrid_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/hybrid_end2end_test.cc @@ -1,987 +1,987 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * 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. - * - */ - -#include <memory> -#include <thread> - -#include <grpc/grpc.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/generic/async_generic_service.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/core/lib/gpr/env.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/test_service_impl.h" -#include "test/cpp/util/byte_buffer_proto_helper.h" - -#include <gtest/gtest.h> - -namespace grpc { -namespace testing { -namespace { - +/* + * + * Copyright 2016 gRPC authors. + * + * 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. + * + */ + +#include <memory> +#include <thread> + +#include <grpc/grpc.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/generic/async_generic_service.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" + +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { +namespace { + #ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL using ::grpc::experimental::CallbackGenericService; using ::grpc::experimental::GenericCallbackServerContext; using ::grpc::experimental::ServerGenericBidiReactor; #endif -void* tag(int i) { return (void*)static_cast<intptr_t>(i); } - -bool VerifyReturnSuccess(CompletionQueue* cq, int i) { - void* got_tag; - bool ok; - EXPECT_TRUE(cq->Next(&got_tag, &ok)); - EXPECT_EQ(tag(i), got_tag); - return ok; -} - -void Verify(CompletionQueue* cq, int i, bool expect_ok) { - EXPECT_EQ(expect_ok, VerifyReturnSuccess(cq, i)); -} - -// Handlers to handle async request at a server. To be run in a separate thread. -template <class Service> -void HandleEcho(Service* service, ServerCompletionQueue* cq, bool dup_service) { - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - EchoRequest recv_request; - EchoResponse send_response; - service->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq, cq, - tag(1)); - Verify(cq, 1, true); - send_response.set_message(recv_request.message()); - if (dup_service) { - send_response.mutable_message()->append("_dup"); - } - response_writer.Finish(send_response, Status::OK, tag(2)); - Verify(cq, 2, true); -} - -// Handlers to handle raw request at a server. To be run in a -// separate thread. Note that this is the same as the async version, except -// that the req/resp are ByteBuffers -template <class Service> -void HandleRawEcho(Service* service, ServerCompletionQueue* cq, - bool /*dup_service*/) { - ServerContext srv_ctx; - GenericServerAsyncResponseWriter response_writer(&srv_ctx); - ByteBuffer recv_buffer; - service->RequestEcho(&srv_ctx, &recv_buffer, &response_writer, cq, cq, - tag(1)); - Verify(cq, 1, true); - EchoRequest recv_request; - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); - EchoResponse send_response; - send_response.set_message(recv_request.message()); - auto send_buffer = SerializeToByteBuffer(&send_response); - response_writer.Finish(*send_buffer, Status::OK, tag(2)); - Verify(cq, 2, true); -} - -template <class Service> -void HandleClientStreaming(Service* service, ServerCompletionQueue* cq) { - ServerContext srv_ctx; - EchoRequest recv_request; - EchoResponse send_response; - ServerAsyncReader<EchoResponse, EchoRequest> srv_stream(&srv_ctx); - service->RequestRequestStream(&srv_ctx, &srv_stream, cq, cq, tag(1)); - Verify(cq, 1, true); - int i = 1; - do { - i++; - send_response.mutable_message()->append(recv_request.message()); - srv_stream.Read(&recv_request, tag(i)); - } while (VerifyReturnSuccess(cq, i)); - srv_stream.Finish(send_response, Status::OK, tag(100)); - Verify(cq, 100, true); -} - -template <class Service> -void HandleRawClientStreaming(Service* service, ServerCompletionQueue* cq) { - ServerContext srv_ctx; - ByteBuffer recv_buffer; - EchoRequest recv_request; - EchoResponse send_response; - GenericServerAsyncReader srv_stream(&srv_ctx); - service->RequestRequestStream(&srv_ctx, &srv_stream, cq, cq, tag(1)); - Verify(cq, 1, true); - int i = 1; - while (true) { - i++; - srv_stream.Read(&recv_buffer, tag(i)); - if (!VerifyReturnSuccess(cq, i)) { - break; - } - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); - send_response.mutable_message()->append(recv_request.message()); - } - auto send_buffer = SerializeToByteBuffer(&send_response); - srv_stream.Finish(*send_buffer, Status::OK, tag(100)); - Verify(cq, 100, true); -} - -template <class Service> -void HandleServerStreaming(Service* service, ServerCompletionQueue* cq) { - ServerContext srv_ctx; - EchoRequest recv_request; - EchoResponse send_response; - ServerAsyncWriter<EchoResponse> srv_stream(&srv_ctx); - service->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, cq, cq, - tag(1)); - Verify(cq, 1, true); - send_response.set_message(recv_request.message() + "0"); - srv_stream.Write(send_response, tag(2)); - Verify(cq, 2, true); - send_response.set_message(recv_request.message() + "1"); - srv_stream.Write(send_response, tag(3)); - Verify(cq, 3, true); - send_response.set_message(recv_request.message() + "2"); - srv_stream.Write(send_response, tag(4)); - Verify(cq, 4, true); - srv_stream.Finish(Status::OK, tag(5)); - Verify(cq, 5, true); -} - -void HandleGenericEcho(GenericServerAsyncReaderWriter* stream, - CompletionQueue* cq) { - ByteBuffer recv_buffer; - stream->Read(&recv_buffer, tag(2)); - Verify(cq, 2, true); - EchoRequest recv_request; - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); - EchoResponse send_response; - send_response.set_message(recv_request.message()); - auto send_buffer = SerializeToByteBuffer(&send_response); - stream->Write(*send_buffer, tag(3)); - Verify(cq, 3, true); - stream->Finish(Status::OK, tag(4)); - Verify(cq, 4, true); -} - -void HandleGenericRequestStream(GenericServerAsyncReaderWriter* stream, - CompletionQueue* cq) { - ByteBuffer recv_buffer; - EchoRequest recv_request; - EchoResponse send_response; - int i = 1; - while (true) { - i++; - stream->Read(&recv_buffer, tag(i)); - if (!VerifyReturnSuccess(cq, i)) { - break; - } - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); - send_response.mutable_message()->append(recv_request.message()); - } - auto send_buffer = SerializeToByteBuffer(&send_response); - stream->Write(*send_buffer, tag(99)); - Verify(cq, 99, true); - stream->Finish(Status::OK, tag(100)); - Verify(cq, 100, true); -} - -// Request and handle one generic call. -void HandleGenericCall(AsyncGenericService* service, - ServerCompletionQueue* cq) { - GenericServerContext srv_ctx; - GenericServerAsyncReaderWriter stream(&srv_ctx); - service->RequestCall(&srv_ctx, &stream, cq, cq, tag(1)); - Verify(cq, 1, true); - if (srv_ctx.method() == "/grpc.testing.EchoTestService/Echo") { - HandleGenericEcho(&stream, cq); - } else if (srv_ctx.method() == - "/grpc.testing.EchoTestService/RequestStream") { - HandleGenericRequestStream(&stream, cq); - } else { // other methods not handled yet. - gpr_log(GPR_ERROR, "method: %s", srv_ctx.method().c_str()); - GPR_ASSERT(0); - } -} - -class TestServiceImplDupPkg - : public ::grpc::testing::duplicate::EchoTestService::Service { - public: - Status Echo(ServerContext* /*context*/, const EchoRequest* request, - EchoResponse* response) override { - response->set_message(request->message() + "_dup"); - return Status::OK; - } -}; - -class HybridEnd2endTest : public ::testing::TestWithParam<bool> { - protected: - HybridEnd2endTest() {} - - static void SetUpTestCase() { -#if TARGET_OS_IPHONE - // Workaround Apple CFStream bug - gpr_setenv("grpc_cfstream", "0"); -#endif - } - - void SetUp() override { - inproc_ = (::testing::UnitTest::GetInstance() - ->current_test_info() - ->value_param() != nullptr) - ? GetParam() - : false; - } - +void* tag(int i) { return (void*)static_cast<intptr_t>(i); } + +bool VerifyReturnSuccess(CompletionQueue* cq, int i) { + void* got_tag; + bool ok; + EXPECT_TRUE(cq->Next(&got_tag, &ok)); + EXPECT_EQ(tag(i), got_tag); + return ok; +} + +void Verify(CompletionQueue* cq, int i, bool expect_ok) { + EXPECT_EQ(expect_ok, VerifyReturnSuccess(cq, i)); +} + +// Handlers to handle async request at a server. To be run in a separate thread. +template <class Service> +void HandleEcho(Service* service, ServerCompletionQueue* cq, bool dup_service) { + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + EchoRequest recv_request; + EchoResponse send_response; + service->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq, cq, + tag(1)); + Verify(cq, 1, true); + send_response.set_message(recv_request.message()); + if (dup_service) { + send_response.mutable_message()->append("_dup"); + } + response_writer.Finish(send_response, Status::OK, tag(2)); + Verify(cq, 2, true); +} + +// Handlers to handle raw request at a server. To be run in a +// separate thread. Note that this is the same as the async version, except +// that the req/resp are ByteBuffers +template <class Service> +void HandleRawEcho(Service* service, ServerCompletionQueue* cq, + bool /*dup_service*/) { + ServerContext srv_ctx; + GenericServerAsyncResponseWriter response_writer(&srv_ctx); + ByteBuffer recv_buffer; + service->RequestEcho(&srv_ctx, &recv_buffer, &response_writer, cq, cq, + tag(1)); + Verify(cq, 1, true); + EchoRequest recv_request; + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); + EchoResponse send_response; + send_response.set_message(recv_request.message()); + auto send_buffer = SerializeToByteBuffer(&send_response); + response_writer.Finish(*send_buffer, Status::OK, tag(2)); + Verify(cq, 2, true); +} + +template <class Service> +void HandleClientStreaming(Service* service, ServerCompletionQueue* cq) { + ServerContext srv_ctx; + EchoRequest recv_request; + EchoResponse send_response; + ServerAsyncReader<EchoResponse, EchoRequest> srv_stream(&srv_ctx); + service->RequestRequestStream(&srv_ctx, &srv_stream, cq, cq, tag(1)); + Verify(cq, 1, true); + int i = 1; + do { + i++; + send_response.mutable_message()->append(recv_request.message()); + srv_stream.Read(&recv_request, tag(i)); + } while (VerifyReturnSuccess(cq, i)); + srv_stream.Finish(send_response, Status::OK, tag(100)); + Verify(cq, 100, true); +} + +template <class Service> +void HandleRawClientStreaming(Service* service, ServerCompletionQueue* cq) { + ServerContext srv_ctx; + ByteBuffer recv_buffer; + EchoRequest recv_request; + EchoResponse send_response; + GenericServerAsyncReader srv_stream(&srv_ctx); + service->RequestRequestStream(&srv_ctx, &srv_stream, cq, cq, tag(1)); + Verify(cq, 1, true); + int i = 1; + while (true) { + i++; + srv_stream.Read(&recv_buffer, tag(i)); + if (!VerifyReturnSuccess(cq, i)) { + break; + } + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); + send_response.mutable_message()->append(recv_request.message()); + } + auto send_buffer = SerializeToByteBuffer(&send_response); + srv_stream.Finish(*send_buffer, Status::OK, tag(100)); + Verify(cq, 100, true); +} + +template <class Service> +void HandleServerStreaming(Service* service, ServerCompletionQueue* cq) { + ServerContext srv_ctx; + EchoRequest recv_request; + EchoResponse send_response; + ServerAsyncWriter<EchoResponse> srv_stream(&srv_ctx); + service->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, cq, cq, + tag(1)); + Verify(cq, 1, true); + send_response.set_message(recv_request.message() + "0"); + srv_stream.Write(send_response, tag(2)); + Verify(cq, 2, true); + send_response.set_message(recv_request.message() + "1"); + srv_stream.Write(send_response, tag(3)); + Verify(cq, 3, true); + send_response.set_message(recv_request.message() + "2"); + srv_stream.Write(send_response, tag(4)); + Verify(cq, 4, true); + srv_stream.Finish(Status::OK, tag(5)); + Verify(cq, 5, true); +} + +void HandleGenericEcho(GenericServerAsyncReaderWriter* stream, + CompletionQueue* cq) { + ByteBuffer recv_buffer; + stream->Read(&recv_buffer, tag(2)); + Verify(cq, 2, true); + EchoRequest recv_request; + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); + EchoResponse send_response; + send_response.set_message(recv_request.message()); + auto send_buffer = SerializeToByteBuffer(&send_response); + stream->Write(*send_buffer, tag(3)); + Verify(cq, 3, true); + stream->Finish(Status::OK, tag(4)); + Verify(cq, 4, true); +} + +void HandleGenericRequestStream(GenericServerAsyncReaderWriter* stream, + CompletionQueue* cq) { + ByteBuffer recv_buffer; + EchoRequest recv_request; + EchoResponse send_response; + int i = 1; + while (true) { + i++; + stream->Read(&recv_buffer, tag(i)); + if (!VerifyReturnSuccess(cq, i)) { + break; + } + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); + send_response.mutable_message()->append(recv_request.message()); + } + auto send_buffer = SerializeToByteBuffer(&send_response); + stream->Write(*send_buffer, tag(99)); + Verify(cq, 99, true); + stream->Finish(Status::OK, tag(100)); + Verify(cq, 100, true); +} + +// Request and handle one generic call. +void HandleGenericCall(AsyncGenericService* service, + ServerCompletionQueue* cq) { + GenericServerContext srv_ctx; + GenericServerAsyncReaderWriter stream(&srv_ctx); + service->RequestCall(&srv_ctx, &stream, cq, cq, tag(1)); + Verify(cq, 1, true); + if (srv_ctx.method() == "/grpc.testing.EchoTestService/Echo") { + HandleGenericEcho(&stream, cq); + } else if (srv_ctx.method() == + "/grpc.testing.EchoTestService/RequestStream") { + HandleGenericRequestStream(&stream, cq); + } else { // other methods not handled yet. + gpr_log(GPR_ERROR, "method: %s", srv_ctx.method().c_str()); + GPR_ASSERT(0); + } +} + +class TestServiceImplDupPkg + : public ::grpc::testing::duplicate::EchoTestService::Service { + public: + Status Echo(ServerContext* /*context*/, const EchoRequest* request, + EchoResponse* response) override { + response->set_message(request->message() + "_dup"); + return Status::OK; + } +}; + +class HybridEnd2endTest : public ::testing::TestWithParam<bool> { + protected: + HybridEnd2endTest() {} + + static void SetUpTestCase() { +#if TARGET_OS_IPHONE + // Workaround Apple CFStream bug + gpr_setenv("grpc_cfstream", "0"); +#endif + } + + void SetUp() override { + inproc_ = (::testing::UnitTest::GetInstance() + ->current_test_info() + ->value_param() != nullptr) + ? GetParam() + : false; + } + bool SetUpServer(::grpc::Service* service1, ::grpc::Service* service2, AsyncGenericService* generic_service, CallbackGenericService* callback_generic_service, int max_message_size = 0) { - int port = grpc_pick_unused_port_or_die(); - server_address_ << "localhost:" << port; - - // Setup server - ServerBuilder builder; - builder.AddListeningPort(server_address_.str(), - grpc::InsecureServerCredentials()); - // Always add a sync unimplemented service: we rely on having at least one - // synchronous method to get a listening cq - builder.RegisterService(&unimplemented_service_); - builder.RegisterService(service1); - if (service2) { - builder.RegisterService(service2); - } - if (generic_service) { - builder.RegisterAsyncGenericService(generic_service); - } - if (callback_generic_service) { + int port = grpc_pick_unused_port_or_die(); + server_address_ << "localhost:" << port; + + // Setup server + ServerBuilder builder; + builder.AddListeningPort(server_address_.str(), + grpc::InsecureServerCredentials()); + // Always add a sync unimplemented service: we rely on having at least one + // synchronous method to get a listening cq + builder.RegisterService(&unimplemented_service_); + builder.RegisterService(service1); + if (service2) { + builder.RegisterService(service2); + } + if (generic_service) { + builder.RegisterAsyncGenericService(generic_service); + } + if (callback_generic_service) { #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL builder.RegisterCallbackGenericService(callback_generic_service); #else - builder.experimental().RegisterCallbackGenericService( - callback_generic_service); + builder.experimental().RegisterCallbackGenericService( + callback_generic_service); #endif - } - - if (max_message_size != 0) { - builder.SetMaxMessageSize(max_message_size); - } - - // Create a separate cq for each potential handler. - for (int i = 0; i < 5; i++) { - cqs_.push_back(builder.AddCompletionQueue(false)); - } - server_ = builder.BuildAndStart(); - - // If there is a generic callback service, this setup is only successful if - // we have an iomgr that can run in the background or are inprocess - return !callback_generic_service || grpc_iomgr_run_in_background() || - inproc_; - } - - void TearDown() override { - if (server_) { - server_->Shutdown(); - } - void* ignored_tag; - bool ignored_ok; - for (auto it = cqs_.begin(); it != cqs_.end(); ++it) { - (*it)->Shutdown(); - while ((*it)->Next(&ignored_tag, &ignored_ok)) - ; - } - } - - void ResetStub() { - std::shared_ptr<Channel> channel = - inproc_ ? server_->InProcessChannel(ChannelArguments()) - : grpc::CreateChannel(server_address_.str(), - InsecureChannelCredentials()); - stub_ = grpc::testing::EchoTestService::NewStub(channel); - } - - // Test all rpc methods. - void TestAllMethods() { - SendEcho(); - SendSimpleClientStreaming(); - SendSimpleServerStreaming(); - SendBidiStreaming(); - } - - void SendEcho() { - EchoRequest send_request; - EchoResponse recv_response; - ClientContext cli_ctx; - cli_ctx.set_wait_for_ready(true); - send_request.set_message("Hello"); - Status recv_status = stub_->Echo(&cli_ctx, send_request, &recv_response); - EXPECT_EQ(send_request.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - } - - void SendEchoToDupService() { - std::shared_ptr<Channel> channel = grpc::CreateChannel( - server_address_.str(), InsecureChannelCredentials()); - auto stub = grpc::testing::duplicate::EchoTestService::NewStub(channel); - EchoRequest send_request; - EchoResponse recv_response; - ClientContext cli_ctx; - cli_ctx.set_wait_for_ready(true); - send_request.set_message("Hello"); - Status recv_status = stub->Echo(&cli_ctx, send_request, &recv_response); - EXPECT_EQ(send_request.message() + "_dup", recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - } - - void SendSimpleClientStreaming() { - EchoRequest send_request; - EchoResponse recv_response; + } + + if (max_message_size != 0) { + builder.SetMaxMessageSize(max_message_size); + } + + // Create a separate cq for each potential handler. + for (int i = 0; i < 5; i++) { + cqs_.push_back(builder.AddCompletionQueue(false)); + } + server_ = builder.BuildAndStart(); + + // If there is a generic callback service, this setup is only successful if + // we have an iomgr that can run in the background or are inprocess + return !callback_generic_service || grpc_iomgr_run_in_background() || + inproc_; + } + + void TearDown() override { + if (server_) { + server_->Shutdown(); + } + void* ignored_tag; + bool ignored_ok; + for (auto it = cqs_.begin(); it != cqs_.end(); ++it) { + (*it)->Shutdown(); + while ((*it)->Next(&ignored_tag, &ignored_ok)) + ; + } + } + + void ResetStub() { + std::shared_ptr<Channel> channel = + inproc_ ? server_->InProcessChannel(ChannelArguments()) + : grpc::CreateChannel(server_address_.str(), + InsecureChannelCredentials()); + stub_ = grpc::testing::EchoTestService::NewStub(channel); + } + + // Test all rpc methods. + void TestAllMethods() { + SendEcho(); + SendSimpleClientStreaming(); + SendSimpleServerStreaming(); + SendBidiStreaming(); + } + + void SendEcho() { + EchoRequest send_request; + EchoResponse recv_response; + ClientContext cli_ctx; + cli_ctx.set_wait_for_ready(true); + send_request.set_message("Hello"); + Status recv_status = stub_->Echo(&cli_ctx, send_request, &recv_response); + EXPECT_EQ(send_request.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + } + + void SendEchoToDupService() { + std::shared_ptr<Channel> channel = grpc::CreateChannel( + server_address_.str(), InsecureChannelCredentials()); + auto stub = grpc::testing::duplicate::EchoTestService::NewStub(channel); + EchoRequest send_request; + EchoResponse recv_response; + ClientContext cli_ctx; + cli_ctx.set_wait_for_ready(true); + send_request.set_message("Hello"); + Status recv_status = stub->Echo(&cli_ctx, send_request, &recv_response); + EXPECT_EQ(send_request.message() + "_dup", recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + } + + void SendSimpleClientStreaming() { + EchoRequest send_request; + EchoResponse recv_response; TString expected_message; - ClientContext cli_ctx; - cli_ctx.set_wait_for_ready(true); - send_request.set_message("Hello"); - auto stream = stub_->RequestStream(&cli_ctx, &recv_response); - for (int i = 0; i < 5; i++) { - EXPECT_TRUE(stream->Write(send_request)); - expected_message.append(send_request.message()); - } - stream->WritesDone(); - Status recv_status = stream->Finish(); - EXPECT_EQ(expected_message, recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - } - - void SendSimpleServerStreaming() { - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_wait_for_ready(true); - request.set_message("hello"); - - auto stream = stub_->ResponseStream(&context, request); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message() + "0"); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message() + "1"); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message() + "2"); - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); - } - - void SendSimpleServerStreamingToDupService() { - std::shared_ptr<Channel> channel = grpc::CreateChannel( - server_address_.str(), InsecureChannelCredentials()); - auto stub = grpc::testing::duplicate::EchoTestService::NewStub(channel); - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_wait_for_ready(true); - request.set_message("hello"); - - auto stream = stub->ResponseStream(&context, request); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message() + "0_dup"); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message() + "1_dup"); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message() + "2_dup"); - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); - } - - void SendBidiStreaming() { - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_wait_for_ready(true); + ClientContext cli_ctx; + cli_ctx.set_wait_for_ready(true); + send_request.set_message("Hello"); + auto stream = stub_->RequestStream(&cli_ctx, &recv_response); + for (int i = 0; i < 5; i++) { + EXPECT_TRUE(stream->Write(send_request)); + expected_message.append(send_request.message()); + } + stream->WritesDone(); + Status recv_status = stream->Finish(); + EXPECT_EQ(expected_message, recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + } + + void SendSimpleServerStreaming() { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_wait_for_ready(true); + request.set_message("hello"); + + auto stream = stub_->ResponseStream(&context, request); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "0"); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "1"); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "2"); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); + } + + void SendSimpleServerStreamingToDupService() { + std::shared_ptr<Channel> channel = grpc::CreateChannel( + server_address_.str(), InsecureChannelCredentials()); + auto stub = grpc::testing::duplicate::EchoTestService::NewStub(channel); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_wait_for_ready(true); + request.set_message("hello"); + + auto stream = stub->ResponseStream(&context, request); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "0_dup"); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "1_dup"); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message() + "2_dup"); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); + } + + void SendBidiStreaming() { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_wait_for_ready(true); TString msg("hello"); - - auto stream = stub_->BidiStream(&context); - - request.set_message(msg + "0"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - request.set_message(msg + "1"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - request.set_message(msg + "2"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - stream->WritesDone(); - EXPECT_FALSE(stream->Read(&response)); - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); - } - - grpc::testing::UnimplementedEchoService::Service unimplemented_service_; - std::vector<std::unique_ptr<ServerCompletionQueue>> cqs_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - std::ostringstream server_address_; - bool inproc_; -}; - -TEST_F(HybridEnd2endTest, AsyncEcho) { - typedef EchoTestService::WithAsyncMethod_Echo<TestServiceImpl> SType; - SType service; - SetUpServer(&service, nullptr, nullptr, nullptr); - ResetStub(); - std::thread echo_handler_thread(HandleEcho<SType>, &service, cqs_[0].get(), - false); - TestAllMethods(); - echo_handler_thread.join(); -} - -TEST_F(HybridEnd2endTest, RawEcho) { - typedef EchoTestService::WithRawMethod_Echo<TestServiceImpl> SType; - SType service; - SetUpServer(&service, nullptr, nullptr, nullptr); - ResetStub(); - std::thread echo_handler_thread(HandleRawEcho<SType>, &service, cqs_[0].get(), - false); - TestAllMethods(); - echo_handler_thread.join(); -} - -TEST_F(HybridEnd2endTest, RawRequestStream) { - typedef EchoTestService::WithRawMethod_RequestStream<TestServiceImpl> SType; - SType service; - SetUpServer(&service, nullptr, nullptr, nullptr); - ResetStub(); - std::thread request_stream_handler_thread(HandleRawClientStreaming<SType>, - &service, cqs_[0].get()); - TestAllMethods(); - request_stream_handler_thread.join(); -} - -TEST_F(HybridEnd2endTest, AsyncEchoRawRequestStream) { - typedef EchoTestService::WithRawMethod_RequestStream< - EchoTestService::WithAsyncMethod_Echo<TestServiceImpl>> - SType; - SType service; - SetUpServer(&service, nullptr, nullptr, nullptr); - ResetStub(); - std::thread echo_handler_thread(HandleEcho<SType>, &service, cqs_[0].get(), - false); - std::thread request_stream_handler_thread(HandleRawClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - request_stream_handler_thread.join(); - echo_handler_thread.join(); -} - -TEST_F(HybridEnd2endTest, GenericEchoRawRequestStream) { - typedef EchoTestService::WithRawMethod_RequestStream< - EchoTestService::WithGenericMethod_Echo<TestServiceImpl>> - SType; - SType service; - AsyncGenericService generic_service; - SetUpServer(&service, nullptr, &generic_service, nullptr); - ResetStub(); - std::thread generic_handler_thread(HandleGenericCall, &generic_service, - cqs_[0].get()); - std::thread request_stream_handler_thread(HandleRawClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - generic_handler_thread.join(); - request_stream_handler_thread.join(); -} - -TEST_F(HybridEnd2endTest, AsyncEchoRequestStream) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithAsyncMethod_Echo<TestServiceImpl>> - SType; - SType service; - SetUpServer(&service, nullptr, nullptr, nullptr); - ResetStub(); - std::thread echo_handler_thread(HandleEcho<SType>, &service, cqs_[0].get(), - false); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - echo_handler_thread.join(); - request_stream_handler_thread.join(); -} - -TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> - SType; - SType service; - SetUpServer(&service, nullptr, nullptr, nullptr); - ResetStub(); - std::thread response_stream_handler_thread(HandleServerStreaming<SType>, - &service, cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - response_stream_handler_thread.join(); - request_stream_handler_thread.join(); -} - -// Add a second service with one sync method. -TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream_SyncDupService) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> - SType; - SType service; - TestServiceImplDupPkg dup_service; - SetUpServer(&service, &dup_service, nullptr, nullptr); - ResetStub(); - std::thread response_stream_handler_thread(HandleServerStreaming<SType>, - &service, cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - SendEchoToDupService(); - response_stream_handler_thread.join(); - request_stream_handler_thread.join(); -} - -// Add a second service with one sync streamed unary method. -class StreamedUnaryDupPkg - : public duplicate::EchoTestService::WithStreamedUnaryMethod_Echo< - TestServiceImplDupPkg> { - public: - Status StreamedEcho( - ServerContext* /*context*/, - ServerUnaryStreamer<EchoRequest, EchoResponse>* stream) override { - EchoRequest req; - EchoResponse resp; - uint32_t next_msg_sz; - stream->NextMessageSize(&next_msg_sz); - gpr_log(GPR_INFO, "Streamed Unary Next Message Size is %u", next_msg_sz); - GPR_ASSERT(stream->Read(&req)); - resp.set_message(req.message() + "_dup"); - GPR_ASSERT(stream->Write(resp)); - return Status::OK; - } -}; - -TEST_F(HybridEnd2endTest, - AsyncRequestStreamResponseStream_SyncStreamedUnaryDupService) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> - SType; - SType service; - StreamedUnaryDupPkg dup_service; - SetUpServer(&service, &dup_service, nullptr, nullptr, 8192); - ResetStub(); - std::thread response_stream_handler_thread(HandleServerStreaming<SType>, - &service, cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - SendEchoToDupService(); - response_stream_handler_thread.join(); - request_stream_handler_thread.join(); -} - -// Add a second service that is fully Streamed Unary -class FullyStreamedUnaryDupPkg - : public duplicate::EchoTestService::StreamedUnaryService { - public: - Status StreamedEcho( - ServerContext* /*context*/, - ServerUnaryStreamer<EchoRequest, EchoResponse>* stream) override { - EchoRequest req; - EchoResponse resp; - uint32_t next_msg_sz; - stream->NextMessageSize(&next_msg_sz); - gpr_log(GPR_INFO, "Streamed Unary Next Message Size is %u", next_msg_sz); - GPR_ASSERT(stream->Read(&req)); - resp.set_message(req.message() + "_dup"); - GPR_ASSERT(stream->Write(resp)); - return Status::OK; - } -}; - -TEST_F(HybridEnd2endTest, - AsyncRequestStreamResponseStream_SyncFullyStreamedUnaryDupService) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> - SType; - SType service; - FullyStreamedUnaryDupPkg dup_service; - SetUpServer(&service, &dup_service, nullptr, nullptr, 8192); - ResetStub(); - std::thread response_stream_handler_thread(HandleServerStreaming<SType>, - &service, cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - SendEchoToDupService(); - response_stream_handler_thread.join(); - request_stream_handler_thread.join(); -} - -// Add a second service with one sync split server streaming method. -class SplitResponseStreamDupPkg - : public duplicate::EchoTestService:: - WithSplitStreamingMethod_ResponseStream<TestServiceImplDupPkg> { - public: - Status StreamedResponseStream( - ServerContext* /*context*/, - ServerSplitStreamer<EchoRequest, EchoResponse>* stream) override { - EchoRequest req; - EchoResponse resp; - uint32_t next_msg_sz; - stream->NextMessageSize(&next_msg_sz); - gpr_log(GPR_INFO, "Split Streamed Next Message Size is %u", next_msg_sz); - GPR_ASSERT(stream->Read(&req)); - for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) { + + auto stream = stub_->BidiStream(&context); + + request.set_message(msg + "0"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "1"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "2"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + stream->WritesDone(); + EXPECT_FALSE(stream->Read(&response)); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); + } + + grpc::testing::UnimplementedEchoService::Service unimplemented_service_; + std::vector<std::unique_ptr<ServerCompletionQueue>> cqs_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + std::ostringstream server_address_; + bool inproc_; +}; + +TEST_F(HybridEnd2endTest, AsyncEcho) { + typedef EchoTestService::WithAsyncMethod_Echo<TestServiceImpl> SType; + SType service; + SetUpServer(&service, nullptr, nullptr, nullptr); + ResetStub(); + std::thread echo_handler_thread(HandleEcho<SType>, &service, cqs_[0].get(), + false); + TestAllMethods(); + echo_handler_thread.join(); +} + +TEST_F(HybridEnd2endTest, RawEcho) { + typedef EchoTestService::WithRawMethod_Echo<TestServiceImpl> SType; + SType service; + SetUpServer(&service, nullptr, nullptr, nullptr); + ResetStub(); + std::thread echo_handler_thread(HandleRawEcho<SType>, &service, cqs_[0].get(), + false); + TestAllMethods(); + echo_handler_thread.join(); +} + +TEST_F(HybridEnd2endTest, RawRequestStream) { + typedef EchoTestService::WithRawMethod_RequestStream<TestServiceImpl> SType; + SType service; + SetUpServer(&service, nullptr, nullptr, nullptr); + ResetStub(); + std::thread request_stream_handler_thread(HandleRawClientStreaming<SType>, + &service, cqs_[0].get()); + TestAllMethods(); + request_stream_handler_thread.join(); +} + +TEST_F(HybridEnd2endTest, AsyncEchoRawRequestStream) { + typedef EchoTestService::WithRawMethod_RequestStream< + EchoTestService::WithAsyncMethod_Echo<TestServiceImpl>> + SType; + SType service; + SetUpServer(&service, nullptr, nullptr, nullptr); + ResetStub(); + std::thread echo_handler_thread(HandleEcho<SType>, &service, cqs_[0].get(), + false); + std::thread request_stream_handler_thread(HandleRawClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + request_stream_handler_thread.join(); + echo_handler_thread.join(); +} + +TEST_F(HybridEnd2endTest, GenericEchoRawRequestStream) { + typedef EchoTestService::WithRawMethod_RequestStream< + EchoTestService::WithGenericMethod_Echo<TestServiceImpl>> + SType; + SType service; + AsyncGenericService generic_service; + SetUpServer(&service, nullptr, &generic_service, nullptr); + ResetStub(); + std::thread generic_handler_thread(HandleGenericCall, &generic_service, + cqs_[0].get()); + std::thread request_stream_handler_thread(HandleRawClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + generic_handler_thread.join(); + request_stream_handler_thread.join(); +} + +TEST_F(HybridEnd2endTest, AsyncEchoRequestStream) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_Echo<TestServiceImpl>> + SType; + SType service; + SetUpServer(&service, nullptr, nullptr, nullptr); + ResetStub(); + std::thread echo_handler_thread(HandleEcho<SType>, &service, cqs_[0].get(), + false); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + echo_handler_thread.join(); + request_stream_handler_thread.join(); +} + +TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> + SType; + SType service; + SetUpServer(&service, nullptr, nullptr, nullptr); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming<SType>, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service with one sync method. +TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream_SyncDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> + SType; + SType service; + TestServiceImplDupPkg dup_service; + SetUpServer(&service, &dup_service, nullptr, nullptr); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming<SType>, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + SendEchoToDupService(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service with one sync streamed unary method. +class StreamedUnaryDupPkg + : public duplicate::EchoTestService::WithStreamedUnaryMethod_Echo< + TestServiceImplDupPkg> { + public: + Status StreamedEcho( + ServerContext* /*context*/, + ServerUnaryStreamer<EchoRequest, EchoResponse>* stream) override { + EchoRequest req; + EchoResponse resp; + uint32_t next_msg_sz; + stream->NextMessageSize(&next_msg_sz); + gpr_log(GPR_INFO, "Streamed Unary Next Message Size is %u", next_msg_sz); + GPR_ASSERT(stream->Read(&req)); + resp.set_message(req.message() + "_dup"); + GPR_ASSERT(stream->Write(resp)); + return Status::OK; + } +}; + +TEST_F(HybridEnd2endTest, + AsyncRequestStreamResponseStream_SyncStreamedUnaryDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> + SType; + SType service; + StreamedUnaryDupPkg dup_service; + SetUpServer(&service, &dup_service, nullptr, nullptr, 8192); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming<SType>, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + SendEchoToDupService(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service that is fully Streamed Unary +class FullyStreamedUnaryDupPkg + : public duplicate::EchoTestService::StreamedUnaryService { + public: + Status StreamedEcho( + ServerContext* /*context*/, + ServerUnaryStreamer<EchoRequest, EchoResponse>* stream) override { + EchoRequest req; + EchoResponse resp; + uint32_t next_msg_sz; + stream->NextMessageSize(&next_msg_sz); + gpr_log(GPR_INFO, "Streamed Unary Next Message Size is %u", next_msg_sz); + GPR_ASSERT(stream->Read(&req)); + resp.set_message(req.message() + "_dup"); + GPR_ASSERT(stream->Write(resp)); + return Status::OK; + } +}; + +TEST_F(HybridEnd2endTest, + AsyncRequestStreamResponseStream_SyncFullyStreamedUnaryDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> + SType; + SType service; + FullyStreamedUnaryDupPkg dup_service; + SetUpServer(&service, &dup_service, nullptr, nullptr, 8192); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming<SType>, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + SendEchoToDupService(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service with one sync split server streaming method. +class SplitResponseStreamDupPkg + : public duplicate::EchoTestService:: + WithSplitStreamingMethod_ResponseStream<TestServiceImplDupPkg> { + public: + Status StreamedResponseStream( + ServerContext* /*context*/, + ServerSplitStreamer<EchoRequest, EchoResponse>* stream) override { + EchoRequest req; + EchoResponse resp; + uint32_t next_msg_sz; + stream->NextMessageSize(&next_msg_sz); + gpr_log(GPR_INFO, "Split Streamed Next Message Size is %u", next_msg_sz); + GPR_ASSERT(stream->Read(&req)); + for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) { resp.set_message(req.message() + ToString(i) + "_dup"); - GPR_ASSERT(stream->Write(resp)); - } - return Status::OK; - } -}; - -TEST_F(HybridEnd2endTest, - AsyncRequestStreamResponseStream_SyncSplitStreamedDupService) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> - SType; - SType service; - SplitResponseStreamDupPkg dup_service; - SetUpServer(&service, &dup_service, nullptr, nullptr, 8192); - ResetStub(); - std::thread response_stream_handler_thread(HandleServerStreaming<SType>, - &service, cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - SendSimpleServerStreamingToDupService(); - response_stream_handler_thread.join(); - request_stream_handler_thread.join(); -} - -// Add a second service that is fully split server streamed -class FullySplitStreamedDupPkg - : public duplicate::EchoTestService::SplitStreamedService { - public: - Status StreamedResponseStream( - ServerContext* /*context*/, - ServerSplitStreamer<EchoRequest, EchoResponse>* stream) override { - EchoRequest req; - EchoResponse resp; - uint32_t next_msg_sz; - stream->NextMessageSize(&next_msg_sz); - gpr_log(GPR_INFO, "Split Streamed Next Message Size is %u", next_msg_sz); - GPR_ASSERT(stream->Read(&req)); - for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) { + GPR_ASSERT(stream->Write(resp)); + } + return Status::OK; + } +}; + +TEST_F(HybridEnd2endTest, + AsyncRequestStreamResponseStream_SyncSplitStreamedDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> + SType; + SType service; + SplitResponseStreamDupPkg dup_service; + SetUpServer(&service, &dup_service, nullptr, nullptr, 8192); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming<SType>, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + SendSimpleServerStreamingToDupService(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service that is fully split server streamed +class FullySplitStreamedDupPkg + : public duplicate::EchoTestService::SplitStreamedService { + public: + Status StreamedResponseStream( + ServerContext* /*context*/, + ServerSplitStreamer<EchoRequest, EchoResponse>* stream) override { + EchoRequest req; + EchoResponse resp; + uint32_t next_msg_sz; + stream->NextMessageSize(&next_msg_sz); + gpr_log(GPR_INFO, "Split Streamed Next Message Size is %u", next_msg_sz); + GPR_ASSERT(stream->Read(&req)); + for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) { resp.set_message(req.message() + ToString(i) + "_dup"); - GPR_ASSERT(stream->Write(resp)); - } - return Status::OK; - } -}; - -TEST_F(HybridEnd2endTest, - AsyncRequestStreamResponseStream_FullySplitStreamedDupService) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> - SType; - SType service; - FullySplitStreamedDupPkg dup_service; - SetUpServer(&service, &dup_service, nullptr, nullptr, 8192); - ResetStub(); - std::thread response_stream_handler_thread(HandleServerStreaming<SType>, - &service, cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - SendSimpleServerStreamingToDupService(); - response_stream_handler_thread.join(); - request_stream_handler_thread.join(); -} - -// Add a second service that is fully server streamed -class FullyStreamedDupPkg : public duplicate::EchoTestService::StreamedService { - public: - Status StreamedEcho( - ServerContext* /*context*/, - ServerUnaryStreamer<EchoRequest, EchoResponse>* stream) override { - EchoRequest req; - EchoResponse resp; - uint32_t next_msg_sz; - stream->NextMessageSize(&next_msg_sz); - gpr_log(GPR_INFO, "Streamed Unary Next Message Size is %u", next_msg_sz); - GPR_ASSERT(stream->Read(&req)); - resp.set_message(req.message() + "_dup"); - GPR_ASSERT(stream->Write(resp)); - return Status::OK; - } - Status StreamedResponseStream( - ServerContext* /*context*/, - ServerSplitStreamer<EchoRequest, EchoResponse>* stream) override { - EchoRequest req; - EchoResponse resp; - uint32_t next_msg_sz; - stream->NextMessageSize(&next_msg_sz); - gpr_log(GPR_INFO, "Split Streamed Next Message Size is %u", next_msg_sz); - GPR_ASSERT(stream->Read(&req)); - for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) { + GPR_ASSERT(stream->Write(resp)); + } + return Status::OK; + } +}; + +TEST_F(HybridEnd2endTest, + AsyncRequestStreamResponseStream_FullySplitStreamedDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> + SType; + SType service; + FullySplitStreamedDupPkg dup_service; + SetUpServer(&service, &dup_service, nullptr, nullptr, 8192); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming<SType>, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + SendSimpleServerStreamingToDupService(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service that is fully server streamed +class FullyStreamedDupPkg : public duplicate::EchoTestService::StreamedService { + public: + Status StreamedEcho( + ServerContext* /*context*/, + ServerUnaryStreamer<EchoRequest, EchoResponse>* stream) override { + EchoRequest req; + EchoResponse resp; + uint32_t next_msg_sz; + stream->NextMessageSize(&next_msg_sz); + gpr_log(GPR_INFO, "Streamed Unary Next Message Size is %u", next_msg_sz); + GPR_ASSERT(stream->Read(&req)); + resp.set_message(req.message() + "_dup"); + GPR_ASSERT(stream->Write(resp)); + return Status::OK; + } + Status StreamedResponseStream( + ServerContext* /*context*/, + ServerSplitStreamer<EchoRequest, EchoResponse>* stream) override { + EchoRequest req; + EchoResponse resp; + uint32_t next_msg_sz; + stream->NextMessageSize(&next_msg_sz); + gpr_log(GPR_INFO, "Split Streamed Next Message Size is %u", next_msg_sz); + GPR_ASSERT(stream->Read(&req)); + for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) { resp.set_message(req.message() + ToString(i) + "_dup"); - GPR_ASSERT(stream->Write(resp)); - } - return Status::OK; - } -}; - -TEST_F(HybridEnd2endTest, - AsyncRequestStreamResponseStream_FullyStreamedDupService) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> - SType; - SType service; - FullyStreamedDupPkg dup_service; - SetUpServer(&service, &dup_service, nullptr, nullptr, 8192); - ResetStub(); - std::thread response_stream_handler_thread(HandleServerStreaming<SType>, - &service, cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - SendEchoToDupService(); - SendSimpleServerStreamingToDupService(); - response_stream_handler_thread.join(); - request_stream_handler_thread.join(); -} - -// Add a second service with one async method. -TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream_AsyncDupService) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> - SType; - SType service; - duplicate::EchoTestService::AsyncService dup_service; - SetUpServer(&service, &dup_service, nullptr, nullptr); - ResetStub(); - std::thread response_stream_handler_thread(HandleServerStreaming<SType>, - &service, cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - std::thread echo_handler_thread( - HandleEcho<duplicate::EchoTestService::AsyncService>, &dup_service, - cqs_[2].get(), true); - TestAllMethods(); - SendEchoToDupService(); - response_stream_handler_thread.join(); - request_stream_handler_thread.join(); - echo_handler_thread.join(); -} - -TEST_F(HybridEnd2endTest, GenericEcho) { - EchoTestService::WithGenericMethod_Echo<TestServiceImpl> service; - AsyncGenericService generic_service; - SetUpServer(&service, nullptr, &generic_service, nullptr); - ResetStub(); - std::thread generic_handler_thread(HandleGenericCall, &generic_service, - cqs_[0].get()); - TestAllMethods(); - generic_handler_thread.join(); -} - -TEST_P(HybridEnd2endTest, CallbackGenericEcho) { - EchoTestService::WithGenericMethod_Echo<TestServiceImpl> service; + GPR_ASSERT(stream->Write(resp)); + } + return Status::OK; + } +}; + +TEST_F(HybridEnd2endTest, + AsyncRequestStreamResponseStream_FullyStreamedDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> + SType; + SType service; + FullyStreamedDupPkg dup_service; + SetUpServer(&service, &dup_service, nullptr, nullptr, 8192); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming<SType>, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + SendEchoToDupService(); + SendSimpleServerStreamingToDupService(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service with one async method. +TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream_AsyncDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>> + SType; + SType service; + duplicate::EchoTestService::AsyncService dup_service; + SetUpServer(&service, &dup_service, nullptr, nullptr); + ResetStub(); + std::thread response_stream_handler_thread(HandleServerStreaming<SType>, + &service, cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + std::thread echo_handler_thread( + HandleEcho<duplicate::EchoTestService::AsyncService>, &dup_service, + cqs_[2].get(), true); + TestAllMethods(); + SendEchoToDupService(); + response_stream_handler_thread.join(); + request_stream_handler_thread.join(); + echo_handler_thread.join(); +} + +TEST_F(HybridEnd2endTest, GenericEcho) { + EchoTestService::WithGenericMethod_Echo<TestServiceImpl> service; + AsyncGenericService generic_service; + SetUpServer(&service, nullptr, &generic_service, nullptr); + ResetStub(); + std::thread generic_handler_thread(HandleGenericCall, &generic_service, + cqs_[0].get()); + TestAllMethods(); + generic_handler_thread.join(); +} + +TEST_P(HybridEnd2endTest, CallbackGenericEcho) { + EchoTestService::WithGenericMethod_Echo<TestServiceImpl> service; class GenericEchoService : public CallbackGenericService { - private: + private: ServerGenericBidiReactor* CreateReactor( GenericCallbackServerContext* context) override { - EXPECT_EQ(context->method(), "/grpc.testing.EchoTestService/Echo"); + EXPECT_EQ(context->method(), "/grpc.testing.EchoTestService/Echo"); gpr_log(GPR_DEBUG, "Constructor of generic service %d", static_cast<int>(context->deadline().time_since_epoch().count())); - + class Reactor : public ServerGenericBidiReactor { - public: - Reactor() { StartRead(&request_); } - - private: - void OnDone() override { delete this; } - void OnReadDone(bool ok) override { - if (!ok) { - EXPECT_EQ(reads_complete_, 1); - } else { - EXPECT_EQ(reads_complete_++, 0); - response_ = request_; - StartWrite(&response_); - StartRead(&request_); - } - } - void OnWriteDone(bool ok) override { - Finish(ok ? Status::OK - : Status(StatusCode::UNKNOWN, "Unexpected failure")); - } - ByteBuffer request_; - ByteBuffer response_; - std::atomic_int reads_complete_{0}; - }; - return new Reactor; - } - } generic_service; - - if (!SetUpServer(&service, nullptr, nullptr, &generic_service)) { - return; - } - ResetStub(); - TestAllMethods(); -} - -TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithGenericMethod_Echo<TestServiceImpl>> - SType; - SType service; - AsyncGenericService generic_service; - SetUpServer(&service, nullptr, &generic_service, nullptr); - ResetStub(); - std::thread generic_handler_thread(HandleGenericCall, &generic_service, - cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - generic_handler_thread.join(); - request_stream_handler_thread.join(); -} - -// Add a second service with one sync method. -TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream_SyncDupService) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithGenericMethod_Echo<TestServiceImpl>> - SType; - SType service; - AsyncGenericService generic_service; - TestServiceImplDupPkg dup_service; - SetUpServer(&service, &dup_service, &generic_service, nullptr); - ResetStub(); - std::thread generic_handler_thread(HandleGenericCall, &generic_service, - cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - TestAllMethods(); - SendEchoToDupService(); - generic_handler_thread.join(); - request_stream_handler_thread.join(); -} - -// Add a second service with one async method. -TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream_AsyncDupService) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithGenericMethod_Echo<TestServiceImpl>> - SType; - SType service; - AsyncGenericService generic_service; - duplicate::EchoTestService::AsyncService dup_service; - SetUpServer(&service, &dup_service, &generic_service, nullptr); - ResetStub(); - std::thread generic_handler_thread(HandleGenericCall, &generic_service, - cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - std::thread echo_handler_thread( - HandleEcho<duplicate::EchoTestService::AsyncService>, &dup_service, - cqs_[2].get(), true); - TestAllMethods(); - SendEchoToDupService(); - generic_handler_thread.join(); - request_stream_handler_thread.join(); - echo_handler_thread.join(); -} - -TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStreamResponseStream) { - typedef EchoTestService::WithAsyncMethod_RequestStream< - EchoTestService::WithGenericMethod_Echo< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>> - SType; - SType service; - AsyncGenericService generic_service; - SetUpServer(&service, nullptr, &generic_service, nullptr); - ResetStub(); - std::thread generic_handler_thread(HandleGenericCall, &generic_service, - cqs_[0].get()); - std::thread request_stream_handler_thread(HandleClientStreaming<SType>, - &service, cqs_[1].get()); - std::thread response_stream_handler_thread(HandleServerStreaming<SType>, - &service, cqs_[2].get()); - TestAllMethods(); - generic_handler_thread.join(); - request_stream_handler_thread.join(); - response_stream_handler_thread.join(); -} - -TEST_F(HybridEnd2endTest, GenericEchoRequestStreamAsyncResponseStream) { - typedef EchoTestService::WithGenericMethod_RequestStream< - EchoTestService::WithGenericMethod_Echo< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>> - SType; - SType service; - AsyncGenericService generic_service; - SetUpServer(&service, nullptr, &generic_service, nullptr); - ResetStub(); - std::thread generic_handler_thread(HandleGenericCall, &generic_service, - cqs_[0].get()); - std::thread generic_handler_thread2(HandleGenericCall, &generic_service, - cqs_[1].get()); - std::thread response_stream_handler_thread(HandleServerStreaming<SType>, - &service, cqs_[2].get()); - TestAllMethods(); - generic_handler_thread.join(); - generic_handler_thread2.join(); - response_stream_handler_thread.join(); -} - -// If WithGenericMethod is called and no generic service is registered, the -// server will fail to build. -TEST_F(HybridEnd2endTest, GenericMethodWithoutGenericService) { - EchoTestService::WithGenericMethod_RequestStream< - EchoTestService::WithGenericMethod_Echo< - EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>> - service; - SetUpServer(&service, nullptr, nullptr, nullptr); - EXPECT_EQ(nullptr, server_.get()); -} - -INSTANTIATE_TEST_SUITE_P(HybridEnd2endTest, HybridEnd2endTest, - ::testing::Bool()); - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + public: + Reactor() { StartRead(&request_); } + + private: + void OnDone() override { delete this; } + void OnReadDone(bool ok) override { + if (!ok) { + EXPECT_EQ(reads_complete_, 1); + } else { + EXPECT_EQ(reads_complete_++, 0); + response_ = request_; + StartWrite(&response_); + StartRead(&request_); + } + } + void OnWriteDone(bool ok) override { + Finish(ok ? Status::OK + : Status(StatusCode::UNKNOWN, "Unexpected failure")); + } + ByteBuffer request_; + ByteBuffer response_; + std::atomic_int reads_complete_{0}; + }; + return new Reactor; + } + } generic_service; + + if (!SetUpServer(&service, nullptr, nullptr, &generic_service)) { + return; + } + ResetStub(); + TestAllMethods(); +} + +TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithGenericMethod_Echo<TestServiceImpl>> + SType; + SType service; + AsyncGenericService generic_service; + SetUpServer(&service, nullptr, &generic_service, nullptr); + ResetStub(); + std::thread generic_handler_thread(HandleGenericCall, &generic_service, + cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + generic_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service with one sync method. +TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream_SyncDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithGenericMethod_Echo<TestServiceImpl>> + SType; + SType service; + AsyncGenericService generic_service; + TestServiceImplDupPkg dup_service; + SetUpServer(&service, &dup_service, &generic_service, nullptr); + ResetStub(); + std::thread generic_handler_thread(HandleGenericCall, &generic_service, + cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + TestAllMethods(); + SendEchoToDupService(); + generic_handler_thread.join(); + request_stream_handler_thread.join(); +} + +// Add a second service with one async method. +TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream_AsyncDupService) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithGenericMethod_Echo<TestServiceImpl>> + SType; + SType service; + AsyncGenericService generic_service; + duplicate::EchoTestService::AsyncService dup_service; + SetUpServer(&service, &dup_service, &generic_service, nullptr); + ResetStub(); + std::thread generic_handler_thread(HandleGenericCall, &generic_service, + cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + std::thread echo_handler_thread( + HandleEcho<duplicate::EchoTestService::AsyncService>, &dup_service, + cqs_[2].get(), true); + TestAllMethods(); + SendEchoToDupService(); + generic_handler_thread.join(); + request_stream_handler_thread.join(); + echo_handler_thread.join(); +} + +TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStreamResponseStream) { + typedef EchoTestService::WithAsyncMethod_RequestStream< + EchoTestService::WithGenericMethod_Echo< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>> + SType; + SType service; + AsyncGenericService generic_service; + SetUpServer(&service, nullptr, &generic_service, nullptr); + ResetStub(); + std::thread generic_handler_thread(HandleGenericCall, &generic_service, + cqs_[0].get()); + std::thread request_stream_handler_thread(HandleClientStreaming<SType>, + &service, cqs_[1].get()); + std::thread response_stream_handler_thread(HandleServerStreaming<SType>, + &service, cqs_[2].get()); + TestAllMethods(); + generic_handler_thread.join(); + request_stream_handler_thread.join(); + response_stream_handler_thread.join(); +} + +TEST_F(HybridEnd2endTest, GenericEchoRequestStreamAsyncResponseStream) { + typedef EchoTestService::WithGenericMethod_RequestStream< + EchoTestService::WithGenericMethod_Echo< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>> + SType; + SType service; + AsyncGenericService generic_service; + SetUpServer(&service, nullptr, &generic_service, nullptr); + ResetStub(); + std::thread generic_handler_thread(HandleGenericCall, &generic_service, + cqs_[0].get()); + std::thread generic_handler_thread2(HandleGenericCall, &generic_service, + cqs_[1].get()); + std::thread response_stream_handler_thread(HandleServerStreaming<SType>, + &service, cqs_[2].get()); + TestAllMethods(); + generic_handler_thread.join(); + generic_handler_thread2.join(); + response_stream_handler_thread.join(); +} + +// If WithGenericMethod is called and no generic service is registered, the +// server will fail to build. +TEST_F(HybridEnd2endTest, GenericMethodWithoutGenericService) { + EchoTestService::WithGenericMethod_RequestStream< + EchoTestService::WithGenericMethod_Echo< + EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>> + service; + SetUpServer(&service, nullptr, nullptr, nullptr); + EXPECT_EQ(nullptr, server_.get()); +} + +INSTANTIATE_TEST_SUITE_P(HybridEnd2endTest, HybridEnd2endTest, + ::testing::Bool()); + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/interceptors_util.cc b/contrib/libs/grpc/test/cpp/end2end/interceptors_util.cc index 2d9bcfcbec..ff88953651 100644 --- a/contrib/libs/grpc/test/cpp/end2end/interceptors_util.cc +++ b/contrib/libs/grpc/test/cpp/end2end/interceptors_util.cc @@ -1,102 +1,102 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ - -#include "test/cpp/end2end/interceptors_util.h" +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ + +#include "test/cpp/end2end/interceptors_util.h" #include <util/string/cast.h> - -namespace grpc { -namespace testing { - -std::atomic<int> DummyInterceptor::num_times_run_; -std::atomic<int> DummyInterceptor::num_times_run_reverse_; -std::atomic<int> DummyInterceptor::num_times_cancel_; - -void MakeCall(const std::shared_ptr<Channel>& channel) { - auto stub = grpc::testing::EchoTestService::NewStub(channel); - ClientContext ctx; - EchoRequest req; - req.mutable_param()->set_echo_metadata(true); - ctx.AddMetadata("testkey", "testvalue"); - req.set_message("Hello"); - EchoResponse resp; - Status s = stub->Echo(&ctx, req, &resp); - EXPECT_EQ(s.ok(), true); - EXPECT_EQ(resp.message(), "Hello"); -} - -void MakeClientStreamingCall(const std::shared_ptr<Channel>& channel) { - auto stub = grpc::testing::EchoTestService::NewStub(channel); - ClientContext ctx; - EchoRequest req; - req.mutable_param()->set_echo_metadata(true); - ctx.AddMetadata("testkey", "testvalue"); - req.set_message("Hello"); - EchoResponse resp; + +namespace grpc { +namespace testing { + +std::atomic<int> DummyInterceptor::num_times_run_; +std::atomic<int> DummyInterceptor::num_times_run_reverse_; +std::atomic<int> DummyInterceptor::num_times_cancel_; + +void MakeCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + req.mutable_param()->set_echo_metadata(true); + ctx.AddMetadata("testkey", "testvalue"); + req.set_message("Hello"); + EchoResponse resp; + Status s = stub->Echo(&ctx, req, &resp); + EXPECT_EQ(s.ok(), true); + EXPECT_EQ(resp.message(), "Hello"); +} + +void MakeClientStreamingCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + req.mutable_param()->set_echo_metadata(true); + ctx.AddMetadata("testkey", "testvalue"); + req.set_message("Hello"); + EchoResponse resp; string expected_resp = ""; - auto writer = stub->RequestStream(&ctx, &resp); - for (int i = 0; i < kNumStreamingMessages; i++) { - writer->Write(req); - expected_resp += "Hello"; - } - writer->WritesDone(); - Status s = writer->Finish(); - EXPECT_EQ(s.ok(), true); - EXPECT_EQ(resp.message(), expected_resp); -} - -void MakeServerStreamingCall(const std::shared_ptr<Channel>& channel) { - auto stub = grpc::testing::EchoTestService::NewStub(channel); - ClientContext ctx; - EchoRequest req; - req.mutable_param()->set_echo_metadata(true); - ctx.AddMetadata("testkey", "testvalue"); - req.set_message("Hello"); - EchoResponse resp; - auto reader = stub->ResponseStream(&ctx, req); - int count = 0; - while (reader->Read(&resp)) { - EXPECT_EQ(resp.message(), "Hello"); - count++; - } - ASSERT_EQ(count, kNumStreamingMessages); - Status s = reader->Finish(); - EXPECT_EQ(s.ok(), true); -} - -void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) { - auto stub = grpc::testing::EchoTestService::NewStub(channel); - ClientContext ctx; - EchoRequest req; - EchoResponse resp; - ctx.AddMetadata("testkey", "testvalue"); + auto writer = stub->RequestStream(&ctx, &resp); + for (int i = 0; i < kNumStreamingMessages; i++) { + writer->Write(req); + expected_resp += "Hello"; + } + writer->WritesDone(); + Status s = writer->Finish(); + EXPECT_EQ(s.ok(), true); + EXPECT_EQ(resp.message(), expected_resp); +} + +void MakeServerStreamingCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; req.mutable_param()->set_echo_metadata(true); - auto stream = stub->BidiStream(&ctx); - for (auto i = 0; i < kNumStreamingMessages; i++) { + ctx.AddMetadata("testkey", "testvalue"); + req.set_message("Hello"); + EchoResponse resp; + auto reader = stub->ResponseStream(&ctx, req); + int count = 0; + while (reader->Read(&resp)) { + EXPECT_EQ(resp.message(), "Hello"); + count++; + } + ASSERT_EQ(count, kNumStreamingMessages); + Status s = reader->Finish(); + EXPECT_EQ(s.ok(), true); +} + +void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + EchoResponse resp; + ctx.AddMetadata("testkey", "testvalue"); + req.mutable_param()->set_echo_metadata(true); + auto stream = stub->BidiStream(&ctx); + for (auto i = 0; i < kNumStreamingMessages; i++) { req.set_message(TString("Hello") + ::ToString(i)); - stream->Write(req); - stream->Read(&resp); - EXPECT_EQ(req.message(), resp.message()); - } - ASSERT_TRUE(stream->WritesDone()); - Status s = stream->Finish(); - EXPECT_EQ(s.ok(), true); -} - + stream->Write(req); + stream->Read(&resp); + EXPECT_EQ(req.message(), resp.message()); + } + ASSERT_TRUE(stream->WritesDone()); + Status s = stream->Finish(); + EXPECT_EQ(s.ok(), true); +} + void MakeAsyncCQCall(const std::shared_ptr<Channel>& channel) { auto stub = grpc::testing::EchoTestService::NewStub(channel); CompletionQueue cq; @@ -152,63 +152,63 @@ void MakeAsyncCQBidiStreamingCall(const std::shared_ptr<Channel>& /*channel*/) { // TODO(yashykt) : Fill this out } -void MakeCallbackCall(const std::shared_ptr<Channel>& channel) { - auto stub = grpc::testing::EchoTestService::NewStub(channel); - ClientContext ctx; - EchoRequest req; - std::mutex mu; - std::condition_variable cv; - bool done = false; - req.mutable_param()->set_echo_metadata(true); - ctx.AddMetadata("testkey", "testvalue"); - req.set_message("Hello"); - EchoResponse resp; - stub->experimental_async()->Echo(&ctx, &req, &resp, - [&resp, &mu, &done, &cv](Status s) { - EXPECT_EQ(s.ok(), true); - EXPECT_EQ(resp.message(), "Hello"); - std::lock_guard<std::mutex> l(mu); - done = true; - cv.notify_one(); - }); - std::unique_lock<std::mutex> l(mu); - while (!done) { - cv.wait(l); - } -} - -bool CheckMetadata(const std::multimap<grpc::string_ref, grpc::string_ref>& map, - const string& key, const string& value) { - for (const auto& pair : map) { - if (pair.first.starts_with(key) && pair.second.starts_with(value)) { - return true; - } - } - return false; -} - +void MakeCallbackCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + std::mutex mu; + std::condition_variable cv; + bool done = false; + req.mutable_param()->set_echo_metadata(true); + ctx.AddMetadata("testkey", "testvalue"); + req.set_message("Hello"); + EchoResponse resp; + stub->experimental_async()->Echo(&ctx, &req, &resp, + [&resp, &mu, &done, &cv](Status s) { + EXPECT_EQ(s.ok(), true); + EXPECT_EQ(resp.message(), "Hello"); + std::lock_guard<std::mutex> l(mu); + done = true; + cv.notify_one(); + }); + std::unique_lock<std::mutex> l(mu); + while (!done) { + cv.wait(l); + } +} + +bool CheckMetadata(const std::multimap<grpc::string_ref, grpc::string_ref>& map, + const string& key, const string& value) { + for (const auto& pair : map) { + if (pair.first.starts_with(key) && pair.second.starts_with(value)) { + return true; + } + } + return false; +} + bool CheckMetadata(const std::multimap<TString, TString>& map, - const string& key, const string& value) { - for (const auto& pair : map) { - if (pair.first == key.c_str() && pair.second == value.c_str()) { - return true; - } - } - return false; -} - -std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> -CreateDummyClientInterceptors() { - std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - creators; - // Add 20 dummy interceptors before hijacking interceptor - creators.reserve(20); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - return creators; -} - -} // namespace testing -} // namespace grpc + const string& key, const string& value) { + for (const auto& pair : map) { + if (pair.first == key.c_str() && pair.second == value.c_str()) { + return true; + } + } + return false; +} + +std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> +CreateDummyClientInterceptors() { + std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + creators; + // Add 20 dummy interceptors before hijacking interceptor + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + return creators; +} + +} // namespace testing +} // namespace grpc diff --git a/contrib/libs/grpc/test/cpp/end2end/interceptors_util.h b/contrib/libs/grpc/test/cpp/end2end/interceptors_util.h index 832a3870c8..c95170bbbc 100644 --- a/contrib/libs/grpc/test/cpp/end2end/interceptors_util.h +++ b/contrib/libs/grpc/test/cpp/end2end/interceptors_util.h @@ -1,107 +1,107 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ - -#include <condition_variable> - -#include <grpcpp/channel.h> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/cpp/util/string_ref_helper.h" - -#include <gtest/gtest.h> - -namespace grpc { -namespace testing { -/* This interceptor does nothing. Just keeps a global count on the number of - * times it was invoked. */ -class DummyInterceptor : public experimental::Interceptor { - public: - DummyInterceptor() {} - - virtual void Intercept(experimental::InterceptorBatchMethods* methods) { - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { - num_times_run_++; - } else if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints:: - POST_RECV_INITIAL_METADATA)) { - num_times_run_reverse_++; - } else if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_CANCEL)) { - num_times_cancel_++; - } - methods->Proceed(); - } - - static void Reset() { - num_times_run_.store(0); - num_times_run_reverse_.store(0); - num_times_cancel_.store(0); - } - - static int GetNumTimesRun() { - EXPECT_EQ(num_times_run_.load(), num_times_run_reverse_.load()); - return num_times_run_.load(); - } - - static int GetNumTimesCancel() { return num_times_cancel_.load(); } - - private: - static std::atomic<int> num_times_run_; - static std::atomic<int> num_times_run_reverse_; - static std::atomic<int> num_times_cancel_; -}; - -class DummyInterceptorFactory - : public experimental::ClientInterceptorFactoryInterface, - public experimental::ServerInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateClientInterceptor( - experimental::ClientRpcInfo* /*info*/) override { - return new DummyInterceptor(); - } - - virtual experimental::Interceptor* CreateServerInterceptor( - experimental::ServerRpcInfo* /*info*/) override { - return new DummyInterceptor(); - } -}; - -/* This interceptor factory returns nullptr on interceptor creation */ -class NullInterceptorFactory - : public experimental::ClientInterceptorFactoryInterface, - public experimental::ServerInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateClientInterceptor( - experimental::ClientRpcInfo* /*info*/) override { - return nullptr; - } - - virtual experimental::Interceptor* CreateServerInterceptor( - experimental::ServerRpcInfo* /*info*/) override { - return nullptr; - } -}; - -class EchoTestServiceStreamingImpl : public EchoTestService::Service { - public: - ~EchoTestServiceStreamingImpl() override {} - +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ + +#include <condition_variable> + +#include <grpcpp/channel.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/cpp/util/string_ref_helper.h" + +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { +/* This interceptor does nothing. Just keeps a global count on the number of + * times it was invoked. */ +class DummyInterceptor : public experimental::Interceptor { + public: + DummyInterceptor() {} + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + num_times_run_++; + } else if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints:: + POST_RECV_INITIAL_METADATA)) { + num_times_run_reverse_++; + } else if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CANCEL)) { + num_times_cancel_++; + } + methods->Proceed(); + } + + static void Reset() { + num_times_run_.store(0); + num_times_run_reverse_.store(0); + num_times_cancel_.store(0); + } + + static int GetNumTimesRun() { + EXPECT_EQ(num_times_run_.load(), num_times_run_reverse_.load()); + return num_times_run_.load(); + } + + static int GetNumTimesCancel() { return num_times_cancel_.load(); } + + private: + static std::atomic<int> num_times_run_; + static std::atomic<int> num_times_run_reverse_; + static std::atomic<int> num_times_cancel_; +}; + +class DummyInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface, + public experimental::ServerInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* /*info*/) override { + return new DummyInterceptor(); + } + + virtual experimental::Interceptor* CreateServerInterceptor( + experimental::ServerRpcInfo* /*info*/) override { + return new DummyInterceptor(); + } +}; + +/* This interceptor factory returns nullptr on interceptor creation */ +class NullInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface, + public experimental::ServerInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* /*info*/) override { + return nullptr; + } + + virtual experimental::Interceptor* CreateServerInterceptor( + experimental::ServerRpcInfo* /*info*/) override { + return nullptr; + } +}; + +class EchoTestServiceStreamingImpl : public EchoTestService::Service { + public: + ~EchoTestServiceStreamingImpl() override {} + Status Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) override { auto client_metadata = context->client_metadata(); @@ -112,66 +112,66 @@ class EchoTestServiceStreamingImpl : public EchoTestService::Service { return Status::OK; } - Status BidiStream( - ServerContext* context, - grpc::ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { - EchoRequest req; - EchoResponse resp; - auto client_metadata = context->client_metadata(); - for (const auto& pair : client_metadata) { - context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second)); - } - - while (stream->Read(&req)) { - resp.set_message(req.message()); - EXPECT_TRUE(stream->Write(resp, grpc::WriteOptions())); - } - return Status::OK; - } - - Status RequestStream(ServerContext* context, - ServerReader<EchoRequest>* reader, - EchoResponse* resp) override { - auto client_metadata = context->client_metadata(); - for (const auto& pair : client_metadata) { - context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second)); - } - - EchoRequest req; + Status BidiStream( + ServerContext* context, + grpc::ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { + EchoRequest req; + EchoResponse resp; + auto client_metadata = context->client_metadata(); + for (const auto& pair : client_metadata) { + context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second)); + } + + while (stream->Read(&req)) { + resp.set_message(req.message()); + EXPECT_TRUE(stream->Write(resp, grpc::WriteOptions())); + } + return Status::OK; + } + + Status RequestStream(ServerContext* context, + ServerReader<EchoRequest>* reader, + EchoResponse* resp) override { + auto client_metadata = context->client_metadata(); + for (const auto& pair : client_metadata) { + context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second)); + } + + EchoRequest req; string response_str = ""; - while (reader->Read(&req)) { - response_str += req.message(); - } - resp->set_message(response_str); - return Status::OK; - } - - Status ResponseStream(ServerContext* context, const EchoRequest* req, - ServerWriter<EchoResponse>* writer) override { - auto client_metadata = context->client_metadata(); - for (const auto& pair : client_metadata) { - context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second)); - } - - EchoResponse resp; - resp.set_message(req->message()); - for (int i = 0; i < 10; i++) { - EXPECT_TRUE(writer->Write(resp)); - } - return Status::OK; - } -}; - -constexpr int kNumStreamingMessages = 10; - -void MakeCall(const std::shared_ptr<Channel>& channel); - -void MakeClientStreamingCall(const std::shared_ptr<Channel>& channel); - -void MakeServerStreamingCall(const std::shared_ptr<Channel>& channel); - -void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel); - + while (reader->Read(&req)) { + response_str += req.message(); + } + resp->set_message(response_str); + return Status::OK; + } + + Status ResponseStream(ServerContext* context, const EchoRequest* req, + ServerWriter<EchoResponse>* writer) override { + auto client_metadata = context->client_metadata(); + for (const auto& pair : client_metadata) { + context->AddTrailingMetadata(ToString(pair.first), ToString(pair.second)); + } + + EchoResponse resp; + resp.set_message(req->message()); + for (int i = 0; i < 10; i++) { + EXPECT_TRUE(writer->Write(resp)); + } + return Status::OK; + } +}; + +constexpr int kNumStreamingMessages = 10; + +void MakeCall(const std::shared_ptr<Channel>& channel); + +void MakeClientStreamingCall(const std::shared_ptr<Channel>& channel); + +void MakeServerStreamingCall(const std::shared_ptr<Channel>& channel); + +void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel); + void MakeAsyncCQCall(const std::shared_ptr<Channel>& channel); void MakeAsyncCQClientStreamingCall(const std::shared_ptr<Channel>& channel); @@ -180,138 +180,138 @@ void MakeAsyncCQServerStreamingCall(const std::shared_ptr<Channel>& channel); void MakeAsyncCQBidiStreamingCall(const std::shared_ptr<Channel>& channel); -void MakeCallbackCall(const std::shared_ptr<Channel>& channel); - -bool CheckMetadata(const std::multimap<grpc::string_ref, grpc::string_ref>& map, - const string& key, const string& value); - +void MakeCallbackCall(const std::shared_ptr<Channel>& channel); + +bool CheckMetadata(const std::multimap<grpc::string_ref, grpc::string_ref>& map, + const string& key, const string& value); + bool CheckMetadata(const std::multimap<TString, TString>& map, - const string& key, const string& value); - -std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> -CreateDummyClientInterceptors(); - -inline void* tag(int i) { return (void*)static_cast<intptr_t>(i); } -inline int detag(void* p) { - return static_cast<int>(reinterpret_cast<intptr_t>(p)); -} - -class Verifier { - public: - Verifier() : lambda_run_(false) {} - // Expect sets the expected ok value for a specific tag - Verifier& Expect(int i, bool expect_ok) { - return ExpectUnless(i, expect_ok, false); - } - // ExpectUnless sets the expected ok value for a specific tag - // unless the tag was already marked seen (as a result of ExpectMaybe) - Verifier& ExpectUnless(int i, bool expect_ok, bool seen) { - if (!seen) { - expectations_[tag(i)] = expect_ok; - } - return *this; - } - // ExpectMaybe sets the expected ok value for a specific tag, but does not - // require it to appear - // If it does, sets *seen to true - Verifier& ExpectMaybe(int i, bool expect_ok, bool* seen) { - if (!*seen) { - maybe_expectations_[tag(i)] = MaybeExpect{expect_ok, seen}; - } - return *this; - } - - // Next waits for 1 async tag to complete, checks its - // expectations, and returns the tag - int Next(CompletionQueue* cq, bool ignore_ok) { - bool ok; - void* got_tag; - EXPECT_TRUE(cq->Next(&got_tag, &ok)); - GotTag(got_tag, ok, ignore_ok); - return detag(got_tag); - } - - template <typename T> - CompletionQueue::NextStatus DoOnceThenAsyncNext( - CompletionQueue* cq, void** got_tag, bool* ok, T deadline, - std::function<void(void)> lambda) { - if (lambda_run_) { - return cq->AsyncNext(got_tag, ok, deadline); - } else { - lambda_run_ = true; - return cq->DoThenAsyncNext(lambda, got_tag, ok, deadline); - } - } - - // Verify keeps calling Next until all currently set - // expected tags are complete - void Verify(CompletionQueue* cq) { Verify(cq, false); } - - // This version of Verify allows optionally ignoring the - // outcome of the expectation - void Verify(CompletionQueue* cq, bool ignore_ok) { - GPR_ASSERT(!expectations_.empty() || !maybe_expectations_.empty()); - while (!expectations_.empty()) { - Next(cq, ignore_ok); - } - } - - // This version of Verify stops after a certain deadline, and uses the - // DoThenAsyncNext API - // to call the lambda - void Verify(CompletionQueue* cq, - std::chrono::system_clock::time_point deadline, - const std::function<void(void)>& lambda) { - if (expectations_.empty()) { - bool ok; - void* got_tag; - EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), - CompletionQueue::TIMEOUT); - } else { - while (!expectations_.empty()) { - bool ok; - void* got_tag; - EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), - CompletionQueue::GOT_EVENT); - GotTag(got_tag, ok, false); - } - } - } - - private: - void GotTag(void* got_tag, bool ok, bool ignore_ok) { - auto it = expectations_.find(got_tag); - if (it != expectations_.end()) { - if (!ignore_ok) { - EXPECT_EQ(it->second, ok); - } - expectations_.erase(it); - } else { - auto it2 = maybe_expectations_.find(got_tag); - if (it2 != maybe_expectations_.end()) { - if (it2->second.seen != nullptr) { - EXPECT_FALSE(*it2->second.seen); - *it2->second.seen = true; - } - if (!ignore_ok) { - EXPECT_EQ(it2->second.ok, ok); - } - } else { - gpr_log(GPR_ERROR, "Unexpected tag: %p", got_tag); - abort(); - } - } - } - - struct MaybeExpect { - bool ok; - bool* seen; - }; - - std::map<void*, bool> expectations_; - std::map<void*, MaybeExpect> maybe_expectations_; - bool lambda_run_; -}; - -} // namespace testing -} // namespace grpc + const string& key, const string& value); + +std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> +CreateDummyClientInterceptors(); + +inline void* tag(int i) { return (void*)static_cast<intptr_t>(i); } +inline int detag(void* p) { + return static_cast<int>(reinterpret_cast<intptr_t>(p)); +} + +class Verifier { + public: + Verifier() : lambda_run_(false) {} + // Expect sets the expected ok value for a specific tag + Verifier& Expect(int i, bool expect_ok) { + return ExpectUnless(i, expect_ok, false); + } + // ExpectUnless sets the expected ok value for a specific tag + // unless the tag was already marked seen (as a result of ExpectMaybe) + Verifier& ExpectUnless(int i, bool expect_ok, bool seen) { + if (!seen) { + expectations_[tag(i)] = expect_ok; + } + return *this; + } + // ExpectMaybe sets the expected ok value for a specific tag, but does not + // require it to appear + // If it does, sets *seen to true + Verifier& ExpectMaybe(int i, bool expect_ok, bool* seen) { + if (!*seen) { + maybe_expectations_[tag(i)] = MaybeExpect{expect_ok, seen}; + } + return *this; + } + + // Next waits for 1 async tag to complete, checks its + // expectations, and returns the tag + int Next(CompletionQueue* cq, bool ignore_ok) { + bool ok; + void* got_tag; + EXPECT_TRUE(cq->Next(&got_tag, &ok)); + GotTag(got_tag, ok, ignore_ok); + return detag(got_tag); + } + + template <typename T> + CompletionQueue::NextStatus DoOnceThenAsyncNext( + CompletionQueue* cq, void** got_tag, bool* ok, T deadline, + std::function<void(void)> lambda) { + if (lambda_run_) { + return cq->AsyncNext(got_tag, ok, deadline); + } else { + lambda_run_ = true; + return cq->DoThenAsyncNext(lambda, got_tag, ok, deadline); + } + } + + // Verify keeps calling Next until all currently set + // expected tags are complete + void Verify(CompletionQueue* cq) { Verify(cq, false); } + + // This version of Verify allows optionally ignoring the + // outcome of the expectation + void Verify(CompletionQueue* cq, bool ignore_ok) { + GPR_ASSERT(!expectations_.empty() || !maybe_expectations_.empty()); + while (!expectations_.empty()) { + Next(cq, ignore_ok); + } + } + + // This version of Verify stops after a certain deadline, and uses the + // DoThenAsyncNext API + // to call the lambda + void Verify(CompletionQueue* cq, + std::chrono::system_clock::time_point deadline, + const std::function<void(void)>& lambda) { + if (expectations_.empty()) { + bool ok; + void* got_tag; + EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), + CompletionQueue::TIMEOUT); + } else { + while (!expectations_.empty()) { + bool ok; + void* got_tag; + EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), + CompletionQueue::GOT_EVENT); + GotTag(got_tag, ok, false); + } + } + } + + private: + void GotTag(void* got_tag, bool ok, bool ignore_ok) { + auto it = expectations_.find(got_tag); + if (it != expectations_.end()) { + if (!ignore_ok) { + EXPECT_EQ(it->second, ok); + } + expectations_.erase(it); + } else { + auto it2 = maybe_expectations_.find(got_tag); + if (it2 != maybe_expectations_.end()) { + if (it2->second.seen != nullptr) { + EXPECT_FALSE(*it2->second.seen); + *it2->second.seen = true; + } + if (!ignore_ok) { + EXPECT_EQ(it2->second.ok, ok); + } + } else { + gpr_log(GPR_ERROR, "Unexpected tag: %p", got_tag); + abort(); + } + } + } + + struct MaybeExpect { + bool ok; + bool* seen; + }; + + std::map<void*, bool> expectations_; + std::map<void*, MaybeExpect> maybe_expectations_; + bool lambda_run_; +}; + +} // namespace testing +} // namespace grpc diff --git a/contrib/libs/grpc/test/cpp/end2end/mock_test.cc b/contrib/libs/grpc/test/cpp/end2end/mock_test.cc index 623fac0020..a3d61c4e98 100644 --- a/contrib/libs/grpc/test/cpp/end2end/mock_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/mock_test.cc @@ -1,47 +1,47 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <climits> - -#include <grpc/grpc.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> -#include <grpcpp/test/default_reactor_test_peer.h> - -#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "src/proto/grpc/testing/echo_mock.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#include <grpcpp/test/mock_stream.h> - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <iostream> - +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <climits> + +#include <grpc/grpc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> +#include <grpcpp/test/default_reactor_test_peer.h> + +#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "src/proto/grpc/testing/echo_mock.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#include <grpcpp/test/mock_stream.h> + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <iostream> + using grpc::testing::DefaultReactorTestPeer; using grpc::testing::EchoRequest; using grpc::testing::EchoResponse; @@ -50,385 +50,385 @@ using grpc::testing::MockClientReaderWriter; using std::vector; using std::chrono::system_clock; using ::testing::_; -using ::testing::AtLeast; -using ::testing::DoAll; -using ::testing::Invoke; -using ::testing::Return; -using ::testing::SaveArg; -using ::testing::SetArgPointee; -using ::testing::WithArg; - -namespace grpc { -namespace testing { - -namespace { -class FakeClient { - public: - explicit FakeClient(EchoTestService::StubInterface* stub) : stub_(stub) {} - - void DoEcho() { - ClientContext context; - EchoRequest request; - EchoResponse response; - request.set_message("hello world"); - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(request.message(), response.message()); - EXPECT_TRUE(s.ok()); - } - - void DoRequestStream() { - EchoRequest request; - EchoResponse response; - - ClientContext context; +using ::testing::AtLeast; +using ::testing::DoAll; +using ::testing::Invoke; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArgPointee; +using ::testing::WithArg; + +namespace grpc { +namespace testing { + +namespace { +class FakeClient { + public: + explicit FakeClient(EchoTestService::StubInterface* stub) : stub_(stub) {} + + void DoEcho() { + ClientContext context; + EchoRequest request; + EchoResponse response; + request.set_message("hello world"); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.ok()); + } + + void DoRequestStream() { + EchoRequest request; + EchoResponse response; + + ClientContext context; TString msg("hello"); TString exp(msg); - - std::unique_ptr<ClientWriterInterface<EchoRequest>> cstream = - stub_->RequestStream(&context, &response); - - request.set_message(msg); - EXPECT_TRUE(cstream->Write(request)); - - msg = ", world"; - request.set_message(msg); - exp.append(msg); - EXPECT_TRUE(cstream->Write(request)); - - cstream->WritesDone(); - Status s = cstream->Finish(); - - EXPECT_EQ(exp, response.message()); - EXPECT_TRUE(s.ok()); - } - - void DoResponseStream() { - EchoRequest request; - EchoResponse response; - request.set_message("hello world"); - - ClientContext context; - std::unique_ptr<ClientReaderInterface<EchoResponse>> cstream = - stub_->ResponseStream(&context, request); - + + std::unique_ptr<ClientWriterInterface<EchoRequest>> cstream = + stub_->RequestStream(&context, &response); + + request.set_message(msg); + EXPECT_TRUE(cstream->Write(request)); + + msg = ", world"; + request.set_message(msg); + exp.append(msg); + EXPECT_TRUE(cstream->Write(request)); + + cstream->WritesDone(); + Status s = cstream->Finish(); + + EXPECT_EQ(exp, response.message()); + EXPECT_TRUE(s.ok()); + } + + void DoResponseStream() { + EchoRequest request; + EchoResponse response; + request.set_message("hello world"); + + ClientContext context; + std::unique_ptr<ClientReaderInterface<EchoResponse>> cstream = + stub_->ResponseStream(&context, request); + TString exp = ""; - EXPECT_TRUE(cstream->Read(&response)); - exp.append(response.message() + " "); - - EXPECT_TRUE(cstream->Read(&response)); - exp.append(response.message()); - - EXPECT_FALSE(cstream->Read(&response)); - EXPECT_EQ(request.message(), exp); - - Status s = cstream->Finish(); - EXPECT_TRUE(s.ok()); - } - - void DoBidiStream() { - EchoRequest request; - EchoResponse response; - ClientContext context; + EXPECT_TRUE(cstream->Read(&response)); + exp.append(response.message() + " "); + + EXPECT_TRUE(cstream->Read(&response)); + exp.append(response.message()); + + EXPECT_FALSE(cstream->Read(&response)); + EXPECT_EQ(request.message(), exp); + + Status s = cstream->Finish(); + EXPECT_TRUE(s.ok()); + } + + void DoBidiStream() { + EchoRequest request; + EchoResponse response; + ClientContext context; TString msg("hello"); - - std::unique_ptr<ClientReaderWriterInterface<EchoRequest, EchoResponse>> - stream = stub_->BidiStream(&context); - - request.set_message(msg + "0"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - request.set_message(msg + "1"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - request.set_message(msg + "2"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(response.message(), request.message()); - - stream->WritesDone(); - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - EXPECT_TRUE(s.ok()); - } - - void ResetStub(EchoTestService::StubInterface* stub) { stub_ = stub; } - - private: - EchoTestService::StubInterface* stub_; -}; - -class CallbackTestServiceImpl - : public EchoTestService::ExperimentalCallbackService { - public: - experimental::ServerUnaryReactor* Echo( - experimental::CallbackServerContext* context, const EchoRequest* request, - EchoResponse* response) override { - // Make the mock service explicitly treat empty input messages as invalid - // arguments so that we can test various results of status. In general, a - // mocked service should just use the original service methods, but we are - // adding this variance in Status return value just to improve coverage in - // this test. - auto* reactor = context->DefaultReactor(); - if (request->message().length() > 0) { - response->set_message(request->message()); - reactor->Finish(Status::OK); - } else { - reactor->Finish(Status(StatusCode::INVALID_ARGUMENT, "Invalid request")); - } - return reactor; - } -}; - -class MockCallbackTest : public ::testing::Test { - protected: - CallbackTestServiceImpl service_; - ServerContext context_; -}; - -TEST_F(MockCallbackTest, MockedCallSucceedsWithWait) { - experimental::CallbackServerContext ctx; - EchoRequest req; - EchoResponse resp; - grpc::internal::Mutex mu; - grpc::internal::CondVar cv; - grpc::Status status; - bool status_set = false; - DefaultReactorTestPeer peer(&ctx, [&](::grpc::Status s) { - grpc::internal::MutexLock l(&mu); - status_set = true; - status = std::move(s); - cv.Signal(); - }); - - req.set_message("mock 1"); - auto* reactor = service_.Echo(&ctx, &req, &resp); - cv.WaitUntil(&mu, [&] { - grpc::internal::MutexLock l(&mu); - return status_set; - }); - EXPECT_EQ(reactor, peer.reactor()); - EXPECT_TRUE(peer.test_status_set()); - EXPECT_TRUE(peer.test_status().ok()); - EXPECT_TRUE(status_set); - EXPECT_TRUE(status.ok()); - EXPECT_EQ(req.message(), resp.message()); -} - -TEST_F(MockCallbackTest, MockedCallSucceeds) { - experimental::CallbackServerContext ctx; - EchoRequest req; - EchoResponse resp; - DefaultReactorTestPeer peer(&ctx); - - req.set_message("ha ha, consider yourself mocked."); - auto* reactor = service_.Echo(&ctx, &req, &resp); - EXPECT_EQ(reactor, peer.reactor()); - EXPECT_TRUE(peer.test_status_set()); - EXPECT_TRUE(peer.test_status().ok()); -} - -TEST_F(MockCallbackTest, MockedCallFails) { - experimental::CallbackServerContext ctx; - EchoRequest req; - EchoResponse resp; - DefaultReactorTestPeer peer(&ctx); - - auto* reactor = service_.Echo(&ctx, &req, &resp); - EXPECT_EQ(reactor, peer.reactor()); - EXPECT_TRUE(peer.test_status_set()); - EXPECT_EQ(peer.test_status().error_code(), StatusCode::INVALID_ARGUMENT); -} - -class TestServiceImpl : public EchoTestService::Service { - public: - Status Echo(ServerContext* /*context*/, const EchoRequest* request, - EchoResponse* response) override { - response->set_message(request->message()); - return Status::OK; - } - - Status RequestStream(ServerContext* /*context*/, - ServerReader<EchoRequest>* reader, - EchoResponse* response) override { - EchoRequest request; + + std::unique_ptr<ClientReaderWriterInterface<EchoRequest, EchoResponse>> + stream = stub_->BidiStream(&context); + + request.set_message(msg + "0"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "1"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + request.set_message(msg + "2"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(response.message(), request.message()); + + stream->WritesDone(); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + EXPECT_TRUE(s.ok()); + } + + void ResetStub(EchoTestService::StubInterface* stub) { stub_ = stub; } + + private: + EchoTestService::StubInterface* stub_; +}; + +class CallbackTestServiceImpl + : public EchoTestService::ExperimentalCallbackService { + public: + experimental::ServerUnaryReactor* Echo( + experimental::CallbackServerContext* context, const EchoRequest* request, + EchoResponse* response) override { + // Make the mock service explicitly treat empty input messages as invalid + // arguments so that we can test various results of status. In general, a + // mocked service should just use the original service methods, but we are + // adding this variance in Status return value just to improve coverage in + // this test. + auto* reactor = context->DefaultReactor(); + if (request->message().length() > 0) { + response->set_message(request->message()); + reactor->Finish(Status::OK); + } else { + reactor->Finish(Status(StatusCode::INVALID_ARGUMENT, "Invalid request")); + } + return reactor; + } +}; + +class MockCallbackTest : public ::testing::Test { + protected: + CallbackTestServiceImpl service_; + ServerContext context_; +}; + +TEST_F(MockCallbackTest, MockedCallSucceedsWithWait) { + experimental::CallbackServerContext ctx; + EchoRequest req; + EchoResponse resp; + grpc::internal::Mutex mu; + grpc::internal::CondVar cv; + grpc::Status status; + bool status_set = false; + DefaultReactorTestPeer peer(&ctx, [&](::grpc::Status s) { + grpc::internal::MutexLock l(&mu); + status_set = true; + status = std::move(s); + cv.Signal(); + }); + + req.set_message("mock 1"); + auto* reactor = service_.Echo(&ctx, &req, &resp); + cv.WaitUntil(&mu, [&] { + grpc::internal::MutexLock l(&mu); + return status_set; + }); + EXPECT_EQ(reactor, peer.reactor()); + EXPECT_TRUE(peer.test_status_set()); + EXPECT_TRUE(peer.test_status().ok()); + EXPECT_TRUE(status_set); + EXPECT_TRUE(status.ok()); + EXPECT_EQ(req.message(), resp.message()); +} + +TEST_F(MockCallbackTest, MockedCallSucceeds) { + experimental::CallbackServerContext ctx; + EchoRequest req; + EchoResponse resp; + DefaultReactorTestPeer peer(&ctx); + + req.set_message("ha ha, consider yourself mocked."); + auto* reactor = service_.Echo(&ctx, &req, &resp); + EXPECT_EQ(reactor, peer.reactor()); + EXPECT_TRUE(peer.test_status_set()); + EXPECT_TRUE(peer.test_status().ok()); +} + +TEST_F(MockCallbackTest, MockedCallFails) { + experimental::CallbackServerContext ctx; + EchoRequest req; + EchoResponse resp; + DefaultReactorTestPeer peer(&ctx); + + auto* reactor = service_.Echo(&ctx, &req, &resp); + EXPECT_EQ(reactor, peer.reactor()); + EXPECT_TRUE(peer.test_status_set()); + EXPECT_EQ(peer.test_status().error_code(), StatusCode::INVALID_ARGUMENT); +} + +class TestServiceImpl : public EchoTestService::Service { + public: + Status Echo(ServerContext* /*context*/, const EchoRequest* request, + EchoResponse* response) override { + response->set_message(request->message()); + return Status::OK; + } + + Status RequestStream(ServerContext* /*context*/, + ServerReader<EchoRequest>* reader, + EchoResponse* response) override { + EchoRequest request; TString resp(""); - while (reader->Read(&request)) { - gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); - resp.append(request.message()); - } - response->set_message(resp); - return Status::OK; - } - - Status ResponseStream(ServerContext* /*context*/, const EchoRequest* request, - ServerWriter<EchoResponse>* writer) override { - EchoResponse response; + while (reader->Read(&request)) { + gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); + resp.append(request.message()); + } + response->set_message(resp); + return Status::OK; + } + + Status ResponseStream(ServerContext* /*context*/, const EchoRequest* request, + ServerWriter<EchoResponse>* writer) override { + EchoResponse response; vector<TString> tokens = split(request->message()); for (const TString& token : tokens) { - response.set_message(token); - writer->Write(response); - } - return Status::OK; - } - - Status BidiStream( - ServerContext* /*context*/, - ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { - EchoRequest request; - EchoResponse response; - while (stream->Read(&request)) { - gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); - response.set_message(request.message()); - stream->Write(response); - } - return Status::OK; - } - - private: + response.set_message(token); + writer->Write(response); + } + return Status::OK; + } + + Status BidiStream( + ServerContext* /*context*/, + ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { + EchoRequest request; + EchoResponse response; + while (stream->Read(&request)) { + gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); + response.set_message(request.message()); + stream->Write(response); + } + return Status::OK; + } + + private: const vector<TString> split(const TString& input) { TString buff(""); vector<TString> result; - - for (auto n : input) { - if (n != ' ') { - buff += n; - continue; - } - if (buff == "") continue; - result.push_back(buff); - buff = ""; - } - if (buff != "") result.push_back(buff); - - return result; - } -}; - -class MockTest : public ::testing::Test { - protected: - MockTest() {} - - void SetUp() override { - int port = grpc_pick_unused_port_or_die(); - server_address_ << "localhost:" << port; - // Setup server - ServerBuilder builder; - builder.AddListeningPort(server_address_.str(), - InsecureServerCredentials()); - builder.RegisterService(&service_); - server_ = builder.BuildAndStart(); - } - - void TearDown() override { server_->Shutdown(); } - - void ResetStub() { - std::shared_ptr<Channel> channel = grpc::CreateChannel( - server_address_.str(), InsecureChannelCredentials()); - stub_ = grpc::testing::EchoTestService::NewStub(channel); - } - - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - std::ostringstream server_address_; - TestServiceImpl service_; -}; - -// Do one real rpc and one mocked one -TEST_F(MockTest, SimpleRpc) { - ResetStub(); - FakeClient client(stub_.get()); - client.DoEcho(); - MockEchoTestServiceStub stub; - EchoResponse resp; - resp.set_message("hello world"); - EXPECT_CALL(stub, Echo(_, _, _)) - .Times(AtLeast(1)) - .WillOnce(DoAll(SetArgPointee<2>(resp), Return(Status::OK))); - client.ResetStub(&stub); - client.DoEcho(); -} - -TEST_F(MockTest, ClientStream) { - ResetStub(); - FakeClient client(stub_.get()); - client.DoRequestStream(); - - MockEchoTestServiceStub stub; - auto w = new MockClientWriter<EchoRequest>(); - EchoResponse resp; - resp.set_message("hello, world"); - - EXPECT_CALL(*w, Write(_, _)).Times(2).WillRepeatedly(Return(true)); - EXPECT_CALL(*w, WritesDone()); - EXPECT_CALL(*w, Finish()).WillOnce(Return(Status::OK)); - - EXPECT_CALL(stub, RequestStreamRaw(_, _)) - .WillOnce(DoAll(SetArgPointee<1>(resp), Return(w))); - client.ResetStub(&stub); - client.DoRequestStream(); -} - -TEST_F(MockTest, ServerStream) { - ResetStub(); - FakeClient client(stub_.get()); - client.DoResponseStream(); - - MockEchoTestServiceStub stub; - auto r = new MockClientReader<EchoResponse>(); - EchoResponse resp1; - resp1.set_message("hello"); - EchoResponse resp2; - resp2.set_message("world"); - - EXPECT_CALL(*r, Read(_)) - .WillOnce(DoAll(SetArgPointee<0>(resp1), Return(true))) - .WillOnce(DoAll(SetArgPointee<0>(resp2), Return(true))) - .WillOnce(Return(false)); - EXPECT_CALL(*r, Finish()).WillOnce(Return(Status::OK)); - - EXPECT_CALL(stub, ResponseStreamRaw(_, _)).WillOnce(Return(r)); - - client.ResetStub(&stub); - client.DoResponseStream(); -} - -ACTION_P(copy, msg) { arg0->set_message(msg->message()); } - -TEST_F(MockTest, BidiStream) { - ResetStub(); - FakeClient client(stub_.get()); - client.DoBidiStream(); - MockEchoTestServiceStub stub; - auto rw = new MockClientReaderWriter<EchoRequest, EchoResponse>(); - EchoRequest msg; - - EXPECT_CALL(*rw, Write(_, _)) - .Times(3) - .WillRepeatedly(DoAll(SaveArg<0>(&msg), Return(true))); - EXPECT_CALL(*rw, Read(_)) - .WillOnce(DoAll(WithArg<0>(copy(&msg)), Return(true))) - .WillOnce(DoAll(WithArg<0>(copy(&msg)), Return(true))) - .WillOnce(DoAll(WithArg<0>(copy(&msg)), Return(true))) - .WillOnce(Return(false)); - EXPECT_CALL(*rw, WritesDone()); - EXPECT_CALL(*rw, Finish()).WillOnce(Return(Status::OK)); - - EXPECT_CALL(stub, BidiStreamRaw(_)).WillOnce(Return(rw)); - client.ResetStub(&stub); - client.DoBidiStream(); -} - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + + for (auto n : input) { + if (n != ' ') { + buff += n; + continue; + } + if (buff == "") continue; + result.push_back(buff); + buff = ""; + } + if (buff != "") result.push_back(buff); + + return result; + } +}; + +class MockTest : public ::testing::Test { + protected: + MockTest() {} + + void SetUp() override { + int port = grpc_pick_unused_port_or_die(); + server_address_ << "localhost:" << port; + // Setup server + ServerBuilder builder; + builder.AddListeningPort(server_address_.str(), + InsecureServerCredentials()); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + + void TearDown() override { server_->Shutdown(); } + + void ResetStub() { + std::shared_ptr<Channel> channel = grpc::CreateChannel( + server_address_.str(), InsecureChannelCredentials()); + stub_ = grpc::testing::EchoTestService::NewStub(channel); + } + + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + std::ostringstream server_address_; + TestServiceImpl service_; +}; + +// Do one real rpc and one mocked one +TEST_F(MockTest, SimpleRpc) { + ResetStub(); + FakeClient client(stub_.get()); + client.DoEcho(); + MockEchoTestServiceStub stub; + EchoResponse resp; + resp.set_message("hello world"); + EXPECT_CALL(stub, Echo(_, _, _)) + .Times(AtLeast(1)) + .WillOnce(DoAll(SetArgPointee<2>(resp), Return(Status::OK))); + client.ResetStub(&stub); + client.DoEcho(); +} + +TEST_F(MockTest, ClientStream) { + ResetStub(); + FakeClient client(stub_.get()); + client.DoRequestStream(); + + MockEchoTestServiceStub stub; + auto w = new MockClientWriter<EchoRequest>(); + EchoResponse resp; + resp.set_message("hello, world"); + + EXPECT_CALL(*w, Write(_, _)).Times(2).WillRepeatedly(Return(true)); + EXPECT_CALL(*w, WritesDone()); + EXPECT_CALL(*w, Finish()).WillOnce(Return(Status::OK)); + + EXPECT_CALL(stub, RequestStreamRaw(_, _)) + .WillOnce(DoAll(SetArgPointee<1>(resp), Return(w))); + client.ResetStub(&stub); + client.DoRequestStream(); +} + +TEST_F(MockTest, ServerStream) { + ResetStub(); + FakeClient client(stub_.get()); + client.DoResponseStream(); + + MockEchoTestServiceStub stub; + auto r = new MockClientReader<EchoResponse>(); + EchoResponse resp1; + resp1.set_message("hello"); + EchoResponse resp2; + resp2.set_message("world"); + + EXPECT_CALL(*r, Read(_)) + .WillOnce(DoAll(SetArgPointee<0>(resp1), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(resp2), Return(true))) + .WillOnce(Return(false)); + EXPECT_CALL(*r, Finish()).WillOnce(Return(Status::OK)); + + EXPECT_CALL(stub, ResponseStreamRaw(_, _)).WillOnce(Return(r)); + + client.ResetStub(&stub); + client.DoResponseStream(); +} + +ACTION_P(copy, msg) { arg0->set_message(msg->message()); } + +TEST_F(MockTest, BidiStream) { + ResetStub(); + FakeClient client(stub_.get()); + client.DoBidiStream(); + MockEchoTestServiceStub stub; + auto rw = new MockClientReaderWriter<EchoRequest, EchoResponse>(); + EchoRequest msg; + + EXPECT_CALL(*rw, Write(_, _)) + .Times(3) + .WillRepeatedly(DoAll(SaveArg<0>(&msg), Return(true))); + EXPECT_CALL(*rw, Read(_)) + .WillOnce(DoAll(WithArg<0>(copy(&msg)), Return(true))) + .WillOnce(DoAll(WithArg<0>(copy(&msg)), Return(true))) + .WillOnce(DoAll(WithArg<0>(copy(&msg)), Return(true))) + .WillOnce(Return(false)); + EXPECT_CALL(*rw, WritesDone()); + EXPECT_CALL(*rw, Finish()).WillOnce(Return(Status::OK)); + + EXPECT_CALL(stub, BidiStreamRaw(_)).WillOnce(Return(rw)); + client.ResetStub(&stub); + client.DoBidiStream(); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/nonblocking_test.cc b/contrib/libs/grpc/test/cpp/end2end/nonblocking_test.cc index 37e696adaa..4be070ec71 100644 --- a/contrib/libs/grpc/test/cpp/end2end/nonblocking_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/nonblocking_test.cc @@ -1,203 +1,203 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ - -#include <memory> - -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/core/lib/gpr/tls.h" -#include "src/core/lib/iomgr/port.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#ifdef GRPC_POSIX_SOCKET -#include "src/core/lib/iomgr/ev_posix.h" -#endif // GRPC_POSIX_SOCKET - -#include <gtest/gtest.h> - -#ifdef GRPC_POSIX_SOCKET -// Thread-local variable to so that only polls from this test assert +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ + +#include <memory> + +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/core/lib/gpr/tls.h" +#include "src/core/lib/iomgr/port.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#ifdef GRPC_POSIX_SOCKET +#include "src/core/lib/iomgr/ev_posix.h" +#endif // GRPC_POSIX_SOCKET + +#include <gtest/gtest.h> + +#ifdef GRPC_POSIX_SOCKET +// Thread-local variable to so that only polls from this test assert // non-blocking (not polls from resolver, timer thread, etc), and only when the // thread is waiting on polls caused by CompletionQueue::AsyncNext (not for // picking a port or other reasons). GPR_TLS_DECL(g_is_nonblocking_poll); - -namespace { - -int maybe_assert_non_blocking_poll(struct pollfd* pfds, nfds_t nfds, - int timeout) { + +namespace { + +int maybe_assert_non_blocking_poll(struct pollfd* pfds, nfds_t nfds, + int timeout) { // Only assert that this poll should have zero timeout if we're in the // middle of a zero-timeout CQ Next. if (gpr_tls_get(&g_is_nonblocking_poll)) { - GPR_ASSERT(timeout == 0); - } - return poll(pfds, nfds, timeout); -} - -} // namespace - -namespace grpc { -namespace testing { -namespace { - -void* tag(int i) { return reinterpret_cast<void*>(static_cast<intptr_t>(i)); } -int detag(void* p) { return static_cast<int>(reinterpret_cast<intptr_t>(p)); } - -class NonblockingTest : public ::testing::Test { - protected: - NonblockingTest() {} - - void SetUp() override { - port_ = grpc_pick_unused_port_or_die(); - server_address_ << "localhost:" << port_; - - // Setup server - BuildAndStartServer(); - } - - bool LoopForTag(void** tag, bool* ok) { + GPR_ASSERT(timeout == 0); + } + return poll(pfds, nfds, timeout); +} + +} // namespace + +namespace grpc { +namespace testing { +namespace { + +void* tag(int i) { return reinterpret_cast<void*>(static_cast<intptr_t>(i)); } +int detag(void* p) { return static_cast<int>(reinterpret_cast<intptr_t>(p)); } + +class NonblockingTest : public ::testing::Test { + protected: + NonblockingTest() {} + + void SetUp() override { + port_ = grpc_pick_unused_port_or_die(); + server_address_ << "localhost:" << port_; + + // Setup server + BuildAndStartServer(); + } + + bool LoopForTag(void** tag, bool* ok) { // Temporarily set the thread-local nonblocking poll flag so that the polls // caused by this loop are indeed sent by the library with zero timeout. intptr_t orig_val = gpr_tls_get(&g_is_nonblocking_poll); gpr_tls_set(&g_is_nonblocking_poll, static_cast<intptr_t>(true)); - for (;;) { - auto r = cq_->AsyncNext(tag, ok, gpr_time_0(GPR_CLOCK_REALTIME)); - if (r == CompletionQueue::SHUTDOWN) { + for (;;) { + auto r = cq_->AsyncNext(tag, ok, gpr_time_0(GPR_CLOCK_REALTIME)); + if (r == CompletionQueue::SHUTDOWN) { gpr_tls_set(&g_is_nonblocking_poll, orig_val); - return false; - } else if (r == CompletionQueue::GOT_EVENT) { + return false; + } else if (r == CompletionQueue::GOT_EVENT) { gpr_tls_set(&g_is_nonblocking_poll, orig_val); - return true; - } - } - } - - void TearDown() override { - server_->Shutdown(); - void* ignored_tag; - bool ignored_ok; - cq_->Shutdown(); - while (LoopForTag(&ignored_tag, &ignored_ok)) - ; - stub_.reset(); - grpc_recycle_unused_port(port_); - } - - void BuildAndStartServer() { - ServerBuilder builder; - builder.AddListeningPort(server_address_.str(), - grpc::InsecureServerCredentials()); - service_.reset(new grpc::testing::EchoTestService::AsyncService()); - builder.RegisterService(service_.get()); - cq_ = builder.AddCompletionQueue(); - server_ = builder.BuildAndStart(); - } - - void ResetStub() { - std::shared_ptr<Channel> channel = grpc::CreateChannel( - server_address_.str(), grpc::InsecureChannelCredentials()); - stub_ = grpc::testing::EchoTestService::NewStub(channel); - } - - void SendRpc(int num_rpcs) { - for (int i = 0; i < num_rpcs; i++) { - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message("hello non-blocking world"); - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub_->PrepareAsyncEcho(&cli_ctx, send_request, cq_.get())); - - response_reader->StartCall(); - response_reader->Finish(&recv_response, &recv_status, tag(4)); - - service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, - cq_.get(), cq_.get(), tag(2)); - - void* got_tag; - bool ok; - EXPECT_TRUE(LoopForTag(&got_tag, &ok)); - EXPECT_TRUE(ok); - EXPECT_EQ(detag(got_tag), 2); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - response_writer.Finish(send_response, Status::OK, tag(3)); - - int tagsum = 0; - int tagprod = 1; - EXPECT_TRUE(LoopForTag(&got_tag, &ok)); - EXPECT_TRUE(ok); - tagsum += detag(got_tag); - tagprod *= detag(got_tag); - - EXPECT_TRUE(LoopForTag(&got_tag, &ok)); - EXPECT_TRUE(ok); - tagsum += detag(got_tag); - tagprod *= detag(got_tag); - - EXPECT_EQ(tagsum, 7); - EXPECT_EQ(tagprod, 12); - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - } - } - - std::unique_ptr<ServerCompletionQueue> cq_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - std::unique_ptr<grpc::testing::EchoTestService::AsyncService> service_; - std::ostringstream server_address_; - int port_; -}; - -TEST_F(NonblockingTest, SimpleRpc) { - ResetStub(); - SendRpc(10); -} - -} // namespace -} // namespace testing -} // namespace grpc - -#endif // GRPC_POSIX_SOCKET - -int main(int argc, char** argv) { -#ifdef GRPC_POSIX_SOCKET - // Override the poll function before anything else can happen - grpc_poll_function = maybe_assert_non_blocking_poll; - - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); + return true; + } + } + } + + void TearDown() override { + server_->Shutdown(); + void* ignored_tag; + bool ignored_ok; + cq_->Shutdown(); + while (LoopForTag(&ignored_tag, &ignored_ok)) + ; + stub_.reset(); + grpc_recycle_unused_port(port_); + } + + void BuildAndStartServer() { + ServerBuilder builder; + builder.AddListeningPort(server_address_.str(), + grpc::InsecureServerCredentials()); + service_.reset(new grpc::testing::EchoTestService::AsyncService()); + builder.RegisterService(service_.get()); + cq_ = builder.AddCompletionQueue(); + server_ = builder.BuildAndStart(); + } + + void ResetStub() { + std::shared_ptr<Channel> channel = grpc::CreateChannel( + server_address_.str(), grpc::InsecureChannelCredentials()); + stub_ = grpc::testing::EchoTestService::NewStub(channel); + } + + void SendRpc(int num_rpcs) { + for (int i = 0; i < num_rpcs; i++) { + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message("hello non-blocking world"); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub_->PrepareAsyncEcho(&cli_ctx, send_request, cq_.get())); + + response_reader->StartCall(); + response_reader->Finish(&recv_response, &recv_status, tag(4)); + + service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, + cq_.get(), cq_.get(), tag(2)); + + void* got_tag; + bool ok; + EXPECT_TRUE(LoopForTag(&got_tag, &ok)); + EXPECT_TRUE(ok); + EXPECT_EQ(detag(got_tag), 2); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + response_writer.Finish(send_response, Status::OK, tag(3)); + + int tagsum = 0; + int tagprod = 1; + EXPECT_TRUE(LoopForTag(&got_tag, &ok)); + EXPECT_TRUE(ok); + tagsum += detag(got_tag); + tagprod *= detag(got_tag); + + EXPECT_TRUE(LoopForTag(&got_tag, &ok)); + EXPECT_TRUE(ok); + tagsum += detag(got_tag); + tagprod *= detag(got_tag); + + EXPECT_EQ(tagsum, 7); + EXPECT_EQ(tagprod, 12); + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + } + } + + std::unique_ptr<ServerCompletionQueue> cq_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + std::unique_ptr<grpc::testing::EchoTestService::AsyncService> service_; + std::ostringstream server_address_; + int port_; +}; + +TEST_F(NonblockingTest, SimpleRpc) { + ResetStub(); + SendRpc(10); +} + +} // namespace +} // namespace testing +} // namespace grpc + +#endif // GRPC_POSIX_SOCKET + +int main(int argc, char** argv) { +#ifdef GRPC_POSIX_SOCKET + // Override the poll function before anything else can happen + grpc_poll_function = maybe_assert_non_blocking_poll; + + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); gpr_tls_init(&g_is_nonblocking_poll); // Start the nonblocking poll thread-local variable as false because the @@ -205,10 +205,10 @@ int main(int argc, char** argv) { // timeout). gpr_tls_set(&g_is_nonblocking_poll, static_cast<intptr_t>(false)); - int ret = RUN_ALL_TESTS(); + int ret = RUN_ALL_TESTS(); gpr_tls_destroy(&g_is_nonblocking_poll); - return ret; + return ret; #else // GRPC_POSIX_SOCKET return 0; #endif // GRPC_POSIX_SOCKET -} +} diff --git a/contrib/libs/grpc/test/cpp/end2end/proto_server_reflection_test.cc b/contrib/libs/grpc/test/cpp/end2end/proto_server_reflection_test.cc index 3418cc9fd2..d79b33da70 100644 --- a/contrib/libs/grpc/test/cpp/end2end/proto_server_reflection_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/proto_server_reflection_test.cc @@ -1,150 +1,150 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * 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. - * - */ - -#include <grpc/grpc.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/ext/proto_server_reflection_plugin.h> -#include <grpcpp/security/credentials.h> -#include <grpcpp/security/server_credentials.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/test_service_impl.h" -#include "test/cpp/util/proto_reflection_descriptor_database.h" - -#include <gtest/gtest.h> - -namespace grpc { -namespace testing { - -class ProtoServerReflectionTest : public ::testing::Test { - public: - ProtoServerReflectionTest() {} - - void SetUp() override { - port_ = grpc_pick_unused_port_or_die(); - ref_desc_pool_ = protobuf::DescriptorPool::generated_pool(); - - ServerBuilder builder; +/* + * + * Copyright 2016 gRPC authors. + * + * 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. + * + */ + +#include <grpc/grpc.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/ext/proto_server_reflection_plugin.h> +#include <grpcpp/security/credentials.h> +#include <grpcpp/security/server_credentials.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/proto_reflection_descriptor_database.h" + +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { + +class ProtoServerReflectionTest : public ::testing::Test { + public: + ProtoServerReflectionTest() {} + + void SetUp() override { + port_ = grpc_pick_unused_port_or_die(); + ref_desc_pool_ = protobuf::DescriptorPool::generated_pool(); + + ServerBuilder builder; TString server_address = "localhost:" + to_string(port_); - builder.AddListeningPort(server_address, InsecureServerCredentials()); - server_ = builder.BuildAndStart(); - } - - void ResetStub() { - string target = "dns:localhost:" + to_string(port_); - std::shared_ptr<Channel> channel = - grpc::CreateChannel(target, InsecureChannelCredentials()); - stub_ = grpc::testing::EchoTestService::NewStub(channel); - desc_db_.reset(new ProtoReflectionDescriptorDatabase(channel)); - desc_pool_.reset(new protobuf::DescriptorPool(desc_db_.get())); - } - - string to_string(const int number) { - std::stringstream strs; - strs << number; - return strs.str(); - } - + builder.AddListeningPort(server_address, InsecureServerCredentials()); + server_ = builder.BuildAndStart(); + } + + void ResetStub() { + string target = "dns:localhost:" + to_string(port_); + std::shared_ptr<Channel> channel = + grpc::CreateChannel(target, InsecureChannelCredentials()); + stub_ = grpc::testing::EchoTestService::NewStub(channel); + desc_db_.reset(new ProtoReflectionDescriptorDatabase(channel)); + desc_pool_.reset(new protobuf::DescriptorPool(desc_db_.get())); + } + + string to_string(const int number) { + std::stringstream strs; + strs << number; + return strs.str(); + } + void CompareService(const TString& service) { - const protobuf::ServiceDescriptor* service_desc = - desc_pool_->FindServiceByName(service); - const protobuf::ServiceDescriptor* ref_service_desc = - ref_desc_pool_->FindServiceByName(service); - EXPECT_TRUE(service_desc != nullptr); - EXPECT_TRUE(ref_service_desc != nullptr); - EXPECT_EQ(service_desc->DebugString(), ref_service_desc->DebugString()); - - const protobuf::FileDescriptor* file_desc = service_desc->file(); - if (known_files_.find(file_desc->package() + "/" + file_desc->name()) != - known_files_.end()) { - EXPECT_EQ(file_desc->DebugString(), - ref_service_desc->file()->DebugString()); - known_files_.insert(file_desc->package() + "/" + file_desc->name()); - } - - for (int i = 0; i < service_desc->method_count(); ++i) { - CompareMethod(service_desc->method(i)->full_name()); - } - } - + const protobuf::ServiceDescriptor* service_desc = + desc_pool_->FindServiceByName(service); + const protobuf::ServiceDescriptor* ref_service_desc = + ref_desc_pool_->FindServiceByName(service); + EXPECT_TRUE(service_desc != nullptr); + EXPECT_TRUE(ref_service_desc != nullptr); + EXPECT_EQ(service_desc->DebugString(), ref_service_desc->DebugString()); + + const protobuf::FileDescriptor* file_desc = service_desc->file(); + if (known_files_.find(file_desc->package() + "/" + file_desc->name()) != + known_files_.end()) { + EXPECT_EQ(file_desc->DebugString(), + ref_service_desc->file()->DebugString()); + known_files_.insert(file_desc->package() + "/" + file_desc->name()); + } + + for (int i = 0; i < service_desc->method_count(); ++i) { + CompareMethod(service_desc->method(i)->full_name()); + } + } + void CompareMethod(const TString& method) { - const protobuf::MethodDescriptor* method_desc = - desc_pool_->FindMethodByName(method); - const protobuf::MethodDescriptor* ref_method_desc = - ref_desc_pool_->FindMethodByName(method); - EXPECT_TRUE(method_desc != nullptr); - EXPECT_TRUE(ref_method_desc != nullptr); - EXPECT_EQ(method_desc->DebugString(), ref_method_desc->DebugString()); - - CompareType(method_desc->input_type()->full_name()); - CompareType(method_desc->output_type()->full_name()); - } - + const protobuf::MethodDescriptor* method_desc = + desc_pool_->FindMethodByName(method); + const protobuf::MethodDescriptor* ref_method_desc = + ref_desc_pool_->FindMethodByName(method); + EXPECT_TRUE(method_desc != nullptr); + EXPECT_TRUE(ref_method_desc != nullptr); + EXPECT_EQ(method_desc->DebugString(), ref_method_desc->DebugString()); + + CompareType(method_desc->input_type()->full_name()); + CompareType(method_desc->output_type()->full_name()); + } + void CompareType(const TString& type) { - if (known_types_.find(type) != known_types_.end()) { - return; - } - - const protobuf::Descriptor* desc = desc_pool_->FindMessageTypeByName(type); - const protobuf::Descriptor* ref_desc = - ref_desc_pool_->FindMessageTypeByName(type); - EXPECT_TRUE(desc != nullptr); - EXPECT_TRUE(ref_desc != nullptr); - EXPECT_EQ(desc->DebugString(), ref_desc->DebugString()); - } - - protected: - std::unique_ptr<Server> server_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<ProtoReflectionDescriptorDatabase> desc_db_; - std::unique_ptr<protobuf::DescriptorPool> desc_pool_; - std::unordered_set<string> known_files_; - std::unordered_set<string> known_types_; - const protobuf::DescriptorPool* ref_desc_pool_; - int port_; - reflection::ProtoServerReflectionPlugin plugin_; -}; - -TEST_F(ProtoServerReflectionTest, CheckResponseWithLocalDescriptorPool) { - ResetStub(); - + if (known_types_.find(type) != known_types_.end()) { + return; + } + + const protobuf::Descriptor* desc = desc_pool_->FindMessageTypeByName(type); + const protobuf::Descriptor* ref_desc = + ref_desc_pool_->FindMessageTypeByName(type); + EXPECT_TRUE(desc != nullptr); + EXPECT_TRUE(ref_desc != nullptr); + EXPECT_EQ(desc->DebugString(), ref_desc->DebugString()); + } + + protected: + std::unique_ptr<Server> server_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<ProtoReflectionDescriptorDatabase> desc_db_; + std::unique_ptr<protobuf::DescriptorPool> desc_pool_; + std::unordered_set<string> known_files_; + std::unordered_set<string> known_types_; + const protobuf::DescriptorPool* ref_desc_pool_; + int port_; + reflection::ProtoServerReflectionPlugin plugin_; +}; + +TEST_F(ProtoServerReflectionTest, CheckResponseWithLocalDescriptorPool) { + ResetStub(); + std::vector<TString> services; - desc_db_->GetServices(&services); - // The service list has at least one service (reflection servcie). - EXPECT_TRUE(services.size() > 0); - - for (auto it = services.begin(); it != services.end(); ++it) { - CompareService(*it); - } -} - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + desc_db_->GetServices(&services); + // The service list has at least one service (reflection servcie). + EXPECT_TRUE(services.size() > 0); + + for (auto it = services.begin(); it != services.end(); ++it) { + CompareService(*it); + } +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/raw_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/raw_end2end_test.cc index 42df83324b..184dc1e5f5 100644 --- a/contrib/libs/grpc/test/cpp/end2end/raw_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/raw_end2end_test.cc @@ -1,370 +1,370 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <cinttypes> -#include <memory> -#include <thread> - -#include <grpc/grpc.h> -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/core/lib/gpr/env.h" -#include "src/core/lib/iomgr/port.h" -#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/util/byte_buffer_proto_helper.h" -#include "test/cpp/util/string_ref_helper.h" - -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; - -namespace grpc { -namespace testing { - -namespace { - -void* tag(int i) { return (void*)static_cast<intptr_t>(i); } -int detag(void* p) { return static_cast<int>(reinterpret_cast<intptr_t>(p)); } - -class Verifier { - public: - Verifier() {} - - // Expect sets the expected ok value for a specific tag - Verifier& Expect(int i, bool expect_ok) { - expectations_[tag(i)] = expect_ok; - return *this; - } - - // Next waits for 1 async tag to complete, checks its - // expectations, and returns the tag - int Next(CompletionQueue* cq, bool ignore_ok) { - bool ok; - void* got_tag; - EXPECT_TRUE(cq->Next(&got_tag, &ok)); - GotTag(got_tag, ok, ignore_ok); - return detag(got_tag); - } - - // Verify keeps calling Next until all currently set - // expected tags are complete - void Verify(CompletionQueue* cq) { - GPR_ASSERT(!expectations_.empty()); - while (!expectations_.empty()) { - Next(cq, false); - } - } - - private: - void GotTag(void* got_tag, bool ok, bool ignore_ok) { - auto it = expectations_.find(got_tag); - if (it != expectations_.end()) { - if (!ignore_ok) { - EXPECT_EQ(it->second, ok); - } - expectations_.erase(it); - } - } - - std::map<void*, bool> expectations_; -}; - -class RawEnd2EndTest : public ::testing::Test { - protected: - RawEnd2EndTest() {} - - void SetUp() override { - port_ = grpc_pick_unused_port_or_die(); - server_address_ << "localhost:" << port_; - } - - void TearDown() override { - server_->Shutdown(); - void* ignored_tag; - bool ignored_ok; - cq_->Shutdown(); - while (cq_->Next(&ignored_tag, &ignored_ok)) - ; - stub_.reset(); - grpc_recycle_unused_port(port_); - } - - template <typename ServerType> - std::unique_ptr<ServerType> BuildAndStartServer() { - ServerBuilder builder; - builder.AddListeningPort(server_address_.str(), - grpc::InsecureServerCredentials()); - std::unique_ptr<ServerType> service(new ServerType()); - builder.RegisterService(service.get()); - cq_ = builder.AddCompletionQueue(); - server_ = builder.BuildAndStart(); - return service; - } - - void ResetStub() { - ChannelArguments args; - std::shared_ptr<Channel> channel = grpc::CreateChannel( - server_address_.str(), grpc::InsecureChannelCredentials()); - stub_ = grpc::testing::EchoTestService::NewStub(channel); - } - - std::unique_ptr<ServerCompletionQueue> cq_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - std::ostringstream server_address_; - int port_; - - // For the client application to populate and send to server. - EchoRequest send_request_; - ::grpc::ByteBuffer send_request_buffer_; - - // For the server to give to gRPC to be populated by incoming request - // from client. - EchoRequest recv_request_; - ::grpc::ByteBuffer recv_request_buffer_; - - // For the server application to populate and send back to client. - EchoResponse send_response_; - ::grpc::ByteBuffer send_response_buffer_; - - // For the client to give to gRPC to be populated by incoming response - // from server. - EchoResponse recv_response_; - ::grpc::ByteBuffer recv_response_buffer_; - Status recv_status_; - - // Both sides need contexts - ClientContext cli_ctx_; - ServerContext srv_ctx_; -}; - -// Regular Async, both peers use proto -TEST_F(RawEnd2EndTest, PureAsyncService) { - typedef grpc::testing::EchoTestService::AsyncService SType; - ResetStub(); - auto service = BuildAndStartServer<SType>(); - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx_); - - send_request_.set_message("hello"); - 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(), - cq_.get(), tag(2)); - response_reader->Finish(&recv_response_, &recv_status_, tag(4)); - Verifier().Expect(2, true).Verify(cq_.get()); - EXPECT_EQ(send_request_.message(), recv_request_.message()); - send_response_.set_message(recv_request_.message()); - response_writer.Finish(send_response_, Status::OK, tag(3)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - - EXPECT_EQ(send_response_.message(), recv_response_.message()); - EXPECT_TRUE(recv_status_.ok()); -} - -// Client uses proto, server uses generic codegen, unary -TEST_F(RawEnd2EndTest, RawServerUnary) { - typedef grpc::testing::EchoTestService::WithRawMethod_Echo< - grpc::testing::EchoTestService::Service> - SType; - ResetStub(); - auto service = BuildAndStartServer<SType>(); - grpc::GenericServerAsyncResponseWriter response_writer(&srv_ctx_); - - send_request_.set_message("hello unary"); - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub_->AsyncEcho(&cli_ctx_, send_request_, cq_.get())); - service->RequestEcho(&srv_ctx_, &recv_request_buffer_, &response_writer, - cq_.get(), cq_.get(), tag(2)); - response_reader->Finish(&recv_response_, &recv_status_, tag(4)); - Verifier().Expect(2, true).Verify(cq_.get()); - EXPECT_TRUE(ParseFromByteBuffer(&recv_request_buffer_, &recv_request_)); - EXPECT_EQ(send_request_.message(), recv_request_.message()); - send_response_.set_message(recv_request_.message()); - EXPECT_TRUE( - SerializeToByteBufferInPlace(&send_response_, &send_response_buffer_)); - response_writer.Finish(send_response_buffer_, Status::OK, tag(3)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - - EXPECT_EQ(send_response_.message(), recv_response_.message()); - EXPECT_TRUE(recv_status_.ok()); -} - -// Client uses proto, server uses generic codegen, client streaming -TEST_F(RawEnd2EndTest, RawServerClientStreaming) { - typedef grpc::testing::EchoTestService::WithRawMethod_RequestStream< - grpc::testing::EchoTestService::Service> - SType; - ResetStub(); - auto service = BuildAndStartServer<SType>(); - - grpc::GenericServerAsyncReader srv_stream(&srv_ctx_); - - send_request_.set_message("hello client streaming"); - 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(), - tag(2)); - - Verifier().Expect(2, true).Expect(1, true).Verify(cq_.get()); - - cli_stream->Write(send_request_, tag(3)); - srv_stream.Read(&recv_request_buffer_, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - ParseFromByteBuffer(&recv_request_buffer_, &recv_request_); - EXPECT_EQ(send_request_.message(), recv_request_.message()); - - cli_stream->Write(send_request_, tag(5)); - srv_stream.Read(&recv_request_buffer_, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - - ParseFromByteBuffer(&recv_request_buffer_, &recv_request_); - EXPECT_EQ(send_request_.message(), recv_request_.message()); - cli_stream->WritesDone(tag(7)); - srv_stream.Read(&recv_request_buffer_, tag(8)); - Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); - - ParseFromByteBuffer(&recv_request_buffer_, &recv_request_); - send_response_.set_message(recv_request_.message()); - SerializeToByteBufferInPlace(&send_response_, &send_response_buffer_); - srv_stream.Finish(send_response_buffer_, Status::OK, tag(9)); - cli_stream->Finish(&recv_status_, tag(10)); - Verifier().Expect(9, true).Expect(10, true).Verify(cq_.get()); - - EXPECT_EQ(send_response_.message(), recv_response_.message()); - EXPECT_TRUE(recv_status_.ok()); -} - -// Client uses proto, server uses generic codegen, server streaming -TEST_F(RawEnd2EndTest, RawServerServerStreaming) { - typedef grpc::testing::EchoTestService::WithRawMethod_ResponseStream< - grpc::testing::EchoTestService::Service> - SType; - ResetStub(); - auto service = BuildAndStartServer<SType>(); - grpc::GenericServerAsyncWriter srv_stream(&srv_ctx_); - - send_request_.set_message("hello server streaming"); - std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream( - stub_->AsyncResponseStream(&cli_ctx_, send_request_, cq_.get(), tag(1))); - - service->RequestResponseStream(&srv_ctx_, &recv_request_buffer_, &srv_stream, - cq_.get(), cq_.get(), tag(2)); - - Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); - ParseFromByteBuffer(&recv_request_buffer_, &recv_request_); - EXPECT_EQ(send_request_.message(), recv_request_.message()); - - send_response_.set_message(recv_request_.message()); - SerializeToByteBufferInPlace(&send_response_, &send_response_buffer_); - srv_stream.Write(send_response_buffer_, tag(3)); - cli_stream->Read(&recv_response_, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - EXPECT_EQ(send_response_.message(), recv_response_.message()); - - srv_stream.Write(send_response_buffer_, tag(5)); - cli_stream->Read(&recv_response_, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - EXPECT_EQ(send_response_.message(), recv_response_.message()); - - srv_stream.Finish(Status::OK, tag(7)); - cli_stream->Read(&recv_response_, tag(8)); - Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); - - cli_stream->Finish(&recv_status_, tag(9)); - Verifier().Expect(9, true).Verify(cq_.get()); - - EXPECT_TRUE(recv_status_.ok()); -} - -// Client uses proto, server uses generic codegen, bidi streaming -TEST_F(RawEnd2EndTest, RawServerBidiStreaming) { - typedef grpc::testing::EchoTestService::WithRawMethod_BidiStream< - grpc::testing::EchoTestService::Service> - SType; - ResetStub(); - auto service = BuildAndStartServer<SType>(); - - grpc::GenericServerAsyncReaderWriter srv_stream(&srv_ctx_); - - send_request_.set_message("hello bidi streaming"); - 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(), - tag(2)); - - Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); - - cli_stream->Write(send_request_, tag(3)); - srv_stream.Read(&recv_request_buffer_, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); - ParseFromByteBuffer(&recv_request_buffer_, &recv_request_); - EXPECT_EQ(send_request_.message(), recv_request_.message()); - - send_response_.set_message(recv_request_.message()); - SerializeToByteBufferInPlace(&send_response_, &send_response_buffer_); - srv_stream.Write(send_response_buffer_, tag(5)); - cli_stream->Read(&recv_response_, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); - EXPECT_EQ(send_response_.message(), recv_response_.message()); - - cli_stream->WritesDone(tag(7)); - srv_stream.Read(&recv_request_buffer_, tag(8)); - Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); - - srv_stream.Finish(Status::OK, tag(9)); - cli_stream->Finish(&recv_status_, tag(10)); - Verifier().Expect(9, true).Expect(10, true).Verify(cq_.get()); - - EXPECT_TRUE(recv_status_.ok()); -} - -// Testing that this pattern compiles -TEST_F(RawEnd2EndTest, CompileTest) { - typedef grpc::testing::EchoTestService::WithRawMethod_Echo< - grpc::testing::EchoTestService::AsyncService> - SType; - ResetStub(); - auto service = BuildAndStartServer<SType>(); -} - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - // Change the backup poll interval from 5s to 100ms to speed up the - // ReconnectChannel test - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - int ret = RUN_ALL_TESTS(); - return ret; -} +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <cinttypes> +#include <memory> +#include <thread> + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/iomgr/port.h" +#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" +#include "test/cpp/util/string_ref_helper.h" + +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; + +namespace grpc { +namespace testing { + +namespace { + +void* tag(int i) { return (void*)static_cast<intptr_t>(i); } +int detag(void* p) { return static_cast<int>(reinterpret_cast<intptr_t>(p)); } + +class Verifier { + public: + Verifier() {} + + // Expect sets the expected ok value for a specific tag + Verifier& Expect(int i, bool expect_ok) { + expectations_[tag(i)] = expect_ok; + return *this; + } + + // Next waits for 1 async tag to complete, checks its + // expectations, and returns the tag + int Next(CompletionQueue* cq, bool ignore_ok) { + bool ok; + void* got_tag; + EXPECT_TRUE(cq->Next(&got_tag, &ok)); + GotTag(got_tag, ok, ignore_ok); + return detag(got_tag); + } + + // Verify keeps calling Next until all currently set + // expected tags are complete + void Verify(CompletionQueue* cq) { + GPR_ASSERT(!expectations_.empty()); + while (!expectations_.empty()) { + Next(cq, false); + } + } + + private: + void GotTag(void* got_tag, bool ok, bool ignore_ok) { + auto it = expectations_.find(got_tag); + if (it != expectations_.end()) { + if (!ignore_ok) { + EXPECT_EQ(it->second, ok); + } + expectations_.erase(it); + } + } + + std::map<void*, bool> expectations_; +}; + +class RawEnd2EndTest : public ::testing::Test { + protected: + RawEnd2EndTest() {} + + void SetUp() override { + port_ = grpc_pick_unused_port_or_die(); + server_address_ << "localhost:" << port_; + } + + void TearDown() override { + server_->Shutdown(); + void* ignored_tag; + bool ignored_ok; + cq_->Shutdown(); + while (cq_->Next(&ignored_tag, &ignored_ok)) + ; + stub_.reset(); + grpc_recycle_unused_port(port_); + } + + template <typename ServerType> + std::unique_ptr<ServerType> BuildAndStartServer() { + ServerBuilder builder; + builder.AddListeningPort(server_address_.str(), + grpc::InsecureServerCredentials()); + std::unique_ptr<ServerType> service(new ServerType()); + builder.RegisterService(service.get()); + cq_ = builder.AddCompletionQueue(); + server_ = builder.BuildAndStart(); + return service; + } + + void ResetStub() { + ChannelArguments args; + std::shared_ptr<Channel> channel = grpc::CreateChannel( + server_address_.str(), grpc::InsecureChannelCredentials()); + stub_ = grpc::testing::EchoTestService::NewStub(channel); + } + + std::unique_ptr<ServerCompletionQueue> cq_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + std::ostringstream server_address_; + int port_; + + // For the client application to populate and send to server. + EchoRequest send_request_; + ::grpc::ByteBuffer send_request_buffer_; + + // For the server to give to gRPC to be populated by incoming request + // from client. + EchoRequest recv_request_; + ::grpc::ByteBuffer recv_request_buffer_; + + // For the server application to populate and send back to client. + EchoResponse send_response_; + ::grpc::ByteBuffer send_response_buffer_; + + // For the client to give to gRPC to be populated by incoming response + // from server. + EchoResponse recv_response_; + ::grpc::ByteBuffer recv_response_buffer_; + Status recv_status_; + + // Both sides need contexts + ClientContext cli_ctx_; + ServerContext srv_ctx_; +}; + +// Regular Async, both peers use proto +TEST_F(RawEnd2EndTest, PureAsyncService) { + typedef grpc::testing::EchoTestService::AsyncService SType; + ResetStub(); + auto service = BuildAndStartServer<SType>(); + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx_); + + send_request_.set_message("hello"); + 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(), + cq_.get(), tag(2)); + response_reader->Finish(&recv_response_, &recv_status_, tag(4)); + Verifier().Expect(2, true).Verify(cq_.get()); + EXPECT_EQ(send_request_.message(), recv_request_.message()); + send_response_.set_message(recv_request_.message()); + response_writer.Finish(send_response_, Status::OK, tag(3)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + + EXPECT_EQ(send_response_.message(), recv_response_.message()); + EXPECT_TRUE(recv_status_.ok()); +} + +// Client uses proto, server uses generic codegen, unary +TEST_F(RawEnd2EndTest, RawServerUnary) { + typedef grpc::testing::EchoTestService::WithRawMethod_Echo< + grpc::testing::EchoTestService::Service> + SType; + ResetStub(); + auto service = BuildAndStartServer<SType>(); + grpc::GenericServerAsyncResponseWriter response_writer(&srv_ctx_); + + send_request_.set_message("hello unary"); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub_->AsyncEcho(&cli_ctx_, send_request_, cq_.get())); + service->RequestEcho(&srv_ctx_, &recv_request_buffer_, &response_writer, + cq_.get(), cq_.get(), tag(2)); + response_reader->Finish(&recv_response_, &recv_status_, tag(4)); + Verifier().Expect(2, true).Verify(cq_.get()); + EXPECT_TRUE(ParseFromByteBuffer(&recv_request_buffer_, &recv_request_)); + EXPECT_EQ(send_request_.message(), recv_request_.message()); + send_response_.set_message(recv_request_.message()); + EXPECT_TRUE( + SerializeToByteBufferInPlace(&send_response_, &send_response_buffer_)); + response_writer.Finish(send_response_buffer_, Status::OK, tag(3)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + + EXPECT_EQ(send_response_.message(), recv_response_.message()); + EXPECT_TRUE(recv_status_.ok()); +} + +// Client uses proto, server uses generic codegen, client streaming +TEST_F(RawEnd2EndTest, RawServerClientStreaming) { + typedef grpc::testing::EchoTestService::WithRawMethod_RequestStream< + grpc::testing::EchoTestService::Service> + SType; + ResetStub(); + auto service = BuildAndStartServer<SType>(); + + grpc::GenericServerAsyncReader srv_stream(&srv_ctx_); + + send_request_.set_message("hello client streaming"); + 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(), + tag(2)); + + Verifier().Expect(2, true).Expect(1, true).Verify(cq_.get()); + + cli_stream->Write(send_request_, tag(3)); + srv_stream.Read(&recv_request_buffer_, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + ParseFromByteBuffer(&recv_request_buffer_, &recv_request_); + EXPECT_EQ(send_request_.message(), recv_request_.message()); + + cli_stream->Write(send_request_, tag(5)); + srv_stream.Read(&recv_request_buffer_, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + + ParseFromByteBuffer(&recv_request_buffer_, &recv_request_); + EXPECT_EQ(send_request_.message(), recv_request_.message()); + cli_stream->WritesDone(tag(7)); + srv_stream.Read(&recv_request_buffer_, tag(8)); + Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); + + ParseFromByteBuffer(&recv_request_buffer_, &recv_request_); + send_response_.set_message(recv_request_.message()); + SerializeToByteBufferInPlace(&send_response_, &send_response_buffer_); + srv_stream.Finish(send_response_buffer_, Status::OK, tag(9)); + cli_stream->Finish(&recv_status_, tag(10)); + Verifier().Expect(9, true).Expect(10, true).Verify(cq_.get()); + + EXPECT_EQ(send_response_.message(), recv_response_.message()); + EXPECT_TRUE(recv_status_.ok()); +} + +// Client uses proto, server uses generic codegen, server streaming +TEST_F(RawEnd2EndTest, RawServerServerStreaming) { + typedef grpc::testing::EchoTestService::WithRawMethod_ResponseStream< + grpc::testing::EchoTestService::Service> + SType; + ResetStub(); + auto service = BuildAndStartServer<SType>(); + grpc::GenericServerAsyncWriter srv_stream(&srv_ctx_); + + send_request_.set_message("hello server streaming"); + std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream( + stub_->AsyncResponseStream(&cli_ctx_, send_request_, cq_.get(), tag(1))); + + service->RequestResponseStream(&srv_ctx_, &recv_request_buffer_, &srv_stream, + cq_.get(), cq_.get(), tag(2)); + + Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); + ParseFromByteBuffer(&recv_request_buffer_, &recv_request_); + EXPECT_EQ(send_request_.message(), recv_request_.message()); + + send_response_.set_message(recv_request_.message()); + SerializeToByteBufferInPlace(&send_response_, &send_response_buffer_); + srv_stream.Write(send_response_buffer_, tag(3)); + cli_stream->Read(&recv_response_, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + EXPECT_EQ(send_response_.message(), recv_response_.message()); + + srv_stream.Write(send_response_buffer_, tag(5)); + cli_stream->Read(&recv_response_, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + EXPECT_EQ(send_response_.message(), recv_response_.message()); + + srv_stream.Finish(Status::OK, tag(7)); + cli_stream->Read(&recv_response_, tag(8)); + Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); + + cli_stream->Finish(&recv_status_, tag(9)); + Verifier().Expect(9, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status_.ok()); +} + +// Client uses proto, server uses generic codegen, bidi streaming +TEST_F(RawEnd2EndTest, RawServerBidiStreaming) { + typedef grpc::testing::EchoTestService::WithRawMethod_BidiStream< + grpc::testing::EchoTestService::Service> + SType; + ResetStub(); + auto service = BuildAndStartServer<SType>(); + + grpc::GenericServerAsyncReaderWriter srv_stream(&srv_ctx_); + + send_request_.set_message("hello bidi streaming"); + 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(), + tag(2)); + + Verifier().Expect(1, true).Expect(2, true).Verify(cq_.get()); + + cli_stream->Write(send_request_, tag(3)); + srv_stream.Read(&recv_request_buffer_, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get()); + ParseFromByteBuffer(&recv_request_buffer_, &recv_request_); + EXPECT_EQ(send_request_.message(), recv_request_.message()); + + send_response_.set_message(recv_request_.message()); + SerializeToByteBufferInPlace(&send_response_, &send_response_buffer_); + srv_stream.Write(send_response_buffer_, tag(5)); + cli_stream->Read(&recv_response_, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq_.get()); + EXPECT_EQ(send_response_.message(), recv_response_.message()); + + cli_stream->WritesDone(tag(7)); + srv_stream.Read(&recv_request_buffer_, tag(8)); + Verifier().Expect(7, true).Expect(8, false).Verify(cq_.get()); + + srv_stream.Finish(Status::OK, tag(9)); + cli_stream->Finish(&recv_status_, tag(10)); + Verifier().Expect(9, true).Expect(10, true).Verify(cq_.get()); + + EXPECT_TRUE(recv_status_.ok()); +} + +// Testing that this pattern compiles +TEST_F(RawEnd2EndTest, CompileTest) { + typedef grpc::testing::EchoTestService::WithRawMethod_Echo< + grpc::testing::EchoTestService::AsyncService> + SType; + ResetStub(); + auto service = BuildAndStartServer<SType>(); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + // Change the backup poll interval from 5s to 100ms to speed up the + // ReconnectChannel test + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + int ret = RUN_ALL_TESTS(); + return ret; +} diff --git a/contrib/libs/grpc/test/cpp/end2end/server_builder_plugin_test.cc b/contrib/libs/grpc/test/cpp/end2end/server_builder_plugin_test.cc index cc368bbb90..004902cad3 100644 --- a/contrib/libs/grpc/test/cpp/end2end/server_builder_plugin_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/server_builder_plugin_test.cc @@ -1,265 +1,265 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * 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. - * - */ - -#include <thread> - -#include <grpc/grpc.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/impl/server_builder_option.h> -#include <grpcpp/impl/server_builder_plugin.h> -#include <grpcpp/impl/server_initializer.h> -#include <grpcpp/security/credentials.h> -#include <grpcpp/security/server_credentials.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/test_service_impl.h" - -#include <gtest/gtest.h> - -#define PLUGIN_NAME "TestServerBuilderPlugin" - -namespace grpc { -namespace testing { - -class TestServerBuilderPlugin : public ServerBuilderPlugin { - public: - TestServerBuilderPlugin() : service_(new TestServiceImpl()) { - init_server_is_called_ = false; - finish_is_called_ = false; - change_arguments_is_called_ = false; - register_service_ = false; - } - +/* + * + * Copyright 2016 gRPC authors. + * + * 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. + * + */ + +#include <thread> + +#include <grpc/grpc.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/impl/server_builder_option.h> +#include <grpcpp/impl/server_builder_plugin.h> +#include <grpcpp/impl/server_initializer.h> +#include <grpcpp/security/credentials.h> +#include <grpcpp/security/server_credentials.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" + +#include <gtest/gtest.h> + +#define PLUGIN_NAME "TestServerBuilderPlugin" + +namespace grpc { +namespace testing { + +class TestServerBuilderPlugin : public ServerBuilderPlugin { + public: + TestServerBuilderPlugin() : service_(new TestServiceImpl()) { + init_server_is_called_ = false; + finish_is_called_ = false; + change_arguments_is_called_ = false; + register_service_ = false; + } + TString name() override { return PLUGIN_NAME; } - - void InitServer(ServerInitializer* si) override { - init_server_is_called_ = true; - if (register_service_) { - si->RegisterService(service_); - } - } - - void Finish(ServerInitializer* /*si*/) override { finish_is_called_ = true; } - + + void InitServer(ServerInitializer* si) override { + init_server_is_called_ = true; + if (register_service_) { + si->RegisterService(service_); + } + } + + void Finish(ServerInitializer* /*si*/) override { finish_is_called_ = true; } + void ChangeArguments(const TString& /*name*/, void* /*value*/) override { - change_arguments_is_called_ = true; - } - - bool has_async_methods() const override { - if (register_service_) { - return service_->has_async_methods(); - } - return false; - } - - bool has_sync_methods() const override { - if (register_service_) { - return service_->has_synchronous_methods(); - } - return false; - } - - void SetRegisterService() { register_service_ = true; } - - bool init_server_is_called() { return init_server_is_called_; } - bool finish_is_called() { return finish_is_called_; } - bool change_arguments_is_called() { return change_arguments_is_called_; } - - private: - bool init_server_is_called_; - bool finish_is_called_; - bool change_arguments_is_called_; - bool register_service_; - std::shared_ptr<TestServiceImpl> service_; -}; - -class InsertPluginServerBuilderOption : public ServerBuilderOption { - public: - InsertPluginServerBuilderOption() { register_service_ = false; } - - void UpdateArguments(ChannelArguments* /*arg*/) override {} - - void UpdatePlugins( - std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) override { - plugins->clear(); - - std::unique_ptr<TestServerBuilderPlugin> plugin( - new TestServerBuilderPlugin()); - if (register_service_) plugin->SetRegisterService(); - plugins->emplace_back(std::move(plugin)); - } - - void SetRegisterService() { register_service_ = true; } - - private: - bool register_service_; -}; - -std::unique_ptr<ServerBuilderPlugin> CreateTestServerBuilderPlugin() { - return std::unique_ptr<ServerBuilderPlugin>(new TestServerBuilderPlugin()); -} - -// Force AddServerBuilderPlugin() to be called at static initialization time. -struct StaticTestPluginInitializer { + change_arguments_is_called_ = true; + } + + bool has_async_methods() const override { + if (register_service_) { + return service_->has_async_methods(); + } + return false; + } + + bool has_sync_methods() const override { + if (register_service_) { + return service_->has_synchronous_methods(); + } + return false; + } + + void SetRegisterService() { register_service_ = true; } + + bool init_server_is_called() { return init_server_is_called_; } + bool finish_is_called() { return finish_is_called_; } + bool change_arguments_is_called() { return change_arguments_is_called_; } + + private: + bool init_server_is_called_; + bool finish_is_called_; + bool change_arguments_is_called_; + bool register_service_; + std::shared_ptr<TestServiceImpl> service_; +}; + +class InsertPluginServerBuilderOption : public ServerBuilderOption { + public: + InsertPluginServerBuilderOption() { register_service_ = false; } + + void UpdateArguments(ChannelArguments* /*arg*/) override {} + + void UpdatePlugins( + std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) override { + plugins->clear(); + + std::unique_ptr<TestServerBuilderPlugin> plugin( + new TestServerBuilderPlugin()); + if (register_service_) plugin->SetRegisterService(); + plugins->emplace_back(std::move(plugin)); + } + + void SetRegisterService() { register_service_ = true; } + + private: + bool register_service_; +}; + +std::unique_ptr<ServerBuilderPlugin> CreateTestServerBuilderPlugin() { + return std::unique_ptr<ServerBuilderPlugin>(new TestServerBuilderPlugin()); +} + +// Force AddServerBuilderPlugin() to be called at static initialization time. +struct StaticTestPluginInitializer { StaticTestPluginInitializer() { ::grpc::ServerBuilder::InternalAddPluginFactory( &CreateTestServerBuilderPlugin); } -} static_plugin_initializer_test_; - -// When the param boolean is true, the ServerBuilder plugin will be added at the -// time of static initialization. When it's false, the ServerBuilder plugin will -// be added using ServerBuilder::SetOption(). -class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> { - public: - ServerBuilderPluginTest() {} - - void SetUp() override { - port_ = grpc_pick_unused_port_or_die(); - builder_.reset(new ServerBuilder()); - } - - void InsertPlugin() { - if (GetParam()) { - // Add ServerBuilder plugin in static initialization - CheckPresent(); - } else { - // Add ServerBuilder plugin using ServerBuilder::SetOption() - builder_->SetOption(std::unique_ptr<ServerBuilderOption>( - new InsertPluginServerBuilderOption())); - } - } - - void InsertPluginWithTestService() { - if (GetParam()) { - // Add ServerBuilder plugin in static initialization - auto plugin = CheckPresent(); - EXPECT_TRUE(plugin); - plugin->SetRegisterService(); - } else { - // Add ServerBuilder plugin using ServerBuilder::SetOption() - std::unique_ptr<InsertPluginServerBuilderOption> option( - new InsertPluginServerBuilderOption()); - option->SetRegisterService(); - builder_->SetOption(std::move(option)); - } - } - - void StartServer() { +} static_plugin_initializer_test_; + +// When the param boolean is true, the ServerBuilder plugin will be added at the +// time of static initialization. When it's false, the ServerBuilder plugin will +// be added using ServerBuilder::SetOption(). +class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> { + public: + ServerBuilderPluginTest() {} + + void SetUp() override { + port_ = grpc_pick_unused_port_or_die(); + builder_.reset(new ServerBuilder()); + } + + void InsertPlugin() { + if (GetParam()) { + // Add ServerBuilder plugin in static initialization + CheckPresent(); + } else { + // Add ServerBuilder plugin using ServerBuilder::SetOption() + builder_->SetOption(std::unique_ptr<ServerBuilderOption>( + new InsertPluginServerBuilderOption())); + } + } + + void InsertPluginWithTestService() { + if (GetParam()) { + // Add ServerBuilder plugin in static initialization + auto plugin = CheckPresent(); + EXPECT_TRUE(plugin); + plugin->SetRegisterService(); + } else { + // Add ServerBuilder plugin using ServerBuilder::SetOption() + std::unique_ptr<InsertPluginServerBuilderOption> option( + new InsertPluginServerBuilderOption()); + option->SetRegisterService(); + builder_->SetOption(std::move(option)); + } + } + + void StartServer() { TString server_address = "localhost:" + to_string(port_); - builder_->AddListeningPort(server_address, InsecureServerCredentials()); - // we run some tests without a service, and for those we need to supply a - // frequently polled completion queue - cq_ = builder_->AddCompletionQueue(); - cq_thread_ = new std::thread(&ServerBuilderPluginTest::RunCQ, this); - server_ = builder_->BuildAndStart(); - EXPECT_TRUE(CheckPresent()); - } - - void ResetStub() { - string target = "dns:localhost:" + to_string(port_); - channel_ = grpc::CreateChannel(target, InsecureChannelCredentials()); - stub_ = grpc::testing::EchoTestService::NewStub(channel_); - } - - void TearDown() override { - auto plugin = CheckPresent(); - EXPECT_TRUE(plugin); - EXPECT_TRUE(plugin->init_server_is_called()); - EXPECT_TRUE(plugin->finish_is_called()); - server_->Shutdown(); - cq_->Shutdown(); - cq_thread_->join(); - delete cq_thread_; - } - - string to_string(const int number) { - std::stringstream strs; - strs << number; - return strs.str(); - } - - protected: - std::shared_ptr<Channel> channel_; - std::unique_ptr<ServerBuilder> builder_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<ServerCompletionQueue> cq_; - std::unique_ptr<Server> server_; - std::thread* cq_thread_; - TestServiceImpl service_; - int port_; - - private: - TestServerBuilderPlugin* CheckPresent() { - auto it = builder_->plugins_.begin(); - for (; it != builder_->plugins_.end(); it++) { - if ((*it)->name() == PLUGIN_NAME) break; - } - if (it != builder_->plugins_.end()) { - return static_cast<TestServerBuilderPlugin*>(it->get()); - } else { - return nullptr; - } - } - - void RunCQ() { - void* tag; - bool ok; - while (cq_->Next(&tag, &ok)) - ; - } -}; - -TEST_P(ServerBuilderPluginTest, PluginWithoutServiceTest) { - InsertPlugin(); - StartServer(); -} - -TEST_P(ServerBuilderPluginTest, PluginWithServiceTest) { - InsertPluginWithTestService(); - StartServer(); - ResetStub(); - - EchoRequest request; - EchoResponse response; - request.set_message("Hello hello hello hello"); - ClientContext context; - context.set_compression_algorithm(GRPC_COMPRESS_GZIP); - Status s = stub_->Echo(&context, request, &response); - EXPECT_EQ(response.message(), request.message()); - EXPECT_TRUE(s.ok()); -} - -INSTANTIATE_TEST_SUITE_P(ServerBuilderPluginTest, ServerBuilderPluginTest, - ::testing::Values(false, true)); - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + builder_->AddListeningPort(server_address, InsecureServerCredentials()); + // we run some tests without a service, and for those we need to supply a + // frequently polled completion queue + cq_ = builder_->AddCompletionQueue(); + cq_thread_ = new std::thread(&ServerBuilderPluginTest::RunCQ, this); + server_ = builder_->BuildAndStart(); + EXPECT_TRUE(CheckPresent()); + } + + void ResetStub() { + string target = "dns:localhost:" + to_string(port_); + channel_ = grpc::CreateChannel(target, InsecureChannelCredentials()); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + void TearDown() override { + auto plugin = CheckPresent(); + EXPECT_TRUE(plugin); + EXPECT_TRUE(plugin->init_server_is_called()); + EXPECT_TRUE(plugin->finish_is_called()); + server_->Shutdown(); + cq_->Shutdown(); + cq_thread_->join(); + delete cq_thread_; + } + + string to_string(const int number) { + std::stringstream strs; + strs << number; + return strs.str(); + } + + protected: + std::shared_ptr<Channel> channel_; + std::unique_ptr<ServerBuilder> builder_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<ServerCompletionQueue> cq_; + std::unique_ptr<Server> server_; + std::thread* cq_thread_; + TestServiceImpl service_; + int port_; + + private: + TestServerBuilderPlugin* CheckPresent() { + auto it = builder_->plugins_.begin(); + for (; it != builder_->plugins_.end(); it++) { + if ((*it)->name() == PLUGIN_NAME) break; + } + if (it != builder_->plugins_.end()) { + return static_cast<TestServerBuilderPlugin*>(it->get()); + } else { + return nullptr; + } + } + + void RunCQ() { + void* tag; + bool ok; + while (cq_->Next(&tag, &ok)) + ; + } +}; + +TEST_P(ServerBuilderPluginTest, PluginWithoutServiceTest) { + InsertPlugin(); + StartServer(); +} + +TEST_P(ServerBuilderPluginTest, PluginWithServiceTest) { + InsertPluginWithTestService(); + StartServer(); + ResetStub(); + + EchoRequest request; + EchoResponse response; + request.set_message("Hello hello hello hello"); + ClientContext context; + context.set_compression_algorithm(GRPC_COMPRESS_GZIP); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); +} + +INSTANTIATE_TEST_SUITE_P(ServerBuilderPluginTest, ServerBuilderPluginTest, + ::testing::Values(false, true)); + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/server_crash_test.cc b/contrib/libs/grpc/test/cpp/end2end/server_crash_test.cc index f8e4ea8eae..3616d680f9 100644 --- a/contrib/libs/grpc/test/cpp/end2end/server_crash_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/server_crash_test.cc @@ -1,160 +1,160 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <grpc/grpc.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/util/subprocess.h" - -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; -using std::chrono::system_clock; - +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <grpc/grpc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/util/subprocess.h" + +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; +using std::chrono::system_clock; + static TString g_root; - -namespace grpc { -namespace testing { - -namespace { - -class ServiceImpl final : public ::grpc::testing::EchoTestService::Service { - public: - ServiceImpl() : bidi_stream_count_(0), response_stream_count_(0) {} - - Status BidiStream( - ServerContext* /*context*/, - ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { - bidi_stream_count_++; - EchoRequest request; - EchoResponse response; - while (stream->Read(&request)) { - gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); - response.set_message(request.message()); - stream->Write(response); - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_seconds(1, GPR_TIMESPAN))); - } - return Status::OK; - } - - Status ResponseStream(ServerContext* /*context*/, - const EchoRequest* /*request*/, - ServerWriter<EchoResponse>* writer) override { - EchoResponse response; - response_stream_count_++; - for (int i = 0;; i++) { - std::ostringstream msg; - msg << "Hello " << i; - response.set_message(msg.str()); - if (!writer->Write(response)) break; - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_seconds(1, GPR_TIMESPAN))); - } - return Status::OK; - } - - int bidi_stream_count() { return bidi_stream_count_; } - - int response_stream_count() { return response_stream_count_; } - - private: - int bidi_stream_count_; - int response_stream_count_; -}; - -class CrashTest : public ::testing::Test { - protected: - CrashTest() {} - + +namespace grpc { +namespace testing { + +namespace { + +class ServiceImpl final : public ::grpc::testing::EchoTestService::Service { + public: + ServiceImpl() : bidi_stream_count_(0), response_stream_count_(0) {} + + Status BidiStream( + ServerContext* /*context*/, + ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { + bidi_stream_count_++; + EchoRequest request; + EchoResponse response; + while (stream->Read(&request)) { + gpr_log(GPR_INFO, "recv msg %s", request.message().c_str()); + response.set_message(request.message()); + stream->Write(response); + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(1, GPR_TIMESPAN))); + } + return Status::OK; + } + + Status ResponseStream(ServerContext* /*context*/, + const EchoRequest* /*request*/, + ServerWriter<EchoResponse>* writer) override { + EchoResponse response; + response_stream_count_++; + for (int i = 0;; i++) { + std::ostringstream msg; + msg << "Hello " << i; + response.set_message(msg.str()); + if (!writer->Write(response)) break; + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(1, GPR_TIMESPAN))); + } + return Status::OK; + } + + int bidi_stream_count() { return bidi_stream_count_; } + + int response_stream_count() { return response_stream_count_; } + + private: + int bidi_stream_count_; + int response_stream_count_; +}; + +class CrashTest : public ::testing::Test { + protected: + CrashTest() {} + std::unique_ptr<Server> CreateServerAndClient(const TString& mode) { - auto port = grpc_pick_unused_port_or_die(); - std::ostringstream addr_stream; - addr_stream << "localhost:" << port; - auto addr = addr_stream.str(); - client_.reset(new SubProcess({g_root + "/server_crash_test_client", - "--address=" + addr, "--mode=" + mode})); - GPR_ASSERT(client_); - - ServerBuilder builder; - builder.AddListeningPort(addr, grpc::InsecureServerCredentials()); - builder.RegisterService(&service_); - return builder.BuildAndStart(); - } - - void KillClient() { client_.reset(); } - - bool HadOneBidiStream() { return service_.bidi_stream_count() == 1; } - - bool HadOneResponseStream() { return service_.response_stream_count() == 1; } - - private: - std::unique_ptr<SubProcess> client_; - ServiceImpl service_; -}; - -TEST_F(CrashTest, ResponseStream) { - auto server = CreateServerAndClient("response"); - - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_seconds(60, GPR_TIMESPAN))); - KillClient(); - server->Shutdown(); - GPR_ASSERT(HadOneResponseStream()); -} - -TEST_F(CrashTest, BidiStream) { - auto server = CreateServerAndClient("bidi"); - - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_seconds(60, GPR_TIMESPAN))); - KillClient(); - server->Shutdown(); - GPR_ASSERT(HadOneBidiStream()); -} - -} // namespace - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { + auto port = grpc_pick_unused_port_or_die(); + std::ostringstream addr_stream; + addr_stream << "localhost:" << port; + auto addr = addr_stream.str(); + client_.reset(new SubProcess({g_root + "/server_crash_test_client", + "--address=" + addr, "--mode=" + mode})); + GPR_ASSERT(client_); + + ServerBuilder builder; + builder.AddListeningPort(addr, grpc::InsecureServerCredentials()); + builder.RegisterService(&service_); + return builder.BuildAndStart(); + } + + void KillClient() { client_.reset(); } + + bool HadOneBidiStream() { return service_.bidi_stream_count() == 1; } + + bool HadOneResponseStream() { return service_.response_stream_count() == 1; } + + private: + std::unique_ptr<SubProcess> client_; + ServiceImpl service_; +}; + +TEST_F(CrashTest, ResponseStream) { + auto server = CreateServerAndClient("response"); + + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(60, GPR_TIMESPAN))); + KillClient(); + server->Shutdown(); + GPR_ASSERT(HadOneResponseStream()); +} + +TEST_F(CrashTest, BidiStream) { + auto server = CreateServerAndClient("bidi"); + + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(60, GPR_TIMESPAN))); + KillClient(); + server->Shutdown(); + GPR_ASSERT(HadOneBidiStream()); +} + +} // namespace + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { TString me = argv[0]; - auto lslash = me.rfind('/'); + auto lslash = me.rfind('/'); if (lslash != TString::npos) { - g_root = me.substr(0, lslash); - } else { - g_root = "."; - } - - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + g_root = me.substr(0, lslash); + } else { + g_root = "."; + } + + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/server_crash_test_client.cc b/contrib/libs/grpc/test/cpp/end2end/server_crash_test_client.cc index 99e8259aa9..202fb2836c 100644 --- a/contrib/libs/grpc/test/cpp/end2end/server_crash_test_client.cc +++ b/contrib/libs/grpc/test/cpp/end2end/server_crash_test_client.cc @@ -1,72 +1,72 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <gflags/gflags.h> -#include <iostream> -#include <memory> -#include <sstream> +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <gflags/gflags.h> +#include <iostream> +#include <memory> +#include <sstream> #include <util/generic/string.h> - -#include <grpc/support/log.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/cpp/util/test_config.h" - -DEFINE_string(address, "", "Address to connect to"); -DEFINE_string(mode, "", "Test mode to use"); - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; - -int main(int argc, char** argv) { - grpc::testing::InitTest(&argc, &argv, true); - auto stub = grpc::testing::EchoTestService::NewStub( - grpc::CreateChannel(FLAGS_address, grpc::InsecureChannelCredentials())); - - EchoRequest request; - EchoResponse response; - grpc::ClientContext context; - context.set_wait_for_ready(true); - - if (FLAGS_mode == "bidi") { - auto stream = stub->BidiStream(&context); - for (int i = 0;; i++) { - std::ostringstream msg; - msg << "Hello " << i; - request.set_message(msg.str()); - GPR_ASSERT(stream->Write(request)); - GPR_ASSERT(stream->Read(&response)); - GPR_ASSERT(response.message() == request.message()); - } - } else if (FLAGS_mode == "response") { - EchoRequest request; - request.set_message("Hello"); - auto stream = stub->ResponseStream(&context, request); - for (;;) { - GPR_ASSERT(stream->Read(&response)); - } - } else { - gpr_log(GPR_ERROR, "invalid test mode '%s'", FLAGS_mode.c_str()); - return 1; - } - - return 0; -} + +#include <grpc/support/log.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/cpp/util/test_config.h" + +DEFINE_string(address, "", "Address to connect to"); +DEFINE_string(mode, "", "Test mode to use"); + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; + +int main(int argc, char** argv) { + grpc::testing::InitTest(&argc, &argv, true); + auto stub = grpc::testing::EchoTestService::NewStub( + grpc::CreateChannel(FLAGS_address, grpc::InsecureChannelCredentials())); + + EchoRequest request; + EchoResponse response; + grpc::ClientContext context; + context.set_wait_for_ready(true); + + if (FLAGS_mode == "bidi") { + auto stream = stub->BidiStream(&context); + for (int i = 0;; i++) { + std::ostringstream msg; + msg << "Hello " << i; + request.set_message(msg.str()); + GPR_ASSERT(stream->Write(request)); + GPR_ASSERT(stream->Read(&response)); + GPR_ASSERT(response.message() == request.message()); + } + } else if (FLAGS_mode == "response") { + EchoRequest request; + request.set_message("Hello"); + auto stream = stub->ResponseStream(&context, request); + for (;;) { + GPR_ASSERT(stream->Read(&response)); + } + } else { + gpr_log(GPR_ERROR, "invalid test mode '%s'", FLAGS_mode.c_str()); + return 1; + } + + return 0; +} diff --git a/contrib/libs/grpc/test/cpp/end2end/server_early_return_test.cc b/contrib/libs/grpc/test/cpp/end2end/server_early_return_test.cc index 973168411c..0f340516b0 100644 --- a/contrib/libs/grpc/test/cpp/end2end/server_early_return_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/server_early_return_test.cc @@ -1,232 +1,232 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ - -#include <grpc/grpc.h> -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/security/credentials.h> -#include <grpcpp/security/server_credentials.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/util/string_ref_helper.h" - -#include <gtest/gtest.h> - -namespace grpc { -namespace testing { -namespace { - -const char kServerReturnStatusCode[] = "server_return_status_code"; -const char kServerDelayBeforeReturnUs[] = "server_delay_before_return_us"; -const char kServerReturnAfterNReads[] = "server_return_after_n_reads"; - -class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { - public: - // Unused methods are not implemented. - - Status RequestStream(ServerContext* context, - ServerReader<EchoRequest>* reader, - EchoResponse* response) override { - int server_return_status_code = - GetIntValueFromMetadata(context, kServerReturnStatusCode, 0); - int server_delay_before_return_us = - GetIntValueFromMetadata(context, kServerDelayBeforeReturnUs, 0); - int server_return_after_n_reads = - GetIntValueFromMetadata(context, kServerReturnAfterNReads, 0); - - EchoRequest request; - while (server_return_after_n_reads--) { - EXPECT_TRUE(reader->Read(&request)); - } - - response->set_message("response msg"); - - gpr_sleep_until(gpr_time_add( - gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_micros(server_delay_before_return_us, GPR_TIMESPAN))); - - return Status(static_cast<StatusCode>(server_return_status_code), ""); - } - - Status BidiStream( - ServerContext* context, - ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { - int server_return_status_code = - GetIntValueFromMetadata(context, kServerReturnStatusCode, 0); - int server_delay_before_return_us = - GetIntValueFromMetadata(context, kServerDelayBeforeReturnUs, 0); - int server_return_after_n_reads = - GetIntValueFromMetadata(context, kServerReturnAfterNReads, 0); - - EchoRequest request; - EchoResponse response; - while (server_return_after_n_reads--) { - EXPECT_TRUE(stream->Read(&request)); - response.set_message(request.message()); - EXPECT_TRUE(stream->Write(response)); - } - - gpr_sleep_until(gpr_time_add( - gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_micros(server_delay_before_return_us, GPR_TIMESPAN))); - - return Status(static_cast<StatusCode>(server_return_status_code), ""); - } - - int GetIntValueFromMetadata(ServerContext* context, const char* key, - int default_value) { - auto metadata = context->client_metadata(); - if (metadata.find(key) != metadata.end()) { - std::istringstream iss(ToString(metadata.find(key)->second)); - iss >> default_value; - } - return default_value; - } -}; - -class ServerEarlyReturnTest : public ::testing::Test { - protected: - ServerEarlyReturnTest() : picked_port_(0) {} - - void SetUp() override { - int port = grpc_pick_unused_port_or_die(); - picked_port_ = port; - server_address_ << "127.0.0.1:" << port; - ServerBuilder builder; - builder.AddListeningPort(server_address_.str(), - InsecureServerCredentials()); - builder.RegisterService(&service_); - server_ = builder.BuildAndStart(); - - channel_ = grpc::CreateChannel(server_address_.str(), - InsecureChannelCredentials()); - stub_ = grpc::testing::EchoTestService::NewStub(channel_); - } - - void TearDown() override { - server_->Shutdown(); - if (picked_port_ > 0) { - grpc_recycle_unused_port(picked_port_); - } - } - - // Client sends 20 requests and the server returns after reading 10 requests. - // If return_cancel is true, server returns CANCELLED status. Otherwise it - // returns OK. - void DoBidiStream(bool return_cancelled) { - EchoRequest request; - EchoResponse response; - ClientContext context; - - context.AddMetadata(kServerReturnAfterNReads, "10"); - if (return_cancelled) { - // "1" means CANCELLED - context.AddMetadata(kServerReturnStatusCode, "1"); - } - context.AddMetadata(kServerDelayBeforeReturnUs, "10000"); - - auto stream = stub_->BidiStream(&context); - - for (int i = 0; i < 20; i++) { +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/security/credentials.h> +#include <grpcpp/security/server_credentials.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/util/string_ref_helper.h" + +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { +namespace { + +const char kServerReturnStatusCode[] = "server_return_status_code"; +const char kServerDelayBeforeReturnUs[] = "server_delay_before_return_us"; +const char kServerReturnAfterNReads[] = "server_return_after_n_reads"; + +class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { + public: + // Unused methods are not implemented. + + Status RequestStream(ServerContext* context, + ServerReader<EchoRequest>* reader, + EchoResponse* response) override { + int server_return_status_code = + GetIntValueFromMetadata(context, kServerReturnStatusCode, 0); + int server_delay_before_return_us = + GetIntValueFromMetadata(context, kServerDelayBeforeReturnUs, 0); + int server_return_after_n_reads = + GetIntValueFromMetadata(context, kServerReturnAfterNReads, 0); + + EchoRequest request; + while (server_return_after_n_reads--) { + EXPECT_TRUE(reader->Read(&request)); + } + + response->set_message("response msg"); + + gpr_sleep_until(gpr_time_add( + gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_micros(server_delay_before_return_us, GPR_TIMESPAN))); + + return Status(static_cast<StatusCode>(server_return_status_code), ""); + } + + Status BidiStream( + ServerContext* context, + ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { + int server_return_status_code = + GetIntValueFromMetadata(context, kServerReturnStatusCode, 0); + int server_delay_before_return_us = + GetIntValueFromMetadata(context, kServerDelayBeforeReturnUs, 0); + int server_return_after_n_reads = + GetIntValueFromMetadata(context, kServerReturnAfterNReads, 0); + + EchoRequest request; + EchoResponse response; + while (server_return_after_n_reads--) { + EXPECT_TRUE(stream->Read(&request)); + response.set_message(request.message()); + EXPECT_TRUE(stream->Write(response)); + } + + gpr_sleep_until(gpr_time_add( + gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_micros(server_delay_before_return_us, GPR_TIMESPAN))); + + return Status(static_cast<StatusCode>(server_return_status_code), ""); + } + + int GetIntValueFromMetadata(ServerContext* context, const char* key, + int default_value) { + auto metadata = context->client_metadata(); + if (metadata.find(key) != metadata.end()) { + std::istringstream iss(ToString(metadata.find(key)->second)); + iss >> default_value; + } + return default_value; + } +}; + +class ServerEarlyReturnTest : public ::testing::Test { + protected: + ServerEarlyReturnTest() : picked_port_(0) {} + + void SetUp() override { + int port = grpc_pick_unused_port_or_die(); + picked_port_ = port; + server_address_ << "127.0.0.1:" << port; + ServerBuilder builder; + builder.AddListeningPort(server_address_.str(), + InsecureServerCredentials()); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + + channel_ = grpc::CreateChannel(server_address_.str(), + InsecureChannelCredentials()); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + void TearDown() override { + server_->Shutdown(); + if (picked_port_ > 0) { + grpc_recycle_unused_port(picked_port_); + } + } + + // Client sends 20 requests and the server returns after reading 10 requests. + // If return_cancel is true, server returns CANCELLED status. Otherwise it + // returns OK. + void DoBidiStream(bool return_cancelled) { + EchoRequest request; + EchoResponse response; + ClientContext context; + + context.AddMetadata(kServerReturnAfterNReads, "10"); + if (return_cancelled) { + // "1" means CANCELLED + context.AddMetadata(kServerReturnStatusCode, "1"); + } + context.AddMetadata(kServerDelayBeforeReturnUs, "10000"); + + auto stream = stub_->BidiStream(&context); + + for (int i = 0; i < 20; i++) { request.set_message(TString("hello") + ToString(i)); - bool write_ok = stream->Write(request); - bool read_ok = stream->Read(&response); - if (i < 10) { - EXPECT_TRUE(write_ok); - EXPECT_TRUE(read_ok); - EXPECT_EQ(response.message(), request.message()); - } else { - EXPECT_FALSE(read_ok); - } - } - - stream->WritesDone(); - EXPECT_FALSE(stream->Read(&response)); - - Status s = stream->Finish(); - if (return_cancelled) { - EXPECT_EQ(s.error_code(), StatusCode::CANCELLED); - } else { - EXPECT_TRUE(s.ok()); - } - } - - void DoRequestStream(bool return_cancelled) { - EchoRequest request; - EchoResponse response; - ClientContext context; - - context.AddMetadata(kServerReturnAfterNReads, "10"); - if (return_cancelled) { - // "1" means CANCELLED - context.AddMetadata(kServerReturnStatusCode, "1"); - } - context.AddMetadata(kServerDelayBeforeReturnUs, "10000"); - - auto stream = stub_->RequestStream(&context, &response); - for (int i = 0; i < 20; i++) { + bool write_ok = stream->Write(request); + bool read_ok = stream->Read(&response); + if (i < 10) { + EXPECT_TRUE(write_ok); + EXPECT_TRUE(read_ok); + EXPECT_EQ(response.message(), request.message()); + } else { + EXPECT_FALSE(read_ok); + } + } + + stream->WritesDone(); + EXPECT_FALSE(stream->Read(&response)); + + Status s = stream->Finish(); + if (return_cancelled) { + EXPECT_EQ(s.error_code(), StatusCode::CANCELLED); + } else { + EXPECT_TRUE(s.ok()); + } + } + + void DoRequestStream(bool return_cancelled) { + EchoRequest request; + EchoResponse response; + ClientContext context; + + context.AddMetadata(kServerReturnAfterNReads, "10"); + if (return_cancelled) { + // "1" means CANCELLED + context.AddMetadata(kServerReturnStatusCode, "1"); + } + context.AddMetadata(kServerDelayBeforeReturnUs, "10000"); + + auto stream = stub_->RequestStream(&context, &response); + for (int i = 0; i < 20; i++) { request.set_message(TString("hello") + ToString(i)); - bool written = stream->Write(request); - if (i < 10) { - EXPECT_TRUE(written); - } - } - stream->WritesDone(); - Status s = stream->Finish(); - if (return_cancelled) { - EXPECT_EQ(s.error_code(), StatusCode::CANCELLED); - } else { - EXPECT_TRUE(s.ok()); - } - } - - std::shared_ptr<Channel> channel_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - std::ostringstream server_address_; - TestServiceImpl service_; - int picked_port_; -}; - -TEST_F(ServerEarlyReturnTest, BidiStreamEarlyOk) { DoBidiStream(false); } - -TEST_F(ServerEarlyReturnTest, BidiStreamEarlyCancel) { DoBidiStream(true); } - -TEST_F(ServerEarlyReturnTest, RequestStreamEarlyOK) { DoRequestStream(false); } -TEST_F(ServerEarlyReturnTest, RequestStreamEarlyCancel) { - DoRequestStream(true); -} - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + bool written = stream->Write(request); + if (i < 10) { + EXPECT_TRUE(written); + } + } + stream->WritesDone(); + Status s = stream->Finish(); + if (return_cancelled) { + EXPECT_EQ(s.error_code(), StatusCode::CANCELLED); + } else { + EXPECT_TRUE(s.ok()); + } + } + + std::shared_ptr<Channel> channel_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + std::ostringstream server_address_; + TestServiceImpl service_; + int picked_port_; +}; + +TEST_F(ServerEarlyReturnTest, BidiStreamEarlyOk) { DoBidiStream(false); } + +TEST_F(ServerEarlyReturnTest, BidiStreamEarlyCancel) { DoBidiStream(true); } + +TEST_F(ServerEarlyReturnTest, RequestStreamEarlyOK) { DoRequestStream(false); } +TEST_F(ServerEarlyReturnTest, RequestStreamEarlyCancel) { + DoRequestStream(true); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/server_interceptors/ya.make b/contrib/libs/grpc/test/cpp/end2end/server_interceptors/ya.make index 4405208f4c..161176f141 100644 --- a/contrib/libs/grpc/test/cpp/end2end/server_interceptors/ya.make +++ b/contrib/libs/grpc/test/cpp/end2end/server_interceptors/ya.make @@ -1,32 +1,32 @@ GTEST_UGLY() - -OWNER( - dvshkurko - g:ymake -) - -ADDINCL( + +OWNER( + dvshkurko + g:ymake +) + +ADDINCL( ${ARCADIA_BUILD_ROOT}/contrib/libs/grpc - ${ARCADIA_ROOT}/contrib/libs/grpc -) - -PEERDIR( - contrib/libs/grpc/src/proto/grpc/core - contrib/libs/grpc/src/proto/grpc/testing - contrib/libs/grpc/src/proto/grpc/testing/duplicate - contrib/libs/grpc/test/core/util - contrib/libs/grpc/test/cpp/end2end - contrib/libs/grpc/test/cpp/util -) - -NO_COMPILER_WARNINGS() - -SRCDIR( - contrib/libs/grpc/test/cpp/end2end -) - -SRCS( - server_interceptors_end2end_test.cc -) - -END() + ${ARCADIA_ROOT}/contrib/libs/grpc +) + +PEERDIR( + contrib/libs/grpc/src/proto/grpc/core + contrib/libs/grpc/src/proto/grpc/testing + contrib/libs/grpc/src/proto/grpc/testing/duplicate + contrib/libs/grpc/test/core/util + contrib/libs/grpc/test/cpp/end2end + contrib/libs/grpc/test/cpp/util +) + +NO_COMPILER_WARNINGS() + +SRCDIR( + contrib/libs/grpc/test/cpp/end2end +) + +SRCS( + server_interceptors_end2end_test.cc +) + +END() diff --git a/contrib/libs/grpc/test/cpp/end2end/server_interceptors_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/server_interceptors_end2end_test.cc index 2f6a71ebd4..6d2dc772ef 100644 --- a/contrib/libs/grpc/test/cpp/end2end/server_interceptors_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/server_interceptors_end2end_test.cc @@ -1,708 +1,708 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ - -#include <memory> -#include <vector> - -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/generic/generic_stub.h> -#include <grpcpp/impl/codegen/proto_utils.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> -#include <grpcpp/support/server_interceptor.h> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/interceptors_util.h" -#include "test/cpp/end2end/test_service_impl.h" -#include "test/cpp/util/byte_buffer_proto_helper.h" - -#include <gtest/gtest.h> - -namespace grpc { -namespace testing { -namespace { - -class LoggingInterceptor : public experimental::Interceptor { - public: - LoggingInterceptor(experimental::ServerRpcInfo* info) { - info_ = info; - - // Check the method name and compare to the type - const char* method = info->method(); - experimental::ServerRpcInfo::Type type = info->type(); - - // Check that we use one of our standard methods with expected type. - // Also allow the health checking service. - // We accept BIDI_STREAMING for Echo in case it's an AsyncGenericService - // being tested (the GenericRpc test). - // The empty method is for the Unimplemented requests that arise - // when draining the CQ. - EXPECT_TRUE( - strstr(method, "/grpc.health") == method || - (strcmp(method, "/grpc.testing.EchoTestService/Echo") == 0 && - (type == experimental::ServerRpcInfo::Type::UNARY || - type == experimental::ServerRpcInfo::Type::BIDI_STREAMING)) || - (strcmp(method, "/grpc.testing.EchoTestService/RequestStream") == 0 && - type == experimental::ServerRpcInfo::Type::CLIENT_STREAMING) || - (strcmp(method, "/grpc.testing.EchoTestService/ResponseStream") == 0 && - type == experimental::ServerRpcInfo::Type::SERVER_STREAMING) || - (strcmp(method, "/grpc.testing.EchoTestService/BidiStream") == 0 && - type == experimental::ServerRpcInfo::Type::BIDI_STREAMING) || - strcmp(method, "/grpc.testing.EchoTestService/Unimplemented") == 0 || - (strcmp(method, "") == 0 && - type == experimental::ServerRpcInfo::Type::BIDI_STREAMING)); - } - - void Intercept(experimental::InterceptorBatchMethods* methods) override { - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { - auto* map = methods->GetSendInitialMetadata(); - // Got nothing better to do here for now - EXPECT_EQ(map->size(), static_cast<unsigned>(0)); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - EchoRequest req; - auto* buffer = methods->GetSerializedSendMessage(); - auto copied_buffer = *buffer; - EXPECT_TRUE( - SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) - .ok()); - EXPECT_TRUE(req.message().find("Hello") == 0); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_STATUS)) { - auto* map = methods->GetSendTrailingMetadata(); - bool found = false; - // Check that we received the metadata as an echo - for (const auto& pair : *map) { - found = pair.first.find("testkey") == 0 && - pair.second.find("testvalue") == 0; - if (found) break; - } - EXPECT_EQ(found, true); - auto status = methods->GetSendStatus(); - EXPECT_EQ(status.ok(), true); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { - auto* map = methods->GetRecvInitialMetadata(); - bool found = false; - // Check that we received the metadata as an echo - for (const auto& pair : *map) { - found = pair.first.find("testkey") == 0 && - pair.second.find("testvalue") == 0; - if (found) break; - } - EXPECT_EQ(found, true); - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { - EchoResponse* resp = - static_cast<EchoResponse*>(methods->GetRecvMessage()); - if (resp != nullptr) { - EXPECT_TRUE(resp->message().find("Hello") == 0); - } - } - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_CLOSE)) { - // Got nothing interesting to do here - } - methods->Proceed(); - } - - private: - experimental::ServerRpcInfo* info_; -}; - -class LoggingInterceptorFactory - : public experimental::ServerInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateServerInterceptor( - experimental::ServerRpcInfo* info) override { - return new LoggingInterceptor(info); - } -}; - -// Test if SendMessage function family works as expected for sync/callback apis -class SyncSendMessageTester : public experimental::Interceptor { - public: - SyncSendMessageTester(experimental::ServerRpcInfo* /*info*/) {} - - void Intercept(experimental::InterceptorBatchMethods* methods) override { - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - string old_msg = - static_cast<const EchoRequest*>(methods->GetSendMessage())->message(); - EXPECT_EQ(old_msg.find("Hello"), 0u); +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ + +#include <memory> +#include <vector> + +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/generic/generic_stub.h> +#include <grpcpp/impl/codegen/proto_utils.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> +#include <grpcpp/support/server_interceptor.h> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/interceptors_util.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" + +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { +namespace { + +class LoggingInterceptor : public experimental::Interceptor { + public: + LoggingInterceptor(experimental::ServerRpcInfo* info) { + info_ = info; + + // Check the method name and compare to the type + const char* method = info->method(); + experimental::ServerRpcInfo::Type type = info->type(); + + // Check that we use one of our standard methods with expected type. + // Also allow the health checking service. + // We accept BIDI_STREAMING for Echo in case it's an AsyncGenericService + // being tested (the GenericRpc test). + // The empty method is for the Unimplemented requests that arise + // when draining the CQ. + EXPECT_TRUE( + strstr(method, "/grpc.health") == method || + (strcmp(method, "/grpc.testing.EchoTestService/Echo") == 0 && + (type == experimental::ServerRpcInfo::Type::UNARY || + type == experimental::ServerRpcInfo::Type::BIDI_STREAMING)) || + (strcmp(method, "/grpc.testing.EchoTestService/RequestStream") == 0 && + type == experimental::ServerRpcInfo::Type::CLIENT_STREAMING) || + (strcmp(method, "/grpc.testing.EchoTestService/ResponseStream") == 0 && + type == experimental::ServerRpcInfo::Type::SERVER_STREAMING) || + (strcmp(method, "/grpc.testing.EchoTestService/BidiStream") == 0 && + type == experimental::ServerRpcInfo::Type::BIDI_STREAMING) || + strcmp(method, "/grpc.testing.EchoTestService/Unimplemented") == 0 || + (strcmp(method, "") == 0 && + type == experimental::ServerRpcInfo::Type::BIDI_STREAMING)); + } + + void Intercept(experimental::InterceptorBatchMethods* methods) override { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + auto* map = methods->GetSendInitialMetadata(); + // Got nothing better to do here for now + EXPECT_EQ(map->size(), static_cast<unsigned>(0)); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSerializedSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_TRUE(req.message().find("Hello") == 0); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_STATUS)) { + auto* map = methods->GetSendTrailingMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.find("testkey") == 0 && + pair.second.find("testvalue") == 0; + if (found) break; + } + EXPECT_EQ(found, true); + auto status = methods->GetSendStatus(); + EXPECT_EQ(status.ok(), true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { + auto* map = methods->GetRecvInitialMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.find("testkey") == 0 && + pair.second.find("testvalue") == 0; + if (found) break; + } + EXPECT_EQ(found, true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + EchoResponse* resp = + static_cast<EchoResponse*>(methods->GetRecvMessage()); + if (resp != nullptr) { + EXPECT_TRUE(resp->message().find("Hello") == 0); + } + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_CLOSE)) { + // Got nothing interesting to do here + } + methods->Proceed(); + } + + private: + experimental::ServerRpcInfo* info_; +}; + +class LoggingInterceptorFactory + : public experimental::ServerInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateServerInterceptor( + experimental::ServerRpcInfo* info) override { + return new LoggingInterceptor(info); + } +}; + +// Test if SendMessage function family works as expected for sync/callback apis +class SyncSendMessageTester : public experimental::Interceptor { + public: + SyncSendMessageTester(experimental::ServerRpcInfo* /*info*/) {} + + void Intercept(experimental::InterceptorBatchMethods* methods) override { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + string old_msg = + static_cast<const EchoRequest*>(methods->GetSendMessage())->message(); + EXPECT_EQ(old_msg.find("Hello"), 0u); new_msg_.set_message(TString("World" + old_msg).c_str()); - methods->ModifySendMessage(&new_msg_); - } - methods->Proceed(); - } - - private: - EchoRequest new_msg_; -}; - -class SyncSendMessageTesterFactory - : public experimental::ServerInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateServerInterceptor( - experimental::ServerRpcInfo* info) override { - return new SyncSendMessageTester(info); - } -}; - -// Test if SendMessage function family works as expected for sync/callback apis -class SyncSendMessageVerifier : public experimental::Interceptor { - public: - SyncSendMessageVerifier(experimental::ServerRpcInfo* /*info*/) {} - - void Intercept(experimental::InterceptorBatchMethods* methods) override { - if (methods->QueryInterceptionHookPoint( - experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - // Make sure that the changes made in SyncSendMessageTester persisted + methods->ModifySendMessage(&new_msg_); + } + methods->Proceed(); + } + + private: + EchoRequest new_msg_; +}; + +class SyncSendMessageTesterFactory + : public experimental::ServerInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateServerInterceptor( + experimental::ServerRpcInfo* info) override { + return new SyncSendMessageTester(info); + } +}; + +// Test if SendMessage function family works as expected for sync/callback apis +class SyncSendMessageVerifier : public experimental::Interceptor { + public: + SyncSendMessageVerifier(experimental::ServerRpcInfo* /*info*/) {} + + void Intercept(experimental::InterceptorBatchMethods* methods) override { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + // Make sure that the changes made in SyncSendMessageTester persisted string old_msg = - static_cast<const EchoRequest*>(methods->GetSendMessage())->message(); - EXPECT_EQ(old_msg.find("World"), 0u); - - // Remove the "World" part of the string that we added earlier - new_msg_.set_message(old_msg.erase(0, 5)); - methods->ModifySendMessage(&new_msg_); - - // LoggingInterceptor verifies that changes got reverted - } - methods->Proceed(); - } - - private: - EchoRequest new_msg_; -}; - -class SyncSendMessageVerifierFactory - : public experimental::ServerInterceptorFactoryInterface { - public: - virtual experimental::Interceptor* CreateServerInterceptor( - experimental::ServerRpcInfo* info) override { - return new SyncSendMessageVerifier(info); - } -}; - -void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) { - auto stub = grpc::testing::EchoTestService::NewStub(channel); - ClientContext ctx; - EchoRequest req; - EchoResponse resp; - ctx.AddMetadata("testkey", "testvalue"); - auto stream = stub->BidiStream(&ctx); - for (auto i = 0; i < 10; i++) { + static_cast<const EchoRequest*>(methods->GetSendMessage())->message(); + EXPECT_EQ(old_msg.find("World"), 0u); + + // Remove the "World" part of the string that we added earlier + new_msg_.set_message(old_msg.erase(0, 5)); + methods->ModifySendMessage(&new_msg_); + + // LoggingInterceptor verifies that changes got reverted + } + methods->Proceed(); + } + + private: + EchoRequest new_msg_; +}; + +class SyncSendMessageVerifierFactory + : public experimental::ServerInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateServerInterceptor( + experimental::ServerRpcInfo* info) override { + return new SyncSendMessageVerifier(info); + } +}; + +void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) { + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + EchoResponse resp; + ctx.AddMetadata("testkey", "testvalue"); + auto stream = stub->BidiStream(&ctx); + for (auto i = 0; i < 10; i++) { req.set_message("Hello" + ::ToString(i)); - stream->Write(req); - stream->Read(&resp); - EXPECT_EQ(req.message(), resp.message()); - } - ASSERT_TRUE(stream->WritesDone()); - Status s = stream->Finish(); - EXPECT_EQ(s.ok(), true); -} - -class ServerInterceptorsEnd2endSyncUnaryTest : public ::testing::Test { - protected: - ServerInterceptorsEnd2endSyncUnaryTest() { - int port = 5004; // grpc_pick_unused_port_or_die(); - - ServerBuilder builder; + stream->Write(req); + stream->Read(&resp); + EXPECT_EQ(req.message(), resp.message()); + } + ASSERT_TRUE(stream->WritesDone()); + Status s = stream->Finish(); + EXPECT_EQ(s.ok(), true); +} + +class ServerInterceptorsEnd2endSyncUnaryTest : public ::testing::Test { + protected: + ServerInterceptorsEnd2endSyncUnaryTest() { + int port = 5004; // grpc_pick_unused_port_or_die(); + + ServerBuilder builder; server_address_ = "localhost:" + ::ToString(port); - builder.AddListeningPort(server_address_, InsecureServerCredentials()); - builder.RegisterService(&service_); - - std::vector< - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> - creators; - creators.push_back( - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( - new SyncSendMessageTesterFactory())); - creators.push_back( - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( - new SyncSendMessageVerifierFactory())); - creators.push_back( - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( - new LoggingInterceptorFactory())); - // Add 20 dummy interceptor factories and null interceptor factories - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - creators.push_back(std::unique_ptr<NullInterceptorFactory>( - new NullInterceptorFactory())); - } - builder.experimental().SetInterceptorCreators(std::move(creators)); - server_ = builder.BuildAndStart(); - } + builder.AddListeningPort(server_address_, InsecureServerCredentials()); + builder.RegisterService(&service_); + + std::vector< + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new SyncSendMessageTesterFactory())); + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new SyncSendMessageVerifierFactory())); + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new LoggingInterceptorFactory())); + // Add 20 dummy interceptor factories and null interceptor factories + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + creators.push_back(std::unique_ptr<NullInterceptorFactory>( + new NullInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + server_ = builder.BuildAndStart(); + } TString server_address_; - TestServiceImpl service_; - std::unique_ptr<Server> server_; -}; - -TEST_F(ServerInterceptorsEnd2endSyncUnaryTest, UnaryTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - auto channel = - grpc::CreateChannel(server_address_, InsecureChannelCredentials()); - MakeCall(channel); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - -class ServerInterceptorsEnd2endSyncStreamingTest : public ::testing::Test { - protected: - ServerInterceptorsEnd2endSyncStreamingTest() { - int port = 5005; // grpc_pick_unused_port_or_die(); - - ServerBuilder builder; + TestServiceImpl service_; + std::unique_ptr<Server> server_; +}; + +TEST_F(ServerInterceptorsEnd2endSyncUnaryTest, UnaryTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + auto channel = + grpc::CreateChannel(server_address_, InsecureChannelCredentials()); + MakeCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +class ServerInterceptorsEnd2endSyncStreamingTest : public ::testing::Test { + protected: + ServerInterceptorsEnd2endSyncStreamingTest() { + int port = 5005; // grpc_pick_unused_port_or_die(); + + ServerBuilder builder; server_address_ = "localhost:" + ::ToString(port); - builder.AddListeningPort(server_address_, InsecureServerCredentials()); - builder.RegisterService(&service_); - - std::vector< - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> - creators; - creators.push_back( - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( - new SyncSendMessageTesterFactory())); - creators.push_back( - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( - new SyncSendMessageVerifierFactory())); - creators.push_back( - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( - new LoggingInterceptorFactory())); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - builder.experimental().SetInterceptorCreators(std::move(creators)); - server_ = builder.BuildAndStart(); - } + builder.AddListeningPort(server_address_, InsecureServerCredentials()); + builder.RegisterService(&service_); + + std::vector< + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new SyncSendMessageTesterFactory())); + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new SyncSendMessageVerifierFactory())); + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new LoggingInterceptorFactory())); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + server_ = builder.BuildAndStart(); + } TString server_address_; - EchoTestServiceStreamingImpl service_; - std::unique_ptr<Server> server_; -}; - -TEST_F(ServerInterceptorsEnd2endSyncStreamingTest, ClientStreamingTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - auto channel = - grpc::CreateChannel(server_address_, InsecureChannelCredentials()); - MakeClientStreamingCall(channel); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - -TEST_F(ServerInterceptorsEnd2endSyncStreamingTest, ServerStreamingTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - auto channel = - grpc::CreateChannel(server_address_, InsecureChannelCredentials()); - MakeServerStreamingCall(channel); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - -TEST_F(ServerInterceptorsEnd2endSyncStreamingTest, BidiStreamingTest) { - ChannelArguments args; - DummyInterceptor::Reset(); - auto channel = - grpc::CreateChannel(server_address_, InsecureChannelCredentials()); - MakeBidiStreamingCall(channel); - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); -} - -class ServerInterceptorsAsyncEnd2endTest : public ::testing::Test {}; - -TEST_F(ServerInterceptorsAsyncEnd2endTest, UnaryTest) { - DummyInterceptor::Reset(); - int port = 5006; // grpc_pick_unused_port_or_die(); + EchoTestServiceStreamingImpl service_; + std::unique_ptr<Server> server_; +}; + +TEST_F(ServerInterceptorsEnd2endSyncStreamingTest, ClientStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + auto channel = + grpc::CreateChannel(server_address_, InsecureChannelCredentials()); + MakeClientStreamingCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ServerInterceptorsEnd2endSyncStreamingTest, ServerStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + auto channel = + grpc::CreateChannel(server_address_, InsecureChannelCredentials()); + MakeServerStreamingCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +TEST_F(ServerInterceptorsEnd2endSyncStreamingTest, BidiStreamingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + auto channel = + grpc::CreateChannel(server_address_, InsecureChannelCredentials()); + MakeBidiStreamingCall(channel); + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); +} + +class ServerInterceptorsAsyncEnd2endTest : public ::testing::Test {}; + +TEST_F(ServerInterceptorsAsyncEnd2endTest, UnaryTest) { + DummyInterceptor::Reset(); + int port = 5006; // grpc_pick_unused_port_or_die(); string server_address = "localhost:" + ::ToString(port); - ServerBuilder builder; - EchoTestService::AsyncService service; - builder.AddListeningPort(server_address, InsecureServerCredentials()); - builder.RegisterService(&service); - std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> - creators; - creators.push_back( - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( - new LoggingInterceptorFactory())); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - builder.experimental().SetInterceptorCreators(std::move(creators)); - auto cq = builder.AddCompletionQueue(); - auto server = builder.BuildAndStart(); - - ChannelArguments args; - auto channel = - grpc::CreateChannel(server_address, InsecureChannelCredentials()); - auto stub = grpc::testing::EchoTestService::NewStub(channel); - - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); - - send_request.set_message("Hello"); - cli_ctx.AddMetadata("testkey", "testvalue"); - 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(), - cq.get(), tag(2)); - - response_reader->Finish(&recv_response, &recv_status, tag(4)); - - Verifier().Expect(2, true).Verify(cq.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - EXPECT_TRUE(CheckMetadata(srv_ctx.client_metadata(), "testkey", "testvalue")); - srv_ctx.AddTrailingMetadata("testkey", "testvalue"); - - send_response.set_message(recv_request.message()); - response_writer.Finish(send_response, Status::OK, tag(3)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq.get()); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - EXPECT_TRUE(CheckMetadata(cli_ctx.GetServerTrailingMetadata(), "testkey", - "testvalue")); - - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); - - server->Shutdown(); - cq->Shutdown(); - void* ignored_tag; - bool ignored_ok; - while (cq->Next(&ignored_tag, &ignored_ok)) - ; - // grpc_recycle_unused_port(port); -} - -TEST_F(ServerInterceptorsAsyncEnd2endTest, BidiStreamingTest) { - DummyInterceptor::Reset(); - int port = 5007; // grpc_pick_unused_port_or_die(); + ServerBuilder builder; + EchoTestService::AsyncService service; + builder.AddListeningPort(server_address, InsecureServerCredentials()); + builder.RegisterService(&service); + std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new LoggingInterceptorFactory())); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + auto cq = builder.AddCompletionQueue(); + auto server = builder.BuildAndStart(); + + ChannelArguments args; + auto channel = + grpc::CreateChannel(server_address, InsecureChannelCredentials()); + auto stub = grpc::testing::EchoTestService::NewStub(channel); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); + + send_request.set_message("Hello"); + cli_ctx.AddMetadata("testkey", "testvalue"); + 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(), + cq.get(), tag(2)); + + response_reader->Finish(&recv_response, &recv_status, tag(4)); + + Verifier().Expect(2, true).Verify(cq.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + EXPECT_TRUE(CheckMetadata(srv_ctx.client_metadata(), "testkey", "testvalue")); + srv_ctx.AddTrailingMetadata("testkey", "testvalue"); + + send_response.set_message(recv_request.message()); + response_writer.Finish(send_response, Status::OK, tag(3)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq.get()); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + EXPECT_TRUE(CheckMetadata(cli_ctx.GetServerTrailingMetadata(), "testkey", + "testvalue")); + + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + + server->Shutdown(); + cq->Shutdown(); + void* ignored_tag; + bool ignored_ok; + while (cq->Next(&ignored_tag, &ignored_ok)) + ; + // grpc_recycle_unused_port(port); +} + +TEST_F(ServerInterceptorsAsyncEnd2endTest, BidiStreamingTest) { + DummyInterceptor::Reset(); + int port = 5007; // grpc_pick_unused_port_or_die(); string server_address = "localhost:" + ::ToString(port); - ServerBuilder builder; - EchoTestService::AsyncService service; - builder.AddListeningPort(server_address, InsecureServerCredentials()); - builder.RegisterService(&service); - std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> - creators; - creators.push_back( - std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( - new LoggingInterceptorFactory())); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - builder.experimental().SetInterceptorCreators(std::move(creators)); - auto cq = builder.AddCompletionQueue(); - auto server = builder.BuildAndStart(); - - ChannelArguments args; - auto channel = - grpc::CreateChannel(server_address, InsecureChannelCredentials()); - auto stub = grpc::testing::EchoTestService::NewStub(channel); - - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - ServerContext srv_ctx; - grpc::ServerAsyncReaderWriter<EchoResponse, EchoRequest> srv_stream(&srv_ctx); - - send_request.set_message("Hello"); - cli_ctx.AddMetadata("testkey", "testvalue"); - 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(), tag(2)); - - Verifier().Expect(1, true).Expect(2, true).Verify(cq.get()); - - EXPECT_TRUE(CheckMetadata(srv_ctx.client_metadata(), "testkey", "testvalue")); - srv_ctx.AddTrailingMetadata("testkey", "testvalue"); - - cli_stream->Write(send_request, tag(3)); - srv_stream.Read(&recv_request, tag(4)); - Verifier().Expect(3, true).Expect(4, true).Verify(cq.get()); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - srv_stream.Write(send_response, tag(5)); - cli_stream->Read(&recv_response, tag(6)); - Verifier().Expect(5, true).Expect(6, true).Verify(cq.get()); - EXPECT_EQ(send_response.message(), recv_response.message()); - - cli_stream->WritesDone(tag(7)); - srv_stream.Read(&recv_request, tag(8)); - Verifier().Expect(7, true).Expect(8, false).Verify(cq.get()); - - srv_stream.Finish(Status::OK, tag(9)); - cli_stream->Finish(&recv_status, tag(10)); - Verifier().Expect(9, true).Expect(10, true).Verify(cq.get()); - - EXPECT_TRUE(recv_status.ok()); - EXPECT_TRUE(CheckMetadata(cli_ctx.GetServerTrailingMetadata(), "testkey", - "testvalue")); - - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); - - server->Shutdown(); - cq->Shutdown(); - void* ignored_tag; - bool ignored_ok; - while (cq->Next(&ignored_tag, &ignored_ok)) - ; - // grpc_recycle_unused_port(port); -} - -TEST_F(ServerInterceptorsAsyncEnd2endTest, GenericRPCTest) { - DummyInterceptor::Reset(); - int port = 5008; // grpc_pick_unused_port_or_die(); + ServerBuilder builder; + EchoTestService::AsyncService service; + builder.AddListeningPort(server_address, InsecureServerCredentials()); + builder.RegisterService(&service); + std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.push_back( + std::unique_ptr<experimental::ServerInterceptorFactoryInterface>( + new LoggingInterceptorFactory())); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + auto cq = builder.AddCompletionQueue(); + auto server = builder.BuildAndStart(); + + ChannelArguments args; + auto channel = + grpc::CreateChannel(server_address, InsecureChannelCredentials()); + auto stub = grpc::testing::EchoTestService::NewStub(channel); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncReaderWriter<EchoResponse, EchoRequest> srv_stream(&srv_ctx); + + send_request.set_message("Hello"); + cli_ctx.AddMetadata("testkey", "testvalue"); + 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(), tag(2)); + + Verifier().Expect(1, true).Expect(2, true).Verify(cq.get()); + + EXPECT_TRUE(CheckMetadata(srv_ctx.client_metadata(), "testkey", "testvalue")); + srv_ctx.AddTrailingMetadata("testkey", "testvalue"); + + cli_stream->Write(send_request, tag(3)); + srv_stream.Read(&recv_request, tag(4)); + Verifier().Expect(3, true).Expect(4, true).Verify(cq.get()); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + srv_stream.Write(send_response, tag(5)); + cli_stream->Read(&recv_response, tag(6)); + Verifier().Expect(5, true).Expect(6, true).Verify(cq.get()); + EXPECT_EQ(send_response.message(), recv_response.message()); + + cli_stream->WritesDone(tag(7)); + srv_stream.Read(&recv_request, tag(8)); + Verifier().Expect(7, true).Expect(8, false).Verify(cq.get()); + + srv_stream.Finish(Status::OK, tag(9)); + cli_stream->Finish(&recv_status, tag(10)); + Verifier().Expect(9, true).Expect(10, true).Verify(cq.get()); + + EXPECT_TRUE(recv_status.ok()); + EXPECT_TRUE(CheckMetadata(cli_ctx.GetServerTrailingMetadata(), "testkey", + "testvalue")); + + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + + server->Shutdown(); + cq->Shutdown(); + void* ignored_tag; + bool ignored_ok; + while (cq->Next(&ignored_tag, &ignored_ok)) + ; + // grpc_recycle_unused_port(port); +} + +TEST_F(ServerInterceptorsAsyncEnd2endTest, GenericRPCTest) { + DummyInterceptor::Reset(); + int port = 5008; // grpc_pick_unused_port_or_die(); string server_address = "localhost:" + ::ToString(port); - ServerBuilder builder; - AsyncGenericService service; - builder.AddListeningPort(server_address, InsecureServerCredentials()); - builder.RegisterAsyncGenericService(&service); - std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> - creators; - creators.reserve(20); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - builder.experimental().SetInterceptorCreators(std::move(creators)); - auto srv_cq = builder.AddCompletionQueue(); - CompletionQueue cli_cq; - auto server = builder.BuildAndStart(); - - ChannelArguments args; - auto channel = - grpc::CreateChannel(server_address, InsecureChannelCredentials()); - GenericStub generic_stub(channel); - + ServerBuilder builder; + AsyncGenericService service; + builder.AddListeningPort(server_address, InsecureServerCredentials()); + builder.RegisterAsyncGenericService(&service); + std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + auto srv_cq = builder.AddCompletionQueue(); + CompletionQueue cli_cq; + auto server = builder.BuildAndStart(); + + ChannelArguments args; + auto channel = + grpc::CreateChannel(server_address, InsecureChannelCredentials()); + GenericStub generic_stub(channel); + const TString kMethodName("/grpc.cpp.test.util.EchoTestService/Echo"); - EchoRequest send_request; - EchoRequest recv_request; - EchoResponse send_response; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - GenericServerContext srv_ctx; - GenericServerAsyncReaderWriter stream(&srv_ctx); - - // The string needs to be long enough to test heap-based slice. - send_request.set_message("Hello"); - cli_ctx.AddMetadata("testkey", "testvalue"); - + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + GenericServerContext srv_ctx; + GenericServerAsyncReaderWriter stream(&srv_ctx); + + // The string needs to be long enough to test heap-based slice. + send_request.set_message("Hello"); + cli_ctx.AddMetadata("testkey", "testvalue"); + CompletionQueue* cq = srv_cq.get(); std::thread request_call([cq]() { Verifier().Expect(4, true).Verify(cq); }); - std::unique_ptr<GenericClientAsyncReaderWriter> call = - generic_stub.PrepareCall(&cli_ctx, kMethodName, &cli_cq); - call->StartCall(tag(1)); - Verifier().Expect(1, true).Verify(&cli_cq); - std::unique_ptr<ByteBuffer> send_buffer = - SerializeToByteBuffer(&send_request); - call->Write(*send_buffer, tag(2)); - // Send ByteBuffer can be destroyed after calling Write. - send_buffer.reset(); - Verifier().Expect(2, true).Verify(&cli_cq); - call->WritesDone(tag(3)); - Verifier().Expect(3, true).Verify(&cli_cq); - - service.RequestCall(&srv_ctx, &stream, srv_cq.get(), srv_cq.get(), tag(4)); - + std::unique_ptr<GenericClientAsyncReaderWriter> call = + generic_stub.PrepareCall(&cli_ctx, kMethodName, &cli_cq); + call->StartCall(tag(1)); + Verifier().Expect(1, true).Verify(&cli_cq); + std::unique_ptr<ByteBuffer> send_buffer = + SerializeToByteBuffer(&send_request); + call->Write(*send_buffer, tag(2)); + // Send ByteBuffer can be destroyed after calling Write. + send_buffer.reset(); + Verifier().Expect(2, true).Verify(&cli_cq); + call->WritesDone(tag(3)); + Verifier().Expect(3, true).Verify(&cli_cq); + + service.RequestCall(&srv_ctx, &stream, srv_cq.get(), srv_cq.get(), tag(4)); + request_call.join(); - EXPECT_EQ(kMethodName, srv_ctx.method()); - EXPECT_TRUE(CheckMetadata(srv_ctx.client_metadata(), "testkey", "testvalue")); - srv_ctx.AddTrailingMetadata("testkey", "testvalue"); - - ByteBuffer recv_buffer; - stream.Read(&recv_buffer, tag(5)); - Verifier().Expect(5, true).Verify(srv_cq.get()); - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); - EXPECT_EQ(send_request.message(), recv_request.message()); - - send_response.set_message(recv_request.message()); - send_buffer = SerializeToByteBuffer(&send_response); - stream.Write(*send_buffer, tag(6)); - send_buffer.reset(); - Verifier().Expect(6, true).Verify(srv_cq.get()); - - stream.Finish(Status::OK, tag(7)); - // Shutdown srv_cq before we try to get the tag back, to verify that the - // interception API handles completion queue shutdowns that take place before - // all the tags are returned - srv_cq->Shutdown(); - Verifier().Expect(7, true).Verify(srv_cq.get()); - - recv_buffer.Clear(); - call->Read(&recv_buffer, tag(8)); - Verifier().Expect(8, true).Verify(&cli_cq); - EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); - - call->Finish(&recv_status, tag(9)); - cli_cq.Shutdown(); - Verifier().Expect(9, true).Verify(&cli_cq); - - EXPECT_EQ(send_response.message(), recv_response.message()); - EXPECT_TRUE(recv_status.ok()); - EXPECT_TRUE(CheckMetadata(cli_ctx.GetServerTrailingMetadata(), "testkey", - "testvalue")); - - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); - - server->Shutdown(); - void* ignored_tag; - bool ignored_ok; - while (cli_cq.Next(&ignored_tag, &ignored_ok)) - ; - while (srv_cq->Next(&ignored_tag, &ignored_ok)) - ; - // grpc_recycle_unused_port(port); -} - -TEST_F(ServerInterceptorsAsyncEnd2endTest, UnimplementedRpcTest) { - DummyInterceptor::Reset(); - int port = 5009; // grpc_pick_unused_port_or_die(); + EXPECT_EQ(kMethodName, srv_ctx.method()); + EXPECT_TRUE(CheckMetadata(srv_ctx.client_metadata(), "testkey", "testvalue")); + srv_ctx.AddTrailingMetadata("testkey", "testvalue"); + + ByteBuffer recv_buffer; + stream.Read(&recv_buffer, tag(5)); + Verifier().Expect(5, true).Verify(srv_cq.get()); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); + EXPECT_EQ(send_request.message(), recv_request.message()); + + send_response.set_message(recv_request.message()); + send_buffer = SerializeToByteBuffer(&send_response); + stream.Write(*send_buffer, tag(6)); + send_buffer.reset(); + Verifier().Expect(6, true).Verify(srv_cq.get()); + + stream.Finish(Status::OK, tag(7)); + // Shutdown srv_cq before we try to get the tag back, to verify that the + // interception API handles completion queue shutdowns that take place before + // all the tags are returned + srv_cq->Shutdown(); + Verifier().Expect(7, true).Verify(srv_cq.get()); + + recv_buffer.Clear(); + call->Read(&recv_buffer, tag(8)); + Verifier().Expect(8, true).Verify(&cli_cq); + EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); + + call->Finish(&recv_status, tag(9)); + cli_cq.Shutdown(); + Verifier().Expect(9, true).Verify(&cli_cq); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); + EXPECT_TRUE(CheckMetadata(cli_ctx.GetServerTrailingMetadata(), "testkey", + "testvalue")); + + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + + server->Shutdown(); + void* ignored_tag; + bool ignored_ok; + while (cli_cq.Next(&ignored_tag, &ignored_ok)) + ; + while (srv_cq->Next(&ignored_tag, &ignored_ok)) + ; + // grpc_recycle_unused_port(port); +} + +TEST_F(ServerInterceptorsAsyncEnd2endTest, UnimplementedRpcTest) { + DummyInterceptor::Reset(); + int port = 5009; // grpc_pick_unused_port_or_die(); string server_address = "localhost:" + ::ToString(port); - ServerBuilder builder; - builder.AddListeningPort(server_address, InsecureServerCredentials()); - std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> - creators; - creators.reserve(20); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - builder.experimental().SetInterceptorCreators(std::move(creators)); - auto cq = builder.AddCompletionQueue(); - auto server = builder.BuildAndStart(); - - ChannelArguments args; - std::shared_ptr<Channel> channel = - grpc::CreateChannel(server_address, InsecureChannelCredentials()); - std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; - stub = grpc::testing::UnimplementedEchoService::NewStub(channel); - EchoRequest send_request; - EchoResponse recv_response; - Status recv_status; - - ClientContext cli_ctx; - send_request.set_message("Hello"); - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( - stub->AsyncUnimplemented(&cli_ctx, send_request, cq.get())); - - response_reader->Finish(&recv_response, &recv_status, tag(4)); - Verifier().Expect(4, true).Verify(cq.get()); - - EXPECT_EQ(StatusCode::UNIMPLEMENTED, recv_status.error_code()); - EXPECT_EQ("", recv_status.error_message()); - - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); - - server->Shutdown(); - cq->Shutdown(); - void* ignored_tag; - bool ignored_ok; - while (cq->Next(&ignored_tag, &ignored_ok)) - ; - // grpc_recycle_unused_port(port); -} - -class ServerInterceptorsSyncUnimplementedEnd2endTest : public ::testing::Test { -}; - -TEST_F(ServerInterceptorsSyncUnimplementedEnd2endTest, UnimplementedRpcTest) { - DummyInterceptor::Reset(); - int port = 5010; // grpc_pick_unused_port_or_die(); + ServerBuilder builder; + builder.AddListeningPort(server_address, InsecureServerCredentials()); + std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + auto cq = builder.AddCompletionQueue(); + auto server = builder.BuildAndStart(); + + ChannelArguments args; + std::shared_ptr<Channel> channel = + grpc::CreateChannel(server_address, InsecureChannelCredentials()); + std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; + stub = grpc::testing::UnimplementedEchoService::NewStub(channel); + EchoRequest send_request; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + send_request.set_message("Hello"); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub->AsyncUnimplemented(&cli_ctx, send_request, cq.get())); + + response_reader->Finish(&recv_response, &recv_status, tag(4)); + Verifier().Expect(4, true).Verify(cq.get()); + + EXPECT_EQ(StatusCode::UNIMPLEMENTED, recv_status.error_code()); + EXPECT_EQ("", recv_status.error_message()); + + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + + server->Shutdown(); + cq->Shutdown(); + void* ignored_tag; + bool ignored_ok; + while (cq->Next(&ignored_tag, &ignored_ok)) + ; + // grpc_recycle_unused_port(port); +} + +class ServerInterceptorsSyncUnimplementedEnd2endTest : public ::testing::Test { +}; + +TEST_F(ServerInterceptorsSyncUnimplementedEnd2endTest, UnimplementedRpcTest) { + DummyInterceptor::Reset(); + int port = 5010; // grpc_pick_unused_port_or_die(); string server_address = "localhost:" + ::ToString(port); - ServerBuilder builder; - TestServiceImpl service; - builder.RegisterService(&service); - builder.AddListeningPort(server_address, InsecureServerCredentials()); - std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> - creators; - creators.reserve(20); - for (auto i = 0; i < 20; i++) { - creators.push_back(std::unique_ptr<DummyInterceptorFactory>( - new DummyInterceptorFactory())); - } - builder.experimental().SetInterceptorCreators(std::move(creators)); - auto server = builder.BuildAndStart(); - - ChannelArguments args; - std::shared_ptr<Channel> channel = - grpc::CreateChannel(server_address, InsecureChannelCredentials()); - std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; - stub = grpc::testing::UnimplementedEchoService::NewStub(channel); - EchoRequest send_request; - EchoResponse recv_response; - - ClientContext cli_ctx; - send_request.set_message("Hello"); - Status recv_status = - stub->Unimplemented(&cli_ctx, send_request, &recv_response); - - EXPECT_EQ(StatusCode::UNIMPLEMENTED, recv_status.error_code()); - EXPECT_EQ("", recv_status.error_message()); - - // Make sure all 20 dummy interceptors were run - EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); - - server->Shutdown(); - // grpc_recycle_unused_port(port); -} - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + ServerBuilder builder; + TestServiceImpl service; + builder.RegisterService(&service); + builder.AddListeningPort(server_address, InsecureServerCredentials()); + std::vector<std::unique_ptr<experimental::ServerInterceptorFactoryInterface>> + creators; + creators.reserve(20); + for (auto i = 0; i < 20; i++) { + creators.push_back(std::unique_ptr<DummyInterceptorFactory>( + new DummyInterceptorFactory())); + } + builder.experimental().SetInterceptorCreators(std::move(creators)); + auto server = builder.BuildAndStart(); + + ChannelArguments args; + std::shared_ptr<Channel> channel = + grpc::CreateChannel(server_address, InsecureChannelCredentials()); + std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub; + stub = grpc::testing::UnimplementedEchoService::NewStub(channel); + EchoRequest send_request; + EchoResponse recv_response; + + ClientContext cli_ctx; + send_request.set_message("Hello"); + Status recv_status = + stub->Unimplemented(&cli_ctx, send_request, &recv_response); + + EXPECT_EQ(StatusCode::UNIMPLEMENTED, recv_status.error_code()); + EXPECT_EQ("", recv_status.error_message()); + + // Make sure all 20 dummy interceptors were run + EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); + + server->Shutdown(); + // grpc_recycle_unused_port(port); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/server_load_reporting_end2end_test.cc b/contrib/libs/grpc/test/cpp/end2end/server_load_reporting_end2end_test.cc index d06b74e363..13833cf66c 100644 --- a/contrib/libs/grpc/test/cpp/end2end/server_load_reporting_end2end_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/server_load_reporting_end2end_test.cc @@ -1,192 +1,192 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ - -#include <grpc/support/port_platform.h> - -#include <thread> - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <grpc++/grpc++.h> -#include <grpc/grpc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpcpp/ext/server_load_reporting.h> -#include <grpcpp/server_builder.h> - -#include "src/proto/grpc/lb/v1/load_reporter.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ + +#include <grpc/support/port_platform.h> + +#include <thread> + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <grpc++/grpc++.h> +#include <grpc/grpc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpcpp/ext/server_load_reporting.h> +#include <grpcpp/server_builder.h> + +#include "src/proto/grpc/lb/v1/load_reporter.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" #include "test/core/util/test_config.h" - -namespace grpc { -namespace testing { -namespace { - -constexpr double kMetricValue = 3.1415; -constexpr char kMetricName[] = "METRIC_PI"; - -// Different messages result in different response statuses. For simplicity in -// computing request bytes, the message sizes should be the same. -const char kOkMessage[] = "hello"; -const char kServerErrorMessage[] = "sverr"; -const char kClientErrorMessage[] = "clerr"; - -class EchoTestServiceImpl : public EchoTestService::Service { - public: - ~EchoTestServiceImpl() override {} - - Status Echo(ServerContext* context, const EchoRequest* request, - EchoResponse* response) override { - if (request->message() == kServerErrorMessage) { - return Status(StatusCode::UNKNOWN, "Server error requested"); - } - if (request->message() == kClientErrorMessage) { - return Status(StatusCode::FAILED_PRECONDITION, "Client error requested"); - } - response->set_message(request->message()); - ::grpc::load_reporter::experimental::AddLoadReportingCost( - context, kMetricName, kMetricValue); - return Status::OK; - } -}; - -class ServerLoadReportingEnd2endTest : public ::testing::Test { - protected: - void SetUp() override { - server_address_ = + +namespace grpc { +namespace testing { +namespace { + +constexpr double kMetricValue = 3.1415; +constexpr char kMetricName[] = "METRIC_PI"; + +// Different messages result in different response statuses. For simplicity in +// computing request bytes, the message sizes should be the same. +const char kOkMessage[] = "hello"; +const char kServerErrorMessage[] = "sverr"; +const char kClientErrorMessage[] = "clerr"; + +class EchoTestServiceImpl : public EchoTestService::Service { + public: + ~EchoTestServiceImpl() override {} + + Status Echo(ServerContext* context, const EchoRequest* request, + EchoResponse* response) override { + if (request->message() == kServerErrorMessage) { + return Status(StatusCode::UNKNOWN, "Server error requested"); + } + if (request->message() == kClientErrorMessage) { + return Status(StatusCode::FAILED_PRECONDITION, "Client error requested"); + } + response->set_message(request->message()); + ::grpc::load_reporter::experimental::AddLoadReportingCost( + context, kMetricName, kMetricValue); + return Status::OK; + } +}; + +class ServerLoadReportingEnd2endTest : public ::testing::Test { + protected: + void SetUp() override { + server_address_ = "localhost:" + ToString(grpc_pick_unused_port_or_die()); - server_ = - ServerBuilder() - .AddListeningPort(server_address_, InsecureServerCredentials()) - .RegisterService(&echo_service_) - .SetOption(std::unique_ptr<::grpc::ServerBuilderOption>( - new ::grpc::load_reporter::experimental:: - LoadReportingServiceServerBuilderOption())) - .BuildAndStart(); - server_thread_ = - std::thread(&ServerLoadReportingEnd2endTest::RunServerLoop, this); - } - - void RunServerLoop() { server_->Wait(); } - - void TearDown() override { - server_->Shutdown(); - server_thread_.join(); - } - + server_ = + ServerBuilder() + .AddListeningPort(server_address_, InsecureServerCredentials()) + .RegisterService(&echo_service_) + .SetOption(std::unique_ptr<::grpc::ServerBuilderOption>( + new ::grpc::load_reporter::experimental:: + LoadReportingServiceServerBuilderOption())) + .BuildAndStart(); + server_thread_ = + std::thread(&ServerLoadReportingEnd2endTest::RunServerLoop, this); + } + + void RunServerLoop() { server_->Wait(); } + + void TearDown() override { + server_->Shutdown(); + server_thread_.join(); + } + void ClientMakeEchoCalls(const TString& lb_id, const TString& lb_tag, const TString& message, size_t num_requests) { - auto stub = EchoTestService::NewStub( - grpc::CreateChannel(server_address_, InsecureChannelCredentials())); + auto stub = EchoTestService::NewStub( + grpc::CreateChannel(server_address_, InsecureChannelCredentials())); TString lb_token = lb_id + lb_tag; - for (int i = 0; i < num_requests; ++i) { - ClientContext ctx; - if (!lb_token.empty()) ctx.AddMetadata(GRPC_LB_TOKEN_MD_KEY, lb_token); - EchoRequest request; - EchoResponse response; - request.set_message(message); - Status status = stub->Echo(&ctx, request, &response); - if (message == kOkMessage) { - ASSERT_EQ(status.error_code(), StatusCode::OK); - ASSERT_EQ(request.message(), response.message()); - } else if (message == kServerErrorMessage) { - ASSERT_EQ(status.error_code(), StatusCode::UNKNOWN); - } else if (message == kClientErrorMessage) { - ASSERT_EQ(status.error_code(), StatusCode::FAILED_PRECONDITION); - } - } - } - + for (int i = 0; i < num_requests; ++i) { + ClientContext ctx; + if (!lb_token.empty()) ctx.AddMetadata(GRPC_LB_TOKEN_MD_KEY, lb_token); + EchoRequest request; + EchoResponse response; + request.set_message(message); + Status status = stub->Echo(&ctx, request, &response); + if (message == kOkMessage) { + ASSERT_EQ(status.error_code(), StatusCode::OK); + ASSERT_EQ(request.message(), response.message()); + } else if (message == kServerErrorMessage) { + ASSERT_EQ(status.error_code(), StatusCode::UNKNOWN); + } else if (message == kClientErrorMessage) { + ASSERT_EQ(status.error_code(), StatusCode::FAILED_PRECONDITION); + } + } + } + TString server_address_; - std::unique_ptr<Server> server_; - std::thread server_thread_; - EchoTestServiceImpl echo_service_; -}; - -TEST_F(ServerLoadReportingEnd2endTest, NoCall) {} - -TEST_F(ServerLoadReportingEnd2endTest, BasicReport) { - auto channel = - grpc::CreateChannel(server_address_, InsecureChannelCredentials()); - auto stub = ::grpc::lb::v1::LoadReporter::NewStub(channel); - ClientContext ctx; - auto stream = stub->ReportLoad(&ctx); - ::grpc::lb::v1::LoadReportRequest request; - request.mutable_initial_request()->set_load_balanced_hostname( - server_address_); - request.mutable_initial_request()->set_load_key("LOAD_KEY"); - request.mutable_initial_request() - ->mutable_load_report_interval() - ->set_seconds(5); - stream->Write(request); - gpr_log(GPR_INFO, "Initial request sent."); - ::grpc::lb::v1::LoadReportResponse response; - stream->Read(&response); + std::unique_ptr<Server> server_; + std::thread server_thread_; + EchoTestServiceImpl echo_service_; +}; + +TEST_F(ServerLoadReportingEnd2endTest, NoCall) {} + +TEST_F(ServerLoadReportingEnd2endTest, BasicReport) { + auto channel = + grpc::CreateChannel(server_address_, InsecureChannelCredentials()); + auto stub = ::grpc::lb::v1::LoadReporter::NewStub(channel); + ClientContext ctx; + auto stream = stub->ReportLoad(&ctx); + ::grpc::lb::v1::LoadReportRequest request; + request.mutable_initial_request()->set_load_balanced_hostname( + server_address_); + request.mutable_initial_request()->set_load_key("LOAD_KEY"); + request.mutable_initial_request() + ->mutable_load_report_interval() + ->set_seconds(5); + stream->Write(request); + gpr_log(GPR_INFO, "Initial request sent."); + ::grpc::lb::v1::LoadReportResponse response; + stream->Read(&response); const TString& lb_id = response.initial_response().load_balancer_id(); - gpr_log(GPR_INFO, "Initial response received (lb_id: %s).", lb_id.c_str()); - ClientMakeEchoCalls(lb_id, "LB_TAG", kOkMessage, 1); - while (true) { - stream->Read(&response); - if (!response.load().empty()) { - ASSERT_EQ(response.load().size(), 3); - for (const auto& load : response.load()) { - if (load.in_progress_report_case()) { - // The special load record that reports the number of in-progress - // calls. - ASSERT_EQ(load.num_calls_in_progress(), 1); - } else if (load.orphaned_load_case()) { - // The call from the balancer doesn't have any valid LB token. - ASSERT_EQ(load.orphaned_load_case(), load.kLoadKeyUnknown); - ASSERT_EQ(load.num_calls_started(), 1); - ASSERT_EQ(load.num_calls_finished_without_error(), 0); - ASSERT_EQ(load.num_calls_finished_with_error(), 0); - } else { - // This corresponds to the calls from the client. - ASSERT_EQ(load.num_calls_started(), 1); - ASSERT_EQ(load.num_calls_finished_without_error(), 1); - ASSERT_EQ(load.num_calls_finished_with_error(), 0); - ASSERT_GE(load.total_bytes_received(), sizeof(kOkMessage)); - ASSERT_GE(load.total_bytes_sent(), sizeof(kOkMessage)); - ASSERT_EQ(load.metric_data().size(), 1); - ASSERT_EQ(load.metric_data().Get(0).metric_name(), kMetricName); - ASSERT_EQ(load.metric_data().Get(0).num_calls_finished_with_metric(), - 1); - ASSERT_EQ(load.metric_data().Get(0).total_metric_value(), - kMetricValue); - } - } - break; - } - } - stream->WritesDone(); - ASSERT_EQ(stream->Finish().error_code(), StatusCode::CANCELLED); -} - -// TODO(juanlishen): Add more tests. - -} // namespace -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { + gpr_log(GPR_INFO, "Initial response received (lb_id: %s).", lb_id.c_str()); + ClientMakeEchoCalls(lb_id, "LB_TAG", kOkMessage, 1); + while (true) { + stream->Read(&response); + if (!response.load().empty()) { + ASSERT_EQ(response.load().size(), 3); + for (const auto& load : response.load()) { + if (load.in_progress_report_case()) { + // The special load record that reports the number of in-progress + // calls. + ASSERT_EQ(load.num_calls_in_progress(), 1); + } else if (load.orphaned_load_case()) { + // The call from the balancer doesn't have any valid LB token. + ASSERT_EQ(load.orphaned_load_case(), load.kLoadKeyUnknown); + ASSERT_EQ(load.num_calls_started(), 1); + ASSERT_EQ(load.num_calls_finished_without_error(), 0); + ASSERT_EQ(load.num_calls_finished_with_error(), 0); + } else { + // This corresponds to the calls from the client. + ASSERT_EQ(load.num_calls_started(), 1); + ASSERT_EQ(load.num_calls_finished_without_error(), 1); + ASSERT_EQ(load.num_calls_finished_with_error(), 0); + ASSERT_GE(load.total_bytes_received(), sizeof(kOkMessage)); + ASSERT_GE(load.total_bytes_sent(), sizeof(kOkMessage)); + ASSERT_EQ(load.metric_data().size(), 1); + ASSERT_EQ(load.metric_data().Get(0).metric_name(), kMetricName); + ASSERT_EQ(load.metric_data().Get(0).num_calls_finished_with_metric(), + 1); + ASSERT_EQ(load.metric_data().Get(0).total_metric_value(), + kMetricValue); + } + } + break; + } + } + stream->WritesDone(); + ASSERT_EQ(stream->Finish().error_code(), StatusCode::CANCELLED); +} + +// TODO(juanlishen): Add more tests. + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/shutdown_test.cc b/contrib/libs/grpc/test/cpp/end2end/shutdown_test.cc index e980c7ce7c..3aa7a766c4 100644 --- a/contrib/libs/grpc/test/cpp/end2end/shutdown_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/shutdown_test.cc @@ -1,170 +1,170 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <thread> - -#include <grpc/grpc.h> -#include <grpc/support/log.h> -#include <grpc/support/sync.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/core/lib/gpr/env.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/util/test_credentials_provider.h" - -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; - -namespace grpc { -namespace testing { - -class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { - public: - explicit TestServiceImpl(gpr_event* ev) : ev_(ev) {} - - Status Echo(ServerContext* context, const EchoRequest* /*request*/, - EchoResponse* /*response*/) override { - gpr_event_set(ev_, (void*)1); - while (!context->IsCancelled()) { - } - return Status::OK; - } - - private: - gpr_event* ev_; -}; - -class ShutdownTest : public ::testing::TestWithParam<string> { - public: - ShutdownTest() : shutdown_(false), service_(&ev_) { gpr_event_init(&ev_); } - - void SetUp() override { - port_ = grpc_pick_unused_port_or_die(); - server_ = SetUpServer(port_); - } - - std::unique_ptr<Server> SetUpServer(const int port) { +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <thread> + +#include <grpc/grpc.h> +#include <grpc/support/log.h> +#include <grpc/support/sync.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/core/lib/gpr/env.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/util/test_credentials_provider.h" + +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; + +namespace grpc { +namespace testing { + +class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { + public: + explicit TestServiceImpl(gpr_event* ev) : ev_(ev) {} + + Status Echo(ServerContext* context, const EchoRequest* /*request*/, + EchoResponse* /*response*/) override { + gpr_event_set(ev_, (void*)1); + while (!context->IsCancelled()) { + } + return Status::OK; + } + + private: + gpr_event* ev_; +}; + +class ShutdownTest : public ::testing::TestWithParam<string> { + public: + ShutdownTest() : shutdown_(false), service_(&ev_) { gpr_event_init(&ev_); } + + void SetUp() override { + port_ = grpc_pick_unused_port_or_die(); + server_ = SetUpServer(port_); + } + + std::unique_ptr<Server> SetUpServer(const int port) { TString server_address = "localhost:" + to_string(port); - - ServerBuilder builder; - auto server_creds = - GetCredentialsProvider()->GetServerCredentials(GetParam()); - builder.AddListeningPort(server_address, server_creds); - builder.RegisterService(&service_); - std::unique_ptr<Server> server = builder.BuildAndStart(); - return server; - } - - void TearDown() override { GPR_ASSERT(shutdown_); } - - void ResetStub() { - string target = "dns:localhost:" + to_string(port_); - ChannelArguments args; - auto channel_creds = - GetCredentialsProvider()->GetChannelCredentials(GetParam(), &args); - channel_ = ::grpc::CreateCustomChannel(target, channel_creds, args); - stub_ = grpc::testing::EchoTestService::NewStub(channel_); - } - - string to_string(const int number) { - std::stringstream strs; - strs << number; - return strs.str(); - } - - void SendRequest() { - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - ClientContext context; - GPR_ASSERT(!shutdown_); - Status s = stub_->Echo(&context, request, &response); - GPR_ASSERT(shutdown_); - } - - protected: - std::shared_ptr<Channel> channel_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - bool shutdown_; - int port_; - gpr_event ev_; - TestServiceImpl service_; -}; - -std::vector<string> GetAllCredentialsTypeList() { + + ServerBuilder builder; + auto server_creds = + GetCredentialsProvider()->GetServerCredentials(GetParam()); + builder.AddListeningPort(server_address, server_creds); + builder.RegisterService(&service_); + std::unique_ptr<Server> server = builder.BuildAndStart(); + return server; + } + + void TearDown() override { GPR_ASSERT(shutdown_); } + + void ResetStub() { + string target = "dns:localhost:" + to_string(port_); + ChannelArguments args; + auto channel_creds = + GetCredentialsProvider()->GetChannelCredentials(GetParam(), &args); + channel_ = ::grpc::CreateCustomChannel(target, channel_creds, args); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + string to_string(const int number) { + std::stringstream strs; + strs << number; + return strs.str(); + } + + void SendRequest() { + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + ClientContext context; + GPR_ASSERT(!shutdown_); + Status s = stub_->Echo(&context, request, &response); + GPR_ASSERT(shutdown_); + } + + protected: + std::shared_ptr<Channel> channel_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + bool shutdown_; + int port_; + gpr_event ev_; + TestServiceImpl service_; +}; + +std::vector<string> GetAllCredentialsTypeList() { std::vector<TString> credentials_types; - if (GetCredentialsProvider()->GetChannelCredentials(kInsecureCredentialsType, - nullptr) != nullptr) { - credentials_types.push_back(kInsecureCredentialsType); - } - auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList(); - for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) { - credentials_types.push_back(*sec); - } - GPR_ASSERT(!credentials_types.empty()); - + if (GetCredentialsProvider()->GetChannelCredentials(kInsecureCredentialsType, + nullptr) != nullptr) { + credentials_types.push_back(kInsecureCredentialsType); + } + auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList(); + for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) { + credentials_types.push_back(*sec); + } + GPR_ASSERT(!credentials_types.empty()); + TString credentials_type_list("credentials types:"); - for (const string& type : credentials_types) { - credentials_type_list.append(" " + type); - } - gpr_log(GPR_INFO, "%s", credentials_type_list.c_str()); - return credentials_types; -} - -INSTANTIATE_TEST_SUITE_P(End2EndShutdown, ShutdownTest, - ::testing::ValuesIn(GetAllCredentialsTypeList())); - -// TODO(ctiller): leaked objects in this test -TEST_P(ShutdownTest, ShutdownTest) { - ResetStub(); - - // send the request in a background thread - std::thread thr(std::bind(&ShutdownTest::SendRequest, this)); - - // wait for the server to get the event - gpr_event_wait(&ev_, gpr_inf_future(GPR_CLOCK_MONOTONIC)); - - shutdown_ = true; - - // shutdown should trigger cancellation causing everything to shutdown - auto deadline = - std::chrono::system_clock::now() + std::chrono::microseconds(100); - server_->Shutdown(deadline); - EXPECT_GE(std::chrono::system_clock::now(), deadline); - - thr.join(); -} - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + for (const string& type : credentials_types) { + credentials_type_list.append(" " + type); + } + gpr_log(GPR_INFO, "%s", credentials_type_list.c_str()); + return credentials_types; +} + +INSTANTIATE_TEST_SUITE_P(End2EndShutdown, ShutdownTest, + ::testing::ValuesIn(GetAllCredentialsTypeList())); + +// TODO(ctiller): leaked objects in this test +TEST_P(ShutdownTest, ShutdownTest) { + ResetStub(); + + // send the request in a background thread + std::thread thr(std::bind(&ShutdownTest::SendRequest, this)); + + // wait for the server to get the event + gpr_event_wait(&ev_, gpr_inf_future(GPR_CLOCK_MONOTONIC)); + + shutdown_ = true; + + // shutdown should trigger cancellation causing everything to shutdown + auto deadline = + std::chrono::system_clock::now() + std::chrono::microseconds(100); + server_->Shutdown(deadline); + EXPECT_GE(std::chrono::system_clock::now(), deadline); + + thr.join(); +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/streaming_throughput_test.cc b/contrib/libs/grpc/test/cpp/end2end/streaming_throughput_test.cc index 1c6f9806f0..f2252063fb 100644 --- a/contrib/libs/grpc/test/cpp/end2end/streaming_throughput_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/streaming_throughput_test.cc @@ -1,193 +1,193 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <time.h> -#include <mutex> -#include <thread> - -#include <grpc/grpc.h> -#include <grpc/support/atm.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/security/credentials.h> -#include <grpcpp/security/server_credentials.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; -using std::chrono::system_clock; - -const char* kLargeString = - "(" - "To be, or not to be- that is the question:" - "Whether 'tis nobler in the mind to suffer" - "The slings and arrows of outrageous fortune" - "Or to take arms against a sea of troubles," - "And by opposing end them. To die- to sleep-" - "No more; and by a sleep to say we end" - "The heartache, and the thousand natural shock" - "That flesh is heir to. 'Tis a consummation" - "Devoutly to be wish'd. To die- to sleep." - "To sleep- perchance to dream: ay, there's the rub!" - "For in that sleep of death what dreams may come" - "When we have shuffled off this mortal coil," - "Must give us pause. There's the respect" - "That makes calamity of so long life." - "For who would bear the whips and scorns of time," - "Th' oppressor's wrong, the proud man's contumely," - "The pangs of despis'd love, the law's delay," - "The insolence of office, and the spurns" - "That patient merit of th' unworthy takes," - "When he himself might his quietus make" - "With a bare bodkin? Who would these fardels bear," - "To grunt and sweat under a weary life," - "But that the dread of something after death-" - "The undiscover'd country, from whose bourn" - "No traveller returns- puzzles the will," - "And makes us rather bear those ills we have" - "Than fly to others that we know not of?" - "Thus conscience does make cowards of us all," - "And thus the native hue of resolution" - "Is sicklied o'er with the pale cast of thought," - "And enterprises of great pith and moment" - "With this regard their currents turn awry" - "And lose the name of action.- Soft you now!" - "The fair Ophelia!- Nymph, in thy orisons" - "Be all my sins rememb'red."; - -namespace grpc { -namespace testing { - -class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { - public: - static void BidiStream_Sender( - ServerReaderWriter<EchoResponse, EchoRequest>* stream, - gpr_atm* should_exit) { - EchoResponse response; - response.set_message(kLargeString); - while (gpr_atm_acq_load(should_exit) == static_cast<gpr_atm>(0)) { - struct timespec tv = {0, 1000000}; // 1 ms - struct timespec rem; - // TODO (vpai): Mark this blocking - while (nanosleep(&tv, &rem) != 0) { - tv = rem; - }; - - stream->Write(response); - } - } - - // Only implement the one method we will be calling for brevity. - Status BidiStream( - ServerContext* /*context*/, - ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { - EchoRequest request; - gpr_atm should_exit; - gpr_atm_rel_store(&should_exit, static_cast<gpr_atm>(0)); - - std::thread sender( - std::bind(&TestServiceImpl::BidiStream_Sender, stream, &should_exit)); - - while (stream->Read(&request)) { - struct timespec tv = {0, 3000000}; // 3 ms - struct timespec rem; - // TODO (vpai): Mark this blocking - while (nanosleep(&tv, &rem) != 0) { - tv = rem; - }; - } - gpr_atm_rel_store(&should_exit, static_cast<gpr_atm>(1)); - sender.join(); - return Status::OK; - } -}; - -class End2endTest : public ::testing::Test { - protected: - void SetUp() override { - int port = grpc_pick_unused_port_or_die(); - server_address_ << "localhost:" << port; - // Setup server - ServerBuilder builder; - builder.AddListeningPort(server_address_.str(), - InsecureServerCredentials()); - builder.RegisterService(&service_); - server_ = builder.BuildAndStart(); - } - - void TearDown() override { server_->Shutdown(); } - - void ResetStub() { - std::shared_ptr<Channel> channel = grpc::CreateChannel( - server_address_.str(), InsecureChannelCredentials()); - stub_ = grpc::testing::EchoTestService::NewStub(channel); - } - - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - std::ostringstream server_address_; - TestServiceImpl service_; -}; - -static void Drainer(ClientReaderWriter<EchoRequest, EchoResponse>* reader) { - EchoResponse response; - while (reader->Read(&response)) { - // Just drain out the responses as fast as possible. - } -} - -TEST_F(End2endTest, StreamingThroughput) { - ResetStub(); - grpc::ClientContext context; - auto stream = stub_->BidiStream(&context); - - auto reader = stream.get(); - std::thread receiver(std::bind(Drainer, reader)); - - for (int i = 0; i < 10000; i++) { - EchoRequest request; - request.set_message(kLargeString); - ASSERT_TRUE(stream->Write(request)); - if (i % 1000 == 0) { - gpr_log(GPR_INFO, "Send count = %d", i); - } - } - stream->WritesDone(); - receiver.join(); -} - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <time.h> +#include <mutex> +#include <thread> + +#include <grpc/grpc.h> +#include <grpc/support/atm.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/security/credentials.h> +#include <grpcpp/security/server_credentials.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; +using std::chrono::system_clock; + +const char* kLargeString = + "(" + "To be, or not to be- that is the question:" + "Whether 'tis nobler in the mind to suffer" + "The slings and arrows of outrageous fortune" + "Or to take arms against a sea of troubles," + "And by opposing end them. To die- to sleep-" + "No more; and by a sleep to say we end" + "The heartache, and the thousand natural shock" + "That flesh is heir to. 'Tis a consummation" + "Devoutly to be wish'd. To die- to sleep." + "To sleep- perchance to dream: ay, there's the rub!" + "For in that sleep of death what dreams may come" + "When we have shuffled off this mortal coil," + "Must give us pause. There's the respect" + "That makes calamity of so long life." + "For who would bear the whips and scorns of time," + "Th' oppressor's wrong, the proud man's contumely," + "The pangs of despis'd love, the law's delay," + "The insolence of office, and the spurns" + "That patient merit of th' unworthy takes," + "When he himself might his quietus make" + "With a bare bodkin? Who would these fardels bear," + "To grunt and sweat under a weary life," + "But that the dread of something after death-" + "The undiscover'd country, from whose bourn" + "No traveller returns- puzzles the will," + "And makes us rather bear those ills we have" + "Than fly to others that we know not of?" + "Thus conscience does make cowards of us all," + "And thus the native hue of resolution" + "Is sicklied o'er with the pale cast of thought," + "And enterprises of great pith and moment" + "With this regard their currents turn awry" + "And lose the name of action.- Soft you now!" + "The fair Ophelia!- Nymph, in thy orisons" + "Be all my sins rememb'red."; + +namespace grpc { +namespace testing { + +class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { + public: + static void BidiStream_Sender( + ServerReaderWriter<EchoResponse, EchoRequest>* stream, + gpr_atm* should_exit) { + EchoResponse response; + response.set_message(kLargeString); + while (gpr_atm_acq_load(should_exit) == static_cast<gpr_atm>(0)) { + struct timespec tv = {0, 1000000}; // 1 ms + struct timespec rem; + // TODO (vpai): Mark this blocking + while (nanosleep(&tv, &rem) != 0) { + tv = rem; + }; + + stream->Write(response); + } + } + + // Only implement the one method we will be calling for brevity. + Status BidiStream( + ServerContext* /*context*/, + ServerReaderWriter<EchoResponse, EchoRequest>* stream) override { + EchoRequest request; + gpr_atm should_exit; + gpr_atm_rel_store(&should_exit, static_cast<gpr_atm>(0)); + + std::thread sender( + std::bind(&TestServiceImpl::BidiStream_Sender, stream, &should_exit)); + + while (stream->Read(&request)) { + struct timespec tv = {0, 3000000}; // 3 ms + struct timespec rem; + // TODO (vpai): Mark this blocking + while (nanosleep(&tv, &rem) != 0) { + tv = rem; + }; + } + gpr_atm_rel_store(&should_exit, static_cast<gpr_atm>(1)); + sender.join(); + return Status::OK; + } +}; + +class End2endTest : public ::testing::Test { + protected: + void SetUp() override { + int port = grpc_pick_unused_port_or_die(); + server_address_ << "localhost:" << port; + // Setup server + ServerBuilder builder; + builder.AddListeningPort(server_address_.str(), + InsecureServerCredentials()); + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + + void TearDown() override { server_->Shutdown(); } + + void ResetStub() { + std::shared_ptr<Channel> channel = grpc::CreateChannel( + server_address_.str(), InsecureChannelCredentials()); + stub_ = grpc::testing::EchoTestService::NewStub(channel); + } + + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + std::ostringstream server_address_; + TestServiceImpl service_; +}; + +static void Drainer(ClientReaderWriter<EchoRequest, EchoResponse>* reader) { + EchoResponse response; + while (reader->Read(&response)) { + // Just drain out the responses as fast as possible. + } +} + +TEST_F(End2endTest, StreamingThroughput) { + ResetStub(); + grpc::ClientContext context; + auto stream = stub_->BidiStream(&context); + + auto reader = stream.get(); + std::thread receiver(std::bind(Drainer, reader)); + + for (int i = 0; i < 10000; i++) { + EchoRequest request; + request.set_message(kLargeString); + ASSERT_TRUE(stream->Write(request)); + if (i % 1000 == 0) { + gpr_log(GPR_INFO, "Send count = %d", i); + } + } + stream->WritesDone(); + receiver.join(); +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/test_health_check_service_impl.cc b/contrib/libs/grpc/test/cpp/end2end/test_health_check_service_impl.cc index 225cb2624b..5b212cba31 100644 --- a/contrib/libs/grpc/test/cpp/end2end/test_health_check_service_impl.cc +++ b/contrib/libs/grpc/test/cpp/end2end/test_health_check_service_impl.cc @@ -1,98 +1,98 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ - -#include "test/cpp/end2end/test_health_check_service_impl.h" - -#include <grpc/grpc.h> - -using grpc::health::v1::HealthCheckRequest; -using grpc::health::v1::HealthCheckResponse; - -namespace grpc { -namespace testing { - -Status HealthCheckServiceImpl::Check(ServerContext* /*context*/, - const HealthCheckRequest* request, - HealthCheckResponse* response) { - std::lock_guard<std::mutex> lock(mu_); - auto iter = status_map_.find(request->service()); - if (iter == status_map_.end()) { - return Status(StatusCode::NOT_FOUND, ""); - } - response->set_status(iter->second); - return Status::OK; -} - -Status HealthCheckServiceImpl::Watch( - ServerContext* context, const HealthCheckRequest* request, - ::grpc::ServerWriter<HealthCheckResponse>* writer) { - auto last_state = HealthCheckResponse::UNKNOWN; - while (!context->IsCancelled()) { - { - std::lock_guard<std::mutex> lock(mu_); - HealthCheckResponse response; - auto iter = status_map_.find(request->service()); - if (iter == status_map_.end()) { - response.set_status(response.SERVICE_UNKNOWN); - } else { - response.set_status(iter->second); - } - if (response.status() != last_state) { - writer->Write(response, ::grpc::WriteOptions()); - last_state = response.status(); - } - } - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis(1000, GPR_TIMESPAN))); - } - return Status::OK; -} - -void HealthCheckServiceImpl::SetStatus( +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ + +#include "test/cpp/end2end/test_health_check_service_impl.h" + +#include <grpc/grpc.h> + +using grpc::health::v1::HealthCheckRequest; +using grpc::health::v1::HealthCheckResponse; + +namespace grpc { +namespace testing { + +Status HealthCheckServiceImpl::Check(ServerContext* /*context*/, + const HealthCheckRequest* request, + HealthCheckResponse* response) { + std::lock_guard<std::mutex> lock(mu_); + auto iter = status_map_.find(request->service()); + if (iter == status_map_.end()) { + return Status(StatusCode::NOT_FOUND, ""); + } + response->set_status(iter->second); + return Status::OK; +} + +Status HealthCheckServiceImpl::Watch( + ServerContext* context, const HealthCheckRequest* request, + ::grpc::ServerWriter<HealthCheckResponse>* writer) { + auto last_state = HealthCheckResponse::UNKNOWN; + while (!context->IsCancelled()) { + { + std::lock_guard<std::mutex> lock(mu_); + HealthCheckResponse response; + auto iter = status_map_.find(request->service()); + if (iter == status_map_.end()) { + response.set_status(response.SERVICE_UNKNOWN); + } else { + response.set_status(iter->second); + } + if (response.status() != last_state) { + writer->Write(response, ::grpc::WriteOptions()); + last_state = response.status(); + } + } + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis(1000, GPR_TIMESPAN))); + } + return Status::OK; +} + +void HealthCheckServiceImpl::SetStatus( const TString& service_name, - HealthCheckResponse::ServingStatus status) { - std::lock_guard<std::mutex> lock(mu_); - if (shutdown_) { - status = HealthCheckResponse::NOT_SERVING; - } - status_map_[service_name] = status; -} - -void HealthCheckServiceImpl::SetAll(HealthCheckResponse::ServingStatus status) { - std::lock_guard<std::mutex> lock(mu_); - if (shutdown_) { - return; - } - for (auto iter = status_map_.begin(); iter != status_map_.end(); ++iter) { - iter->second = status; - } -} - -void HealthCheckServiceImpl::Shutdown() { - std::lock_guard<std::mutex> lock(mu_); - if (shutdown_) { - return; - } - shutdown_ = true; - for (auto iter = status_map_.begin(); iter != status_map_.end(); ++iter) { - iter->second = HealthCheckResponse::NOT_SERVING; - } -} - -} // namespace testing -} // namespace grpc + HealthCheckResponse::ServingStatus status) { + std::lock_guard<std::mutex> lock(mu_); + if (shutdown_) { + status = HealthCheckResponse::NOT_SERVING; + } + status_map_[service_name] = status; +} + +void HealthCheckServiceImpl::SetAll(HealthCheckResponse::ServingStatus status) { + std::lock_guard<std::mutex> lock(mu_); + if (shutdown_) { + return; + } + for (auto iter = status_map_.begin(); iter != status_map_.end(); ++iter) { + iter->second = status; + } +} + +void HealthCheckServiceImpl::Shutdown() { + std::lock_guard<std::mutex> lock(mu_); + if (shutdown_) { + return; + } + shutdown_ = true; + for (auto iter = status_map_.begin(); iter != status_map_.end(); ++iter) { + iter->second = HealthCheckResponse::NOT_SERVING; + } +} + +} // namespace testing +} // namespace grpc diff --git a/contrib/libs/grpc/test/cpp/end2end/test_health_check_service_impl.h b/contrib/libs/grpc/test/cpp/end2end/test_health_check_service_impl.h index 3bb4d4f9ca..d370e4693a 100644 --- a/contrib/libs/grpc/test/cpp/end2end/test_health_check_service_impl.h +++ b/contrib/libs/grpc/test/cpp/end2end/test_health_check_service_impl.h @@ -1,58 +1,58 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * 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. - * - */ -#ifndef GRPC_TEST_CPP_END2END_TEST_HEALTH_CHECK_SERVICE_IMPL_H -#define GRPC_TEST_CPP_END2END_TEST_HEALTH_CHECK_SERVICE_IMPL_H - -#include <map> -#include <mutex> - -#include <grpcpp/server_context.h> -#include <grpcpp/support/status.h> - -#include "src/proto/grpc/health/v1/health.grpc.pb.h" - -namespace grpc { -namespace testing { - -// A sample sync implementation of the health checking service. This does the -// same thing as the default one. -class HealthCheckServiceImpl : public health::v1::Health::Service { - public: - Status Check(ServerContext* context, - const health::v1::HealthCheckRequest* request, - health::v1::HealthCheckResponse* response) override; - Status Watch(ServerContext* context, - const health::v1::HealthCheckRequest* request, - ServerWriter<health::v1::HealthCheckResponse>* writer) override; +/* + * + * Copyright 2018 gRPC authors. + * + * 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. + * + */ +#ifndef GRPC_TEST_CPP_END2END_TEST_HEALTH_CHECK_SERVICE_IMPL_H +#define GRPC_TEST_CPP_END2END_TEST_HEALTH_CHECK_SERVICE_IMPL_H + +#include <map> +#include <mutex> + +#include <grpcpp/server_context.h> +#include <grpcpp/support/status.h> + +#include "src/proto/grpc/health/v1/health.grpc.pb.h" + +namespace grpc { +namespace testing { + +// A sample sync implementation of the health checking service. This does the +// same thing as the default one. +class HealthCheckServiceImpl : public health::v1::Health::Service { + public: + Status Check(ServerContext* context, + const health::v1::HealthCheckRequest* request, + health::v1::HealthCheckResponse* response) override; + Status Watch(ServerContext* context, + const health::v1::HealthCheckRequest* request, + ServerWriter<health::v1::HealthCheckResponse>* writer) override; void SetStatus(const TString& service_name, - health::v1::HealthCheckResponse::ServingStatus status); - void SetAll(health::v1::HealthCheckResponse::ServingStatus status); - - void Shutdown(); - - private: - std::mutex mu_; - bool shutdown_ = false; + health::v1::HealthCheckResponse::ServingStatus status); + void SetAll(health::v1::HealthCheckResponse::ServingStatus status); + + void Shutdown(); + + private: + std::mutex mu_; + bool shutdown_ = false; std::map<const TString, health::v1::HealthCheckResponse::ServingStatus> - status_map_; -}; - -} // namespace testing -} // namespace grpc - -#endif // GRPC_TEST_CPP_END2END_TEST_HEALTH_CHECK_SERVICE_IMPL_H + status_map_; +}; + +} // namespace testing +} // namespace grpc + +#endif // GRPC_TEST_CPP_END2END_TEST_HEALTH_CHECK_SERVICE_IMPL_H diff --git a/contrib/libs/grpc/test/cpp/end2end/test_service_impl.cc b/contrib/libs/grpc/test/cpp/end2end/test_service_impl.cc index 55821905e4..078977e824 100644 --- a/contrib/libs/grpc/test/cpp/end2end/test_service_impl.cc +++ b/contrib/libs/grpc/test/cpp/end2end/test_service_impl.cc @@ -1,144 +1,144 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * 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. - * - */ - -#include "test/cpp/end2end/test_service_impl.h" - -#include <grpc/support/log.h> +/* + * + * Copyright 2016 gRPC authors. + * + * 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. + * + */ + +#include "test/cpp/end2end/test_service_impl.h" + +#include <grpc/support/log.h> #include <grpcpp/alarm.h> -#include <grpcpp/security/credentials.h> -#include <grpcpp/server_context.h> -#include <gtest/gtest.h> - +#include <grpcpp/security/credentials.h> +#include <grpcpp/server_context.h> +#include <gtest/gtest.h> + #include <util/generic/string.h> -#include <thread> - -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/cpp/util/string_ref_helper.h" - -using std::chrono::system_clock; - -namespace grpc { -namespace testing { +#include <thread> + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/cpp/util/string_ref_helper.h" + +using std::chrono::system_clock; + +namespace grpc { +namespace testing { namespace internal { - -// When echo_deadline is requested, deadline seen in the ServerContext is set in -// the response in seconds. -void MaybeEchoDeadline(experimental::ServerContextBase* context, - const EchoRequest* request, EchoResponse* response) { - if (request->has_param() && request->param().echo_deadline()) { - gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_REALTIME); - if (context->deadline() != system_clock::time_point::max()) { - Timepoint2Timespec(context->deadline(), &deadline); - } - response->mutable_param()->set_request_deadline(deadline.tv_sec); - } -} - + +// When echo_deadline is requested, deadline seen in the ServerContext is set in +// the response in seconds. +void MaybeEchoDeadline(experimental::ServerContextBase* context, + const EchoRequest* request, EchoResponse* response) { + if (request->has_param() && request->param().echo_deadline()) { + gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_REALTIME); + if (context->deadline() != system_clock::time_point::max()) { + Timepoint2Timespec(context->deadline(), &deadline); + } + response->mutable_param()->set_request_deadline(deadline.tv_sec); + } +} + void CheckServerAuthContext(const experimental::ServerContextBase* context, const TString& expected_transport_security_type, const TString& expected_client_identity) { - std::shared_ptr<const AuthContext> auth_ctx = context->auth_context(); - std::vector<grpc::string_ref> tst = - auth_ctx->FindPropertyValues("transport_security_type"); - EXPECT_EQ(1u, tst.size()); - EXPECT_EQ(expected_transport_security_type.c_str(), ToString(tst[0])); - if (expected_client_identity.empty()) { - EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty()); - EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty()); - EXPECT_FALSE(auth_ctx->IsPeerAuthenticated()); - } else { - auto identity = auth_ctx->GetPeerIdentity(); - EXPECT_TRUE(auth_ctx->IsPeerAuthenticated()); - EXPECT_EQ(1u, identity.size()); + std::shared_ptr<const AuthContext> auth_ctx = context->auth_context(); + std::vector<grpc::string_ref> tst = + auth_ctx->FindPropertyValues("transport_security_type"); + EXPECT_EQ(1u, tst.size()); + EXPECT_EQ(expected_transport_security_type.c_str(), ToString(tst[0])); + if (expected_client_identity.empty()) { + EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty()); + EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty()); + EXPECT_FALSE(auth_ctx->IsPeerAuthenticated()); + } else { + auto identity = auth_ctx->GetPeerIdentity(); + EXPECT_TRUE(auth_ctx->IsPeerAuthenticated()); + EXPECT_EQ(1u, identity.size()); EXPECT_EQ(expected_client_identity.c_str(), ToString(identity[0])); - } -} - -// Returns the number of pairs in metadata that exactly match the given -// key-value pair. Returns -1 if the pair wasn't found. -int MetadataMatchCount( - const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, + } +} + +// Returns the number of pairs in metadata that exactly match the given +// key-value pair. Returns -1 if the pair wasn't found. +int MetadataMatchCount( + const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, const TString& key, const TString& value) { - int count = 0; - for (const auto& metadatum : metadata) { - if (ToString(metadatum.first) == key && - ToString(metadatum.second) == value) { - count++; - } - } - return count; -} - -int GetIntValueFromMetadataHelper( - const char* key, - const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, - int default_value) { - if (metadata.find(key) != metadata.end()) { - std::istringstream iss(ToString(metadata.find(key)->second)); - iss >> default_value; - gpr_log(GPR_INFO, "%s : %d", key, default_value); - } - - return default_value; -} - -int GetIntValueFromMetadata( - const char* key, - const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, - int default_value) { - return GetIntValueFromMetadataHelper(key, metadata, default_value); -} - -void ServerTryCancel(ServerContext* context) { - EXPECT_FALSE(context->IsCancelled()); - context->TryCancel(); - gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); - // Now wait until it's really canceled - while (!context->IsCancelled()) { - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(1000, GPR_TIMESPAN))); - } -} - -void ServerTryCancelNonblocking(experimental::CallbackServerContext* context) { - EXPECT_FALSE(context->IsCancelled()); - context->TryCancel(); + int count = 0; + for (const auto& metadatum : metadata) { + if (ToString(metadatum.first) == key && + ToString(metadatum.second) == value) { + count++; + } + } + return count; +} + +int GetIntValueFromMetadataHelper( + const char* key, + const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, + int default_value) { + if (metadata.find(key) != metadata.end()) { + std::istringstream iss(ToString(metadata.find(key)->second)); + iss >> default_value; + gpr_log(GPR_INFO, "%s : %d", key, default_value); + } + + return default_value; +} + +int GetIntValueFromMetadata( + const char* key, + const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, + int default_value) { + return GetIntValueFromMetadataHelper(key, metadata, default_value); +} + +void ServerTryCancel(ServerContext* context) { + EXPECT_FALSE(context->IsCancelled()); + context->TryCancel(); + gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); + // Now wait until it's really canceled + while (!context->IsCancelled()) { + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(1000, GPR_TIMESPAN))); + } +} + +void ServerTryCancelNonblocking(experimental::CallbackServerContext* context) { + EXPECT_FALSE(context->IsCancelled()); + context->TryCancel(); gpr_log(GPR_INFO, "Server called TryCancelNonblocking() to cancel the request"); -} - +} + } // namespace internal - -experimental::ServerUnaryReactor* CallbackTestServiceImpl::Echo( - experimental::CallbackServerContext* context, const EchoRequest* request, - EchoResponse* response) { - class Reactor : public ::grpc::experimental::ServerUnaryReactor { - public: - Reactor(CallbackTestServiceImpl* service, - experimental::CallbackServerContext* ctx, - const EchoRequest* request, EchoResponse* response) - : service_(service), ctx_(ctx), req_(request), resp_(response) { - // It should be safe to call IsCancelled here, even though we don't know - // the result. Call it asynchronously to see if we trigger any data races. + +experimental::ServerUnaryReactor* CallbackTestServiceImpl::Echo( + experimental::CallbackServerContext* context, const EchoRequest* request, + EchoResponse* response) { + class Reactor : public ::grpc::experimental::ServerUnaryReactor { + public: + Reactor(CallbackTestServiceImpl* service, + experimental::CallbackServerContext* ctx, + const EchoRequest* request, EchoResponse* response) + : service_(service), ctx_(ctx), req_(request), resp_(response) { + // It should be safe to call IsCancelled here, even though we don't know + // the result. Call it asynchronously to see if we trigger any data races. // Join it in OnDone (technically that could be blocking but shouldn't be // for very long). - async_cancel_check_ = std::thread([this] { (void)ctx_->IsCancelled(); }); - + async_cancel_check_ = std::thread([this] { (void)ctx_->IsCancelled(); }); + started_ = true; if (request->has_param() && @@ -158,349 +158,349 @@ experimental::ServerUnaryReactor* CallbackTestServiceImpl::Echo( void StartRpc() { if (req_->has_param() && req_->param().server_sleep_us() > 0) { - // Set an alarm for that much time - alarm_.experimental().Set( - gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + // Set an alarm for that much time + alarm_.experimental().Set( + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_micros(req_->param().server_sleep_us(), GPR_TIMESPAN)), - [this](bool ok) { NonDelayed(ok); }); + [this](bool ok) { NonDelayed(ok); }); return; - } + } NonDelayed(true); - } - void OnSendInitialMetadataDone(bool ok) override { - EXPECT_TRUE(ok); - initial_metadata_sent_ = true; - } - void OnCancel() override { - EXPECT_TRUE(started_); - EXPECT_TRUE(ctx_->IsCancelled()); - on_cancel_invoked_ = true; + } + void OnSendInitialMetadataDone(bool ok) override { + EXPECT_TRUE(ok); + initial_metadata_sent_ = true; + } + void OnCancel() override { + EXPECT_TRUE(started_); + EXPECT_TRUE(ctx_->IsCancelled()); + on_cancel_invoked_ = true; std::lock_guard<std::mutex> l(cancel_mu_); cancel_cv_.notify_one(); - } - void OnDone() override { - if (req_->has_param() && req_->param().echo_metadata_initially()) { - EXPECT_TRUE(initial_metadata_sent_); - } - EXPECT_EQ(ctx_->IsCancelled(), on_cancel_invoked_); + } + void OnDone() override { + if (req_->has_param() && req_->param().echo_metadata_initially()) { + EXPECT_TRUE(initial_metadata_sent_); + } + EXPECT_EQ(ctx_->IsCancelled(), on_cancel_invoked_); // Validate that finishing with a non-OK status doesn't cause cancellation if (req_->has_param() && req_->param().has_expected_error()) { EXPECT_FALSE(on_cancel_invoked_); } - async_cancel_check_.join(); + async_cancel_check_.join(); if (rpc_wait_thread_.joinable()) { rpc_wait_thread_.join(); } if (finish_when_cancelled_.joinable()) { finish_when_cancelled_.join(); } - delete this; - } - - private: - void NonDelayed(bool ok) { - if (!ok) { - EXPECT_TRUE(ctx_->IsCancelled()); - Finish(Status::CANCELLED); - return; - } - if (req_->has_param() && req_->param().server_die()) { - gpr_log(GPR_ERROR, "The request should not reach application handler."); - GPR_ASSERT(0); - } - if (req_->has_param() && req_->param().has_expected_error()) { - const auto& error = req_->param().expected_error(); - Finish(Status(static_cast<StatusCode>(error.code()), - error.error_message(), error.binary_error_details())); - return; - } + delete this; + } + + private: + void NonDelayed(bool ok) { + if (!ok) { + EXPECT_TRUE(ctx_->IsCancelled()); + Finish(Status::CANCELLED); + return; + } + if (req_->has_param() && req_->param().server_die()) { + gpr_log(GPR_ERROR, "The request should not reach application handler."); + GPR_ASSERT(0); + } + if (req_->has_param() && req_->param().has_expected_error()) { + const auto& error = req_->param().expected_error(); + Finish(Status(static_cast<StatusCode>(error.code()), + error.error_message(), error.binary_error_details())); + return; + } int server_try_cancel = internal::GetIntValueFromMetadata( - kServerTryCancelRequest, ctx_->client_metadata(), DO_NOT_CANCEL); - if (server_try_cancel != DO_NOT_CANCEL) { - // Since this is a unary RPC, by the time this server handler is called, - // the 'request' message is already read from the client. So the - // scenarios in server_try_cancel don't make much sense. Just cancel the - // RPC as long as server_try_cancel is not DO_NOT_CANCEL - EXPECT_FALSE(ctx_->IsCancelled()); - ctx_->TryCancel(); - gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); + kServerTryCancelRequest, ctx_->client_metadata(), DO_NOT_CANCEL); + if (server_try_cancel != DO_NOT_CANCEL) { + // Since this is a unary RPC, by the time this server handler is called, + // the 'request' message is already read from the client. So the + // scenarios in server_try_cancel don't make much sense. Just cancel the + // RPC as long as server_try_cancel is not DO_NOT_CANCEL + EXPECT_FALSE(ctx_->IsCancelled()); + ctx_->TryCancel(); + gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); FinishWhenCancelledAsync(); - return; - } - resp_->set_message(req_->message()); + return; + } + resp_->set_message(req_->message()); internal::MaybeEchoDeadline(ctx_, req_, resp_); - if (service_->host_) { - resp_->mutable_param()->set_host(*service_->host_); - } - if (req_->has_param() && req_->param().client_cancel_after_us()) { - { - std::unique_lock<std::mutex> lock(service_->mu_); - service_->signal_client_ = true; - } + if (service_->host_) { + resp_->mutable_param()->set_host(*service_->host_); + } + if (req_->has_param() && req_->param().client_cancel_after_us()) { + { + std::unique_lock<std::mutex> lock(service_->mu_); + service_->signal_client_ = true; + } FinishWhenCancelledAsync(); - return; - } else if (req_->has_param() && req_->param().server_cancel_after_us()) { - alarm_.experimental().Set( - gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(req_->param().server_cancel_after_us(), - GPR_TIMESPAN)), - [this](bool) { Finish(Status::CANCELLED); }); - return; - } else if (!req_->has_param() || !req_->param().skip_cancelled_check()) { - EXPECT_FALSE(ctx_->IsCancelled()); - } - - if (req_->has_param() && req_->param().echo_metadata_initially()) { - const std::multimap<grpc::string_ref, grpc::string_ref>& - client_metadata = ctx_->client_metadata(); - for (const auto& metadatum : client_metadata) { - ctx_->AddInitialMetadata(ToString(metadatum.first), - ToString(metadatum.second)); - } - StartSendInitialMetadata(); - } - - if (req_->has_param() && req_->param().echo_metadata()) { - const std::multimap<grpc::string_ref, grpc::string_ref>& - client_metadata = ctx_->client_metadata(); - for (const auto& metadatum : client_metadata) { - ctx_->AddTrailingMetadata(ToString(metadatum.first), - ToString(metadatum.second)); - } - // Terminate rpc with error and debug info in trailer. - if (req_->param().debug_info().stack_entries_size() || - !req_->param().debug_info().detail().empty()) { + return; + } else if (req_->has_param() && req_->param().server_cancel_after_us()) { + alarm_.experimental().Set( + gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(req_->param().server_cancel_after_us(), + GPR_TIMESPAN)), + [this](bool) { Finish(Status::CANCELLED); }); + return; + } else if (!req_->has_param() || !req_->param().skip_cancelled_check()) { + EXPECT_FALSE(ctx_->IsCancelled()); + } + + if (req_->has_param() && req_->param().echo_metadata_initially()) { + const std::multimap<grpc::string_ref, grpc::string_ref>& + client_metadata = ctx_->client_metadata(); + for (const auto& metadatum : client_metadata) { + ctx_->AddInitialMetadata(ToString(metadatum.first), + ToString(metadatum.second)); + } + StartSendInitialMetadata(); + } + + if (req_->has_param() && req_->param().echo_metadata()) { + const std::multimap<grpc::string_ref, grpc::string_ref>& + client_metadata = ctx_->client_metadata(); + for (const auto& metadatum : client_metadata) { + ctx_->AddTrailingMetadata(ToString(metadatum.first), + ToString(metadatum.second)); + } + // Terminate rpc with error and debug info in trailer. + if (req_->param().debug_info().stack_entries_size() || + !req_->param().debug_info().detail().empty()) { TString serialized_debug_info = - req_->param().debug_info().SerializeAsString(); - ctx_->AddTrailingMetadata(kDebugInfoTrailerKey, - serialized_debug_info); - Finish(Status::CANCELLED); - return; - } - } - if (req_->has_param() && - (req_->param().expected_client_identity().length() > 0 || - req_->param().check_auth_context())) { + req_->param().debug_info().SerializeAsString(); + ctx_->AddTrailingMetadata(kDebugInfoTrailerKey, + serialized_debug_info); + Finish(Status::CANCELLED); + return; + } + } + if (req_->has_param() && + (req_->param().expected_client_identity().length() > 0 || + req_->param().check_auth_context())) { internal::CheckServerAuthContext( ctx_, req_->param().expected_transport_security_type(), req_->param().expected_client_identity()); - } - if (req_->has_param() && req_->param().response_message_length() > 0) { - resp_->set_message( + } + if (req_->has_param() && req_->param().response_message_length() > 0) { + resp_->set_message( TString(req_->param().response_message_length(), '\0')); - } - if (req_->has_param() && req_->param().echo_peer()) { - resp_->mutable_param()->set_peer(ctx_->peer().c_str()); - } - Finish(Status::OK); - } + } + if (req_->has_param() && req_->param().echo_peer()) { + resp_->mutable_param()->set_peer(ctx_->peer().c_str()); + } + Finish(Status::OK); + } void FinishWhenCancelledAsync() { finish_when_cancelled_ = std::thread([this] { std::unique_lock<std::mutex> l(cancel_mu_); cancel_cv_.wait(l, [this] { return ctx_->IsCancelled(); }); - Finish(Status::CANCELLED); + Finish(Status::CANCELLED); }); - } - - CallbackTestServiceImpl* const service_; - experimental::CallbackServerContext* const ctx_; - const EchoRequest* const req_; - EchoResponse* const resp_; - Alarm alarm_; + } + + CallbackTestServiceImpl* const service_; + experimental::CallbackServerContext* const ctx_; + const EchoRequest* const req_; + EchoResponse* const resp_; + Alarm alarm_; std::mutex cancel_mu_; std::condition_variable cancel_cv_; bool initial_metadata_sent_ = false; bool started_ = false; bool on_cancel_invoked_ = false; - std::thread async_cancel_check_; + std::thread async_cancel_check_; std::thread rpc_wait_thread_; std::thread finish_when_cancelled_; - }; - - return new Reactor(this, context, request, response); -} - -experimental::ServerUnaryReactor* -CallbackTestServiceImpl::CheckClientInitialMetadata( + }; + + return new Reactor(this, context, request, response); +} + +experimental::ServerUnaryReactor* +CallbackTestServiceImpl::CheckClientInitialMetadata( experimental::CallbackServerContext* context, const SimpleRequest42*, SimpleResponse42*) { - class Reactor : public ::grpc::experimental::ServerUnaryReactor { - public: - explicit Reactor(experimental::CallbackServerContext* ctx) { + class Reactor : public ::grpc::experimental::ServerUnaryReactor { + public: + explicit Reactor(experimental::CallbackServerContext* ctx) { EXPECT_EQ(internal::MetadataMatchCount(ctx->client_metadata(), kCheckClientInitialMetadataKey, kCheckClientInitialMetadataVal), - 1); - EXPECT_EQ(ctx->client_metadata().count(kCheckClientInitialMetadataKey), - 1u); - Finish(Status::OK); - } - void OnDone() override { delete this; } - }; - - return new Reactor(context); -} - -experimental::ServerReadReactor<EchoRequest>* -CallbackTestServiceImpl::RequestStream( - experimental::CallbackServerContext* context, EchoResponse* response) { - // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by - // the server by calling ServerContext::TryCancel() depending on the - // value: - // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server - // reads any message from the client CANCEL_DURING_PROCESSING: The RPC - // is cancelled while the server is reading messages from the client - // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads - // all the messages from the client + 1); + EXPECT_EQ(ctx->client_metadata().count(kCheckClientInitialMetadataKey), + 1u); + Finish(Status::OK); + } + void OnDone() override { delete this; } + }; + + return new Reactor(context); +} + +experimental::ServerReadReactor<EchoRequest>* +CallbackTestServiceImpl::RequestStream( + experimental::CallbackServerContext* context, EchoResponse* response) { + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by + // the server by calling ServerContext::TryCancel() depending on the + // value: + // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server + // reads any message from the client CANCEL_DURING_PROCESSING: The RPC + // is cancelled while the server is reading messages from the client + // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads + // all the messages from the client int server_try_cancel = internal::GetIntValueFromMetadata( - kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); - if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { + kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); + if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { internal::ServerTryCancelNonblocking(context); - // Don't need to provide a reactor since the RPC is canceled - return nullptr; - } - - class Reactor : public ::grpc::experimental::ServerReadReactor<EchoRequest> { - public: - Reactor(experimental::CallbackServerContext* ctx, EchoResponse* response, - int server_try_cancel) - : ctx_(ctx), - response_(response), - server_try_cancel_(server_try_cancel) { - EXPECT_NE(server_try_cancel, CANCEL_BEFORE_PROCESSING); - response->set_message(""); - - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - ctx->TryCancel(); - // Don't wait for it here - } - StartRead(&request_); - setup_done_ = true; - } - void OnDone() override { delete this; } - void OnCancel() override { - EXPECT_TRUE(setup_done_); - EXPECT_TRUE(ctx_->IsCancelled()); - FinishOnce(Status::CANCELLED); - } - void OnReadDone(bool ok) override { - if (ok) { - response_->mutable_message()->append(request_.message()); - num_msgs_read_++; - StartRead(&request_); - } else { - gpr_log(GPR_INFO, "Read: %d messages", num_msgs_read_); - - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - // Let OnCancel recover this - return; - } - if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { + // Don't need to provide a reactor since the RPC is canceled + return nullptr; + } + + class Reactor : public ::grpc::experimental::ServerReadReactor<EchoRequest> { + public: + Reactor(experimental::CallbackServerContext* ctx, EchoResponse* response, + int server_try_cancel) + : ctx_(ctx), + response_(response), + server_try_cancel_(server_try_cancel) { + EXPECT_NE(server_try_cancel, CANCEL_BEFORE_PROCESSING); + response->set_message(""); + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + ctx->TryCancel(); + // Don't wait for it here + } + StartRead(&request_); + setup_done_ = true; + } + void OnDone() override { delete this; } + void OnCancel() override { + EXPECT_TRUE(setup_done_); + EXPECT_TRUE(ctx_->IsCancelled()); + FinishOnce(Status::CANCELLED); + } + void OnReadDone(bool ok) override { + if (ok) { + response_->mutable_message()->append(request_.message()); + num_msgs_read_++; + StartRead(&request_); + } else { + gpr_log(GPR_INFO, "Read: %d messages", num_msgs_read_); + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + // Let OnCancel recover this + return; + } + if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { internal::ServerTryCancelNonblocking(ctx_); - return; - } - FinishOnce(Status::OK); - } - } - - private: - void FinishOnce(const Status& s) { - std::lock_guard<std::mutex> l(finish_mu_); - if (!finished_) { - Finish(s); - finished_ = true; - } - } - - experimental::CallbackServerContext* const ctx_; - EchoResponse* const response_; - EchoRequest request_; - int num_msgs_read_{0}; - int server_try_cancel_; - std::mutex finish_mu_; - bool finished_{false}; - bool setup_done_{false}; - }; - - return new Reactor(context, response, server_try_cancel); -} - -// Return 'kNumResponseStreamMsgs' messages. -// TODO(yangg) make it generic by adding a parameter into EchoRequest -experimental::ServerWriteReactor<EchoResponse>* -CallbackTestServiceImpl::ResponseStream( - experimental::CallbackServerContext* context, const EchoRequest* request) { - // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by - // the server by calling ServerContext::TryCancel() depending on the - // value: - // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server - // reads any message from the client CANCEL_DURING_PROCESSING: The RPC - // is cancelled while the server is reading messages from the client - // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads - // all the messages from the client + return; + } + FinishOnce(Status::OK); + } + } + + private: + void FinishOnce(const Status& s) { + std::lock_guard<std::mutex> l(finish_mu_); + if (!finished_) { + Finish(s); + finished_ = true; + } + } + + experimental::CallbackServerContext* const ctx_; + EchoResponse* const response_; + EchoRequest request_; + int num_msgs_read_{0}; + int server_try_cancel_; + std::mutex finish_mu_; + bool finished_{false}; + bool setup_done_{false}; + }; + + return new Reactor(context, response, server_try_cancel); +} + +// Return 'kNumResponseStreamMsgs' messages. +// TODO(yangg) make it generic by adding a parameter into EchoRequest +experimental::ServerWriteReactor<EchoResponse>* +CallbackTestServiceImpl::ResponseStream( + experimental::CallbackServerContext* context, const EchoRequest* request) { + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by + // the server by calling ServerContext::TryCancel() depending on the + // value: + // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server + // reads any message from the client CANCEL_DURING_PROCESSING: The RPC + // is cancelled while the server is reading messages from the client + // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads + // all the messages from the client int server_try_cancel = internal::GetIntValueFromMetadata( - kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); - if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { + kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); + if (server_try_cancel == CANCEL_BEFORE_PROCESSING) { internal::ServerTryCancelNonblocking(context); - } - - class Reactor - : public ::grpc::experimental::ServerWriteReactor<EchoResponse> { - public: - Reactor(experimental::CallbackServerContext* ctx, - const EchoRequest* request, int server_try_cancel) - : ctx_(ctx), request_(request), server_try_cancel_(server_try_cancel) { + } + + class Reactor + : public ::grpc::experimental::ServerWriteReactor<EchoResponse> { + public: + Reactor(experimental::CallbackServerContext* ctx, + const EchoRequest* request, int server_try_cancel) + : ctx_(ctx), request_(request), server_try_cancel_(server_try_cancel) { server_coalescing_api_ = internal::GetIntValueFromMetadata( - kServerUseCoalescingApi, ctx->client_metadata(), 0); + kServerUseCoalescingApi, ctx->client_metadata(), 0); server_responses_to_send_ = internal::GetIntValueFromMetadata( - kServerResponseStreamsToSend, ctx->client_metadata(), - kServerDefaultResponseStreamsToSend); - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - ctx->TryCancel(); - } - if (server_try_cancel_ != CANCEL_BEFORE_PROCESSING) { - if (num_msgs_sent_ < server_responses_to_send_) { - NextWrite(); - } - } - setup_done_ = true; - } - void OnDone() override { delete this; } - void OnCancel() override { - EXPECT_TRUE(setup_done_); - EXPECT_TRUE(ctx_->IsCancelled()); - FinishOnce(Status::CANCELLED); - } - void OnWriteDone(bool /*ok*/) override { - if (num_msgs_sent_ < server_responses_to_send_) { - NextWrite(); - } else if (server_coalescing_api_ != 0) { - // We would have already done Finish just after the WriteLast - } else if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - // Let OnCancel recover this - } else if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { + kServerResponseStreamsToSend, ctx->client_metadata(), + kServerDefaultResponseStreamsToSend); + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + ctx->TryCancel(); + } + if (server_try_cancel_ != CANCEL_BEFORE_PROCESSING) { + if (num_msgs_sent_ < server_responses_to_send_) { + NextWrite(); + } + } + setup_done_ = true; + } + void OnDone() override { delete this; } + void OnCancel() override { + EXPECT_TRUE(setup_done_); + EXPECT_TRUE(ctx_->IsCancelled()); + FinishOnce(Status::CANCELLED); + } + void OnWriteDone(bool /*ok*/) override { + if (num_msgs_sent_ < server_responses_to_send_) { + NextWrite(); + } else if (server_coalescing_api_ != 0) { + // We would have already done Finish just after the WriteLast + } else if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + // Let OnCancel recover this + } else if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { internal::ServerTryCancelNonblocking(ctx_); - } else { - FinishOnce(Status::OK); - } - } - - private: - void FinishOnce(const Status& s) { - std::lock_guard<std::mutex> l(finish_mu_); - if (!finished_) { - Finish(s); - finished_ = true; - } - } - - void NextWrite() { - response_.set_message(request_->message() + + } else { + FinishOnce(Status::OK); + } + } + + private: + void FinishOnce(const Status& s) { + std::lock_guard<std::mutex> l(finish_mu_); + if (!finished_) { + Finish(s); + finished_ = true; + } + } + + void NextWrite() { + response_.set_message(request_->message() + ::ToString(num_msgs_sent_)); - if (num_msgs_sent_ == server_responses_to_send_ - 1 && - server_coalescing_api_ != 0) { + if (num_msgs_sent_ == server_responses_to_send_ - 1 && + server_coalescing_api_ != 0) { { std::lock_guard<std::mutex> l(finish_mu_); if (!finished_) { @@ -508,59 +508,59 @@ CallbackTestServiceImpl::ResponseStream( StartWriteLast(&response_, WriteOptions()); } } - // If we use WriteLast, we shouldn't wait before attempting Finish - FinishOnce(Status::OK); - } else { + // If we use WriteLast, we shouldn't wait before attempting Finish + FinishOnce(Status::OK); + } else { std::lock_guard<std::mutex> l(finish_mu_); if (!finished_) { num_msgs_sent_++; StartWrite(&response_); } - } - } - experimental::CallbackServerContext* const ctx_; - const EchoRequest* const request_; - EchoResponse response_; - int num_msgs_sent_{0}; - int server_try_cancel_; - int server_coalescing_api_; - int server_responses_to_send_; - std::mutex finish_mu_; - bool finished_{false}; - bool setup_done_{false}; - }; - return new Reactor(context, request, server_try_cancel); -} - -experimental::ServerBidiReactor<EchoRequest, EchoResponse>* -CallbackTestServiceImpl::BidiStream( - experimental::CallbackServerContext* context) { - class Reactor : public ::grpc::experimental::ServerBidiReactor<EchoRequest, - EchoResponse> { - public: - explicit Reactor(experimental::CallbackServerContext* ctx) : ctx_(ctx) { - // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by - // the server by calling ServerContext::TryCancel() depending on the - // value: - // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server - // reads any message from the client CANCEL_DURING_PROCESSING: The RPC - // is cancelled while the server is reading messages from the client - // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads - // all the messages from the client + } + } + experimental::CallbackServerContext* const ctx_; + const EchoRequest* const request_; + EchoResponse response_; + int num_msgs_sent_{0}; + int server_try_cancel_; + int server_coalescing_api_; + int server_responses_to_send_; + std::mutex finish_mu_; + bool finished_{false}; + bool setup_done_{false}; + }; + return new Reactor(context, request, server_try_cancel); +} + +experimental::ServerBidiReactor<EchoRequest, EchoResponse>* +CallbackTestServiceImpl::BidiStream( + experimental::CallbackServerContext* context) { + class Reactor : public ::grpc::experimental::ServerBidiReactor<EchoRequest, + EchoResponse> { + public: + explicit Reactor(experimental::CallbackServerContext* ctx) : ctx_(ctx) { + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by + // the server by calling ServerContext::TryCancel() depending on the + // value: + // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server + // reads any message from the client CANCEL_DURING_PROCESSING: The RPC + // is cancelled while the server is reading messages from the client + // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads + // all the messages from the client server_try_cancel_ = internal::GetIntValueFromMetadata( - kServerTryCancelRequest, ctx->client_metadata(), DO_NOT_CANCEL); + kServerTryCancelRequest, ctx->client_metadata(), DO_NOT_CANCEL); server_write_last_ = internal::GetIntValueFromMetadata( kServerFinishAfterNReads, ctx->client_metadata(), 0); - if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { + if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { internal::ServerTryCancelNonblocking(ctx); - } else { - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - ctx->TryCancel(); - } - StartRead(&request_); - } - setup_done_ = true; - } + } else { + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + ctx->TryCancel(); + } + StartRead(&request_); + } + setup_done_ = true; + } void OnDone() override { { // Use the same lock as finish to make sure that OnDone isn't inlined. @@ -570,15 +570,15 @@ CallbackTestServiceImpl::BidiStream( } delete this; } - void OnCancel() override { - EXPECT_TRUE(setup_done_); - EXPECT_TRUE(ctx_->IsCancelled()); - FinishOnce(Status::CANCELLED); - } - void OnReadDone(bool ok) override { - if (ok) { - num_msgs_read_++; - response_.set_message(request_.message()); + void OnCancel() override { + EXPECT_TRUE(setup_done_); + EXPECT_TRUE(ctx_->IsCancelled()); + FinishOnce(Status::CANCELLED); + } + void OnReadDone(bool ok) override { + if (ok) { + num_msgs_read_++; + response_.set_message(request_.message()); std::lock_guard<std::mutex> l(finish_mu_); if (!finished_) { if (num_msgs_read_ == server_write_last_) { @@ -588,51 +588,51 @@ CallbackTestServiceImpl::BidiStream( StartWrite(&response_); return; } - } - } - - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - // Let OnCancel handle this - } else if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { + } + } + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + // Let OnCancel handle this + } else if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { internal::ServerTryCancelNonblocking(ctx_); - } else { - FinishOnce(Status::OK); - } - } - void OnWriteDone(bool /*ok*/) override { - std::lock_guard<std::mutex> l(finish_mu_); - if (!finished_) { - StartRead(&request_); - } - } - - private: - void FinishOnce(const Status& s) { - std::lock_guard<std::mutex> l(finish_mu_); - if (!finished_) { - finished_ = true; + } else { + FinishOnce(Status::OK); + } + } + void OnWriteDone(bool /*ok*/) override { + std::lock_guard<std::mutex> l(finish_mu_); + if (!finished_) { + StartRead(&request_); + } + } + + private: + void FinishOnce(const Status& s) { + std::lock_guard<std::mutex> l(finish_mu_); + if (!finished_) { + finished_ = true; // Finish asynchronously to make sure that there are no deadlocks. finish_thread_ = std::thread([this, s] { std::lock_guard<std::mutex> l(finish_mu_); Finish(s); }); - } - } - - experimental::CallbackServerContext* const ctx_; - EchoRequest request_; - EchoResponse response_; - int num_msgs_read_{0}; - int server_try_cancel_; - int server_write_last_; - std::mutex finish_mu_; - bool finished_{false}; - bool setup_done_{false}; + } + } + + experimental::CallbackServerContext* const ctx_; + EchoRequest request_; + EchoResponse response_; + int num_msgs_read_{0}; + int server_try_cancel_; + int server_write_last_; + std::mutex finish_mu_; + bool finished_{false}; + bool setup_done_{false}; std::thread finish_thread_; - }; - - return new Reactor(context); -} - -} // namespace testing -} // namespace grpc + }; + + return new Reactor(context); +} + +} // namespace testing +} // namespace grpc diff --git a/contrib/libs/grpc/test/cpp/end2end/test_service_impl.h b/contrib/libs/grpc/test/cpp/end2end/test_service_impl.h index b3adaa3b85..5f207f1979 100644 --- a/contrib/libs/grpc/test/cpp/end2end/test_service_impl.h +++ b/contrib/libs/grpc/test/cpp/end2end/test_service_impl.h @@ -1,64 +1,64 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * 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. - * - */ - -#ifndef GRPC_TEST_CPP_END2END_TEST_SERVICE_IMPL_H -#define GRPC_TEST_CPP_END2END_TEST_SERVICE_IMPL_H - +/* + * + * Copyright 2016 gRPC authors. + * + * 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. + * + */ + +#ifndef GRPC_TEST_CPP_END2END_TEST_SERVICE_IMPL_H +#define GRPC_TEST_CPP_END2END_TEST_SERVICE_IMPL_H + #include <condition_variable> -#include <memory> -#include <mutex> - -#include <grpc/grpc.h> +#include <memory> +#include <mutex> + +#include <grpc/grpc.h> #include <grpc/support/log.h> #include <grpcpp/alarm.h> #include <grpcpp/security/credentials.h> -#include <grpcpp/server_context.h> +#include <grpcpp/server_context.h> #include <gtest/gtest.h> - + #include <util/generic/string.h> #include <thread> -#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/cpp/util/string_ref_helper.h" - + #include <util/string/cast.h> using std::chrono::system_clock; -namespace grpc { -namespace testing { - -const int kServerDefaultResponseStreamsToSend = 3; -const char* const kServerResponseStreamsToSend = "server_responses_to_send"; -const char* const kServerTryCancelRequest = "server_try_cancel"; -const char* const kDebugInfoTrailerKey = "debug-info-bin"; -const char* const kServerFinishAfterNReads = "server_finish_after_n_reads"; -const char* const kServerUseCoalescingApi = "server_use_coalescing_api"; -const char* const kCheckClientInitialMetadataKey = "custom_client_metadata"; -const char* const kCheckClientInitialMetadataVal = "Value for client metadata"; - -typedef enum { - DO_NOT_CANCEL = 0, - CANCEL_BEFORE_PROCESSING, - CANCEL_DURING_PROCESSING, - CANCEL_AFTER_PROCESSING -} ServerTryCancelRequestPhase; - +namespace grpc { +namespace testing { + +const int kServerDefaultResponseStreamsToSend = 3; +const char* const kServerResponseStreamsToSend = "server_responses_to_send"; +const char* const kServerTryCancelRequest = "server_try_cancel"; +const char* const kDebugInfoTrailerKey = "debug-info-bin"; +const char* const kServerFinishAfterNReads = "server_finish_after_n_reads"; +const char* const kServerUseCoalescingApi = "server_use_coalescing_api"; +const char* const kCheckClientInitialMetadataKey = "custom_client_metadata"; +const char* const kCheckClientInitialMetadataVal = "Value for client metadata"; + +typedef enum { + DO_NOT_CANCEL = 0, + CANCEL_BEFORE_PROCESSING, + CANCEL_DURING_PROCESSING, + CANCEL_AFTER_PROCESSING +} ServerTryCancelRequestPhase; + namespace internal { // When echo_deadline is requested, deadline seen in the ServerContext is set in // the response in seconds. @@ -119,19 +119,19 @@ class TestServiceSignaller { template <typename RpcService> class TestMultipleServiceImpl : public RpcService { - public: + public: TestMultipleServiceImpl() : signal_client_(false), host_() {} explicit TestMultipleServiceImpl(const TString& host) : signal_client_(false), host_(new TString(host)) {} - - Status Echo(ServerContext* context, const EchoRequest* request, + + Status Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) { if (request->has_param() && request->param().server_notify_client_when_started()) { signaller_.SignalClientThatRpcStarted(); signaller_.ServerWaitToContinue(); } - + // A bit of sleep to make sure that short deadline tests fail if (request->has_param() && request->param().server_sleep_us() > 0) { gpr_sleep_until( @@ -248,7 +248,7 @@ class TestMultipleServiceImpl : public RpcService { return Echo(context, request, response); } - Status CheckClientInitialMetadata(ServerContext* context, + Status CheckClientInitialMetadata(ServerContext* context, const SimpleRequest42* /*request*/, SimpleResponse42* /*response*/) { EXPECT_EQ(internal::MetadataMatchCount(context->client_metadata(), @@ -259,11 +259,11 @@ class TestMultipleServiceImpl : public RpcService { context->client_metadata().count(kCheckClientInitialMetadataKey)); return Status::OK; } - - // Unimplemented is left unimplemented to test the returned error. - - Status RequestStream(ServerContext* context, - ServerReader<EchoRequest>* reader, + + // Unimplemented is left unimplemented to test the returned error. + + Status RequestStream(ServerContext* context, + ServerReader<EchoRequest>* reader, EchoResponse* response) { // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by // the server by calling ServerContext::TryCancel() depending on the value: @@ -275,7 +275,7 @@ class TestMultipleServiceImpl : public RpcService { // all the messages from the client int server_try_cancel = internal::GetIntValueFromMetadata( kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); - + EchoRequest request; response->set_message(""); @@ -312,7 +312,7 @@ class TestMultipleServiceImpl : public RpcService { // Return 'kNumResponseStreamMsgs' messages. // TODO(yangg) make it generic by adding a parameter into EchoRequest - Status ResponseStream(ServerContext* context, const EchoRequest* request, + Status ResponseStream(ServerContext* context, const EchoRequest* request, ServerWriter<EchoResponse>* writer) { // If server_try_cancel is set in the metadata, the RPC is cancelled by the // server by calling ServerContext::TryCancel() depending on the value: @@ -324,10 +324,10 @@ class TestMultipleServiceImpl : public RpcService { // all the messages to the client int server_try_cancel = internal::GetIntValueFromMetadata( kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); - + int server_coalescing_api = internal::GetIntValueFromMetadata( kServerUseCoalescingApi, context->client_metadata(), 0); - + int server_responses_to_send = internal::GetIntValueFromMetadata( kServerResponseStreamsToSend, context->client_metadata(), kServerDefaultResponseStreamsToSend); @@ -426,70 +426,70 @@ class TestMultipleServiceImpl : public RpcService { } // Unimplemented is left unimplemented to test the returned error. - bool signal_client() { - std::unique_lock<std::mutex> lock(mu_); - return signal_client_; - } + bool signal_client() { + std::unique_lock<std::mutex> lock(mu_); + return signal_client_; + } void ClientWaitUntilRpcStarted() { signaller_.ClientWaitUntilRpcStarted(); } void SignalServerToContinue() { signaller_.SignalServerToContinue(); } uint64_t RpcsWaitingForClientCancel() { std::unique_lock<std::mutex> lock(mu_); return rpcs_waiting_for_client_cancel_; } - - private: - bool signal_client_; - std::mutex mu_; + + private: + bool signal_client_; + std::mutex mu_; TestServiceSignaller signaller_; std::unique_ptr<TString> host_; uint64_t rpcs_waiting_for_client_cancel_ = 0; -}; - -class CallbackTestServiceImpl - : public ::grpc::testing::EchoTestService::ExperimentalCallbackService { - public: - CallbackTestServiceImpl() : signal_client_(false), host_() {} +}; + +class CallbackTestServiceImpl + : public ::grpc::testing::EchoTestService::ExperimentalCallbackService { + public: + CallbackTestServiceImpl() : signal_client_(false), host_() {} explicit CallbackTestServiceImpl(const TString& host) : signal_client_(false), host_(new TString(host)) {} - - experimental::ServerUnaryReactor* Echo( - experimental::CallbackServerContext* context, const EchoRequest* request, - EchoResponse* response) override; - - experimental::ServerUnaryReactor* CheckClientInitialMetadata( + + experimental::ServerUnaryReactor* Echo( + experimental::CallbackServerContext* context, const EchoRequest* request, + EchoResponse* response) override; + + experimental::ServerUnaryReactor* CheckClientInitialMetadata( experimental::CallbackServerContext* context, const SimpleRequest42*, SimpleResponse42*) override; - - experimental::ServerReadReactor<EchoRequest>* RequestStream( - experimental::CallbackServerContext* context, - EchoResponse* response) override; - - experimental::ServerWriteReactor<EchoResponse>* ResponseStream( - experimental::CallbackServerContext* context, - const EchoRequest* request) override; - - experimental::ServerBidiReactor<EchoRequest, EchoResponse>* BidiStream( - experimental::CallbackServerContext* context) override; - - // Unimplemented is left unimplemented to test the returned error. - bool signal_client() { - std::unique_lock<std::mutex> lock(mu_); - return signal_client_; - } + + experimental::ServerReadReactor<EchoRequest>* RequestStream( + experimental::CallbackServerContext* context, + EchoResponse* response) override; + + experimental::ServerWriteReactor<EchoResponse>* ResponseStream( + experimental::CallbackServerContext* context, + const EchoRequest* request) override; + + experimental::ServerBidiReactor<EchoRequest, EchoResponse>* BidiStream( + experimental::CallbackServerContext* context) override; + + // Unimplemented is left unimplemented to test the returned error. + bool signal_client() { + std::unique_lock<std::mutex> lock(mu_); + return signal_client_; + } void ClientWaitUntilRpcStarted() { signaller_.ClientWaitUntilRpcStarted(); } void SignalServerToContinue() { signaller_.SignalServerToContinue(); } - - private: - bool signal_client_; - std::mutex mu_; + + private: + bool signal_client_; + std::mutex mu_; TestServiceSignaller signaller_; std::unique_ptr<TString> host_; -}; - +}; + using TestServiceImpl = TestMultipleServiceImpl<::grpc::testing::EchoTestService::Service>; -} // namespace testing -} // namespace grpc - -#endif // GRPC_TEST_CPP_END2END_TEST_SERVICE_IMPL_H +} // namespace testing +} // namespace grpc + +#endif // GRPC_TEST_CPP_END2END_TEST_SERVICE_IMPL_H diff --git a/contrib/libs/grpc/test/cpp/end2end/thread/ya.make_ b/contrib/libs/grpc/test/cpp/end2end/thread/ya.make_ index 296111dfc2..afabda1c8f 100644 --- a/contrib/libs/grpc/test/cpp/end2end/thread/ya.make_ +++ b/contrib/libs/grpc/test/cpp/end2end/thread/ya.make_ @@ -1,31 +1,31 @@ GTEST_UGLY() - -OWNER( - dvshkurko - g:ymake -) - -ADDINCL( - ${ARCADIA_ROOT}/contrib/libs/grpc -) - -PEERDIR( - contrib/libs/grpc/src/proto/grpc/core - contrib/libs/grpc/src/proto/grpc/testing - contrib/libs/grpc/src/proto/grpc/testing/duplicate - contrib/libs/grpc/test/core/util - contrib/libs/grpc/test/cpp/end2end - contrib/libs/grpc/test/cpp/util -) - -NO_COMPILER_WARNINGS() - -SRCDIR( - contrib/libs/grpc/test/cpp/end2end -) - -SRCS( - thread_stress_test.cc -) - -END() + +OWNER( + dvshkurko + g:ymake +) + +ADDINCL( + ${ARCADIA_ROOT}/contrib/libs/grpc +) + +PEERDIR( + contrib/libs/grpc/src/proto/grpc/core + contrib/libs/grpc/src/proto/grpc/testing + contrib/libs/grpc/src/proto/grpc/testing/duplicate + contrib/libs/grpc/test/core/util + contrib/libs/grpc/test/cpp/end2end + contrib/libs/grpc/test/cpp/util +) + +NO_COMPILER_WARNINGS() + +SRCDIR( + contrib/libs/grpc/test/cpp/end2end +) + +SRCS( + thread_stress_test.cc +) + +END() diff --git a/contrib/libs/grpc/test/cpp/end2end/thread_stress_test.cc b/contrib/libs/grpc/test/cpp/end2end/thread_stress_test.cc index d187a8a952..8acb953729 100644 --- a/contrib/libs/grpc/test/cpp/end2end/thread_stress_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/thread_stress_test.cc @@ -1,442 +1,442 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * 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. - * - */ - -#include <cinttypes> -#include <mutex> -#include <thread> - -#include <grpc/grpc.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/impl/codegen/sync.h> -#include <grpcpp/resource_quota.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/core/lib/gpr/env.h" -#include "src/core/lib/surface/api_trace.h" -#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#include <gtest/gtest.h> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; -using std::chrono::system_clock; - -const int kNumThreads = 100; // Number of threads -const int kNumAsyncSendThreads = 2; -const int kNumAsyncReceiveThreads = 50; -const int kNumAsyncServerThreads = 50; -const int kNumRpcs = 1000; // Number of RPCs per thread - -namespace grpc { -namespace testing { - -class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { - public: - TestServiceImpl() {} - - Status Echo(ServerContext* /*context*/, const EchoRequest* request, - EchoResponse* response) override { - response->set_message(request->message()); - return Status::OK; - } -}; - -template <class Service> -class CommonStressTest { - public: - CommonStressTest() : kMaxMessageSize_(8192) { -#if TARGET_OS_IPHONE - // Workaround Apple CFStream bug - gpr_setenv("grpc_cfstream", "0"); -#endif - } - virtual ~CommonStressTest() {} - virtual void SetUp() = 0; - virtual void TearDown() = 0; - virtual void ResetStub() = 0; - virtual bool AllowExhaustion() = 0; - grpc::testing::EchoTestService::Stub* GetStub() { return stub_.get(); } - - protected: - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; - std::unique_ptr<Server> server_; - - virtual void SetUpStart(ServerBuilder* builder, Service* service) = 0; - void SetUpStartCommon(ServerBuilder* builder, Service* service) { - builder->RegisterService(service); - builder->SetMaxMessageSize( - kMaxMessageSize_); // For testing max message size. - } - void SetUpEnd(ServerBuilder* builder) { server_ = builder->BuildAndStart(); } - void TearDownStart() { server_->Shutdown(); } - void TearDownEnd() {} - - private: - const int kMaxMessageSize_; -}; - -template <class Service> -class CommonStressTestInsecure : public CommonStressTest<Service> { - public: - void ResetStub() override { - std::shared_ptr<Channel> channel = grpc::CreateChannel( - server_address_.str(), InsecureChannelCredentials()); - this->stub_ = grpc::testing::EchoTestService::NewStub(channel); - } - bool AllowExhaustion() override { return false; } - - protected: - void SetUpStart(ServerBuilder* builder, Service* service) override { - int port = 5003; // grpc_pick_unused_port_or_die(); - this->server_address_ << "localhost:" << port; - // Setup server - builder->AddListeningPort(server_address_.str(), - InsecureServerCredentials()); - this->SetUpStartCommon(builder, service); - } - - private: - std::ostringstream server_address_; -}; - -template <class Service, bool allow_resource_exhaustion> -class CommonStressTestInproc : public CommonStressTest<Service> { - public: - void ResetStub() override { - ChannelArguments args; - std::shared_ptr<Channel> channel = this->server_->InProcessChannel(args); - this->stub_ = grpc::testing::EchoTestService::NewStub(channel); - } - bool AllowExhaustion() override { return allow_resource_exhaustion; } - - protected: - void SetUpStart(ServerBuilder* builder, Service* service) override { - this->SetUpStartCommon(builder, service); - } -}; - -template <class BaseClass> -class CommonStressTestSyncServer : public BaseClass { - public: - void SetUp() override { - ServerBuilder builder; - this->SetUpStart(&builder, &service_); - this->SetUpEnd(&builder); - } - void TearDown() override { - this->TearDownStart(); - this->TearDownEnd(); - } - - private: - TestServiceImpl service_; -}; - -template <class BaseClass> -class CommonStressTestSyncServerLowThreadCount : public BaseClass { - public: - void SetUp() override { - ServerBuilder builder; - ResourceQuota quota; - this->SetUpStart(&builder, &service_); - quota.SetMaxThreads(4); - builder.SetResourceQuota(quota); - this->SetUpEnd(&builder); - } - void TearDown() override { - this->TearDownStart(); - this->TearDownEnd(); - } - - private: - TestServiceImpl service_; -}; - -template <class BaseClass> -class CommonStressTestAsyncServer : public BaseClass { - public: - CommonStressTestAsyncServer() : contexts_(kNumAsyncServerThreads * 100) {} - void SetUp() override { - shutting_down_ = false; - ServerBuilder builder; - this->SetUpStart(&builder, &service_); - cq_ = builder.AddCompletionQueue(); - this->SetUpEnd(&builder); - for (int i = 0; i < kNumAsyncServerThreads * 100; i++) { - RefreshContext(i); - } - for (int i = 0; i < kNumAsyncServerThreads; i++) { - server_threads_.emplace_back(&CommonStressTestAsyncServer::ProcessRpcs, - this); - } - } - void TearDown() override { - { - grpc::internal::MutexLock l(&mu_); - this->TearDownStart(); - shutting_down_ = true; - cq_->Shutdown(); - } - - for (int i = 0; i < kNumAsyncServerThreads; i++) { - server_threads_[i].join(); - } - - void* ignored_tag; - bool ignored_ok; - while (cq_->Next(&ignored_tag, &ignored_ok)) - ; - this->TearDownEnd(); - } - - private: - void ProcessRpcs() { - void* tag; - bool ok; - while (cq_->Next(&tag, &ok)) { - if (ok) { - int i = static_cast<int>(reinterpret_cast<intptr_t>(tag)); - switch (contexts_[i].state) { - case Context::READY: { - contexts_[i].state = Context::DONE; - EchoResponse send_response; - send_response.set_message(contexts_[i].recv_request.message()); - contexts_[i].response_writer->Finish(send_response, Status::OK, - tag); - break; - } - case Context::DONE: - RefreshContext(i); - break; - } - } - } - } - void RefreshContext(int i) { - grpc::internal::MutexLock l(&mu_); - if (!shutting_down_) { - contexts_[i].state = Context::READY; - contexts_[i].srv_ctx.reset(new ServerContext); - contexts_[i].response_writer.reset( - new grpc::ServerAsyncResponseWriter<EchoResponse>( - contexts_[i].srv_ctx.get())); - service_.RequestEcho(contexts_[i].srv_ctx.get(), - &contexts_[i].recv_request, - contexts_[i].response_writer.get(), cq_.get(), - cq_.get(), (void*)static_cast<intptr_t>(i)); - } - } - struct Context { - std::unique_ptr<ServerContext> srv_ctx; - std::unique_ptr<grpc::ServerAsyncResponseWriter<EchoResponse>> - response_writer; - EchoRequest recv_request; - enum { READY, DONE } state; - }; - std::vector<Context> contexts_; - ::grpc::testing::EchoTestService::AsyncService service_; - std::unique_ptr<ServerCompletionQueue> cq_; - bool shutting_down_; - grpc::internal::Mutex mu_; - std::vector<std::thread> server_threads_; -}; - -template <class Common> -class End2endTest : public ::testing::Test { - protected: - End2endTest() {} - void SetUp() override { common_.SetUp(); } - void TearDown() override { common_.TearDown(); } - void ResetStub() { common_.ResetStub(); } - - Common common_; -}; - -static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs, - bool allow_exhaustion, gpr_atm* errors) { - EchoRequest request; - EchoResponse response; - request.set_message("Hello"); - - for (int i = 0; i < num_rpcs; ++i) { - ClientContext context; - Status s = stub->Echo(&context, request, &response); - EXPECT_TRUE(s.ok() || (allow_exhaustion && - s.error_code() == StatusCode::RESOURCE_EXHAUSTED)); - if (!s.ok()) { - if (!(allow_exhaustion && - s.error_code() == StatusCode::RESOURCE_EXHAUSTED)) { - gpr_log(GPR_ERROR, "RPC error: %d: %s", s.error_code(), - s.error_message().c_str()); - } - gpr_atm_no_barrier_fetch_add(errors, static_cast<gpr_atm>(1)); - } else { - EXPECT_EQ(response.message(), request.message()); - } - } -} - -typedef ::testing::Types< - CommonStressTestSyncServer<CommonStressTestInsecure<TestServiceImpl>>, - CommonStressTestSyncServer<CommonStressTestInproc<TestServiceImpl, false>>, - CommonStressTestSyncServerLowThreadCount< - CommonStressTestInproc<TestServiceImpl, true>>, - CommonStressTestAsyncServer< - CommonStressTestInsecure<grpc::testing::EchoTestService::AsyncService>>, - CommonStressTestAsyncServer<CommonStressTestInproc< - grpc::testing::EchoTestService::AsyncService, false>>> - CommonTypes; -TYPED_TEST_SUITE(End2endTest, CommonTypes); -TYPED_TEST(End2endTest, ThreadStress) { - this->common_.ResetStub(); - std::vector<std::thread> threads; - gpr_atm errors; - gpr_atm_rel_store(&errors, static_cast<gpr_atm>(0)); - threads.reserve(kNumThreads); - for (int i = 0; i < kNumThreads; ++i) { - threads.emplace_back(SendRpc, this->common_.GetStub(), kNumRpcs, - this->common_.AllowExhaustion(), &errors); - } - for (int i = 0; i < kNumThreads; ++i) { - threads[i].join(); - } - uint64_t error_cnt = static_cast<uint64_t>(gpr_atm_no_barrier_load(&errors)); - if (error_cnt != 0) { - gpr_log(GPR_INFO, "RPC error count: %" PRIu64, error_cnt); - } - // If this test allows resource exhaustion, expect that it actually sees some - if (this->common_.AllowExhaustion()) { - EXPECT_GT(error_cnt, static_cast<uint64_t>(0)); - } -} - -template <class Common> -class AsyncClientEnd2endTest : public ::testing::Test { - protected: - AsyncClientEnd2endTest() : rpcs_outstanding_(0) {} - - void SetUp() override { common_.SetUp(); } - void TearDown() override { - void* ignored_tag; - bool ignored_ok; - while (cq_.Next(&ignored_tag, &ignored_ok)) - ; - common_.TearDown(); - } - - void Wait() { - grpc::internal::MutexLock l(&mu_); - while (rpcs_outstanding_ != 0) { - cv_.Wait(&mu_); - } - - cq_.Shutdown(); - } - - struct AsyncClientCall { - EchoResponse response; - ClientContext context; - Status status; - std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader; - }; - - void AsyncSendRpc(int num_rpcs) { - for (int i = 0; i < num_rpcs; ++i) { - AsyncClientCall* call = new AsyncClientCall; - EchoRequest request; +/* + * + * Copyright 2015 gRPC authors. + * + * 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. + * + */ + +#include <cinttypes> +#include <mutex> +#include <thread> + +#include <grpc/grpc.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/impl/codegen/sync.h> +#include <grpcpp/resource_quota.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/surface/api_trace.h" +#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#include <gtest/gtest.h> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; +using std::chrono::system_clock; + +const int kNumThreads = 100; // Number of threads +const int kNumAsyncSendThreads = 2; +const int kNumAsyncReceiveThreads = 50; +const int kNumAsyncServerThreads = 50; +const int kNumRpcs = 1000; // Number of RPCs per thread + +namespace grpc { +namespace testing { + +class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { + public: + TestServiceImpl() {} + + Status Echo(ServerContext* /*context*/, const EchoRequest* request, + EchoResponse* response) override { + response->set_message(request->message()); + return Status::OK; + } +}; + +template <class Service> +class CommonStressTest { + public: + CommonStressTest() : kMaxMessageSize_(8192) { +#if TARGET_OS_IPHONE + // Workaround Apple CFStream bug + gpr_setenv("grpc_cfstream", "0"); +#endif + } + virtual ~CommonStressTest() {} + virtual void SetUp() = 0; + virtual void TearDown() = 0; + virtual void ResetStub() = 0; + virtual bool AllowExhaustion() = 0; + grpc::testing::EchoTestService::Stub* GetStub() { return stub_.get(); } + + protected: + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<Server> server_; + + virtual void SetUpStart(ServerBuilder* builder, Service* service) = 0; + void SetUpStartCommon(ServerBuilder* builder, Service* service) { + builder->RegisterService(service); + builder->SetMaxMessageSize( + kMaxMessageSize_); // For testing max message size. + } + void SetUpEnd(ServerBuilder* builder) { server_ = builder->BuildAndStart(); } + void TearDownStart() { server_->Shutdown(); } + void TearDownEnd() {} + + private: + const int kMaxMessageSize_; +}; + +template <class Service> +class CommonStressTestInsecure : public CommonStressTest<Service> { + public: + void ResetStub() override { + std::shared_ptr<Channel> channel = grpc::CreateChannel( + server_address_.str(), InsecureChannelCredentials()); + this->stub_ = grpc::testing::EchoTestService::NewStub(channel); + } + bool AllowExhaustion() override { return false; } + + protected: + void SetUpStart(ServerBuilder* builder, Service* service) override { + int port = 5003; // grpc_pick_unused_port_or_die(); + this->server_address_ << "localhost:" << port; + // Setup server + builder->AddListeningPort(server_address_.str(), + InsecureServerCredentials()); + this->SetUpStartCommon(builder, service); + } + + private: + std::ostringstream server_address_; +}; + +template <class Service, bool allow_resource_exhaustion> +class CommonStressTestInproc : public CommonStressTest<Service> { + public: + void ResetStub() override { + ChannelArguments args; + std::shared_ptr<Channel> channel = this->server_->InProcessChannel(args); + this->stub_ = grpc::testing::EchoTestService::NewStub(channel); + } + bool AllowExhaustion() override { return allow_resource_exhaustion; } + + protected: + void SetUpStart(ServerBuilder* builder, Service* service) override { + this->SetUpStartCommon(builder, service); + } +}; + +template <class BaseClass> +class CommonStressTestSyncServer : public BaseClass { + public: + void SetUp() override { + ServerBuilder builder; + this->SetUpStart(&builder, &service_); + this->SetUpEnd(&builder); + } + void TearDown() override { + this->TearDownStart(); + this->TearDownEnd(); + } + + private: + TestServiceImpl service_; +}; + +template <class BaseClass> +class CommonStressTestSyncServerLowThreadCount : public BaseClass { + public: + void SetUp() override { + ServerBuilder builder; + ResourceQuota quota; + this->SetUpStart(&builder, &service_); + quota.SetMaxThreads(4); + builder.SetResourceQuota(quota); + this->SetUpEnd(&builder); + } + void TearDown() override { + this->TearDownStart(); + this->TearDownEnd(); + } + + private: + TestServiceImpl service_; +}; + +template <class BaseClass> +class CommonStressTestAsyncServer : public BaseClass { + public: + CommonStressTestAsyncServer() : contexts_(kNumAsyncServerThreads * 100) {} + void SetUp() override { + shutting_down_ = false; + ServerBuilder builder; + this->SetUpStart(&builder, &service_); + cq_ = builder.AddCompletionQueue(); + this->SetUpEnd(&builder); + for (int i = 0; i < kNumAsyncServerThreads * 100; i++) { + RefreshContext(i); + } + for (int i = 0; i < kNumAsyncServerThreads; i++) { + server_threads_.emplace_back(&CommonStressTestAsyncServer::ProcessRpcs, + this); + } + } + void TearDown() override { + { + grpc::internal::MutexLock l(&mu_); + this->TearDownStart(); + shutting_down_ = true; + cq_->Shutdown(); + } + + for (int i = 0; i < kNumAsyncServerThreads; i++) { + server_threads_[i].join(); + } + + void* ignored_tag; + bool ignored_ok; + while (cq_->Next(&ignored_tag, &ignored_ok)) + ; + this->TearDownEnd(); + } + + private: + void ProcessRpcs() { + void* tag; + bool ok; + while (cq_->Next(&tag, &ok)) { + if (ok) { + int i = static_cast<int>(reinterpret_cast<intptr_t>(tag)); + switch (contexts_[i].state) { + case Context::READY: { + contexts_[i].state = Context::DONE; + EchoResponse send_response; + send_response.set_message(contexts_[i].recv_request.message()); + contexts_[i].response_writer->Finish(send_response, Status::OK, + tag); + break; + } + case Context::DONE: + RefreshContext(i); + break; + } + } + } + } + void RefreshContext(int i) { + grpc::internal::MutexLock l(&mu_); + if (!shutting_down_) { + contexts_[i].state = Context::READY; + contexts_[i].srv_ctx.reset(new ServerContext); + contexts_[i].response_writer.reset( + new grpc::ServerAsyncResponseWriter<EchoResponse>( + contexts_[i].srv_ctx.get())); + service_.RequestEcho(contexts_[i].srv_ctx.get(), + &contexts_[i].recv_request, + contexts_[i].response_writer.get(), cq_.get(), + cq_.get(), (void*)static_cast<intptr_t>(i)); + } + } + struct Context { + std::unique_ptr<ServerContext> srv_ctx; + std::unique_ptr<grpc::ServerAsyncResponseWriter<EchoResponse>> + response_writer; + EchoRequest recv_request; + enum { READY, DONE } state; + }; + std::vector<Context> contexts_; + ::grpc::testing::EchoTestService::AsyncService service_; + std::unique_ptr<ServerCompletionQueue> cq_; + bool shutting_down_; + grpc::internal::Mutex mu_; + std::vector<std::thread> server_threads_; +}; + +template <class Common> +class End2endTest : public ::testing::Test { + protected: + End2endTest() {} + void SetUp() override { common_.SetUp(); } + void TearDown() override { common_.TearDown(); } + void ResetStub() { common_.ResetStub(); } + + Common common_; +}; + +static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs, + bool allow_exhaustion, gpr_atm* errors) { + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + + for (int i = 0; i < num_rpcs; ++i) { + ClientContext context; + Status s = stub->Echo(&context, request, &response); + EXPECT_TRUE(s.ok() || (allow_exhaustion && + s.error_code() == StatusCode::RESOURCE_EXHAUSTED)); + if (!s.ok()) { + if (!(allow_exhaustion && + s.error_code() == StatusCode::RESOURCE_EXHAUSTED)) { + gpr_log(GPR_ERROR, "RPC error: %d: %s", s.error_code(), + s.error_message().c_str()); + } + gpr_atm_no_barrier_fetch_add(errors, static_cast<gpr_atm>(1)); + } else { + EXPECT_EQ(response.message(), request.message()); + } + } +} + +typedef ::testing::Types< + CommonStressTestSyncServer<CommonStressTestInsecure<TestServiceImpl>>, + CommonStressTestSyncServer<CommonStressTestInproc<TestServiceImpl, false>>, + CommonStressTestSyncServerLowThreadCount< + CommonStressTestInproc<TestServiceImpl, true>>, + CommonStressTestAsyncServer< + CommonStressTestInsecure<grpc::testing::EchoTestService::AsyncService>>, + CommonStressTestAsyncServer<CommonStressTestInproc< + grpc::testing::EchoTestService::AsyncService, false>>> + CommonTypes; +TYPED_TEST_SUITE(End2endTest, CommonTypes); +TYPED_TEST(End2endTest, ThreadStress) { + this->common_.ResetStub(); + std::vector<std::thread> threads; + gpr_atm errors; + gpr_atm_rel_store(&errors, static_cast<gpr_atm>(0)); + threads.reserve(kNumThreads); + for (int i = 0; i < kNumThreads; ++i) { + threads.emplace_back(SendRpc, this->common_.GetStub(), kNumRpcs, + this->common_.AllowExhaustion(), &errors); + } + for (int i = 0; i < kNumThreads; ++i) { + threads[i].join(); + } + uint64_t error_cnt = static_cast<uint64_t>(gpr_atm_no_barrier_load(&errors)); + if (error_cnt != 0) { + gpr_log(GPR_INFO, "RPC error count: %" PRIu64, error_cnt); + } + // If this test allows resource exhaustion, expect that it actually sees some + if (this->common_.AllowExhaustion()) { + EXPECT_GT(error_cnt, static_cast<uint64_t>(0)); + } +} + +template <class Common> +class AsyncClientEnd2endTest : public ::testing::Test { + protected: + AsyncClientEnd2endTest() : rpcs_outstanding_(0) {} + + void SetUp() override { common_.SetUp(); } + void TearDown() override { + void* ignored_tag; + bool ignored_ok; + while (cq_.Next(&ignored_tag, &ignored_ok)) + ; + common_.TearDown(); + } + + void Wait() { + grpc::internal::MutexLock l(&mu_); + while (rpcs_outstanding_ != 0) { + cv_.Wait(&mu_); + } + + cq_.Shutdown(); + } + + struct AsyncClientCall { + EchoResponse response; + ClientContext context; + Status status; + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader; + }; + + void AsyncSendRpc(int num_rpcs) { + for (int i = 0; i < num_rpcs; ++i) { + AsyncClientCall* call = new AsyncClientCall; + EchoRequest request; request.set_message(TString("Hello: " + grpc::to_string(i)).c_str()); - call->response_reader = - common_.GetStub()->AsyncEcho(&call->context, request, &cq_); - call->response_reader->Finish(&call->response, &call->status, - (void*)call); - - grpc::internal::MutexLock l(&mu_); - rpcs_outstanding_++; - } - } - - void AsyncCompleteRpc() { - while (true) { - void* got_tag; - bool ok = false; - if (!cq_.Next(&got_tag, &ok)) break; - AsyncClientCall* call = static_cast<AsyncClientCall*>(got_tag); - if (!ok) { - gpr_log(GPR_DEBUG, "Error: %d", call->status.error_code()); - } - delete call; - - bool notify; - { - grpc::internal::MutexLock l(&mu_); - rpcs_outstanding_--; - notify = (rpcs_outstanding_ == 0); - } - if (notify) { - cv_.Signal(); - } - } - } - - Common common_; - CompletionQueue cq_; - grpc::internal::Mutex mu_; - grpc::internal::CondVar cv_; - int rpcs_outstanding_; -}; - -TYPED_TEST_SUITE(AsyncClientEnd2endTest, CommonTypes); -TYPED_TEST(AsyncClientEnd2endTest, ThreadStress) { - this->common_.ResetStub(); - std::vector<std::thread> send_threads, completion_threads; - for (int i = 0; i < kNumAsyncReceiveThreads; ++i) { - completion_threads.emplace_back( - &AsyncClientEnd2endTest_ThreadStress_Test<TypeParam>::AsyncCompleteRpc, - this); - } - for (int i = 0; i < kNumAsyncSendThreads; ++i) { - send_threads.emplace_back( - &AsyncClientEnd2endTest_ThreadStress_Test<TypeParam>::AsyncSendRpc, - this, kNumRpcs); - } - for (int i = 0; i < kNumAsyncSendThreads; ++i) { - send_threads[i].join(); - } - - this->Wait(); - for (int i = 0; i < kNumAsyncReceiveThreads; ++i) { - completion_threads[i].join(); - } -} - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + call->response_reader = + common_.GetStub()->AsyncEcho(&call->context, request, &cq_); + call->response_reader->Finish(&call->response, &call->status, + (void*)call); + + grpc::internal::MutexLock l(&mu_); + rpcs_outstanding_++; + } + } + + void AsyncCompleteRpc() { + while (true) { + void* got_tag; + bool ok = false; + if (!cq_.Next(&got_tag, &ok)) break; + AsyncClientCall* call = static_cast<AsyncClientCall*>(got_tag); + if (!ok) { + gpr_log(GPR_DEBUG, "Error: %d", call->status.error_code()); + } + delete call; + + bool notify; + { + grpc::internal::MutexLock l(&mu_); + rpcs_outstanding_--; + notify = (rpcs_outstanding_ == 0); + } + if (notify) { + cv_.Signal(); + } + } + } + + Common common_; + CompletionQueue cq_; + grpc::internal::Mutex mu_; + grpc::internal::CondVar cv_; + int rpcs_outstanding_; +}; + +TYPED_TEST_SUITE(AsyncClientEnd2endTest, CommonTypes); +TYPED_TEST(AsyncClientEnd2endTest, ThreadStress) { + this->common_.ResetStub(); + std::vector<std::thread> send_threads, completion_threads; + for (int i = 0; i < kNumAsyncReceiveThreads; ++i) { + completion_threads.emplace_back( + &AsyncClientEnd2endTest_ThreadStress_Test<TypeParam>::AsyncCompleteRpc, + this); + } + for (int i = 0; i < kNumAsyncSendThreads; ++i) { + send_threads.emplace_back( + &AsyncClientEnd2endTest_ThreadStress_Test<TypeParam>::AsyncSendRpc, + this, kNumRpcs); + } + for (int i = 0; i < kNumAsyncSendThreads; ++i) { + send_threads[i].join(); + } + + this->Wait(); + for (int i = 0; i < kNumAsyncReceiveThreads; ++i) { + completion_threads[i].join(); + } +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/contrib/libs/grpc/test/cpp/end2end/time_change_test.cc b/contrib/libs/grpc/test/cpp/end2end/time_change_test.cc index d83b0ae7a4..48b9eace12 100644 --- a/contrib/libs/grpc/test/cpp/end2end/time_change_test.cc +++ b/contrib/libs/grpc/test/cpp/end2end/time_change_test.cc @@ -1,367 +1,367 @@ -/* - * - * Copyright 2019 gRPC authors. - * - * 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. - * - */ - -#include <grpc/grpc.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <grpcpp/channel.h> -#include <grpcpp/client_context.h> -#include <grpcpp/create_channel.h> -#include <grpcpp/server.h> -#include <grpcpp/server_builder.h> -#include <grpcpp/server_context.h> - -#include "src/core/lib/iomgr/timer.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/test_service_impl.h" -#include "test/cpp/util/subprocess.h" - -#include <gtest/gtest.h> -#include <sys/time.h> -#include <thread> - -using grpc::testing::EchoRequest; -using grpc::testing::EchoResponse; - +/* + * + * Copyright 2019 gRPC authors. + * + * 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. + * + */ + +#include <grpc/grpc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpcpp/channel.h> +#include <grpcpp/client_context.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/server.h> +#include <grpcpp/server_builder.h> +#include <grpcpp/server_context.h> + +#include "src/core/lib/iomgr/timer.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/subprocess.h" + +#include <gtest/gtest.h> +#include <sys/time.h> +#include <thread> + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; + static TString g_root; - -static gpr_mu g_mu; -extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type); -gpr_timespec (*gpr_now_impl_orig)(gpr_clock_type clock_type) = gpr_now_impl; -static int g_time_shift_sec = 0; -static int g_time_shift_nsec = 0; -static gpr_timespec now_impl(gpr_clock_type clock) { - auto ts = gpr_now_impl_orig(clock); - // We only manipulate the realtime clock to simulate changes in wall-clock - // time - if (clock != GPR_CLOCK_REALTIME) { - return ts; - } - GPR_ASSERT(ts.tv_nsec >= 0); - GPR_ASSERT(ts.tv_nsec < GPR_NS_PER_SEC); - gpr_mu_lock(&g_mu); - ts.tv_sec += g_time_shift_sec; - ts.tv_nsec += g_time_shift_nsec; - gpr_mu_unlock(&g_mu); - if (ts.tv_nsec >= GPR_NS_PER_SEC) { - ts.tv_nsec -= GPR_NS_PER_SEC; - ++ts.tv_sec; - } else if (ts.tv_nsec < 0) { - --ts.tv_sec; - ts.tv_nsec = GPR_NS_PER_SEC + ts.tv_nsec; - } - return ts; -} - -// offset the value returned by gpr_now(GPR_CLOCK_REALTIME) by msecs -// milliseconds -static void set_now_offset(int msecs) { - gpr_mu_lock(&g_mu); - g_time_shift_sec = msecs / 1000; - g_time_shift_nsec = (msecs % 1000) * 1e6; - gpr_mu_unlock(&g_mu); -} - -// restore the original implementation of gpr_now() -static void reset_now_offset() { - gpr_mu_lock(&g_mu); - g_time_shift_sec = 0; - g_time_shift_nsec = 0; - gpr_mu_unlock(&g_mu); -} - -namespace grpc { -namespace testing { - -namespace { - -// gpr_now() is called with invalid clock_type -TEST(TimespecTest, GprNowInvalidClockType) { - // initialize to some junk value - gpr_clock_type invalid_clock_type = (gpr_clock_type)32641; - EXPECT_DEATH(gpr_now(invalid_clock_type), ".*"); -} - -// Add timespan with negative nanoseconds -TEST(TimespecTest, GprTimeAddNegativeNs) { - gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); - gpr_timespec bad_ts = {1, -1000, GPR_TIMESPAN}; - EXPECT_DEATH(gpr_time_add(now, bad_ts), ".*"); -} - -// Subtract timespan with negative nanoseconds -TEST(TimespecTest, GprTimeSubNegativeNs) { - // Nanoseconds must always be positive. Negative timestamps are represented by - // (negative seconds, positive nanoseconds) - gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); - gpr_timespec bad_ts = {1, -1000, GPR_TIMESPAN}; - EXPECT_DEATH(gpr_time_sub(now, bad_ts), ".*"); -} - -// Add negative milliseconds to gpr_timespec -TEST(TimespecTest, GrpcNegativeMillisToTimespec) { - // -1500 milliseconds converts to timespec (-2 secs, 5 * 10^8 nsec) - gpr_timespec ts = grpc_millis_to_timespec(-1500, GPR_CLOCK_MONOTONIC); - GPR_ASSERT(ts.tv_sec = -2); - GPR_ASSERT(ts.tv_nsec = 5e8); - GPR_ASSERT(ts.clock_type == GPR_CLOCK_MONOTONIC); -} - -class TimeChangeTest : public ::testing::Test { - protected: - TimeChangeTest() {} - - static void SetUpTestCase() { - auto port = grpc_pick_unused_port_or_die(); - std::ostringstream addr_stream; - addr_stream << "localhost:" << port; - server_address_ = addr_stream.str(); - server_.reset(new SubProcess({ - g_root + "/client_crash_test_server", - "--address=" + server_address_, - })); - GPR_ASSERT(server_); - // connect to server and make sure it's reachable. - auto channel = - grpc::CreateChannel(server_address_, InsecureChannelCredentials()); - GPR_ASSERT(channel); - EXPECT_TRUE(channel->WaitForConnected( - grpc_timeout_milliseconds_to_deadline(30000))); - } - - static void TearDownTestCase() { server_.reset(); } - - void SetUp() { - channel_ = - grpc::CreateChannel(server_address_, InsecureChannelCredentials()); - GPR_ASSERT(channel_); - stub_ = grpc::testing::EchoTestService::NewStub(channel_); - } - - void TearDown() { reset_now_offset(); } - - std::unique_ptr<grpc::testing::EchoTestService::Stub> CreateStub() { - return grpc::testing::EchoTestService::NewStub(channel_); - } - - std::shared_ptr<Channel> GetChannel() { return channel_; } - // time jump offsets in milliseconds - const int TIME_OFFSET1 = 20123; - const int TIME_OFFSET2 = 5678; - - private: + +static gpr_mu g_mu; +extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type); +gpr_timespec (*gpr_now_impl_orig)(gpr_clock_type clock_type) = gpr_now_impl; +static int g_time_shift_sec = 0; +static int g_time_shift_nsec = 0; +static gpr_timespec now_impl(gpr_clock_type clock) { + auto ts = gpr_now_impl_orig(clock); + // We only manipulate the realtime clock to simulate changes in wall-clock + // time + if (clock != GPR_CLOCK_REALTIME) { + return ts; + } + GPR_ASSERT(ts.tv_nsec >= 0); + GPR_ASSERT(ts.tv_nsec < GPR_NS_PER_SEC); + gpr_mu_lock(&g_mu); + ts.tv_sec += g_time_shift_sec; + ts.tv_nsec += g_time_shift_nsec; + gpr_mu_unlock(&g_mu); + if (ts.tv_nsec >= GPR_NS_PER_SEC) { + ts.tv_nsec -= GPR_NS_PER_SEC; + ++ts.tv_sec; + } else if (ts.tv_nsec < 0) { + --ts.tv_sec; + ts.tv_nsec = GPR_NS_PER_SEC + ts.tv_nsec; + } + return ts; +} + +// offset the value returned by gpr_now(GPR_CLOCK_REALTIME) by msecs +// milliseconds +static void set_now_offset(int msecs) { + gpr_mu_lock(&g_mu); + g_time_shift_sec = msecs / 1000; + g_time_shift_nsec = (msecs % 1000) * 1e6; + gpr_mu_unlock(&g_mu); +} + +// restore the original implementation of gpr_now() +static void reset_now_offset() { + gpr_mu_lock(&g_mu); + g_time_shift_sec = 0; + g_time_shift_nsec = 0; + gpr_mu_unlock(&g_mu); +} + +namespace grpc { +namespace testing { + +namespace { + +// gpr_now() is called with invalid clock_type +TEST(TimespecTest, GprNowInvalidClockType) { + // initialize to some junk value + gpr_clock_type invalid_clock_type = (gpr_clock_type)32641; + EXPECT_DEATH(gpr_now(invalid_clock_type), ".*"); +} + +// Add timespan with negative nanoseconds +TEST(TimespecTest, GprTimeAddNegativeNs) { + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + gpr_timespec bad_ts = {1, -1000, GPR_TIMESPAN}; + EXPECT_DEATH(gpr_time_add(now, bad_ts), ".*"); +} + +// Subtract timespan with negative nanoseconds +TEST(TimespecTest, GprTimeSubNegativeNs) { + // Nanoseconds must always be positive. Negative timestamps are represented by + // (negative seconds, positive nanoseconds) + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + gpr_timespec bad_ts = {1, -1000, GPR_TIMESPAN}; + EXPECT_DEATH(gpr_time_sub(now, bad_ts), ".*"); +} + +// Add negative milliseconds to gpr_timespec +TEST(TimespecTest, GrpcNegativeMillisToTimespec) { + // -1500 milliseconds converts to timespec (-2 secs, 5 * 10^8 nsec) + gpr_timespec ts = grpc_millis_to_timespec(-1500, GPR_CLOCK_MONOTONIC); + GPR_ASSERT(ts.tv_sec = -2); + GPR_ASSERT(ts.tv_nsec = 5e8); + GPR_ASSERT(ts.clock_type == GPR_CLOCK_MONOTONIC); +} + +class TimeChangeTest : public ::testing::Test { + protected: + TimeChangeTest() {} + + static void SetUpTestCase() { + auto port = grpc_pick_unused_port_or_die(); + std::ostringstream addr_stream; + addr_stream << "localhost:" << port; + server_address_ = addr_stream.str(); + server_.reset(new SubProcess({ + g_root + "/client_crash_test_server", + "--address=" + server_address_, + })); + GPR_ASSERT(server_); + // connect to server and make sure it's reachable. + auto channel = + grpc::CreateChannel(server_address_, InsecureChannelCredentials()); + GPR_ASSERT(channel); + EXPECT_TRUE(channel->WaitForConnected( + grpc_timeout_milliseconds_to_deadline(30000))); + } + + static void TearDownTestCase() { server_.reset(); } + + void SetUp() { + channel_ = + grpc::CreateChannel(server_address_, InsecureChannelCredentials()); + GPR_ASSERT(channel_); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + void TearDown() { reset_now_offset(); } + + std::unique_ptr<grpc::testing::EchoTestService::Stub> CreateStub() { + return grpc::testing::EchoTestService::NewStub(channel_); + } + + std::shared_ptr<Channel> GetChannel() { return channel_; } + // time jump offsets in milliseconds + const int TIME_OFFSET1 = 20123; + const int TIME_OFFSET2 = 5678; + + private: static TString server_address_; - static std::unique_ptr<SubProcess> server_; - std::shared_ptr<Channel> channel_; - std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; -}; + static std::unique_ptr<SubProcess> server_; + std::shared_ptr<Channel> channel_; + std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; +}; TString TimeChangeTest::server_address_; -std::unique_ptr<SubProcess> TimeChangeTest::server_; - -// Wall-clock time jumps forward on client before bidi stream is created -TEST_F(TimeChangeTest, TimeJumpForwardBeforeStreamCreated) { - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); - context.AddMetadata(kServerResponseStreamsToSend, "1"); - - auto channel = GetChannel(); - GPR_ASSERT(channel); - EXPECT_TRUE( - channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); - auto stub = CreateStub(); - - // time jumps forward by TIME_OFFSET1 milliseconds - set_now_offset(TIME_OFFSET1); - auto stream = stub->BidiStream(&context); - request.set_message("Hello"); - EXPECT_TRUE(stream->Write(request)); - - EXPECT_TRUE(stream->WritesDone()); - EXPECT_TRUE(stream->Read(&response)); - - auto status = stream->Finish(); - EXPECT_TRUE(status.ok()); -} - -// Wall-clock time jumps back on client before bidi stream is created -TEST_F(TimeChangeTest, TimeJumpBackBeforeStreamCreated) { - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); - context.AddMetadata(kServerResponseStreamsToSend, "1"); - - auto channel = GetChannel(); - GPR_ASSERT(channel); - EXPECT_TRUE( - channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); - auto stub = CreateStub(); - - // time jumps back by TIME_OFFSET1 milliseconds - set_now_offset(-TIME_OFFSET1); - auto stream = stub->BidiStream(&context); - request.set_message("Hello"); - EXPECT_TRUE(stream->Write(request)); - - EXPECT_TRUE(stream->WritesDone()); - EXPECT_TRUE(stream->Read(&response)); - EXPECT_EQ(request.message(), response.message()); - - auto status = stream->Finish(); - EXPECT_TRUE(status.ok()); -} - -// Wall-clock time jumps forward on client while call is in progress -TEST_F(TimeChangeTest, TimeJumpForwardAfterStreamCreated) { - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); - context.AddMetadata(kServerResponseStreamsToSend, "2"); - - auto channel = GetChannel(); - GPR_ASSERT(channel); - EXPECT_TRUE( - channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); - auto stub = CreateStub(); - - auto stream = stub->BidiStream(&context); - - request.set_message("Hello"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - - // time jumps forward by TIME_OFFSET1 milliseconds. - set_now_offset(TIME_OFFSET1); - - request.set_message("World"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->WritesDone()); - EXPECT_TRUE(stream->Read(&response)); - - auto status = stream->Finish(); - EXPECT_TRUE(status.ok()); -} - -// Wall-clock time jumps back on client while call is in progress -TEST_F(TimeChangeTest, TimeJumpBackAfterStreamCreated) { - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); - context.AddMetadata(kServerResponseStreamsToSend, "2"); - - auto channel = GetChannel(); - GPR_ASSERT(channel); - EXPECT_TRUE( - channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); - auto stub = CreateStub(); - - auto stream = stub->BidiStream(&context); - - request.set_message("Hello"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->Read(&response)); - - // time jumps back TIME_OFFSET1 milliseconds. - set_now_offset(-TIME_OFFSET1); - - request.set_message("World"); - EXPECT_TRUE(stream->Write(request)); - EXPECT_TRUE(stream->WritesDone()); - EXPECT_TRUE(stream->Read(&response)); - - auto status = stream->Finish(); - EXPECT_TRUE(status.ok()); -} - -// Wall-clock time jumps forward and backwards during call -TEST_F(TimeChangeTest, TimeJumpForwardAndBackDuringCall) { - EchoRequest request; - EchoResponse response; - ClientContext context; - context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); - context.AddMetadata(kServerResponseStreamsToSend, "2"); - - auto channel = GetChannel(); - GPR_ASSERT(channel); - - EXPECT_TRUE( - channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); - auto stub = CreateStub(); - auto stream = stub->BidiStream(&context); - - request.set_message("Hello"); - EXPECT_TRUE(stream->Write(request)); - - // time jumps back by TIME_OFFSET2 milliseconds - set_now_offset(-TIME_OFFSET2); - - EXPECT_TRUE(stream->Read(&response)); - request.set_message("World"); - - // time jumps forward by TIME_OFFSET milliseconds - set_now_offset(TIME_OFFSET1); - - EXPECT_TRUE(stream->Write(request)); - - // time jumps back by TIME_OFFSET2 milliseconds - set_now_offset(-TIME_OFFSET2); - - EXPECT_TRUE(stream->WritesDone()); - - // time jumps back by TIME_OFFSET2 milliseconds - set_now_offset(-TIME_OFFSET2); - - EXPECT_TRUE(stream->Read(&response)); - - // time jumps back by TIME_OFFSET2 milliseconds - set_now_offset(-TIME_OFFSET2); - - auto status = stream->Finish(); - EXPECT_TRUE(status.ok()); -} - -} // namespace - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { +std::unique_ptr<SubProcess> TimeChangeTest::server_; + +// Wall-clock time jumps forward on client before bidi stream is created +TEST_F(TimeChangeTest, TimeJumpForwardBeforeStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "1"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + // time jumps forward by TIME_OFFSET1 milliseconds + set_now_offset(TIME_OFFSET1); + auto stream = stub->BidiStream(&context); + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps back on client before bidi stream is created +TEST_F(TimeChangeTest, TimeJumpBackBeforeStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "1"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + // time jumps back by TIME_OFFSET1 milliseconds + set_now_offset(-TIME_OFFSET1); + auto stream = stub->BidiStream(&context); + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(request.message(), response.message()); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps forward on client while call is in progress +TEST_F(TimeChangeTest, TimeJumpForwardAfterStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + + // time jumps forward by TIME_OFFSET1 milliseconds. + set_now_offset(TIME_OFFSET1); + + request.set_message("World"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps back on client while call is in progress +TEST_F(TimeChangeTest, TimeJumpBackAfterStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + + // time jumps back TIME_OFFSET1 milliseconds. + set_now_offset(-TIME_OFFSET1); + + request.set_message("World"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps forward and backwards during call +TEST_F(TimeChangeTest, TimeJumpForwardAndBackDuringCall) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE(stream->Read(&response)); + request.set_message("World"); + + // time jumps forward by TIME_OFFSET milliseconds + set_now_offset(TIME_OFFSET1); + + EXPECT_TRUE(stream->Write(request)); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE(stream->WritesDone()); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE(stream->Read(&response)); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +} // namespace + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { TString me = argv[0]; - // get index of last slash in path to test binary - auto lslash = me.rfind('/'); - // set g_root = path to directory containing test binary + // get index of last slash in path to test binary + auto lslash = me.rfind('/'); + // set g_root = path to directory containing test binary if (lslash != TString::npos) { - g_root = me.substr(0, lslash); - } else { - g_root = "."; - } - - gpr_mu_init(&g_mu); - gpr_now_impl = now_impl; - - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - auto ret = RUN_ALL_TESTS(); - return ret; -} + g_root = me.substr(0, lslash); + } else { + g_root = "."; + } + + gpr_mu_init(&g_mu); + gpr_now_impl = now_impl; + + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + auto ret = RUN_ALL_TESTS(); + return ret; +} diff --git a/contrib/libs/grpc/test/cpp/end2end/ya.make b/contrib/libs/grpc/test/cpp/end2end/ya.make index 56b0d699f3..b9c1dc7fe0 100644 --- a/contrib/libs/grpc/test/cpp/end2end/ya.make +++ b/contrib/libs/grpc/test/cpp/end2end/ya.make @@ -1,67 +1,67 @@ -LIBRARY() - +LIBRARY() + LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) - + OWNER(dvshkurko) -PEERDIR( - contrib/libs/grpc/src/proto/grpc/health/v1 - contrib/libs/grpc/src/proto/grpc/testing - contrib/libs/grpc/src/proto/grpc/testing/duplicate - contrib/libs/grpc/test/cpp/util - contrib/libs/grpc +PEERDIR( + contrib/libs/grpc/src/proto/grpc/health/v1 + contrib/libs/grpc/src/proto/grpc/testing + contrib/libs/grpc/src/proto/grpc/testing/duplicate + contrib/libs/grpc/test/cpp/util + contrib/libs/grpc contrib/restricted/googletest/googlemock contrib/restricted/googletest/googletest -) - +) + ADDINCL( ${ARCADIA_BUILD_ROOT}/contrib/libs/grpc contrib/libs/grpc ) - -NO_COMPILER_WARNINGS() - -SRCS( - # async_end2end_test.cc - # channelz_service_test.cc - # client_callback_end2end_test.cc - # client_crash_test.cc - # client_crash_test_server.cc - # client_interceptors_end2end_test.cc - # client_lb_end2end_test.cc lb needs opencensus, not enabled. - # end2end_test.cc - # exception_test.cc - # filter_end2end_test.cc - # generic_end2end_test.cc - # grpclb_end2end_test.cc lb needs opencensus, not enabled. - # health_service_end2end_test.cc - # hybrid_end2end_test.cc - interceptors_util.cc - # mock_test.cc - # nonblocking_test.cc - # proto_server_reflection_test.cc - # raw_end2end_test.cc - # server_builder_plugin_test.cc - # server_crash_test.cc - # server_crash_test_client.cc - # server_early_return_test.cc - # server_interceptors_end2end_test.cc - # server_load_reporting_end2end_test.cc - # shutdown_test.cc - # streaming_throughput_test.cc - test_health_check_service_impl.cc - test_service_impl.cc - # thread_stress_test.cc - # time_change_test.cc -) - -END() - -RECURSE_FOR_TESTS( - health - server_interceptors - # Needs new gtest - # thread -) + +NO_COMPILER_WARNINGS() + +SRCS( + # async_end2end_test.cc + # channelz_service_test.cc + # client_callback_end2end_test.cc + # client_crash_test.cc + # client_crash_test_server.cc + # client_interceptors_end2end_test.cc + # client_lb_end2end_test.cc lb needs opencensus, not enabled. + # end2end_test.cc + # exception_test.cc + # filter_end2end_test.cc + # generic_end2end_test.cc + # grpclb_end2end_test.cc lb needs opencensus, not enabled. + # health_service_end2end_test.cc + # hybrid_end2end_test.cc + interceptors_util.cc + # mock_test.cc + # nonblocking_test.cc + # proto_server_reflection_test.cc + # raw_end2end_test.cc + # server_builder_plugin_test.cc + # server_crash_test.cc + # server_crash_test_client.cc + # server_early_return_test.cc + # server_interceptors_end2end_test.cc + # server_load_reporting_end2end_test.cc + # shutdown_test.cc + # streaming_throughput_test.cc + test_health_check_service_impl.cc + test_service_impl.cc + # thread_stress_test.cc + # time_change_test.cc +) + +END() + +RECURSE_FOR_TESTS( + health + server_interceptors + # Needs new gtest + # thread +) diff --git a/contrib/libs/grpc/test/cpp/util/byte_buffer_test.cc b/contrib/libs/grpc/test/cpp/util/byte_buffer_test.cc index 2354b46f51..c63f351a8f 100644 --- a/contrib/libs/grpc/test/cpp/util/byte_buffer_test.cc +++ b/contrib/libs/grpc/test/cpp/util/byte_buffer_test.cc @@ -38,13 +38,13 @@ namespace { const char* kContent1 = "hello xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char* kContent2 = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy world"; -class ByteBufferTest : public ::testing::Test { - protected: - static void SetUpTestCase() { grpc_init(); } +class ByteBufferTest : public ::testing::Test { + protected: + static void SetUpTestCase() { grpc_init(); } + + static void TearDownTestCase() { grpc_shutdown(); } +}; - static void TearDownTestCase() { grpc_shutdown(); } -}; - TEST_F(ByteBufferTest, CopyCtor) { ByteBuffer buffer1; EXPECT_FALSE(buffer1.Valid()); diff --git a/contrib/libs/grpc/test/cpp/util/cli_call.h b/contrib/libs/grpc/test/cpp/util/cli_call.h index 5284b00084..79d00d99f4 100644 --- a/contrib/libs/grpc/test/cpp/util/cli_call.h +++ b/contrib/libs/grpc/test/cpp/util/cli_call.h @@ -27,7 +27,7 @@ #include <map> -namespace grpc { +namespace grpc { class ClientContext; diff --git a/contrib/libs/grpc/test/cpp/util/cli_call_test.cc b/contrib/libs/grpc/test/cpp/util/cli_call_test.cc index e99c6a28b9..4f0544b2e5 100644 --- a/contrib/libs/grpc/test/cpp/util/cli_call_test.cc +++ b/contrib/libs/grpc/test/cpp/util/cli_call_test.cc @@ -74,8 +74,8 @@ class CliCallTest : public ::testing::Test { void TearDown() override { server_->Shutdown(); } void ResetStub() { - channel_ = grpc::CreateChannel(server_address_.str(), - InsecureChannelCredentials()); + channel_ = grpc::CreateChannel(server_address_.str(), + InsecureChannelCredentials()); stub_ = grpc::testing::EchoTestService::NewStub(channel_); } diff --git a/contrib/libs/grpc/test/cpp/util/cli_credentials.cc b/contrib/libs/grpc/test/cpp/util/cli_credentials.cc index e7127f9296..efd548eb9b 100644 --- a/contrib/libs/grpc/test/cpp/util/cli_credentials.cc +++ b/contrib/libs/grpc/test/cpp/util/cli_credentials.cc @@ -41,11 +41,11 @@ DEFINE_string( "validation."); DEFINE_string( ssl_client_cert, "", - "If not empty, load this PEM formatted client certificate file. Requires " + "If not empty, load this PEM formatted client certificate file. Requires " "use of --ssl_client_key."); DEFINE_string( ssl_client_key, "", - "If not empty, load this PEM formatted private key. Requires use of " + "If not empty, load this PEM formatted private key. Requires use of " "--ssl_client_cert"); DEFINE_string( local_connect_type, "local_tcp", diff --git a/contrib/libs/grpc/test/cpp/util/create_test_channel.cc b/contrib/libs/grpc/test/cpp/util/create_test_channel.cc index d660428537..86d8e22af1 100644 --- a/contrib/libs/grpc/test/cpp/util/create_test_channel.cc +++ b/contrib/libs/grpc/test/cpp/util/create_test_channel.cc @@ -42,8 +42,8 @@ const char kProdTlsCredentialsType[] = "prod_ssl"; class SslCredentialProvider : public testing::CredentialTypeProvider { public: std::shared_ptr<ChannelCredentials> GetChannelCredentials( - grpc::ChannelArguments* /*args*/) override { - return grpc::SslCredentials(SslCredentialsOptions()); + grpc::ChannelArguments* /*args*/) override { + return grpc::SslCredentials(SslCredentialsOptions()); } std::shared_ptr<ServerCredentials> GetServerCredentials() override { return nullptr; @@ -90,76 +90,76 @@ std::shared_ptr<Channel> CreateTestChannel( const TString& override_hostname, bool use_prod_roots, const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args) { - return CreateTestChannel(server, cred_type, override_hostname, use_prod_roots, - creds, args, - /*interceptor_creators=*/{}); -} - -std::shared_ptr<Channel> CreateTestChannel( + return CreateTestChannel(server, cred_type, override_hostname, use_prod_roots, + creds, args, + /*interceptor_creators=*/{}); +} + +std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& override_hostname, - testing::transport_security security_type, bool use_prod_roots, - const std::shared_ptr<CallCredentials>& creds, - const ChannelArguments& args) { - return CreateTestChannel(server, override_hostname, security_type, - use_prod_roots, creds, args, - /*interceptor_creators=*/{}); -} - -std::shared_ptr<Channel> CreateTestChannel( + testing::transport_security security_type, bool use_prod_roots, + const std::shared_ptr<CallCredentials>& creds, + const ChannelArguments& args) { + return CreateTestChannel(server, override_hostname, security_type, + use_prod_roots, creds, args, + /*interceptor_creators=*/{}); +} + +std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& override_hostname, - testing::transport_security security_type, bool use_prod_roots, - const std::shared_ptr<CallCredentials>& creds) { - return CreateTestChannel(server, override_hostname, security_type, - use_prod_roots, creds, ChannelArguments()); -} - -std::shared_ptr<Channel> CreateTestChannel( + testing::transport_security security_type, bool use_prod_roots, + const std::shared_ptr<CallCredentials>& creds) { + return CreateTestChannel(server, override_hostname, security_type, + use_prod_roots, creds, ChannelArguments()); +} + +std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& override_hostname, - testing::transport_security security_type, bool use_prod_roots) { - return CreateTestChannel(server, override_hostname, security_type, - use_prod_roots, std::shared_ptr<CallCredentials>()); -} - -// Shortcut for end2end and interop tests. -std::shared_ptr<Channel> CreateTestChannel( + testing::transport_security security_type, bool use_prod_roots) { + return CreateTestChannel(server, override_hostname, security_type, + use_prod_roots, std::shared_ptr<CallCredentials>()); +} + +// Shortcut for end2end and interop tests. +std::shared_ptr<Channel> CreateTestChannel( const TString& server, testing::transport_security security_type) { - return CreateTestChannel(server, "foo.test.google.fr", security_type, false); -} - -std::shared_ptr<Channel> CreateTestChannel( + return CreateTestChannel(server, "foo.test.google.fr", security_type, false); +} + +std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& credential_type, - const std::shared_ptr<CallCredentials>& creds) { - ChannelArguments channel_args; + const std::shared_ptr<CallCredentials>& creds) { + ChannelArguments channel_args; MaybeSetCustomChannelArgs(&channel_args); - std::shared_ptr<ChannelCredentials> channel_creds = - testing::GetCredentialsProvider()->GetChannelCredentials(credential_type, - &channel_args); - GPR_ASSERT(channel_creds != nullptr); - if (creds.get()) { - channel_creds = grpc::CompositeChannelCredentials(channel_creds, creds); - } - return ::grpc::CreateCustomChannel(server, channel_creds, channel_args); -} - -std::shared_ptr<Channel> CreateTestChannel( + std::shared_ptr<ChannelCredentials> channel_creds = + testing::GetCredentialsProvider()->GetChannelCredentials(credential_type, + &channel_args); + GPR_ASSERT(channel_creds != nullptr); + if (creds.get()) { + channel_creds = grpc::CompositeChannelCredentials(channel_creds, creds); + } + return ::grpc::CreateCustomChannel(server, channel_creds, channel_args); +} + +std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& cred_type, const TString& override_hostname, bool use_prod_roots, - const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args, - std::vector< - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators) { + const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args, + std::vector< + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators) { ChannelArguments channel_args(args); MaybeSetCustomChannelArgs(&channel_args); std::shared_ptr<ChannelCredentials> channel_creds; if (cred_type.empty()) { - if (interceptor_creators.empty()) { - return ::grpc::CreateCustomChannel(server, InsecureChannelCredentials(), + if (interceptor_creators.empty()) { + return ::grpc::CreateCustomChannel(server, InsecureChannelCredentials(), channel_args); - } else { - return experimental::CreateCustomChannelWithInterceptors( + } else { + return experimental::CreateCustomChannelWithInterceptors( server, InsecureChannelCredentials(), channel_args, - std::move(interceptor_creators)); - } + std::move(interceptor_creators)); + } } else if (cred_type == testing::kTlsCredentialsType) { // cred_type == "ssl" if (use_prod_roots) { gpr_once_init(&g_once_init_add_prod_ssl_provider, &AddProdSslType); @@ -177,65 +177,65 @@ std::shared_ptr<Channel> CreateTestChannel( const TString& connect_to = server.empty() ? override_hostname : server; if (creds.get()) { - channel_creds = grpc::CompositeChannelCredentials(channel_creds, creds); + channel_creds = grpc::CompositeChannelCredentials(channel_creds, creds); + } + if (interceptor_creators.empty()) { + return ::grpc::CreateCustomChannel(connect_to, channel_creds, + channel_args); + } else { + return experimental::CreateCustomChannelWithInterceptors( + connect_to, channel_creds, channel_args, + std::move(interceptor_creators)); } - if (interceptor_creators.empty()) { - return ::grpc::CreateCustomChannel(connect_to, channel_creds, - channel_args); - } else { - return experimental::CreateCustomChannelWithInterceptors( - connect_to, channel_creds, channel_args, - std::move(interceptor_creators)); - } } else { channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials( cred_type, &channel_args); GPR_ASSERT(channel_creds != nullptr); - if (interceptor_creators.empty()) { + if (interceptor_creators.empty()) { return ::grpc::CreateCustomChannel(server, channel_creds, channel_args); - } else { - return experimental::CreateCustomChannelWithInterceptors( + } else { + return experimental::CreateCustomChannelWithInterceptors( server, channel_creds, channel_args, std::move(interceptor_creators)); - } + } } } std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& override_hostname, testing::transport_security security_type, bool use_prod_roots, - const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args, - std::vector< - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators) { + const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args, + std::vector< + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators) { TString credential_type = security_type == testing::ALTS ? testing::kAltsCredentialsType : (security_type == testing::TLS ? testing::kTlsCredentialsType : testing::kInsecureCredentialsType); - return CreateTestChannel(server, credential_type, override_hostname, - use_prod_roots, creds, args, - std::move(interceptor_creators)); + return CreateTestChannel(server, credential_type, override_hostname, + use_prod_roots, creds, args, + std::move(interceptor_creators)); } std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& override_hostname, testing::transport_security security_type, bool use_prod_roots, - const std::shared_ptr<CallCredentials>& creds, - std::vector< - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators) { + const std::shared_ptr<CallCredentials>& creds, + std::vector< + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators) { return CreateTestChannel(server, override_hostname, security_type, - use_prod_roots, creds, ChannelArguments(), - std::move(interceptor_creators)); + use_prod_roots, creds, ChannelArguments(), + std::move(interceptor_creators)); } std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& credential_type, - const std::shared_ptr<CallCredentials>& creds, - std::vector< - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators) { + const std::shared_ptr<CallCredentials>& creds, + std::vector< + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators) { ChannelArguments channel_args; MaybeSetCustomChannelArgs(&channel_args); std::shared_ptr<ChannelCredentials> channel_creds = @@ -243,10 +243,10 @@ std::shared_ptr<Channel> CreateTestChannel( &channel_args); GPR_ASSERT(channel_creds != nullptr); if (creds.get()) { - channel_creds = grpc::CompositeChannelCredentials(channel_creds, creds); + channel_creds = grpc::CompositeChannelCredentials(channel_creds, creds); } - return experimental::CreateCustomChannelWithInterceptors( - server, channel_creds, channel_args, std::move(interceptor_creators)); + return experimental::CreateCustomChannelWithInterceptors( + server, channel_creds, channel_args, std::move(interceptor_creators)); } } // namespace grpc diff --git a/contrib/libs/grpc/test/cpp/util/create_test_channel.h b/contrib/libs/grpc/test/cpp/util/create_test_channel.h index 9ce9ca7fc5..ed4ce6c11b 100644 --- a/contrib/libs/grpc/test/cpp/util/create_test_channel.h +++ b/contrib/libs/grpc/test/cpp/util/create_test_channel.h @@ -21,10 +21,10 @@ #include <memory> -#include <grpcpp/channel.h> -#include <grpcpp/impl/codegen/client_interceptor.h> +#include <grpcpp/channel.h> +#include <grpcpp/impl/codegen/client_interceptor.h> #include <grpcpp/security/credentials.h> -#include <grpcpp/support/channel_arguments.h> +#include <grpcpp/support/channel_arguments.h> namespace grpc { class Channel; @@ -63,37 +63,37 @@ std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& credential_type, const std::shared_ptr<CallCredentials>& creds); -std::shared_ptr<Channel> CreateTestChannel( +std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& override_hostname, - testing::transport_security security_type, bool use_prod_roots, - const std::shared_ptr<CallCredentials>& creds, - std::vector< - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators); - -std::shared_ptr<Channel> CreateTestChannel( + testing::transport_security security_type, bool use_prod_roots, + const std::shared_ptr<CallCredentials>& creds, + std::vector< + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators); + +std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& override_hostname, - testing::transport_security security_type, bool use_prod_roots, - const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args, - std::vector< - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators); - -std::shared_ptr<Channel> CreateTestChannel( + testing::transport_security security_type, bool use_prod_roots, + const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args, + std::vector< + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators); + +std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& cred_type, const TString& override_hostname, bool use_prod_roots, - const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args, - std::vector< - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators); - -std::shared_ptr<Channel> CreateTestChannel( + const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args, + std::vector< + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators); + +std::shared_ptr<Channel> CreateTestChannel( const TString& server, const TString& credential_type, - const std::shared_ptr<CallCredentials>& creds, - std::vector< - std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> - interceptor_creators); - + const std::shared_ptr<CallCredentials>& creds, + std::vector< + std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> + interceptor_creators); + } // namespace grpc #endif // GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H diff --git a/contrib/libs/grpc/test/cpp/util/grpc_tool.cc b/contrib/libs/grpc/test/cpp/util/grpc_tool.cc index 850ff70803..30f3024e25 100644 --- a/contrib/libs/grpc/test/cpp/util/grpc_tool.cc +++ b/contrib/libs/grpc/test/cpp/util/grpc_tool.cc @@ -233,8 +233,8 @@ std::shared_ptr<grpc::Channel> CreateCliChannel( args.SetString(GRPC_ARG_SERVICE_CONFIG, FLAGS_default_service_config.c_str()); } - return ::grpc::CreateCustomChannel(server_address, cred.GetCredentials(), - args); + return ::grpc::CreateCustomChannel(server_address, cred.GetCredentials(), + args); } struct Command { @@ -443,7 +443,7 @@ bool GrpcTool::ListServices(int argc, const char** argv, return callback(output); } -bool GrpcTool::PrintType(int /*argc*/, const char** argv, +bool GrpcTool::PrintType(int /*argc*/, const char** argv, const CliCredentials& cred, GrpcToolOutputCallback callback) { CommandUsage( @@ -485,8 +485,8 @@ bool GrpcTool::CallMethod(int argc, const char** argv, " fallback when parsing request/response\n" " --proto_path ; The search path of proto files, valid" " only when --protofiles is given\n" - " --noremotedb ; Don't attempt to use reflection service" - " at all\n" + " --noremotedb ; Don't attempt to use reflection service" + " at all\n" " --metadata ; The metadata to be sent to the server\n" " --infile ; Input filename (defaults to stdin)\n" " --outfile ; Output filename (defaults to stdout)\n" @@ -618,7 +618,7 @@ bool GrpcTool::CallMethod(int argc, const char** argv, call.WritesDoneAndWait(); read_thread.join(); - gpr_mu_destroy(&parser_mu); + gpr_mu_destroy(&parser_mu); std::multimap<grpc::string_ref, grpc::string_ref> server_trailing_metadata; Status status = call.Finish(&server_trailing_metadata); @@ -847,8 +847,8 @@ bool GrpcTool::ParseMessage(int argc, const char** argv, " fallback when parsing request/response\n" " --proto_path ; The search path of proto files, valid" " only when --protofiles is given\n" - " --noremotedb ; Don't attempt to use reflection service" - " at all\n" + " --noremotedb ; Don't attempt to use reflection service" + " at all\n" " --infile ; Input filename (defaults to stdin)\n" " --outfile ; Output filename (defaults to stdout)\n" " --binary_input ; Input in binary format\n" diff --git a/contrib/libs/grpc/test/cpp/util/grpc_tool_test.cc b/contrib/libs/grpc/test/cpp/util/grpc_tool_test.cc index ebabc74772..ff610daadd 100644 --- a/contrib/libs/grpc/test/cpp/util/grpc_tool_test.cc +++ b/contrib/libs/grpc/test/cpp/util/grpc_tool_test.cc @@ -471,9 +471,9 @@ TEST_F(GrpcToolTest, TypeNotFound) { const char* argv[] = {"grpc_cli", "type", server_address.c_str(), "grpc.testing.DummyRequest"}; - EXPECT_TRUE(1 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(), - std::bind(PrintStream, &output_stream, - std::placeholders::_1))); + EXPECT_TRUE(1 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(), + std::bind(PrintStream, &output_stream, + std::placeholders::_1))); ShutdownServer(); } diff --git a/contrib/libs/grpc/test/cpp/util/metrics_server.cc b/contrib/libs/grpc/test/cpp/util/metrics_server.cc index 69a17cf384..0493da053e 100644 --- a/contrib/libs/grpc/test/cpp/util/metrics_server.cc +++ b/contrib/libs/grpc/test/cpp/util/metrics_server.cc @@ -51,7 +51,7 @@ long QpsGauge::Get() { } grpc::Status MetricsServiceImpl::GetAllGauges( - ServerContext* /*context*/, const EmptyMessage* /*request*/, + ServerContext* /*context*/, const EmptyMessage* /*request*/, ServerWriter<GaugeResponse>* writer) { gpr_log(GPR_DEBUG, "GetAllGauges called"); @@ -66,7 +66,7 @@ grpc::Status MetricsServiceImpl::GetAllGauges( return Status::OK; } -grpc::Status MetricsServiceImpl::GetGauge(ServerContext* /*context*/, +grpc::Status MetricsServiceImpl::GetGauge(ServerContext* /*context*/, const GaugeRequest* request, GaugeResponse* response) { std::lock_guard<std::mutex> lock(mu_); diff --git a/contrib/libs/grpc/test/cpp/util/metrics_server.h b/contrib/libs/grpc/test/cpp/util/metrics_server.h index 2c3c358d1c..10ffa7b4dd 100644 --- a/contrib/libs/grpc/test/cpp/util/metrics_server.h +++ b/contrib/libs/grpc/test/cpp/util/metrics_server.h @@ -21,8 +21,8 @@ #include <map> #include <mutex> -#include <grpcpp/server.h> - +#include <grpcpp/server.h> + #include "src/proto/grpc/testing/metrics.grpc.pb.h" #include "src/proto/grpc/testing/metrics.pb.h" diff --git a/contrib/libs/grpc/test/cpp/util/proto_file_parser.h b/contrib/libs/grpc/test/cpp/util/proto_file_parser.h index 8ae383001c..c0445641c7 100644 --- a/contrib/libs/grpc/test/cpp/util/proto_file_parser.h +++ b/contrib/libs/grpc/test/cpp/util/proto_file_parser.h @@ -62,7 +62,7 @@ class ProtoFileParser { /// \param is_json_format if \c true the \c formatted_proto is treated as a /// json-formatted proto, otherwise it is treated as a text-formatted /// proto - /// \return the serialised binary proto representation of \c formatted_proto + /// \return the serialised binary proto representation of \c formatted_proto TString GetSerializedProtoFromMethod(const TString& method, const TString& formatted_proto, bool is_request, @@ -71,7 +71,7 @@ class ProtoFileParser { /// Converts a text or json string to its proto representation for the given /// message type. /// \param formatted_proto the text- or json-formatted proto string - /// \return the serialised binary proto representation of \c formatted_proto + /// \return the serialised binary proto representation of \c formatted_proto TString GetSerializedProtoFromMessageType( const TString& message_type_name, const TString& formatted_proto, bool is_json_format); diff --git a/contrib/libs/grpc/test/cpp/util/proto_reflection_descriptor_database.cc b/contrib/libs/grpc/test/cpp/util/proto_reflection_descriptor_database.cc index 488f382999..27a4c1e4cf 100644 --- a/contrib/libs/grpc/test/cpp/util/proto_reflection_descriptor_database.cc +++ b/contrib/libs/grpc/test/cpp/util/proto_reflection_descriptor_database.cc @@ -44,16 +44,16 @@ ProtoReflectionDescriptorDatabase::~ProtoReflectionDescriptorDatabase() { Status status = stream_->Finish(); if (!status.ok()) { if (status.error_code() == StatusCode::UNIMPLEMENTED) { - fprintf(stderr, + fprintf(stderr, "Reflection request not implemented; " - "is the ServerReflection service enabled?\n"); - } else { - fprintf(stderr, - "ServerReflectionInfo rpc failed. Error code: %d, message: %s, " - "debug info: %s\n", - static_cast<int>(status.error_code()), - status.error_message().c_str(), - ctx_.debug_error_string().c_str()); + "is the ServerReflection service enabled?\n"); + } else { + fprintf(stderr, + "ServerReflectionInfo rpc failed. Error code: %d, message: %s, " + "debug info: %s\n", + static_cast<int>(status.error_code()), + status.error_message().c_str(), + ctx_.debug_error_string().c_str()); } } } diff --git a/contrib/libs/grpc/test/cpp/util/proto_reflection_descriptor_database.h b/contrib/libs/grpc/test/cpp/util/proto_reflection_descriptor_database.h index 6f6244278e..cdd6f0cccd 100644 --- a/contrib/libs/grpc/test/cpp/util/proto_reflection_descriptor_database.h +++ b/contrib/libs/grpc/test/cpp/util/proto_reflection_descriptor_database.h @@ -44,7 +44,7 @@ class ProtoReflectionDescriptorDatabase : public protobuf::DescriptorDatabase { // The following four methods implement DescriptorDatabase interfaces. // - // Find a file by file name. Fills in *output and returns true if found. + // Find a file by file name. Fills in *output and returns true if found. // Otherwise, returns false, leaving the contents of *output undefined. bool FindFileByName(const google::protobuf::string& filename, protobuf::FileDescriptorProto* output) override; diff --git a/contrib/libs/grpc/test/cpp/util/slice_test.cc b/contrib/libs/grpc/test/cpp/util/slice_test.cc index eeab4b298c..d7e945ae38 100644 --- a/contrib/libs/grpc/test/cpp/util/slice_test.cc +++ b/contrib/libs/grpc/test/cpp/util/slice_test.cc @@ -35,10 +35,10 @@ const char* kContent = "hello xxxxxxxxxxxxxxxxxxxx world"; class SliceTest : public ::testing::Test { protected: - static void SetUpTestCase() { grpc_init(); } - - static void TearDownTestCase() { grpc_shutdown(); } - + static void SetUpTestCase() { grpc_init(); } + + static void TearDownTestCase() { grpc_shutdown(); } + void CheckSliceSize(const Slice& s, const TString& content) { EXPECT_EQ(content.size(), s.size()); } @@ -82,7 +82,7 @@ TEST_F(SliceTest, SliceNew) { } TEST_F(SliceTest, SliceNewDoNothing) { - Slice spp(const_cast<char*>(kContent), strlen(kContent), [](void* /*p*/) {}); + Slice spp(const_cast<char*>(kContent), strlen(kContent), [](void* /*p*/) {}); CheckSlice(spp, kContent); } @@ -106,7 +106,7 @@ TEST_F(SliceTest, SliceNewWithUserData) { TEST_F(SliceTest, SliceNewLen) { Slice spp(const_cast<char*>(kContent), strlen(kContent), - [](void* /*p*/, size_t l) { EXPECT_EQ(l, strlen(kContent)); }); + [](void* /*p*/, size_t l) { EXPECT_EQ(l, strlen(kContent)); }); CheckSlice(spp, kContent); } diff --git a/contrib/libs/grpc/test/cpp/util/test_credentials_provider.cc b/contrib/libs/grpc/test/cpp/util/test_credentials_provider.cc index 98a89b51ee..f7134b773f 100644 --- a/contrib/libs/grpc/test/cpp/util/test_credentials_provider.cc +++ b/contrib/libs/grpc/test/cpp/util/test_credentials_provider.cc @@ -19,50 +19,50 @@ #include "test/cpp/util/test_credentials_provider.h" -#include <cstdio> -#include <fstream> -#include <iostream> - +#include <cstdio> +#include <fstream> +#include <iostream> + #include <mutex> #include <unordered_map> -#include <gflags/gflags.h> +#include <gflags/gflags.h> #include <grpc/support/log.h> #include <grpc/support/sync.h> -#include <grpcpp/security/server_credentials.h> +#include <grpcpp/security/server_credentials.h> #include "test/core/end2end/data/ssl_test_data.h" -DEFINE_string(tls_cert_file, "", "The TLS cert file used when --use_tls=true"); -DEFINE_string(tls_key_file, "", "The TLS key file used when --use_tls=true"); - +DEFINE_string(tls_cert_file, "", "The TLS cert file used when --use_tls=true"); +DEFINE_string(tls_key_file, "", "The TLS key file used when --use_tls=true"); + namespace grpc { namespace testing { namespace { TString ReadFile(const TString& src_path) { - std::ifstream src; - src.open(src_path, std::ifstream::in | std::ifstream::binary); - + std::ifstream src; + src.open(src_path, std::ifstream::in | std::ifstream::binary); + TString contents; - src.seekg(0, std::ios::end); - contents.reserve(src.tellg()); - src.seekg(0, std::ios::beg); - contents.assign((std::istreambuf_iterator<char>(src)), - (std::istreambuf_iterator<char>())); - return contents; -} - + src.seekg(0, std::ios::end); + contents.reserve(src.tellg()); + src.seekg(0, std::ios::beg); + contents.assign((std::istreambuf_iterator<char>(src)), + (std::istreambuf_iterator<char>())); + return contents; +} + class DefaultCredentialsProvider : public CredentialsProvider { public: - DefaultCredentialsProvider() { - if (!FLAGS_tls_key_file.empty()) { - custom_server_key_ = ReadFile(FLAGS_tls_key_file); - } - if (!FLAGS_tls_cert_file.empty()) { - custom_server_cert_ = ReadFile(FLAGS_tls_cert_file); - } - } + DefaultCredentialsProvider() { + if (!FLAGS_tls_key_file.empty()) { + custom_server_key_ = ReadFile(FLAGS_tls_key_file); + } + if (!FLAGS_tls_cert_file.empty()) { + custom_server_cert_ = ReadFile(FLAGS_tls_cert_file); + } + } ~DefaultCredentialsProvider() override {} void AddSecureType( @@ -92,7 +92,7 @@ class DefaultCredentialsProvider : public CredentialsProvider { } else if (type == grpc::testing::kTlsCredentialsType) { SslCredentialsOptions ssl_opts = {test_root_cert, "", ""}; args->SetSslTargetNameOverride("foo.test.google.fr"); - return grpc::SslCredentials(ssl_opts); + return grpc::SslCredentials(ssl_opts); } else if (type == grpc::testing::kGoogleDefaultCredentialsType) { return grpc::GoogleDefaultCredentials(); } else { @@ -118,15 +118,15 @@ class DefaultCredentialsProvider : public CredentialsProvider { } else if (type == grpc::testing::kTlsCredentialsType) { SslServerCredentialsOptions ssl_opts; ssl_opts.pem_root_certs = ""; - if (!custom_server_key_.empty() && !custom_server_cert_.empty()) { - SslServerCredentialsOptions::PemKeyCertPair pkcp = { - custom_server_key_, custom_server_cert_}; - ssl_opts.pem_key_cert_pairs.push_back(pkcp); - } else { - SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key, - test_server1_cert}; - ssl_opts.pem_key_cert_pairs.push_back(pkcp); - } + if (!custom_server_key_.empty() && !custom_server_cert_.empty()) { + SslServerCredentialsOptions::PemKeyCertPair pkcp = { + custom_server_key_, custom_server_cert_}; + ssl_opts.pem_key_cert_pairs.push_back(pkcp); + } else { + SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key, + test_server1_cert}; + ssl_opts.pem_key_cert_pairs.push_back(pkcp); + } return SslServerCredentials(ssl_opts); } else { std::unique_lock<std::mutex> lock(mu_); diff --git a/contrib/libs/grpc/test/cpp/util/ya.make b/contrib/libs/grpc/test/cpp/util/ya.make index 72346d2811..f043cc5b14 100644 --- a/contrib/libs/grpc/test/cpp/util/ya.make +++ b/contrib/libs/grpc/test/cpp/util/ya.make @@ -9,7 +9,7 @@ OWNER(orivej) PEERDIR( contrib/libs/gflags contrib/libs/protoc - contrib/libs/grpc/src/proto/grpc/reflection/v1alpha + contrib/libs/grpc/src/proto/grpc/reflection/v1alpha contrib/restricted/googletest/googlemock contrib/restricted/googletest/googletest ) @@ -22,14 +22,14 @@ ADDINCL( NO_COMPILER_WARNINGS() SRCS( - byte_buffer_proto_helper.cc + byte_buffer_proto_helper.cc # grpc_cli_libs: cli_call.cc cli_credentials.cc grpc_tool.cc proto_file_parser.cc service_describer.cc - string_ref_helper.cc + string_ref_helper.cc # grpc++_proto_reflection_desc_db: proto_reflection_descriptor_database.cc # grpc++_test_config: |