xref: /aosp_15_r20/frameworks/native/libs/binder/tests/binderRpcTestFixture.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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