blob: 6cde9f7f8dc8b591a4979f14e0db42c8d648f801 [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
Andrei Homescu96834632022-10-14 00:49:49 +000082 BinderRpcTestProcessSession(BinderRpcTestProcessSession&&) = default;
83 ~BinderRpcTestProcessSession() {
84 if (!expectAlreadyShutdown) {
85 EXPECT_NE(nullptr, rootIface);
86 if (rootIface == nullptr) return;
87
88 std::vector<int32_t> remoteCounts;
89 // calling over any sessions counts across all sessions
90 EXPECT_OK(rootIface->countBinders(&remoteCounts));
91 EXPECT_EQ(remoteCounts.size(), proc->sessions.size());
92 for (auto remoteCount : remoteCounts) {
93 EXPECT_EQ(remoteCount, 1);
94 }
95
96 // even though it is on another thread, shutdown races with
97 // the transaction reply being written
98 if (auto status = rootIface->scheduleShutdown(); !status.isOk()) {
99 EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status;
100 }
101 }
102
103 rootIface = nullptr;
104 rootBinder = nullptr;
105 }
106};
107
108class BinderRpc : public ::testing::TestWithParam<
109 std::tuple<SocketType, RpcSecurity, uint32_t, uint32_t, bool, bool>> {
110public:
111 SocketType socketType() const { return std::get<0>(GetParam()); }
112 RpcSecurity rpcSecurity() const { return std::get<1>(GetParam()); }
113 uint32_t clientVersion() const { return std::get<2>(GetParam()); }
114 uint32_t serverVersion() const { return std::get<3>(GetParam()); }
115 bool serverSingleThreaded() const { return std::get<4>(GetParam()); }
116 bool noKernel() const { return std::get<5>(GetParam()); }
117
118 bool clientOrServerSingleThreaded() const {
119 return !kEnableRpcThreads || serverSingleThreaded();
120 }
121
122 // Whether the test params support sending FDs in parcels.
123 bool supportsFdTransport() const {
Andrei Homescu68a55612022-08-02 01:25:15 +0000124 if (socketType() == SocketType::TIPC) {
125 // Trusty does not support file descriptors yet
126 return false;
127 }
Andrei Homescu96834632022-10-14 00:49:49 +0000128 return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
129 (socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX ||
Alice Wang893a9912022-10-24 10:44:09 +0000130 socketType() == SocketType::UNIX_BOOTSTRAP ||
131 socketType() == SocketType::UNIX_RAW);
Andrei Homescu96834632022-10-14 00:49:49 +0000132 }
133
134 void SetUp() override {
135 if (socketType() == SocketType::UNIX_BOOTSTRAP && rpcSecurity() == RpcSecurity::TLS) {
136 GTEST_SKIP() << "Unix bootstrap not supported over a TLS transport";
137 }
138 }
139
140 BinderRpcTestProcessSession createRpcTestSocketServerProcess(const BinderRpcOptions& options) {
141 BinderRpcTestProcessSession ret{
142 .proc = createRpcTestSocketServerProcessEtc(options),
143 };
144
145 ret.rootBinder = ret.proc->sessions.empty() ? nullptr : ret.proc->sessions.at(0).root;
146 ret.rootIface = interface_cast<IBinderRpcTest>(ret.rootBinder);
147
148 return ret;
149 }
150
Andrei Homescuf30148c2023-03-10 00:31:45 +0000151 static std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) {
152 auto [type, security, clientVersion, serverVersion, singleThreaded, noKernel] = info.param;
153 auto ret = PrintToString(type) + "_" + newFactory(security)->toCString() + "_clientV" +
154 std::to_string(clientVersion) + "_serverV" + std::to_string(serverVersion);
155 if (singleThreaded) {
156 ret += "_single_threaded";
157 } else {
158 ret += "_multi_threaded";
159 }
160 if (noKernel) {
161 ret += "_no_kernel";
162 } else {
163 ret += "_with_kernel";
164 }
165 return ret;
166 }
Andrei Homescu96834632022-10-14 00:49:49 +0000167
168protected:
Andrei Homescuf30148c2023-03-10 00:31:45 +0000169 static std::unique_ptr<RpcTransportCtxFactory> newFactory(RpcSecurity rpcSecurity);
170
Andrei Homescu96834632022-10-14 00:49:49 +0000171 std::unique_ptr<ProcessSession> createRpcTestSocketServerProcessEtc(
172 const BinderRpcOptions& options);
173};
174
175} // namespace android