blob: 2c9646b30e433ecf6e1e88781c137a029b07d6c5 [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;
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
55struct 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
Steven Moreland67f85902023-03-15 01:13:49 +000067 // 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)
74 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
Tomasz Wasilczykfdf54812023-06-28 14:14:35 -070082 BinderRpcTestProcessSession(std::unique_ptr<ProcessSession> proc) : proc(std::move(proc)){};
Andrei Homescu96834632022-10-14 00:49:49 +000083 BinderRpcTestProcessSession(BinderRpcTestProcessSession&&) = default;
84 ~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
Steven Morelandb469f432023-07-28 22:13:47 +0000109struct BinderRpcParam {
110 SocketType type;
111 RpcSecurity security;
112 uint32_t clientVersion;
113 uint32_t serverVersion;
114 bool singleThreaded;
115 bool noKernel;
116};
117class BinderRpc : public ::testing::TestWithParam<BinderRpcParam> {
Andrei Homescu96834632022-10-14 00:49:49 +0000118public:
Steven Morelandb469f432023-07-28 22:13:47 +0000119 // TODO: avoid unnecessary layer of indirection
120 SocketType socketType() const { return GetParam().type; }
121 RpcSecurity rpcSecurity() const { return GetParam().security; }
122 uint32_t clientVersion() const { return GetParam().clientVersion; }
123 uint32_t serverVersion() const { return GetParam().serverVersion; }
124 bool serverSingleThreaded() const { return GetParam().singleThreaded; }
125 bool noKernel() const { return GetParam().noKernel; }
Andrei Homescu96834632022-10-14 00:49:49 +0000126
127 bool clientOrServerSingleThreaded() const {
128 return !kEnableRpcThreads || serverSingleThreaded();
129 }
130
131 // Whether the test params support sending FDs in parcels.
132 bool supportsFdTransport() const {
Andrei Homescu68a55612022-08-02 01:25:15 +0000133 if (socketType() == SocketType::TIPC) {
134 // Trusty does not support file descriptors yet
135 return false;
136 }
Andrei Homescu96834632022-10-14 00:49:49 +0000137 return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
138 (socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX ||
Alice Wang893a9912022-10-24 10:44:09 +0000139 socketType() == SocketType::UNIX_BOOTSTRAP ||
140 socketType() == SocketType::UNIX_RAW);
Andrei Homescu96834632022-10-14 00:49:49 +0000141 }
142
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
149 BinderRpcTestProcessSession createRpcTestSocketServerProcess(const BinderRpcOptions& options) {
Tomasz Wasilczykfdf54812023-06-28 14:14:35 -0700150 BinderRpcTestProcessSession ret(createRpcTestSocketServerProcessEtc(options));
Andrei Homescu96834632022-10-14 00:49:49 +0000151
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
Andrei Homescuf30148c2023-03-10 00:31:45 +0000158 static std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) {
Steven Morelandb469f432023-07-28 22:13:47 +0000159 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) {
Andrei Homescuf30148c2023-03-10 00:31:45 +0000164 ret += "_single_threaded";
165 } else {
166 ret += "_multi_threaded";
167 }
Steven Morelandb469f432023-07-28 22:13:47 +0000168 if (info.param.noKernel) {
Andrei Homescuf30148c2023-03-10 00:31:45 +0000169 ret += "_no_kernel";
170 } else {
171 ret += "_with_kernel";
172 }
173 return ret;
174 }
Andrei Homescu96834632022-10-14 00:49:49 +0000175
176protected:
Andrei Homescuf30148c2023-03-10 00:31:45 +0000177 static std::unique_ptr<RpcTransportCtxFactory> newFactory(RpcSecurity rpcSecurity);
178
Andrei Homescu96834632022-10-14 00:49:49 +0000179 std::unique_ptr<ProcessSession> createRpcTestSocketServerProcessEtc(
180 const BinderRpcOptions& options);
181};
182
183} // namespace android