blob: 0b8920b5a65524d6bbdf775831a50869711b0522 [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
109class BinderRpc : public ::testing::TestWithParam<
110 std::tuple<SocketType, RpcSecurity, uint32_t, uint32_t, bool, bool>> {
111public:
112 SocketType socketType() const { return std::get<0>(GetParam()); }
113 RpcSecurity rpcSecurity() const { return std::get<1>(GetParam()); }
114 uint32_t clientVersion() const { return std::get<2>(GetParam()); }
115 uint32_t serverVersion() const { return std::get<3>(GetParam()); }
116 bool serverSingleThreaded() const { return std::get<4>(GetParam()); }
117 bool noKernel() const { return std::get<5>(GetParam()); }
118
119 bool clientOrServerSingleThreaded() const {
120 return !kEnableRpcThreads || serverSingleThreaded();
121 }
122
123 // Whether the test params support sending FDs in parcels.
124 bool supportsFdTransport() const {
Andrei Homescu68a55612022-08-02 01:25:15 +0000125 if (socketType() == SocketType::TIPC) {
126 // Trusty does not support file descriptors yet
127 return false;
128 }
Andrei Homescu96834632022-10-14 00:49:49 +0000129 return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
130 (socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX ||
Alice Wang893a9912022-10-24 10:44:09 +0000131 socketType() == SocketType::UNIX_BOOTSTRAP ||
132 socketType() == SocketType::UNIX_RAW);
Andrei Homescu96834632022-10-14 00:49:49 +0000133 }
134
135 void SetUp() override {
136 if (socketType() == SocketType::UNIX_BOOTSTRAP && rpcSecurity() == RpcSecurity::TLS) {
137 GTEST_SKIP() << "Unix bootstrap not supported over a TLS transport";
138 }
139 }
140
141 BinderRpcTestProcessSession createRpcTestSocketServerProcess(const BinderRpcOptions& options) {
Tomasz Wasilczykfdf54812023-06-28 14:14:35 -0700142 BinderRpcTestProcessSession ret(createRpcTestSocketServerProcessEtc(options));
Andrei Homescu96834632022-10-14 00:49:49 +0000143
144 ret.rootBinder = ret.proc->sessions.empty() ? nullptr : ret.proc->sessions.at(0).root;
145 ret.rootIface = interface_cast<IBinderRpcTest>(ret.rootBinder);
146
147 return ret;
148 }
149
Andrei Homescuf30148c2023-03-10 00:31:45 +0000150 static std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) {
151 auto [type, security, clientVersion, serverVersion, singleThreaded, noKernel] = info.param;
152 auto ret = PrintToString(type) + "_" + newFactory(security)->toCString() + "_clientV" +
153 std::to_string(clientVersion) + "_serverV" + std::to_string(serverVersion);
154 if (singleThreaded) {
155 ret += "_single_threaded";
156 } else {
157 ret += "_multi_threaded";
158 }
159 if (noKernel) {
160 ret += "_no_kernel";
161 } else {
162 ret += "_with_kernel";
163 }
164 return ret;
165 }
Andrei Homescu96834632022-10-14 00:49:49 +0000166
167protected:
Andrei Homescuf30148c2023-03-10 00:31:45 +0000168 static std::unique_ptr<RpcTransportCtxFactory> newFactory(RpcSecurity rpcSecurity);
169
Andrei Homescu96834632022-10-14 00:49:49 +0000170 std::unique_ptr<ProcessSession> createRpcTestSocketServerProcessEtc(
171 const BinderRpcOptions& options);
172};
173
174} // namespace android