blob: c8a8acc0a0ee8411ecef23d685f5e3013a9c3c9e [file] [log] [blame]
Andrei Homescu96834632022-10-14 00:49:49 +00001/*
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
29namespace android {
30
31// Abstract base class with a virtual destructor that handles the
32// ownership of a process session for BinderRpcTestSession below
33class ProcessSession {
34public:
35 struct SessionInfo {
36 sp<RpcSession> session;
37 sp<IBinder> root;
Devin Moore18f63752024-08-08 21:01:24 +000038// 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
Andrei Homescu96834632022-10-14 00:49:49 +000044 };
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
61struct 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
Steven Moreland67f85902023-03-15 01:13:49 +000073 // 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)
80 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
Tomasz Wasilczykfdf54812023-06-28 14:14:35 -070088 BinderRpcTestProcessSession(std::unique_ptr<ProcessSession> proc) : proc(std::move(proc)){};
Andrei Homescu96834632022-10-14 00:49:49 +000089 BinderRpcTestProcessSession(BinderRpcTestProcessSession&&) = default;
90 ~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
Steven Morelandb469f432023-07-28 22:13:47 +0000115struct BinderRpcParam {
116 SocketType type;
117 RpcSecurity security;
118 uint32_t clientVersion;
119 uint32_t serverVersion;
120 bool singleThreaded;
121 bool noKernel;
122};
123class BinderRpc : public ::testing::TestWithParam<BinderRpcParam> {
Andrei Homescu96834632022-10-14 00:49:49 +0000124public:
Steven Morelandb469f432023-07-28 22:13:47 +0000125 // TODO: avoid unnecessary layer of indirection
126 SocketType socketType() const { return GetParam().type; }
127 RpcSecurity rpcSecurity() const { return GetParam().security; }
128 uint32_t clientVersion() const { return GetParam().clientVersion; }
129 uint32_t serverVersion() const { return GetParam().serverVersion; }
130 bool serverSingleThreaded() const { return GetParam().singleThreaded; }
131 bool noKernel() const { return GetParam().noKernel; }
Andrei Homescu96834632022-10-14 00:49:49 +0000132
133 bool clientOrServerSingleThreaded() const {
134 return !kEnableRpcThreads || serverSingleThreaded();
135 }
136
137 // Whether the test params support sending FDs in parcels.
138 bool supportsFdTransport() const {
Andrei Homescu68a55612022-08-02 01:25:15 +0000139 if (socketType() == SocketType::TIPC) {
140 // Trusty does not support file descriptors yet
141 return false;
142 }
Andrei Homescu96834632022-10-14 00:49:49 +0000143 return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
144 (socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX ||
Alice Wang893a9912022-10-24 10:44:09 +0000145 socketType() == SocketType::UNIX_BOOTSTRAP ||
146 socketType() == SocketType::UNIX_RAW);
Andrei Homescu96834632022-10-14 00:49:49 +0000147 }
148
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
155 BinderRpcTestProcessSession createRpcTestSocketServerProcess(const BinderRpcOptions& options) {
Tomasz Wasilczykfdf54812023-06-28 14:14:35 -0700156 BinderRpcTestProcessSession ret(createRpcTestSocketServerProcessEtc(options));
Andrei Homescu96834632022-10-14 00:49:49 +0000157
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
Andrei Homescuf30148c2023-03-10 00:31:45 +0000164 static std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) {
Steven Morelandb469f432023-07-28 22:13:47 +0000165 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) {
Andrei Homescuf30148c2023-03-10 00:31:45 +0000170 ret += "_single_threaded";
171 } else {
172 ret += "_multi_threaded";
173 }
Steven Morelandb469f432023-07-28 22:13:47 +0000174 if (info.param.noKernel) {
Andrei Homescuf30148c2023-03-10 00:31:45 +0000175 ret += "_no_kernel";
176 } else {
177 ret += "_with_kernel";
178 }
179 return ret;
180 }
Andrei Homescu96834632022-10-14 00:49:49 +0000181
182protected:
Andrei Homescuf30148c2023-03-10 00:31:45 +0000183 static std::unique_ptr<RpcTransportCtxFactory> newFactory(RpcSecurity rpcSecurity);
184
Andrei Homescu96834632022-10-14 00:49:49 +0000185 std::unique_ptr<ProcessSession> createRpcTestSocketServerProcessEtc(
186 const BinderRpcOptions& options);
187};
188
189} // namespace android