blob: 99b96e95542dd606c873c23e86402244c9dd0381 [file] [log] [blame]
Chris Ye0783e992020-06-02 21:34:49 -07001/*
2 * Copyright (C) 2020 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#include <BnInputFlingerQuery.h>
18#include <IInputFlingerQuery.h>
19
20#include <android/os/BnInputFlinger.h>
21#include <android/os/BnSetInputWindowsListener.h>
22#include <android/os/IInputFlinger.h>
23#include <android/os/ISetInputWindowsListener.h>
24
25#include <binder/Binder.h>
26#include <binder/IPCThreadState.h>
27#include <binder/IServiceManager.h>
28#include <binder/Parcel.h>
29#include <binder/ProcessState.h>
30
31#include <input/Input.h>
32#include <input/InputTransport.h>
33#include <input/InputWindow.h>
34
35#include <gtest/gtest.h>
36#include <inttypes.h>
37#include <linux/uinput.h>
38#include <log/log.h>
39#include <ui/Rect.h>
40#include <ui/Region.h>
41#include <chrono>
42#include <thread>
43#include <unordered_map>
44
45#define TAG "InputFlingerServiceTest"
46
47using android::os::BnInputFlinger;
48using android::os::BnSetInputWindowsListener;
49using android::os::IInputFlinger;
50using android::os::ISetInputWindowsListener;
51
52using std::chrono_literals::operator""ms;
53using std::chrono_literals::operator""s;
54
55namespace android {
56
57static const sp<IBinder> TestInfoToken = new BBinder();
Vishnu Naire798b472020-07-23 13:52:21 -070058static const sp<IBinder> FocusedTestInfoToken = new BBinder();
Chris Ye0783e992020-06-02 21:34:49 -070059static constexpr int32_t TestInfoId = 1;
60static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo";
Michael Wright44753b12020-07-08 13:48:11 +010061static constexpr Flags<InputWindowInfo::Flag> TestInfoFlags = InputWindowInfo::Flag::NOT_FOCUSABLE;
62static constexpr InputWindowInfo::Type TestInfoType = InputWindowInfo::Type::INPUT_METHOD;
Chris Ye0783e992020-06-02 21:34:49 -070063static constexpr std::chrono::duration TestInfoDispatchingTimeout = 2532ms;
64static constexpr int32_t TestInfoFrameLeft = 93;
65static constexpr int32_t TestInfoFrameTop = 34;
66static constexpr int32_t TestInfoFrameRight = 16;
67static constexpr int32_t TestInfoFrameBottom = 19;
68static constexpr int32_t TestInfoSurfaceInset = 17;
69static constexpr float TestInfoGlobalScaleFactor = 0.3;
70static constexpr float TestInfoWindowXScale = 0.4;
71static constexpr float TestInfoWindowYScale = 0.5;
72static const Rect TestInfoTouchableRegionRect = {100 /* left */, 150 /* top */, 400 /* right */,
73 450 /* bottom */};
74static const Region TestInfoTouchableRegion(TestInfoTouchableRegionRect);
75static constexpr bool TestInfoVisible = false;
Chris Ye0783e992020-06-02 21:34:49 -070076static constexpr bool TestInfoTrustedOverlay = true;
Vishnu Nair47074b82020-08-14 11:54:47 -070077static constexpr bool TestInfoFocusable = false;
Chris Ye0783e992020-06-02 21:34:49 -070078static constexpr bool TestInfoHasWallpaper = false;
79static constexpr bool TestInfoPaused = false;
80static constexpr int32_t TestInfoOwnerPid = 19;
81static constexpr int32_t TestInfoOwnerUid = 24;
Michael Wright44753b12020-07-08 13:48:11 +010082static constexpr InputWindowInfo::Feature TestInfoInputFeatures =
83 InputWindowInfo::Feature::NO_INPUT_CHANNEL;
Chris Ye0783e992020-06-02 21:34:49 -070084static constexpr int32_t TestInfoDisplayId = 34;
85static constexpr int32_t TestInfoPortalToDisplayId = 2;
86static constexpr bool TestInfoReplaceTouchableRegionWithCrop = true;
87static const sp<IBinder> TestInfoTouchableRegionCropHandle = new BBinder();
88
89static const std::string TestAppInfoName = "InputFlingerServiceTestInputApplicationInfo";
90static const sp<IBinder> TestAppInfoToken = new BBinder();
91static constexpr std::chrono::duration TestAppInfoDispatchingTimeout = 12345678ms;
92
93static const String16 kTestServiceName = String16("InputFlingerService");
94static const String16 kQueryServiceName = String16("InputFlingerQueryService");
95
96struct SetInputWindowsListener;
97// --- InputFlingerServiceTest ---
98class InputFlingerServiceTest : public testing::Test {
99public:
100 void SetUp() override;
101 void TearDown() override;
102
103protected:
104 void InitializeInputFlinger();
Vishnu Naire798b472020-07-23 13:52:21 -0700105 void setInputWindowsByInfos(const std::vector<InputWindowInfo>& infos);
106 void setFocusedWindow(const sp<IBinder> token, const sp<IBinder> focusedToken,
107 nsecs_t timestampNanos);
Chris Ye0783e992020-06-02 21:34:49 -0700108
109 void setInputWindowsFinished();
110 void verifyInputWindowInfo(const InputWindowInfo& info) const;
111 InputWindowInfo& getInfo() const { return const_cast<InputWindowInfo&>(mInfo); }
112
113 sp<IInputFlinger> mService;
114 sp<IInputFlingerQuery> mQuery;
115
116private:
117 sp<SetInputWindowsListener> mSetInputWindowsListener;
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500118 std::unique_ptr<InputChannel> mServerChannel, mClientChannel;
Chris Ye0783e992020-06-02 21:34:49 -0700119 InputWindowInfo mInfo;
120 std::mutex mLock;
121 std::condition_variable mSetInputWindowsFinishedCondition;
122};
123
124struct SetInputWindowsListener : BnSetInputWindowsListener {
125 explicit SetInputWindowsListener(std::function<void()> cbFunc) : mCbFunc(cbFunc) {}
126
127 binder::Status onSetInputWindowsFinished() override;
128
129 std::function<void()> mCbFunc;
130};
131
132class TestInputManager : public BnInputFlinger {
133protected:
134 virtual ~TestInputManager(){};
135
136public:
137 TestInputManager(){};
138 void checkFdFlags(const android::base::unique_fd& fd);
139
140 binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles);
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500141 binder::Status getInputChannels(std::vector<::android::InputChannel>* channels);
Vishnu Naire798b472020-07-23 13:52:21 -0700142 binder::Status getLastFocusRequest(FocusRequest*);
Chris Ye0783e992020-06-02 21:34:49 -0700143
144 status_t dump(int fd, const Vector<String16>& args) override;
145
146 binder::Status setInputWindows(
147 const std::vector<InputWindowInfo>& handles,
148 const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
149
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500150 binder::Status registerInputChannel(const InputChannel& channel) override;
151 binder::Status unregisterInputChannel(const InputChannel& channel) override;
Vishnu Naire798b472020-07-23 13:52:21 -0700152 binder::Status setFocusedWindow(const FocusRequest&) override;
Chris Ye0783e992020-06-02 21:34:49 -0700153
154private:
155 mutable Mutex mLock;
156 std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mHandlesPerDisplay;
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500157 std::vector<std::shared_ptr<InputChannel>> mInputChannels;
Vishnu Naire798b472020-07-23 13:52:21 -0700158 FocusRequest mFocusRequest;
Chris Ye0783e992020-06-02 21:34:49 -0700159};
160
161class TestInputQuery : public BnInputFlingerQuery {
162public:
163 TestInputQuery(sp<android::TestInputManager> manager) : mManager(manager){};
164 binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override;
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500165 binder::Status getInputChannels(std::vector<::android::InputChannel>* channels) override;
Vishnu Naire798b472020-07-23 13:52:21 -0700166 binder::Status getLastFocusRequest(FocusRequest*) override;
Chris Ye0783e992020-06-02 21:34:49 -0700167
168private:
169 sp<android::TestInputManager> mManager;
170};
171
172binder::Status TestInputQuery::getInputWindows(
173 std::vector<::android::InputWindowInfo>* inputHandles) {
174 return mManager->getInputWindows(inputHandles);
175}
176
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500177binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannel>* channels) {
178 return mManager->getInputChannels(channels);
Chris Ye0783e992020-06-02 21:34:49 -0700179}
180
Vishnu Naire798b472020-07-23 13:52:21 -0700181binder::Status TestInputQuery::getLastFocusRequest(FocusRequest* request) {
182 return mManager->getLastFocusRequest(request);
183}
184
Chris Ye0783e992020-06-02 21:34:49 -0700185binder::Status SetInputWindowsListener::onSetInputWindowsFinished() {
186 if (mCbFunc != nullptr) {
187 mCbFunc();
188 }
189 return binder::Status::ok();
190}
191
192binder::Status TestInputManager::setInputWindows(
193 const std::vector<InputWindowInfo>& infos,
194 const sp<ISetInputWindowsListener>& setInputWindowsListener) {
195 AutoMutex _l(mLock);
196
197 for (const auto& info : infos) {
198 mHandlesPerDisplay.emplace(info.displayId, std::vector<sp<InputWindowHandle>>());
199 mHandlesPerDisplay[info.displayId].push_back(new InputWindowHandle(info));
200 }
201 if (setInputWindowsListener) {
202 setInputWindowsListener->onSetInputWindowsFinished();
203 }
204 return binder::Status::ok();
205}
206
207void TestInputManager::checkFdFlags(const android::base::unique_fd& fd) {
208 const int result = fcntl(fd, F_GETFL);
209 EXPECT_NE(result, -1);
210 EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK);
211}
212
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500213binder::Status TestInputManager::registerInputChannel(const InputChannel& channel) {
Chris Ye0783e992020-06-02 21:34:49 -0700214 AutoMutex _l(mLock);
215 // check Fd flags
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500216 checkFdFlags(channel.getFd());
Chris Ye0783e992020-06-02 21:34:49 -0700217
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500218 mInputChannels.push_back(channel.dup());
Chris Ye0783e992020-06-02 21:34:49 -0700219
220 return binder::Status::ok();
221}
222
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500223binder::Status TestInputManager::unregisterInputChannel(const InputChannel& channel) {
Chris Ye0783e992020-06-02 21:34:49 -0700224 AutoMutex _l(mLock);
225 // check Fd flags
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500226 checkFdFlags(channel.getFd());
Chris Ye0783e992020-06-02 21:34:49 -0700227
228 auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(),
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500229 [&](std::shared_ptr<InputChannel>& c) { return *c == channel; });
Chris Ye0783e992020-06-02 21:34:49 -0700230 if (it != mInputChannels.end()) {
231 mInputChannels.erase(it);
232 }
233
234 return binder::Status::ok();
235}
236
237status_t TestInputManager::dump(int fd, const Vector<String16>& args) {
238 std::string dump;
239
240 dump += " InputFlinger dump\n";
241
242 ::write(fd, dump.c_str(), dump.size());
243 return NO_ERROR;
244}
245
246binder::Status TestInputManager::getInputWindows(
247 std::vector<::android::InputWindowInfo>* inputInfos) {
248 for (auto& [displayId, inputHandles] : mHandlesPerDisplay) {
249 for (auto& inputHandle : inputHandles) {
250 inputInfos->push_back(*inputHandle->getInfo());
251 }
252 }
253 return binder::Status::ok();
254}
255
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500256binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannel>* channels) {
257 channels->clear();
258 for (std::shared_ptr<InputChannel>& channel : mInputChannels) {
259 channels->push_back(*channel);
Chris Ye0783e992020-06-02 21:34:49 -0700260 }
261 return binder::Status::ok();
262}
263
Vishnu Naire798b472020-07-23 13:52:21 -0700264binder::Status TestInputManager::getLastFocusRequest(FocusRequest* request) {
265 *request = mFocusRequest;
266 return binder::Status::ok();
267}
268
269binder::Status TestInputManager::setFocusedWindow(const FocusRequest& request) {
270 mFocusRequest = request;
271 return binder::Status::ok();
272}
273
Chris Ye0783e992020-06-02 21:34:49 -0700274void InputFlingerServiceTest::SetUp() {
275 mSetInputWindowsListener = new SetInputWindowsListener([&]() {
276 std::unique_lock<std::mutex> lock(mLock);
277 mSetInputWindowsFinishedCondition.notify_all();
278 });
279 InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
280
281 mInfo.token = TestInfoToken;
282 mInfo.id = TestInfoId;
283 mInfo.name = TestInfoName;
Michael Wright44753b12020-07-08 13:48:11 +0100284 mInfo.flags = TestInfoFlags;
285 mInfo.type = TestInfoType;
Chris Ye0783e992020-06-02 21:34:49 -0700286 mInfo.dispatchingTimeout = TestInfoDispatchingTimeout;
287 mInfo.frameLeft = TestInfoFrameLeft;
288 mInfo.frameTop = TestInfoFrameTop;
289 mInfo.frameRight = TestInfoFrameRight;
290 mInfo.frameBottom = TestInfoFrameBottom;
291 mInfo.surfaceInset = TestInfoSurfaceInset;
292 mInfo.globalScaleFactor = TestInfoGlobalScaleFactor;
chaviw9eaa22c2020-07-01 16:21:27 -0700293 mInfo.transform.set({TestInfoWindowXScale, 0, TestInfoFrameLeft, 0, TestInfoWindowYScale,
294 TestInfoFrameTop, 0, 0, 1});
Chris Ye0783e992020-06-02 21:34:49 -0700295 mInfo.touchableRegion = TestInfoTouchableRegion;
296 mInfo.visible = TestInfoVisible;
Chris Ye0783e992020-06-02 21:34:49 -0700297 mInfo.trustedOverlay = TestInfoTrustedOverlay;
Vishnu Nair47074b82020-08-14 11:54:47 -0700298 mInfo.focusable = TestInfoFocusable;
299
Chris Ye0783e992020-06-02 21:34:49 -0700300 mInfo.hasWallpaper = TestInfoHasWallpaper;
301 mInfo.paused = TestInfoPaused;
302 mInfo.ownerPid = TestInfoOwnerPid;
303 mInfo.ownerUid = TestInfoOwnerUid;
304 mInfo.inputFeatures = TestInfoInputFeatures;
305 mInfo.displayId = TestInfoDisplayId;
306 mInfo.portalToDisplayId = TestInfoPortalToDisplayId;
307 mInfo.replaceTouchableRegionWithCrop = TestInfoReplaceTouchableRegionWithCrop;
308 mInfo.touchableRegionCropHandle = TestInfoTouchableRegionCropHandle;
309
310 mInfo.applicationInfo.name = TestAppInfoName;
311 mInfo.applicationInfo.token = TestAppInfoToken;
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500312 mInfo.applicationInfo.dispatchingTimeoutMillis =
313 std::chrono::duration_cast<std::chrono::milliseconds>(TestAppInfoDispatchingTimeout)
314 .count();
Chris Ye0783e992020-06-02 21:34:49 -0700315
316 InitializeInputFlinger();
317}
318
319void InputFlingerServiceTest::TearDown() {}
320
321void InputFlingerServiceTest::verifyInputWindowInfo(const InputWindowInfo& info) const {
322 EXPECT_EQ(mInfo, info);
323}
324
325void InputFlingerServiceTest::InitializeInputFlinger() {
326 sp<IBinder> input(defaultServiceManager()->waitForService(kTestServiceName));
327 ASSERT_TRUE(input != nullptr);
328 mService = interface_cast<IInputFlinger>(input);
329
330 input = defaultServiceManager()->waitForService(kQueryServiceName);
331 ASSERT_TRUE(input != nullptr);
332 mQuery = interface_cast<IInputFlingerQuery>(input);
333}
334
Vishnu Naire798b472020-07-23 13:52:21 -0700335void InputFlingerServiceTest::setInputWindowsByInfos(const std::vector<InputWindowInfo>& infos) {
Chris Ye0783e992020-06-02 21:34:49 -0700336 std::unique_lock<std::mutex> lock(mLock);
337 mService->setInputWindows(infos, mSetInputWindowsListener);
338 // Verify listener call
339 EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout);
Chris Ye0783e992020-06-02 21:34:49 -0700340}
341
Vishnu Naire798b472020-07-23 13:52:21 -0700342void InputFlingerServiceTest::setFocusedWindow(const sp<IBinder> token,
343 const sp<IBinder> focusedToken,
344 nsecs_t timestampNanos) {
345 FocusRequest request;
346 request.token = TestInfoToken;
347 request.focusedToken = focusedToken;
348 request.timestamp = timestampNanos;
349 mService->setFocusedWindow(request);
350 // call set input windows and wait for the callback to drain the queue.
351 setInputWindowsByInfos(std::vector<InputWindowInfo>());
352}
353
Chris Ye0783e992020-06-02 21:34:49 -0700354/**
355 * Test InputFlinger service interface SetInputWindows
356 */
357TEST_F(InputFlingerServiceTest, InputWindow_SetInputWindows) {
358 std::vector<InputWindowInfo> infos = {getInfo()};
359 setInputWindowsByInfos(infos);
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500360
361 // Verify input windows from service
362 std::vector<::android::InputWindowInfo> windowInfos;
363 mQuery->getInputWindows(&windowInfos);
364 for (const ::android::InputWindowInfo& windowInfo : windowInfos) {
365 verifyInputWindowInfo(windowInfo);
366 }
Chris Ye0783e992020-06-02 21:34:49 -0700367}
368
369/**
370 * Test InputFlinger service interface registerInputChannel
371 */
372TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) {
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500373 std::unique_ptr<InputChannel> serverChannel, clientChannel;
Chris Ye0783e992020-06-02 21:34:49 -0700374
375 InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500376 mService->registerInputChannel(*serverChannel);
Chris Ye0783e992020-06-02 21:34:49 -0700377
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500378 std::vector<::android::InputChannel> channels;
379 mQuery->getInputChannels(&channels);
380 ASSERT_EQ(channels.size(), 1UL);
381 EXPECT_EQ(channels[0], *serverChannel);
Chris Ye0783e992020-06-02 21:34:49 -0700382
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500383 mService->unregisterInputChannel(*serverChannel);
384 mQuery->getInputChannels(&channels);
385 EXPECT_EQ(channels.size(), 0UL);
Chris Ye0783e992020-06-02 21:34:49 -0700386}
387
388/**
389 * Test InputFlinger service interface registerInputChannel with invalid cases
390 */
391TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) {
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500392 std::unique_ptr<InputChannel> serverChannel, clientChannel;
Chris Ye0783e992020-06-02 21:34:49 -0700393 InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
394
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500395 std::vector<::android::InputChannel> channels;
396 mQuery->getInputChannels(&channels);
397 EXPECT_EQ(channels.size(), 0UL);
Chris Ye0783e992020-06-02 21:34:49 -0700398
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500399 mService->registerInputChannel(InputChannel());
400 mService->unregisterInputChannel(*clientChannel);
Chris Ye0783e992020-06-02 21:34:49 -0700401
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500402 mService->registerInputChannel(*serverChannel);
403 mService->registerInputChannel(*clientChannel);
404 mQuery->getInputChannels(&channels);
405 EXPECT_EQ(channels.size(), 2UL);
Chris Ye0783e992020-06-02 21:34:49 -0700406
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500407 mService->unregisterInputChannel(*clientChannel);
408 mService->unregisterInputChannel(*serverChannel);
409 mQuery->getInputChannels(&channels);
410 EXPECT_EQ(channels.size(), 0UL);
Chris Ye0783e992020-06-02 21:34:49 -0700411}
412
Vishnu Naire798b472020-07-23 13:52:21 -0700413TEST_F(InputFlingerServiceTest, InputWindow_setFocusedWindow) {
414 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
415 setFocusedWindow(TestInfoToken, nullptr /* focusedToken */, now);
416
417 FocusRequest request;
418 mQuery->getLastFocusRequest(&request);
419
420 EXPECT_EQ(request.token, TestInfoToken);
421 EXPECT_EQ(request.focusedToken, nullptr);
422 EXPECT_EQ(request.timestamp, now);
423}
424
425TEST_F(InputFlingerServiceTest, InputWindow_setFocusedWindowWithFocusedToken) {
426 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
427 setFocusedWindow(TestInfoToken, FocusedTestInfoToken, now);
428
429 FocusRequest request;
430 mQuery->getLastFocusRequest(&request);
431
432 EXPECT_EQ(request.token, TestInfoToken);
433 EXPECT_EQ(request.focusedToken, FocusedTestInfoToken);
434 EXPECT_EQ(request.timestamp, now);
435}
436
Chris Ye0783e992020-06-02 21:34:49 -0700437} // namespace android
438
439int main(int argc, char** argv) {
440 pid_t forkPid = fork();
441
442 if (forkPid == 0) {
443 // Server process
444 android::sp<android::TestInputManager> manager = new android::TestInputManager();
445 android::sp<android::TestInputQuery> query = new android::TestInputQuery(manager);
446
447 android::defaultServiceManager()->addService(android::kTestServiceName, manager,
448 false /*allowIsolated*/);
449 android::defaultServiceManager()->addService(android::kQueryServiceName, query,
450 false /*allowIsolated*/);
451 android::ProcessState::self()->startThreadPool();
452 android::IPCThreadState::self()->joinThreadPool();
453 } else {
454 android::ProcessState::self()->startThreadPool();
455 ::testing::InitGoogleTest(&argc, argv);
Chris Yec4669842020-07-14 17:10:09 -0700456 int result = RUN_ALL_TESTS();
457 kill(forkPid, SIGKILL);
458 return result;
Chris Ye0783e992020-06-02 21:34:49 -0700459 }
460 return 0;
461}