mirror of https://github.com/grpc/grpc.git
Add binder server (#27036)
Add `grpc::BinderServerCredentials()` and other related functionalities for the server to listen to binder transactions through a phony "binder port". The APIs are temporarily placed in internal headers until the corresponding gRFC is merged.pull/27254/head
parent
f9a2a7401a
commit
3df113f6d6
11 changed files with 758 additions and 3 deletions
@ -0,0 +1,50 @@ |
||||
# Copyright 2021 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. |
||||
|
||||
load("//bazel:grpc_build_system.bzl", "grpc_cc_library") |
||||
|
||||
licenses(["notice"]) |
||||
|
||||
package( |
||||
default_visibility = ["//visibility:public"], |
||||
features = [ |
||||
"layering_check", |
||||
], |
||||
) |
||||
|
||||
grpc_cc_library( |
||||
name = "grpc_transport_binder_server", |
||||
srcs = [ |
||||
"binder_server.cc", |
||||
"binder_server_credentials.cc", |
||||
], |
||||
hdrs = [ |
||||
"binder_server.h", |
||||
"binder_server_credentials.h", |
||||
], |
||||
external_deps = [ |
||||
"absl/container:flat_hash_map", |
||||
"absl/memory", |
||||
"absl/status", |
||||
], |
||||
language = "c++", |
||||
deps = [ |
||||
"//:gpr_platform", |
||||
"//:grpc++_internals", |
||||
"//:grpc_base_c", |
||||
"//src/core/ext/transport/binder/transport:binder_transport", |
||||
"//src/core/ext/transport/binder/wire_format:binder", |
||||
"//src/core/ext/transport/binder/wire_format:binder_android", |
||||
], |
||||
) |
@ -0,0 +1,179 @@ |
||||
// Copyright 2021 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/impl/codegen/port_platform.h> |
||||
|
||||
#include <grpc/grpc.h> |
||||
#include <memory> |
||||
#include <string> |
||||
#include <utility> |
||||
|
||||
#include "absl/memory/memory.h" |
||||
#include "src/core/ext/transport/binder/server/binder_server.h" |
||||
#include "src/core/ext/transport/binder/transport/binder_transport.h" |
||||
#include "src/core/ext/transport/binder/wire_format/binder_android.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/surface/server.h" |
||||
#include "src/core/lib/transport/error_utils.h" |
||||
|
||||
namespace grpc { |
||||
namespace experimental { |
||||
namespace binder { |
||||
|
||||
void* GetEndpointBinder(const std::string& service) { |
||||
return grpc_get_endpoint_binder(service); |
||||
} |
||||
|
||||
void AddEndpointBinder(const std::string& service, void* endpoint_binder) { |
||||
grpc_add_endpoint_binder(service, endpoint_binder); |
||||
} |
||||
|
||||
void RemoveEndpointBinder(const std::string& service) { |
||||
grpc_remove_endpoint_binder(service); |
||||
} |
||||
|
||||
} // namespace binder
|
||||
} // namespace experimental
|
||||
} // namespace grpc
|
||||
|
||||
grpc_core::Mutex* g_endpoint_binder_pool_mu = nullptr; |
||||
absl::flat_hash_map<std::string, void*>* g_endpoint_binder_pool = nullptr; |
||||
|
||||
void grpc_endpoint_binder_pool_init() { |
||||
g_endpoint_binder_pool_mu = new grpc_core::Mutex(); |
||||
g_endpoint_binder_pool = new absl::flat_hash_map<std::string, void*>(); |
||||
} |
||||
|
||||
void grpc_endpoint_binder_pool_shutdown() { |
||||
g_endpoint_binder_pool_mu->Lock(); |
||||
delete g_endpoint_binder_pool; |
||||
g_endpoint_binder_pool_mu->Unlock(); |
||||
delete g_endpoint_binder_pool_mu; |
||||
} |
||||
|
||||
void grpc_add_endpoint_binder(const std::string& service, |
||||
void* endpoint_binder) { |
||||
grpc_core::MutexLock lock(g_endpoint_binder_pool_mu); |
||||
(*g_endpoint_binder_pool)[service] = endpoint_binder; |
||||
} |
||||
|
||||
void grpc_remove_endpoint_binder(const std::string& service) { |
||||
grpc_core::MutexLock lock(g_endpoint_binder_pool_mu); |
||||
g_endpoint_binder_pool->erase(service); |
||||
} |
||||
|
||||
void* grpc_get_endpoint_binder(const std::string& service) { |
||||
grpc_core::MutexLock lock(g_endpoint_binder_pool_mu); |
||||
auto iter = g_endpoint_binder_pool->find(service); |
||||
return iter == g_endpoint_binder_pool->end() ? nullptr : iter->second; |
||||
} |
||||
|
||||
namespace grpc_core { |
||||
|
||||
class BinderServerListener : public Server::ListenerInterface { |
||||
public: |
||||
BinderServerListener(Server* server, std::string addr, |
||||
BinderTxReceiverFactory factory) |
||||
: server_(server), addr_(std::move(addr)), factory_(std::move(factory)) {} |
||||
|
||||
void Start(Server* /*server*/, |
||||
const std::vector<grpc_pollset*>* /*pollsets*/) override { |
||||
tx_receiver_ = factory_([this](transaction_code_t code, |
||||
const grpc_binder::ReadableParcel* parcel) { |
||||
return OnSetupTransport(code, parcel); |
||||
}); |
||||
endpoint_binder_ = tx_receiver_->GetRawBinder(); |
||||
grpc_add_endpoint_binder(addr_, endpoint_binder_); |
||||
} |
||||
|
||||
channelz::ListenSocketNode* channelz_listen_socket_node() const override { |
||||
return nullptr; |
||||
} |
||||
|
||||
void SetOnDestroyDone(grpc_closure* on_destroy_done) override { |
||||
on_destroy_done_ = on_destroy_done; |
||||
} |
||||
|
||||
void Orphan() override { delete this; } |
||||
|
||||
~BinderServerListener() override { |
||||
ExecCtx::Get()->Flush(); |
||||
if (on_destroy_done_) { |
||||
ExecCtx::Run(DEBUG_LOCATION, on_destroy_done_, GRPC_ERROR_NONE); |
||||
ExecCtx::Get()->Flush(); |
||||
} |
||||
grpc_remove_endpoint_binder(addr_); |
||||
} |
||||
|
||||
private: |
||||
absl::Status OnSetupTransport(transaction_code_t code, |
||||
const grpc_binder::ReadableParcel* parcel) { |
||||
grpc_core::ExecCtx exec_ctx; |
||||
if (grpc_binder::BinderTransportTxCode(code) != |
||||
grpc_binder::BinderTransportTxCode::SETUP_TRANSPORT) { |
||||
return absl::InvalidArgumentError("Not a SETUP_TRANSPORT request"); |
||||
} |
||||
int version; |
||||
absl::Status status = parcel->ReadInt32(&version); |
||||
if (!status.ok()) { |
||||
return status; |
||||
} |
||||
gpr_log(GPR_INFO, "version = %d", version); |
||||
// TODO(waynetu): Check supported version.
|
||||
std::unique_ptr<grpc_binder::Binder> client_binder{}; |
||||
status = parcel->ReadBinder(&client_binder); |
||||
if (!status.ok()) { |
||||
return status; |
||||
} |
||||
if (!client_binder) { |
||||
return absl::InvalidArgumentError("NULL binder read from the parcel"); |
||||
} |
||||
client_binder->Initialize(); |
||||
// Finish the second half of SETUP_TRANSPORT in
|
||||
// grpc_create_binder_transport_server().
|
||||
grpc_transport* server_transport = |
||||
grpc_create_binder_transport_server(std::move(client_binder)); |
||||
GPR_ASSERT(server_transport); |
||||
grpc_channel_args* args = grpc_channel_args_copy(server_->channel_args()); |
||||
grpc_error_handle error = server_->SetupTransport(server_transport, nullptr, |
||||
args, nullptr, nullptr); |
||||
grpc_channel_args_destroy(args); |
||||
return grpc_error_to_absl_status(error); |
||||
} |
||||
|
||||
Server* server_; |
||||
grpc_closure* on_destroy_done_ = nullptr; |
||||
std::string addr_; |
||||
BinderTxReceiverFactory factory_; |
||||
void* endpoint_binder_ = nullptr; |
||||
std::unique_ptr<grpc_binder::TransactionReceiver> tx_receiver_; |
||||
}; |
||||
|
||||
bool AddBinderPort(const std::string& addr, grpc_server* server, |
||||
BinderTxReceiverFactory factory) { |
||||
const std::string kBinderUriScheme = "binder:"; |
||||
if (addr.compare(0, kBinderUriScheme.size(), kBinderUriScheme) != 0) { |
||||
return false; |
||||
} |
||||
size_t pos = kBinderUriScheme.size(); |
||||
while (pos < addr.size() && addr[pos] == '/') pos++; |
||||
grpc_core::Server* core_server = server->core_server.get(); |
||||
core_server->AddListener( |
||||
grpc_core::OrphanablePtr<grpc_core::Server::ListenerInterface>( |
||||
new grpc_core::BinderServerListener(core_server, addr.substr(pos), |
||||
std::move(factory)))); |
||||
return true; |
||||
} |
||||
|
||||
} // namespace grpc_core
|
@ -0,0 +1,70 @@ |
||||
// Copyright 2021 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_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_H |
||||
#define GRPC_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_H |
||||
|
||||
#include <grpc/impl/codegen/port_platform.h> |
||||
|
||||
#include <string> |
||||
|
||||
#include "absl/container/flat_hash_map.h" |
||||
#include "absl/status/status.h" |
||||
#include "src/core/ext/transport/binder/transport/binder_transport.h" |
||||
#include "src/core/ext/transport/binder/wire_format/binder.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/surface/server.h" |
||||
#include "src/core/lib/transport/error_utils.h" |
||||
|
||||
// TODO(waynetu): This is part of the public API and should be moved to the
|
||||
// include/ folder.
|
||||
namespace grpc { |
||||
namespace experimental { |
||||
namespace binder { |
||||
|
||||
void* GetEndpointBinder(const std::string& service); |
||||
void AddEndpointBinder(const std::string& service, void* endpoint_binder); |
||||
void RemoveEndpointBinder(const std::string& service); |
||||
|
||||
} // namespace binder
|
||||
} // namespace experimental
|
||||
} // namespace grpc
|
||||
|
||||
extern grpc_core::Mutex* g_endpoint_binder_pool_mu; |
||||
extern absl::flat_hash_map<std::string, void*>* g_endpoint_binder_pool; |
||||
|
||||
// TODO(waynetu): Can these two functions be called in grpc_init() and
|
||||
// grpc_shutdown()?
|
||||
void grpc_endpoint_binder_pool_init(); |
||||
void grpc_endpoint_binder_pool_shutdown(); |
||||
|
||||
void grpc_add_endpoint_binder(const std::string& service, |
||||
void* endpoint_binder); |
||||
void grpc_remove_endpoint_binder(const std::string& service); |
||||
void* grpc_get_endpoint_binder(const std::string& service); |
||||
|
||||
namespace grpc_core { |
||||
|
||||
// Consume a callback, produce a transaction listener. This is used to perform
|
||||
// testing in non-Android environments where the actual binder is not available.
|
||||
using BinderTxReceiverFactory = |
||||
std::function<std::unique_ptr<grpc_binder::TransactionReceiver>( |
||||
grpc_binder::TransactionReceiver::OnTransactCb)>; |
||||
|
||||
bool AddBinderPort(const std::string& addr, grpc_server* server, |
||||
BinderTxReceiverFactory factory); |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_H
|
@ -0,0 +1,61 @@ |
||||
// Copyright 2021 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/impl/codegen/port_platform.h> |
||||
|
||||
#include <grpcpp/security/server_credentials.h> |
||||
|
||||
#include "src/core/ext/transport/binder/server/binder_server.h" |
||||
#include "src/core/ext/transport/binder/wire_format/binder_android.h" |
||||
|
||||
namespace grpc { |
||||
namespace experimental { |
||||
|
||||
namespace { |
||||
|
||||
class BinderServerCredentialsImpl final : public ServerCredentials { |
||||
public: |
||||
#ifdef GPR_ANDROID |
||||
int AddPortToServer(const std::string& addr, grpc_server* server) override { |
||||
return grpc_core::AddBinderPort( |
||||
std::string(addr), server, |
||||
[](grpc_binder::TransactionReceiver::OnTransactCb transact_cb) { |
||||
return absl::make_unique<grpc_binder::TransactionReceiverAndroid>( |
||||
nullptr, std::move(transact_cb)); |
||||
}); |
||||
} |
||||
#else |
||||
int AddPortToServer(const std::string& /*addr*/, |
||||
grpc_server* /*server*/) override { |
||||
return 0; |
||||
} |
||||
#endif // GPR_ANDROID
|
||||
|
||||
void SetAuthMetadataProcessor( |
||||
const std::shared_ptr<AuthMetadataProcessor>& /*processor*/) override { |
||||
GPR_ASSERT(false); |
||||
} |
||||
|
||||
private: |
||||
bool IsInsecure() const override { return true; } |
||||
}; |
||||
|
||||
} // namespace
|
||||
|
||||
std::shared_ptr<ServerCredentials> BinderServerCredentials() { |
||||
return std::shared_ptr<ServerCredentials>(new BinderServerCredentialsImpl()); |
||||
} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc
|
@ -0,0 +1,35 @@ |
||||
// Copyright 2021 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_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_CREDENTIALS_H |
||||
#define GRPC_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_CREDENTIALS_H |
||||
|
||||
#include <grpc/impl/codegen/port_platform.h> |
||||
|
||||
#include <grpcpp/security/server_credentials.h> |
||||
|
||||
namespace grpc { |
||||
namespace experimental { |
||||
|
||||
/// Builds Binder ServerCredentials.
|
||||
///
|
||||
/// Calling \a ServerBuilder::AddListeningPort() with Binder ServerCredentials
|
||||
/// in a non-Android environment will make the subsequent call to
|
||||
/// \a ServerBuilder::BuildAndStart() returns a null pointer.
|
||||
std::shared_ptr<grpc::ServerCredentials> BinderServerCredentials(); |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPC_CORE_EXT_TRANSPORT_BINDER_SERVER_BINDER_SERVER_CREDENTIALS_H
|
@ -0,0 +1,211 @@ |
||||
// Copyright 2021 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 "src/core/ext/transport/binder/server/binder_server.h" |
||||
|
||||
#include <grpcpp/grpcpp.h> |
||||
#include <grpcpp/impl/grpc_library.h> |
||||
#include <gtest/gtest.h> |
||||
#include <memory> |
||||
#include <thread> |
||||
#include <vector> |
||||
|
||||
#include "absl/memory/memory.h" |
||||
#include "src/core/ext/transport/binder/client/channel_create_impl.h" |
||||
#include "src/core/ext/transport/binder/server/binder_server.h" |
||||
#include "src/core/ext/transport/binder/server/binder_server_credentials.h" |
||||
#include "test/core/transport/binder/end2end/echo_service.h" |
||||
#include "test/core/transport/binder/end2end/fake_binder.h" |
||||
#include "test/core/util/test_config.h" |
||||
#include "test/cpp/end2end/test_service_impl.h" |
||||
|
||||
namespace grpc { |
||||
namespace testing { |
||||
|
||||
namespace { |
||||
|
||||
class BinderServerCredentialsImpl final : public ServerCredentials { |
||||
public: |
||||
int AddPortToServer(const std::string& addr, grpc_server* server) override { |
||||
return grpc_core::AddBinderPort( |
||||
addr, server, |
||||
[](grpc_binder::TransactionReceiver::OnTransactCb transact_cb) { |
||||
return absl::make_unique< |
||||
grpc_binder::end2end_testing::FakeTransactionReceiver>( |
||||
nullptr, std::move(transact_cb)); |
||||
}); |
||||
} |
||||
|
||||
void SetAuthMetadataProcessor( |
||||
const std::shared_ptr<AuthMetadataProcessor>& /*processor*/) override { |
||||
GPR_ASSERT(false); |
||||
} |
||||
|
||||
private: |
||||
bool IsInsecure() const override { return true; } |
||||
}; |
||||
|
||||
} // namespace
|
||||
|
||||
std::shared_ptr<ServerCredentials> BinderServerCredentials() { |
||||
return std::shared_ptr<ServerCredentials>(new BinderServerCredentialsImpl()); |
||||
} |
||||
|
||||
std::shared_ptr<grpc::Channel> CreateBinderChannel( |
||||
std::unique_ptr<grpc_binder::Binder> endpoint_binder) { |
||||
grpc::internal::GrpcLibrary init_lib; |
||||
init_lib.init(); |
||||
|
||||
return grpc::CreateChannelInternal( |
||||
"", |
||||
grpc::internal::CreateChannelFromBinderImpl(std::move(endpoint_binder), |
||||
nullptr), |
||||
std::vector<std::unique_ptr< |
||||
grpc::experimental::ClientInterceptorFactoryInterface>>()); |
||||
} |
||||
|
||||
} // namespace testing
|
||||
} // namespace grpc
|
||||
|
||||
namespace { |
||||
|
||||
class BinderServerTest : public ::testing::Test { |
||||
public: |
||||
BinderServerTest() { |
||||
grpc_binder::end2end_testing::g_transaction_processor = |
||||
new grpc_binder::end2end_testing::TransactionProcessor(); |
||||
} |
||||
~BinderServerTest() override { |
||||
delete grpc_binder::end2end_testing::g_transaction_processor; |
||||
} |
||||
static void SetUpTestSuite() { |
||||
grpc_init(); |
||||
grpc_endpoint_binder_pool_init(); |
||||
} |
||||
static void TearDownTestSuite() { |
||||
grpc_endpoint_binder_pool_shutdown(); |
||||
grpc_shutdown(); |
||||
} |
||||
}; |
||||
|
||||
#ifndef GPR_ANDROID |
||||
TEST(BinderServerCredentialsTest, FailedInNonAndroidEnvironments) { |
||||
grpc::ServerBuilder server_builder; |
||||
grpc::testing::TestServiceImpl service; |
||||
server_builder.RegisterService(&service); |
||||
server_builder.AddListeningPort( |
||||
"binder://fail", grpc::experimental::BinderServerCredentials()); |
||||
EXPECT_EQ(server_builder.BuildAndStart(), nullptr); |
||||
} |
||||
#endif // !GPR_ANDROID
|
||||
|
||||
TEST_F(BinderServerTest, BuildAndStart) { |
||||
grpc::ServerBuilder server_builder; |
||||
grpc_binder::end2end_testing::EchoServer service; |
||||
server_builder.RegisterService(&service); |
||||
server_builder.AddListeningPort("binder://example.service", |
||||
grpc::testing::BinderServerCredentials()); |
||||
std::unique_ptr<grpc::Server> server = server_builder.BuildAndStart(); |
||||
EXPECT_NE(grpc::experimental::binder::GetEndpointBinder("example.service"), |
||||
nullptr); |
||||
server->Shutdown(); |
||||
EXPECT_EQ(grpc::experimental::binder::GetEndpointBinder("example.service"), |
||||
nullptr); |
||||
} |
||||
|
||||
TEST_F(BinderServerTest, BuildAndStartFailed) { |
||||
grpc::ServerBuilder server_builder; |
||||
grpc_binder::end2end_testing::EchoServer service; |
||||
server_builder.RegisterService(&service); |
||||
// Error: binder address should begin with binder:
|
||||
server_builder.AddListeningPort("localhost:12345", |
||||
grpc::testing::BinderServerCredentials()); |
||||
std::unique_ptr<grpc::Server> server = server_builder.BuildAndStart(); |
||||
EXPECT_EQ(server, nullptr); |
||||
} |
||||
|
||||
TEST_F(BinderServerTest, CreateChannelWithEndpointBinder) { |
||||
grpc::ServerBuilder server_builder; |
||||
grpc_binder::end2end_testing::EchoServer service; |
||||
server_builder.RegisterService(&service); |
||||
server_builder.AddListeningPort("binder://example.service", |
||||
grpc::testing::BinderServerCredentials()); |
||||
std::unique_ptr<grpc::Server> server = server_builder.BuildAndStart(); |
||||
void* raw_endpoint_binder = |
||||
grpc::experimental::binder::GetEndpointBinder("example.service"); |
||||
std::unique_ptr<grpc_binder::Binder> endpoint_binder = |
||||
absl::make_unique<grpc_binder::end2end_testing::FakeBinder>( |
||||
static_cast<grpc_binder::end2end_testing::FakeEndpoint*>( |
||||
raw_endpoint_binder)); |
||||
std::shared_ptr<grpc::Channel> channel = |
||||
grpc::testing::CreateBinderChannel(std::move(endpoint_binder)); |
||||
std::unique_ptr<grpc_binder::end2end_testing::EchoService::Stub> stub = |
||||
grpc_binder::end2end_testing::EchoService::NewStub(channel); |
||||
grpc_binder::end2end_testing::EchoRequest request; |
||||
grpc_binder::end2end_testing::EchoResponse response; |
||||
grpc::ClientContext context; |
||||
request.set_text("BinderServerBuilder"); |
||||
grpc::Status status = stub->EchoUnaryCall(&context, request, &response); |
||||
EXPECT_TRUE(status.ok()); |
||||
EXPECT_EQ(response.text(), "BinderServerBuilder"); |
||||
server->Shutdown(); |
||||
} |
||||
|
||||
TEST_F(BinderServerTest, CreateChannelWithEndpointBinderMultipleConnections) { |
||||
grpc::ServerBuilder server_builder; |
||||
grpc_binder::end2end_testing::EchoServer service; |
||||
server_builder.RegisterService(&service); |
||||
server_builder.AddListeningPort( |
||||
"binder://example.service.multiple.connections", |
||||
grpc::testing::BinderServerCredentials()); |
||||
std::unique_ptr<grpc::Server> server = server_builder.BuildAndStart(); |
||||
void* raw_endpoint_binder = grpc::experimental::binder::GetEndpointBinder( |
||||
"example.service.multiple.connections"); |
||||
constexpr size_t kNumThreads = 128; |
||||
|
||||
auto thread_fn = [&](size_t id) { |
||||
std::unique_ptr<grpc_binder::Binder> endpoint_binder = |
||||
absl::make_unique<grpc_binder::end2end_testing::FakeBinder>( |
||||
static_cast<grpc_binder::end2end_testing::FakeEndpoint*>( |
||||
raw_endpoint_binder)); |
||||
std::shared_ptr<grpc::Channel> channel = |
||||
grpc::testing::CreateBinderChannel(std::move(endpoint_binder)); |
||||
std::unique_ptr<grpc_binder::end2end_testing::EchoService::Stub> stub = |
||||
grpc_binder::end2end_testing::EchoService::NewStub(channel); |
||||
grpc_binder::end2end_testing::EchoRequest request; |
||||
grpc_binder::end2end_testing::EchoResponse response; |
||||
grpc::ClientContext context; |
||||
request.set_text(absl::StrFormat("BinderServerBuilder-%d", id)); |
||||
grpc::Status status = stub->EchoUnaryCall(&context, request, &response); |
||||
EXPECT_TRUE(status.ok()); |
||||
EXPECT_EQ(response.text(), absl::StrFormat("BinderServerBuilder-%d", id)); |
||||
}; |
||||
|
||||
std::vector<std::thread> threads(kNumThreads); |
||||
for (size_t i = 0; i < kNumThreads; ++i) { |
||||
threads[i] = std::thread(thread_fn, i); |
||||
} |
||||
for (auto& thr : threads) { |
||||
thr.join(); |
||||
} |
||||
server->Shutdown(); |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) { |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
grpc::testing::TestEnvironment env(argc, argv); |
||||
return RUN_ALL_TESTS(); |
||||
} |
Loading…
Reference in new issue