1 /*
2  * Copyright (C) 2019 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 <chrono>
18 #include <iostream>
19 #include <mutex>
20 #include <thread>
21 
22 #include "adbconnection/client.h"
23 #include "adbconnection/common.h"
24 #include "adbconnection/server.h"
25 
26 #include <gtest/gtest.h>
27 
28 // How this test works. Normally, the client lives in ART process and the server live in adbd.
29 // They communicate over UDS "@jdwp-control", each using a poll system (we don't have here).
30 //
31 // We spawn the client and the server in the same process. They still use the same UDS to
32 // communicate. The fdevent from adbd system is mocked with a single loop (server_callback). The
33 // conditional variable is used to pace the test (send then assert).
34 
35 ProcessInfo info = {};
36 
37 // The client synchronize with the server with mx and cv
38 std::mutex mx;
39 std::condition_variable cv;
onUpdateReceived()40 void onUpdateReceived() {
41   std::lock_guard<std::mutex> lock(mx);
42   cv.notify_one();
43 }
waitForUpdateReceived()44 void waitForUpdateReceived() {
45   std::unique_lock<std::mutex> lock(mx);
46   cv.wait(lock);
47 }
48 
server_callback(int fd,ProcessInfo process)49 void server_callback(int fd, ProcessInfo process) {
50   info = process;
51   onUpdateReceived();
52   // After the first processinfo update is received, jdwp_service in adbd takes over reading
53   // from the fd leveraging fdevent system. We emulate it by reading on a regular basis.
54   while (true) {
55     auto optional = readProcessInfoFromSocket(fd);
56     if (optional) {
57       info = *optional;
58       onUpdateReceived();
59     }
60     std::this_thread::sleep_for(std::chrono::milliseconds(10));
61   }
62 }
63 
64 // This test mimics an app starting up and sending data as zygote is specializing
TEST(LibAdbConnectionTest,TestComm)65 TEST(LibAdbConnectionTest, TestComm) {
66   // Start a fake server
67   std::thread([]() { adbconnection_listen(server_callback); }).detach();
68   // Let the server start
69   sleep(1);
70 
71   const char* isa = "arch_foo";
72   const AdbConnectionClientInfo infos[] = {
73       {.type = AdbConnectionClientInfoType::pid, .data.pid = 666},
74       {.type = AdbConnectionClientInfoType::debuggable, .data.debuggable = true},
75       {.type = AdbConnectionClientInfoType::profileable, .data.profileable = true},
76       {.type = AdbConnectionClientInfoType::architecture,
77        .data.architecture.name = isa,
78        .data.architecture.size = strlen(isa)},
79   };
80 
81   //   Send the first batch of data (mimic the app starting up)
82   const AdbConnectionClientInfo* info_ptrs[] = {&infos[0], &infos[1], &infos[2], &infos[3]};
83   auto ctx = adbconnection_client_new(info_ptrs, std::size(infos));
84   EXPECT_TRUE(ctx != nullptr);
85   EXPECT_FALSE(adbconnection_client_has_pending_update());
86 
87   waitForUpdateReceived();
88   EXPECT_EQ(info.pid, infos[0].data.pid);
89   EXPECT_TRUE(info.debuggable);
90   EXPECT_TRUE(info.profileable);
91   EXPECT_EQ(info.architecture, isa);
92   EXPECT_FALSE(adbconnection_client_has_pending_update());
93 
94   adbconnection_client_set_current_process_name("my_process_name");
95   adbconnection_client_add_application("my_package_name");
96   adbconnection_client_add_application("my_package_name2");
97   adbconnection_client_remove_application("my_package_name2");
98   adbconnection_client_set_user_id(888);
99   adbconnection_client_set_waiting_for_debugger(true);
100 
101   EXPECT_TRUE(adbconnection_client_has_pending_update());
102 
103   // Send an update
104   adbconnection_client_send_update(ctx);
105   EXPECT_FALSE(adbconnection_client_has_pending_update());
106 
107   waitForUpdateReceived();
108   EXPECT_EQ(info.package_names.size(), 1);
109   EXPECT_EQ(info.package_names.count("my_package_name"), 1);
110   EXPECT_EQ(info.process_name, "my_process_name");
111   EXPECT_EQ(info.user_id, 888);
112   EXPECT_TRUE(info.waiting_for_debugger);
113 }