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
Ta-Wei Tu 3 years ago committed by GitHub
parent f9a2a7401a
commit 3df113f6d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 66
      CMakeLists.txt
  2. 44
      build_autogenerated.yaml
  3. 50
      src/core/ext/transport/binder/server/BUILD
  4. 179
      src/core/ext/transport/binder/server/binder_server.cc
  5. 70
      src/core/ext/transport/binder/server/binder_server.h
  6. 61
      src/core/ext/transport/binder/server/binder_server_credentials.cc
  7. 35
      src/core/ext/transport/binder/server/binder_server_credentials.h
  8. 17
      test/core/transport/binder/end2end/BUILD
  9. 211
      test/core/transport/binder/end2end/binder_server_test.cc
  10. 4
      test/core/transport/binder/end2end/fake_binder.h
  11. 24
      tools/run_tests/generated/tests.json

66
CMakeLists.txt generated

@ -753,6 +753,7 @@ if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bdp_estimator_test)
endif()
add_dependencies(buildtests_cxx binder_server_test)
add_dependencies(buildtests_cxx binder_transport_test)
add_dependencies(buildtests_cxx bitset_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
@ -8381,6 +8382,71 @@ endif()
endif()
if(gRPC_BUILD_TESTS)
add_executable(binder_server_test
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.pb.cc
${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.pb.h
${_gRPC_PROTO_GENS_DIR}/test/core/transport/binder/end2end/echo.grpc.pb.h
src/core/ext/transport/binder/client/channel_create_impl.cc
src/core/ext/transport/binder/server/binder_server.cc
src/core/ext/transport/binder/server/binder_server_credentials.cc
src/core/ext/transport/binder/transport/binder_transport.cc
src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
src/core/ext/transport/binder/wire_format/binder_android.cc
src/core/ext/transport/binder/wire_format/binder_constants.cc
src/core/ext/transport/binder/wire_format/transaction.cc
src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
src/core/ext/transport/binder/wire_format/wire_writer.cc
test/core/transport/binder/end2end/binder_server_test.cc
test/core/transport/binder/end2end/echo_service.cc
test/core/transport/binder/end2end/fake_binder.cc
test/cpp/end2end/test_service_impl.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(binder_server_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(binder_server_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::random_random
grpc++_test_util
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(binder_transport_test
src/core/ext/transport/binder/transport/binder_transport.cc
src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc

@ -4553,6 +4553,50 @@ targets:
- posix
- mac
uses_polling: false
- name: binder_server_test
gtest: true
build: test
language: c++
headers:
- src/core/ext/transport/binder/client/channel_create_impl.h
- src/core/ext/transport/binder/server/binder_server.h
- src/core/ext/transport/binder/server/binder_server_credentials.h
- src/core/ext/transport/binder/transport/binder_stream.h
- src/core/ext/transport/binder/transport/binder_transport.h
- src/core/ext/transport/binder/utils/transport_stream_receiver.h
- src/core/ext/transport/binder/utils/transport_stream_receiver_impl.h
- src/core/ext/transport/binder/wire_format/binder.h
- src/core/ext/transport/binder/wire_format/binder_android.h
- src/core/ext/transport/binder/wire_format/binder_constants.h
- src/core/ext/transport/binder/wire_format/transaction.h
- src/core/ext/transport/binder/wire_format/wire_reader.h
- src/core/ext/transport/binder/wire_format/wire_reader_impl.h
- src/core/ext/transport/binder/wire_format/wire_writer.h
- test/core/transport/binder/end2end/echo_service.h
- test/core/transport/binder/end2end/fake_binder.h
- test/cpp/end2end/test_service_impl.h
src:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- test/core/transport/binder/end2end/echo.proto
- src/core/ext/transport/binder/client/channel_create_impl.cc
- src/core/ext/transport/binder/server/binder_server.cc
- src/core/ext/transport/binder/server/binder_server_credentials.cc
- src/core/ext/transport/binder/transport/binder_transport.cc
- src/core/ext/transport/binder/utils/transport_stream_receiver_impl.cc
- src/core/ext/transport/binder/wire_format/binder_android.cc
- src/core/ext/transport/binder/wire_format/binder_constants.cc
- src/core/ext/transport/binder/wire_format/transaction.cc
- src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
- src/core/ext/transport/binder/wire_format/wire_writer.cc
- test/core/transport/binder/end2end/binder_server_test.cc
- test/core/transport/binder/end2end/echo_service.cc
- test/core/transport/binder/end2end/fake_binder.cc
- test/cpp/end2end/test_service_impl.cc
deps:
- absl/random:random
- grpc++_test_util
- name: binder_transport_test
gtest: true
build: test

@ -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

@ -110,3 +110,20 @@ grpc_cc_test(
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test(
name = "binder_server_test",
srcs = ["binder_server_test.cc"],
external_deps = [
"gtest",
],
deps = [
"//:grpc++",
"//src/core/ext/transport/binder/client:grpc_transport_binder_client_impl",
"//src/core/ext/transport/binder/server:grpc_transport_binder_server",
"//test/core/transport/binder/end2end:echo_service",
"//test/core/transport/binder/end2end:fake_binder",
"//test/core/util:grpc_test_util",
"//test/cpp/end2end:test_service_impl",
],
)

@ -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();
}

@ -182,9 +182,7 @@ class PersistentFakeTransactionReceiver {
// other end of the tunnel by following the information in its endpoint.
class FakeBinder final : public Binder {
public:
explicit FakeBinder(FakeEndpoint* endpoint) : endpoint_(endpoint) {
endpoint_->owner = this;
}
explicit FakeBinder(FakeEndpoint* endpoint) : endpoint_(endpoint) {}
void Initialize() override {}
absl::Status PrepareTransaction() override {

@ -3429,6 +3429,30 @@
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "binder_server_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save