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 // Trusty defines its own socket APIs in trusty_ipc.h but doesn't include 39 // sockaddr types. 40 #ifndef __TRUSTY__ 41 sockaddr_storage addr; 42 socklen_t addrLen; 43 #endif 44 }; 45 46 // client session objects associated with other process 47 // each one represents a separate session 48 std::vector<SessionInfo> sessions; 49 50 virtual ~ProcessSession() = 0; 51 52 // If the process exits with a status, run the given callback on that value. 53 virtual void setCustomExitStatusCheck(std::function<void(int wstatus)> f) = 0; 54 55 // Kill the process. Avoid if possible. Shutdown gracefully via an RPC instead. 56 virtual void terminate() = 0; 57 }; 58 59 // Process session where the process hosts IBinderRpcTest, the server used 60 // for most testing here 61 struct BinderRpcTestProcessSession { 62 std::unique_ptr<ProcessSession> proc; 63 64 // pre-fetched root object (for first session) 65 sp<IBinder> rootBinder; 66 67 // pre-casted root object (for first session) 68 sp<IBinderRpcTest> rootIface; 69 70 // whether session should be invalidated by end of run 71 bool expectAlreadyShutdown = false; 72 73 // TODO(b/271830568): fix this in binderRpcTest, we always use the first session to cause the 74 // remote process to shutdown. Normally, when we shutdown, the default in the destructor is to 75 // check that there are no leaks and shutdown. However, when there are incoming threadpools, 76 // there will be a few extra binder threads there, so we can't shutdown the server. We should 77 // consider an alternative way of doing the test so that we don't need this, some ideas, such as 78 // program in understanding of incoming threadpool into the destructor so that (e.g. 79 // intelligently wait for sessions to shutdown now that they will do this) forceShutdownBinderRpcTestProcessSession80 void forceShutdown() { 81 if (auto status = rootIface->scheduleShutdown(); !status.isOk()) { 82 EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status; 83 } 84 EXPECT_TRUE(proc->sessions.at(0).session->shutdownAndWait(true)); 85 expectAlreadyShutdown = true; 86 } 87 BinderRpcTestProcessSessionBinderRpcTestProcessSession88 BinderRpcTestProcessSession(std::unique_ptr<ProcessSession> proc) : proc(std::move(proc)){}; 89 BinderRpcTestProcessSession(BinderRpcTestProcessSession&&) = default; ~BinderRpcTestProcessSessionBinderRpcTestProcessSession90 ~BinderRpcTestProcessSession() { 91 if (!expectAlreadyShutdown) { 92 EXPECT_NE(nullptr, rootIface); 93 if (rootIface == nullptr) return; 94 95 std::vector<int32_t> remoteCounts; 96 // calling over any sessions counts across all sessions 97 EXPECT_OK(rootIface->countBinders(&remoteCounts)); 98 EXPECT_EQ(remoteCounts.size(), proc->sessions.size()); 99 for (auto remoteCount : remoteCounts) { 100 EXPECT_EQ(remoteCount, 1); 101 } 102 103 // even though it is on another thread, shutdown races with 104 // the transaction reply being written 105 if (auto status = rootIface->scheduleShutdown(); !status.isOk()) { 106 EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status; 107 } 108 } 109 110 rootIface = nullptr; 111 rootBinder = nullptr; 112 } 113 }; 114 115 struct BinderRpcParam { 116 SocketType type; 117 RpcSecurity security; 118 uint32_t clientVersion; 119 uint32_t serverVersion; 120 bool singleThreaded; 121 bool noKernel; 122 }; 123 class BinderRpc : public ::testing::TestWithParam<BinderRpcParam> { 124 public: 125 // TODO: avoid unnecessary layer of indirection socketType()126 SocketType socketType() const { return GetParam().type; } rpcSecurity()127 RpcSecurity rpcSecurity() const { return GetParam().security; } clientVersion()128 uint32_t clientVersion() const { return GetParam().clientVersion; } serverVersion()129 uint32_t serverVersion() const { return GetParam().serverVersion; } serverSingleThreaded()130 bool serverSingleThreaded() const { return GetParam().singleThreaded; } noKernel()131 bool noKernel() const { return GetParam().noKernel; } 132 clientOrServerSingleThreaded()133 bool clientOrServerSingleThreaded() const { 134 return !kEnableRpcThreads || serverSingleThreaded(); 135 } 136 137 // Whether the test params support sending FDs in parcels. supportsFdTransport()138 bool supportsFdTransport() const { 139 if (socketType() == SocketType::TIPC) { 140 // Trusty does not support file descriptors yet 141 return false; 142 } 143 return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS && 144 (socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX || 145 socketType() == SocketType::UNIX_BOOTSTRAP || 146 socketType() == SocketType::UNIX_RAW); 147 } 148 SetUp()149 void SetUp() override { 150 if (socketType() == SocketType::UNIX_BOOTSTRAP && rpcSecurity() == RpcSecurity::TLS) { 151 GTEST_SKIP() << "Unix bootstrap not supported over a TLS transport"; 152 } 153 } 154 createRpcTestSocketServerProcess(const BinderRpcOptions & options)155 BinderRpcTestProcessSession createRpcTestSocketServerProcess(const BinderRpcOptions& options) { 156 BinderRpcTestProcessSession ret(createRpcTestSocketServerProcessEtc(options)); 157 158 ret.rootBinder = ret.proc->sessions.empty() ? nullptr : ret.proc->sessions.at(0).root; 159 ret.rootIface = interface_cast<IBinderRpcTest>(ret.rootBinder); 160 161 return ret; 162 } 163 PrintParamInfo(const testing::TestParamInfo<ParamType> & info)164 static std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) { 165 auto ret = PrintToString(info.param.type) + "_" + 166 newFactory(info.param.security)->toCString() + "_clientV" + 167 std::to_string(info.param.clientVersion) + "_serverV" + 168 std::to_string(info.param.serverVersion); 169 if (info.param.singleThreaded) { 170 ret += "_single_threaded"; 171 } else { 172 ret += "_multi_threaded"; 173 } 174 if (info.param.noKernel) { 175 ret += "_no_kernel"; 176 } else { 177 ret += "_with_kernel"; 178 } 179 return ret; 180 } 181 182 protected: 183 static std::unique_ptr<RpcTransportCtxFactory> newFactory(RpcSecurity rpcSecurity); 184 185 std::unique_ptr<ProcessSession> createRpcTestSocketServerProcessEtc( 186 const BinderRpcOptions& options); 187 }; 188 189 } // namespace android 190