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 BinderRpcTestProcessSessionBinderRpcTestProcessSession82 BinderRpcTestProcessSession(std::unique_ptr<ProcessSession> proc) : proc(std::move(proc)){}; 83 BinderRpcTestProcessSession(BinderRpcTestProcessSession&&) = default; ~BinderRpcTestProcessSessionBinderRpcTestProcessSession84 ~BinderRpcTestProcessSession() { 85 if (!expectAlreadyShutdown) { 86 EXPECT_NE(nullptr, rootIface); 87 if (rootIface == nullptr) return; 88 89 std::vector<int32_t> remoteCounts; 90 // calling over any sessions counts across all sessions 91 EXPECT_OK(rootIface->countBinders(&remoteCounts)); 92 EXPECT_EQ(remoteCounts.size(), proc->sessions.size()); 93 for (auto remoteCount : remoteCounts) { 94 EXPECT_EQ(remoteCount, 1); 95 } 96 97 // even though it is on another thread, shutdown races with 98 // the transaction reply being written 99 if (auto status = rootIface->scheduleShutdown(); !status.isOk()) { 100 EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status; 101 } 102 } 103 104 rootIface = nullptr; 105 rootBinder = nullptr; 106 } 107 }; 108 109 struct BinderRpcParam { 110 SocketType type; 111 RpcSecurity security; 112 uint32_t clientVersion; 113 uint32_t serverVersion; 114 bool singleThreaded; 115 bool noKernel; 116 }; 117 class BinderRpc : public ::testing::TestWithParam<BinderRpcParam> { 118 public: 119 // TODO: avoid unnecessary layer of indirection socketType()120 SocketType socketType() const { return GetParam().type; } rpcSecurity()121 RpcSecurity rpcSecurity() const { return GetParam().security; } clientVersion()122 uint32_t clientVersion() const { return GetParam().clientVersion; } serverVersion()123 uint32_t serverVersion() const { return GetParam().serverVersion; } serverSingleThreaded()124 bool serverSingleThreaded() const { return GetParam().singleThreaded; } noKernel()125 bool noKernel() const { return GetParam().noKernel; } 126 clientOrServerSingleThreaded()127 bool clientOrServerSingleThreaded() const { 128 return !kEnableRpcThreads || serverSingleThreaded(); 129 } 130 131 // Whether the test params support sending FDs in parcels. supportsFdTransport()132 bool supportsFdTransport() const { 133 if (socketType() == SocketType::TIPC) { 134 // Trusty does not support file descriptors yet 135 return false; 136 } 137 return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS && 138 (socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX || 139 socketType() == SocketType::UNIX_BOOTSTRAP || 140 socketType() == SocketType::UNIX_RAW); 141 } 142 SetUp()143 void SetUp() override { 144 if (socketType() == SocketType::UNIX_BOOTSTRAP && rpcSecurity() == RpcSecurity::TLS) { 145 GTEST_SKIP() << "Unix bootstrap not supported over a TLS transport"; 146 } 147 } 148 createRpcTestSocketServerProcess(const BinderRpcOptions & options)149 BinderRpcTestProcessSession createRpcTestSocketServerProcess(const BinderRpcOptions& options) { 150 BinderRpcTestProcessSession ret(createRpcTestSocketServerProcessEtc(options)); 151 152 ret.rootBinder = ret.proc->sessions.empty() ? nullptr : ret.proc->sessions.at(0).root; 153 ret.rootIface = interface_cast<IBinderRpcTest>(ret.rootBinder); 154 155 return ret; 156 } 157 PrintParamInfo(const testing::TestParamInfo<ParamType> & info)158 static std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) { 159 auto ret = PrintToString(info.param.type) + "_" + 160 newFactory(info.param.security)->toCString() + "_clientV" + 161 std::to_string(info.param.clientVersion) + "_serverV" + 162 std::to_string(info.param.serverVersion); 163 if (info.param.singleThreaded) { 164 ret += "_single_threaded"; 165 } else { 166 ret += "_multi_threaded"; 167 } 168 if (info.param.noKernel) { 169 ret += "_no_kernel"; 170 } else { 171 ret += "_with_kernel"; 172 } 173 return ret; 174 } 175 176 protected: 177 static std::unique_ptr<RpcTransportCtxFactory> newFactory(RpcSecurity rpcSecurity); 178 179 std::unique_ptr<ProcessSession> createRpcTestSocketServerProcessEtc( 180 const BinderRpcOptions& options); 181 }; 182 183 } // namespace android 184