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