1//===-- PlatformAndroidTest.cpp -------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Plugins/Platform/Android/PlatformAndroid.h"
10#include "Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h"
11#include "TestingSupport/SubsystemRAII.h"
12#include "TestingSupport/TestUtilities.h"
13#include "lldb/Utility/Connection.h"
14#include "gmock/gmock.h"
15
16using namespace lldb;
17using namespace lldb_private;
18using namespace lldb_private::platform_android;
19using namespace testing;
20
21namespace {
22
23class MockSyncService : public AdbClient::SyncService {
24public:
25 MockSyncService() : SyncService(std::unique_ptr<Connection>()) {}
26
27 MOCK_METHOD2(PullFile,
28 Status(const FileSpec &remote_file, const FileSpec &local_file));
29 MOCK_METHOD4(Stat, Status(const FileSpec &remote_file, uint32_t &mode,
30 uint32_t &size, uint32_t &mtime));
31};
32
33typedef std::unique_ptr<AdbClient::SyncService> SyncServiceUP;
34
35class MockAdbClient : public AdbClient {
36public:
37 explicit MockAdbClient() : AdbClient("mock") {}
38
39 MOCK_METHOD3(ShellToFile,
40 Status(const char *command, std::chrono::milliseconds timeout,
41 const FileSpec &output_file_spec));
42 MOCK_METHOD1(GetSyncService, SyncServiceUP(Status &error));
43};
44
45class PlatformAndroidTest : public PlatformAndroid, public ::testing::Test {
46public:
47 PlatformAndroidTest() : PlatformAndroid(false) {
48 m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());
49 }
50
51 MOCK_METHOD1(GetAdbClient, AdbClientUP(Status &error));
52 MOCK_METHOD0(GetPropertyPackageName, llvm::StringRef());
53};
54
55} // namespace
56
57TEST_F(PlatformAndroidTest, DownloadModuleSliceWithAdbClientError) {
58 EXPECT_CALL(*this, GetAdbClient(_))
59 .Times(n: 1)
60 .WillOnce(once_action: DoAll(action: WithArg<0>(action: [](auto &arg) {
61 arg = Status::FromErrorString(
62 str: "Failed to create AdbClient");
63 }),
64 action: Return(value: ByMove(x: AdbClientUP()))));
65
66 EXPECT_TRUE(
67 DownloadModuleSlice(
68 FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,
69 3600, FileSpec())
70 .Fail());
71}
72
73TEST_F(PlatformAndroidTest, DownloadModuleSliceWithNormalFile) {
74 auto sync_service = new MockSyncService();
75 EXPECT_CALL(*sync_service, Stat(FileSpec("/system/lib64/libc.so"), _, _, _))
76 .Times(n: 1)
77 .WillOnce(once_action: DoAll(action: SetArgReferee<1>(1), action: Return(value: Status())));
78 EXPECT_CALL(*sync_service, PullFile(FileSpec("/system/lib64/libc.so"), _))
79 .Times(n: 1)
80 .WillOnce(once_action: Return(value: Status()));
81
82 auto adb_client = new MockAdbClient();
83 EXPECT_CALL(*adb_client, GetSyncService(_))
84 .Times(n: 1)
85 .WillOnce(once_action: Return(value: ByMove(x: SyncServiceUP(sync_service))));
86
87 EXPECT_CALL(*this, GetAdbClient(_))
88 .Times(n: 1)
89 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client))));
90
91 EXPECT_TRUE(
92 DownloadModuleSlice(FileSpec("/system/lib64/libc.so"), 0, 0, FileSpec())
93 .Success());
94}
95
96TEST_F(PlatformAndroidTest, DownloadModuleSliceWithZipFile) {
97 auto adb_client = new MockAdbClient();
98 EXPECT_CALL(*adb_client,
99 ShellToFile(StrEq("dd if='/system/app/Test/Test.apk' "
100 "iflag=skip_bytes,count_bytes "
101 "skip=4096 count=3600 status=none"),
102 _, _))
103 .Times(n: 1)
104 .WillOnce(once_action: Return(value: Status()));
105
106 EXPECT_CALL(*this, GetAdbClient(_))
107 .Times(n: 1)
108 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client))));
109
110 EXPECT_TRUE(
111 DownloadModuleSlice(
112 FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,
113 3600, FileSpec())
114 .Success());
115}
116
117TEST_F(PlatformAndroidTest, DownloadModuleSliceWithZipFileAndRunAs) {
118 auto adb_client = new MockAdbClient();
119 EXPECT_CALL(*adb_client,
120 ShellToFile(StrEq("run-as 'com.example.test' "
121 "dd if='/system/app/Test/Test.apk' "
122 "iflag=skip_bytes,count_bytes "
123 "skip=4096 count=3600 status=none"),
124 _, _))
125 .Times(n: 1)
126 .WillOnce(once_action: Return(value: Status()));
127
128 EXPECT_CALL(*this, GetPropertyPackageName())
129 .Times(n: 1)
130 .WillOnce(once_action: Return(value: llvm::StringRef("com.example.test")));
131
132 EXPECT_CALL(*this, GetAdbClient(_))
133 .Times(n: 1)
134 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client))));
135
136 EXPECT_TRUE(
137 DownloadModuleSlice(
138 FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,
139 3600, FileSpec())
140 .Success());
141}
142
143TEST_F(PlatformAndroidTest, GetFileWithNormalFile) {
144 auto sync_service = new MockSyncService();
145 EXPECT_CALL(*sync_service, Stat(FileSpec("/data/local/tmp/test"), _, _, _))
146 .Times(n: 1)
147 .WillOnce(once_action: DoAll(action: SetArgReferee<1>(1), action: Return(value: Status())));
148 EXPECT_CALL(*sync_service, PullFile(FileSpec("/data/local/tmp/test"), _))
149 .Times(n: 1)
150 .WillOnce(once_action: Return(value: Status()));
151
152 auto adb_client = new MockAdbClient();
153 EXPECT_CALL(*adb_client, GetSyncService(_))
154 .Times(n: 1)
155 .WillOnce(once_action: Return(value: ByMove(x: SyncServiceUP(sync_service))));
156
157 EXPECT_CALL(*this, GetAdbClient(_))
158 .Times(n: 1)
159 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client))));
160
161 EXPECT_TRUE(GetFile(FileSpec("/data/local/tmp/test"), FileSpec()).Success());
162}
163
164TEST_F(PlatformAndroidTest, GetFileWithCatFallback) {
165 auto sync_service = new MockSyncService();
166 EXPECT_CALL(
167 *sync_service,
168 Stat(FileSpec("/data/data/com.example.app/lib-main/libtest.so"), _, _, _))
169 .Times(n: 1)
170 .WillOnce(once_action: DoAll(action: SetArgReferee<1>(0), action: Return(value: Status())));
171
172 auto adb_client0 = new MockAdbClient();
173 EXPECT_CALL(*adb_client0, GetSyncService(_))
174 .Times(n: 1)
175 .WillOnce(once_action: Return(value: ByMove(x: SyncServiceUP(sync_service))));
176
177 auto adb_client1 = new MockAdbClient();
178 EXPECT_CALL(
179 *adb_client1,
180 ShellToFile(StrEq("cat '/data/data/com.example.app/lib-main/libtest.so'"),
181 _, _))
182 .Times(n: 1)
183 .WillOnce(once_action: Return(value: Status()));
184
185 EXPECT_CALL(*this, GetAdbClient(_))
186 .Times(n: 2)
187 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client0))))
188 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client1))));
189
190 EXPECT_TRUE(
191 GetFile(FileSpec("/data/data/com.example.app/lib-main/libtest.so"),
192 FileSpec())
193 .Success());
194}
195
196TEST_F(PlatformAndroidTest, GetFileWithCatFallbackAndRunAs) {
197 auto sync_service = new MockSyncService();
198 EXPECT_CALL(
199 *sync_service,
200 Stat(FileSpec("/data/data/com.example.app/lib-main/libtest.so"), _, _, _))
201 .Times(n: 1)
202 .WillOnce(once_action: DoAll(action: SetArgReferee<1>(0), action: Return(value: Status())));
203
204 auto adb_client0 = new MockAdbClient();
205 EXPECT_CALL(*adb_client0, GetSyncService(_))
206 .Times(n: 1)
207 .WillOnce(once_action: Return(value: ByMove(x: SyncServiceUP(sync_service))));
208
209 auto adb_client1 = new MockAdbClient();
210 EXPECT_CALL(
211 *adb_client1,
212 ShellToFile(StrEq("run-as 'com.example.app' "
213 "cat '/data/data/com.example.app/lib-main/libtest.so'"),
214 _, _))
215 .Times(n: 1)
216 .WillOnce(once_action: Return(value: Status()));
217
218 EXPECT_CALL(*this, GetPropertyPackageName())
219 .Times(n: 1)
220 .WillOnce(once_action: Return(value: llvm::StringRef("com.example.app")));
221
222 EXPECT_CALL(*this, GetAdbClient(_))
223 .Times(n: 2)
224 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client0))))
225 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client1))));
226
227 EXPECT_TRUE(
228 GetFile(FileSpec("/data/data/com.example.app/lib-main/libtest.so"),
229 FileSpec())
230 .Success());
231}
232

source code of lldb/unittests/Platform/Android/PlatformAndroidTest.cpp