From 1b6f12f5aca242777ee6c80c764bf01a32af16de Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Thu, 3 Jun 2021 20:01:57 -0700 Subject: Add binderHostDeviceTest This is an integration test for servicedispatcher. It tests servicedispatcher and adb forwarding that the host service manager, `createRpcDelegateServiceManager()`, provides. Test: atest Bug: 182914638 Change-Id: Ia9ff8306dddb1f48422a73594017680930175461 --- libs/binder/TEST_MAPPING | 3 + libs/binder/tests/Android.bp | 46 ++++++ libs/binder/tests/binderHostDeviceTest.cpp | 170 ++++++++++++++++++++++ libs/binder/tests/binderHostDeviceTest.xml | 27 ++++ libs/binder/tests/binderHostDeviceTestService.cpp | 54 +++++++ 5 files changed, 300 insertions(+) create mode 100644 libs/binder/tests/binderHostDeviceTest.cpp create mode 100644 libs/binder/tests/binderHostDeviceTest.xml create mode 100644 libs/binder/tests/binderHostDeviceTestService.cpp diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING index e04e326f48..012a9befdc 100644 --- a/libs/binder/TEST_MAPPING +++ b/libs/binder/TEST_MAPPING @@ -15,6 +15,9 @@ { "name": "binderDriverInterfaceTest" }, + { + "name": "binderHostDeviceTest" + }, { "name": "binderTextOutputTest" }, diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp index d5a2b61a0c..1f844e1ee6 100644 --- a/libs/binder/tests/Android.bp +++ b/libs/binder/tests/Android.bp @@ -348,3 +348,49 @@ cc_test_host { }, }, } + +cc_test_host { + name: "binderHostDeviceTest", + defaults: ["binder_test_defaults"], + srcs: ["binderHostDeviceTest.cpp"], + test_config: "binderHostDeviceTest.xml", + shared_libs: [ + "libbase", + "libbinder", + "liblog", + "libutils", + ], + static_libs: [ + "libgmock", + ], + target_required: [ + "binderHostDeviceTestService", + ], + test_suites: ["general-tests"], + target: { + darwin: { + enabled: false, + }, + }, + test_options: { + unit_test: false, + }, +} + +cc_test { + name: "binderHostDeviceTestService", + // The binary is named differently from the module so that PushFilePreparer pushes the binary + // directly, not the test module directory. + stem: "binderHostDeviceTest-service", + defaults: ["binder_test_defaults"], + gtest: false, + auto_gen_config: false, + srcs: ["binderHostDeviceTestService.cpp"], + shared_libs: [ + "libbase", + "libbinder", + "liblog", + "libutils", + ], + test_suites: ["general-tests"], +} diff --git a/libs/binder/tests/binderHostDeviceTest.cpp b/libs/binder/tests/binderHostDeviceTest.cpp new file mode 100644 index 0000000000..5dd92121ba --- /dev/null +++ b/libs/binder/tests/binderHostDeviceTest.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +// Integration test for servicedispatcher + adb forward. Requires ADB. + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "../UtilsHost.h" + +using ::android::setDefaultServiceManager; +using ::android::base::EndsWith; +using ::android::base::Join; +using ::android::base::ParseBool; +using ::android::base::ParseBoolResult; +using ::android::base::Split; +using ::android::base::StartsWith; +using ::android::base::StringReplace; +using ::android::base::Trim; +using ::android::base::testing::Ok; +using ::std::chrono_literals::operator""ms; +using ::std::string_literals::operator""s; +using ::testing::AllOf; +using ::testing::Contains; +using ::testing::ContainsRegex; +using ::testing::ExplainMatchResult; +using ::testing::InitGoogleMock; + +namespace android { + +namespace { + +constexpr const char* kServiceBinary = "/data/local/tmp/binderHostDeviceTest-service"; +constexpr const char* kServiceName = "binderHostDeviceTestService"; +constexpr const char* kDescriptor = "android.binderHostDeviceTestService"; + +// e.g. EXPECT_THAT(expr, StatusEq(OK)) << "additional message"; +MATCHER_P(StatusEq, expected, (negation ? "not " : "") + statusToString(expected)) { + *result_listener << statusToString(arg); + return expected == arg; +} + +void initHostRpcServiceManagerOnce() { + static std::once_flag gSmOnce; + std::call_once(gSmOnce, [] { setDefaultServiceManager(createRpcDelegateServiceManager()); }); +} + +// Test for host service manager. +class HostDeviceTest : public ::testing::Test { +public: + void SetUp() override { + auto debuggableResult = execute(Split("adb shell getprop ro.debuggable", " "), nullptr); + ASSERT_THAT(debuggableResult, Ok()); + ASSERT_EQ(0, debuggableResult->exitCode) << *debuggableResult; + auto debuggableBool = ParseBool(Trim(debuggableResult->stdout)); + ASSERT_NE(ParseBoolResult::kError, debuggableBool) << Trim(debuggableResult->stdout); + if (debuggableBool == ParseBoolResult::kFalse) { + GTEST_SKIP() << "ro.debuggable=" << Trim(debuggableResult->stdout); + } + + auto lsResult = execute(Split("adb shell which servicedispatcher", " "), nullptr); + ASSERT_THAT(lsResult, Ok()); + if (lsResult->exitCode != 0) { + GTEST_SKIP() << "b/182914638: until feature is fully enabled, skip test on devices " + "without servicedispatcher"; + } + + initHostRpcServiceManagerOnce(); + ASSERT_NE(nullptr, defaultServiceManager()) << "No defaultServiceManager() over RPC"; + + auto service = execute({"adb", "shell", kServiceBinary, kServiceName, kDescriptor}, + &CommandResult::stdoutEndsWithNewLine); + ASSERT_THAT(service, Ok()); + ASSERT_EQ(std::nullopt, service->exitCode) << *service; + mService = std::move(*service); + } + void TearDown() override { mService.reset(); } + + [[nodiscard]] static sp get(unsigned int hostPort) { + auto rpcSession = RpcSession::make(); + if (!rpcSession->setupInetClient("127.0.0.1", hostPort)) { + ADD_FAILURE() << "Failed to setupInetClient on " << hostPort; + return nullptr; + } + return rpcSession->getRootObject(); + } + +private: + std::optional mService; +}; + +TEST_F(HostDeviceTest, List) { + auto sm = defaultServiceManager(); + + auto services = sm->listServices(); + ASSERT_THAT(services, Contains(String16(kServiceName))); +} + +TEST_F(HostDeviceTest, CheckService) { + auto sm = defaultServiceManager(); + + auto rpcBinder = sm->checkService(String16(kServiceName)); + ASSERT_NE(nullptr, rpcBinder); + + EXPECT_THAT(rpcBinder->pingBinder(), StatusEq(OK)); + EXPECT_EQ(String16(kDescriptor), rpcBinder->getInterfaceDescriptor()); +} + +TEST_F(HostDeviceTest, GetService) { + auto sm = defaultServiceManager(); + + auto rpcBinder = sm->getService(String16(kServiceName)); + ASSERT_NE(nullptr, rpcBinder); + + EXPECT_THAT(rpcBinder->pingBinder(), StatusEq(OK)); + EXPECT_EQ(String16(kDescriptor), rpcBinder->getInterfaceDescriptor()); +} + +TEST_F(HostDeviceTest, WaitForService) { + auto sm = defaultServiceManager(); + + auto rpcBinder = sm->waitForService(String16(kServiceName)); + ASSERT_NE(nullptr, rpcBinder); + + EXPECT_THAT(rpcBinder->pingBinder(), StatusEq(OK)); + EXPECT_EQ(String16(kDescriptor), rpcBinder->getInterfaceDescriptor()); +} + +TEST_F(HostDeviceTest, TenClients) { + auto sm = defaultServiceManager(); + + auto threadFn = [&] { + auto rpcBinder = sm->checkService(String16(kServiceName)); + ASSERT_NE(nullptr, rpcBinder); + + EXPECT_THAT(rpcBinder->pingBinder(), StatusEq(OK)); + EXPECT_EQ(String16(kDescriptor), rpcBinder->getInterfaceDescriptor()); + }; + + std::vector threads; + for (size_t i = 0; i < 10; ++i) threads.emplace_back(threadFn); + for (auto& thread : threads) thread.join(); +} + +} // namespace + +} // namespace android diff --git a/libs/binder/tests/binderHostDeviceTest.xml b/libs/binder/tests/binderHostDeviceTest.xml new file mode 100644 index 0000000000..250ed3a725 --- /dev/null +++ b/libs/binder/tests/binderHostDeviceTest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/libs/binder/tests/binderHostDeviceTestService.cpp b/libs/binder/tests/binderHostDeviceTestService.cpp new file mode 100644 index 0000000000..6ddd2e73be --- /dev/null +++ b/libs/binder/tests/binderHostDeviceTestService.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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 + +#include +#include +#include +#include +#include + +namespace { +class Service : public android::BBinder { +public: + Service(std::string_view descriptor) : mDescriptor(descriptor.data(), descriptor.size()) {} + const android::String16& getInterfaceDescriptor() const override { return mDescriptor; } + +private: + android::String16 mDescriptor; +}; +} // namespace + +int main(int argc, char** argv) { + if (argc != 3) { + std::cerr << "usage: " << argv[0] << " " << std::endl; + return EX_USAGE; + } + auto name = argv[1]; + auto descriptor = argv[2]; + + auto sm = android::defaultServiceManager(); + CHECK(sm != nullptr); + auto service = android::sp::make(descriptor); + auto status = sm->addService(android::String16(name), service); + CHECK_EQ(android::OK, status) << android::statusToString(status); + std::cout << "running..." << std::endl; + android::ProcessState::self()->startThreadPool(); + android::IPCThreadState::self()->joinThreadPool(); + LOG(ERROR) << "joinThreadPool exits"; + return EX_SOFTWARE; +} -- cgit v1.2.3-59-g8ed1b