• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     };
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
55 struct 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 
67     // 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)
forceShutdownBinderRpcTestProcessSession74     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 
82     BinderRpcTestProcessSession(BinderRpcTestProcessSession&&) = default;
~BinderRpcTestProcessSessionBinderRpcTestProcessSession83     ~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 
108 class BinderRpc : public ::testing::TestWithParam<
109                           std::tuple<SocketType, RpcSecurity, uint32_t, uint32_t, bool, bool>> {
110 public:
socketType()111     SocketType socketType() const { return std::get<0>(GetParam()); }
rpcSecurity()112     RpcSecurity rpcSecurity() const { return std::get<1>(GetParam()); }
clientVersion()113     uint32_t clientVersion() const { return std::get<2>(GetParam()); }
serverVersion()114     uint32_t serverVersion() const { return std::get<3>(GetParam()); }
serverSingleThreaded()115     bool serverSingleThreaded() const { return std::get<4>(GetParam()); }
noKernel()116     bool noKernel() const { return std::get<5>(GetParam()); }
117 
clientOrServerSingleThreaded()118     bool clientOrServerSingleThreaded() const {
119         return !kEnableRpcThreads || serverSingleThreaded();
120     }
121 
122     // Whether the test params support sending FDs in parcels.
supportsFdTransport()123     bool supportsFdTransport() const {
124         if (socketType() == SocketType::TIPC) {
125             // Trusty does not support file descriptors yet
126             return false;
127         }
128         return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
129                 (socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX ||
130                  socketType() == SocketType::UNIX_BOOTSTRAP ||
131                  socketType() == SocketType::UNIX_RAW);
132     }
133 
SetUp()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 
createRpcTestSocketServerProcess(const BinderRpcOptions & options)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 
PrintParamInfo(const testing::TestParamInfo<ParamType> & info)151     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     }
167 
168 protected:
169     static std::unique_ptr<RpcTransportCtxFactory> newFactory(RpcSecurity rpcSecurity);
170 
171     std::unique_ptr<ProcessSession> createRpcTestSocketServerProcessEtc(
172             const BinderRpcOptions& options);
173 };
174 
175 } // namespace android
176