1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <gtest/gtest.h> 20 21 #include "binderRpcTestCommon.h" 22 23 #define EXPECT_OK(status) \ 24 do { \ 25 android::binder::Status stat = (status); \ 26 EXPECT_TRUE(stat.isOk()) << stat; \ 27 } while (false) 28 29 namespace android { 30 31 // Abstract base class with a virtual destructor that handles the 32 // ownership of a process session for BinderRpcTestSession below 33 class ProcessSession { 34 public: 35 struct SessionInfo { 36 sp<RpcSession> session; 37 sp<IBinder> root; 38 }; 39 40 // client session objects associated with other process 41 // each one represents a separate session 42 std::vector<SessionInfo> sessions; 43 44 virtual ~ProcessSession() = 0; 45 46 // If the process exits with a status, run the given callback on that value. 47 virtual void setCustomExitStatusCheck(std::function<void(int wstatus)> f) = 0; 48 49 // Kill the process. Avoid if possible. Shutdown gracefully via an RPC instead. 50 virtual void terminate() = 0; 51 }; 52 53 // Process session where the process hosts IBinderRpcTest, the server used 54 // for most testing here 55 struct BinderRpcTestProcessSession { 56 std::unique_ptr<ProcessSession> proc; 57 58 // pre-fetched root object (for first session) 59 sp<IBinder> rootBinder; 60 61 // pre-casted root object (for first session) 62 sp<IBinderRpcTest> rootIface; 63 64 // whether session should be invalidated by end of run 65 bool expectAlreadyShutdown = false; 66 67 // TODO(b/271830568): fix this in binderRpcTest, we always use the first session to cause the 68 // remote process to shutdown. Normally, when we shutdown, the default in the destructor is to 69 // check that there are no leaks and shutdown. However, when there are incoming threadpools, 70 // there will be a few extra binder threads there, so we can't shutdown the server. We should 71 // consider an alternative way of doing the test so that we don't need this, some ideas, such as 72 // program in understanding of incoming threadpool into the destructor so that (e.g. 73 // intelligently wait for sessions to shutdown now that they will do this) forceShutdownBinderRpcTestProcessSession74 void forceShutdown() { 75 if (auto status = rootIface->scheduleShutdown(); !status.isOk()) { 76 EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status; 77 } 78 EXPECT_TRUE(proc->sessions.at(0).session->shutdownAndWait(true)); 79 expectAlreadyShutdown = true; 80 } 81 82 BinderRpcTestProcessSession(BinderRpcTestProcessSession&&) = default; ~BinderRpcTestProcessSessionBinderRpcTestProcessSession83 ~BinderRpcTestProcessSession() { 84 if (!expectAlreadyShutdown) { 85 EXPECT_NE(nullptr, rootIface); 86 if (rootIface == nullptr) return; 87 88 std::vector<int32_t> remoteCounts; 89 // calling over any sessions counts across all sessions 90 EXPECT_OK(rootIface->countBinders(&remoteCounts)); 91 EXPECT_EQ(remoteCounts.size(), proc->sessions.size()); 92 for (auto remoteCount : remoteCounts) { 93 EXPECT_EQ(remoteCount, 1); 94 } 95 96 // even though it is on another thread, shutdown races with 97 // the transaction reply being written 98 if (auto status = rootIface->scheduleShutdown(); !status.isOk()) { 99 EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status; 100 } 101 } 102 103 rootIface = nullptr; 104 rootBinder = nullptr; 105 } 106 }; 107 108 class BinderRpc : public ::testing::TestWithParam< 109 std::tuple<SocketType, RpcSecurity, uint32_t, uint32_t, bool, bool>> { 110 public: socketType()111 SocketType socketType() const { return std::get<0>(GetParam()); } rpcSecurity()112 RpcSecurity rpcSecurity() const { return std::get<1>(GetParam()); } clientVersion()113 uint32_t clientVersion() const { return std::get<2>(GetParam()); } serverVersion()114 uint32_t serverVersion() const { return std::get<3>(GetParam()); } serverSingleThreaded()115 bool serverSingleThreaded() const { return std::get<4>(GetParam()); } noKernel()116 bool noKernel() const { return std::get<5>(GetParam()); } 117 clientOrServerSingleThreaded()118 bool clientOrServerSingleThreaded() const { 119 return !kEnableRpcThreads || serverSingleThreaded(); 120 } 121 122 // Whether the test params support sending FDs in parcels. supportsFdTransport()123 bool supportsFdTransport() const { 124 if (socketType() == SocketType::TIPC) { 125 // Trusty does not support file descriptors yet 126 return false; 127 } 128 return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS && 129 (socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX || 130 socketType() == SocketType::UNIX_BOOTSTRAP || 131 socketType() == SocketType::UNIX_RAW); 132 } 133 SetUp()134 void SetUp() override { 135 if (socketType() == SocketType::UNIX_BOOTSTRAP && rpcSecurity() == RpcSecurity::TLS) { 136 GTEST_SKIP() << "Unix bootstrap not supported over a TLS transport"; 137 } 138 } 139 createRpcTestSocketServerProcess(const BinderRpcOptions & options)140 BinderRpcTestProcessSession createRpcTestSocketServerProcess(const BinderRpcOptions& options) { 141 BinderRpcTestProcessSession ret{ 142 .proc = createRpcTestSocketServerProcessEtc(options), 143 }; 144 145 ret.rootBinder = ret.proc->sessions.empty() ? nullptr : ret.proc->sessions.at(0).root; 146 ret.rootIface = interface_cast<IBinderRpcTest>(ret.rootBinder); 147 148 return ret; 149 } 150 PrintParamInfo(const testing::TestParamInfo<ParamType> & info)151 static std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) { 152 auto [type, security, clientVersion, serverVersion, singleThreaded, noKernel] = info.param; 153 auto ret = PrintToString(type) + "_" + newFactory(security)->toCString() + "_clientV" + 154 std::to_string(clientVersion) + "_serverV" + std::to_string(serverVersion); 155 if (singleThreaded) { 156 ret += "_single_threaded"; 157 } else { 158 ret += "_multi_threaded"; 159 } 160 if (noKernel) { 161 ret += "_no_kernel"; 162 } else { 163 ret += "_with_kernel"; 164 } 165 return ret; 166 } 167 168 protected: 169 static std::unique_ptr<RpcTransportCtxFactory> newFactory(RpcSecurity rpcSecurity); 170 171 std::unique_ptr<ProcessSession> createRpcTestSocketServerProcessEtc( 172 const BinderRpcOptions& options); 173 }; 174 175 } // namespace android 176