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("Failed to create AdbClient");
62 }),
63 action: Return(value: ByMove(x: AdbClientUP()))));
64
65 EXPECT_TRUE(
66 DownloadModuleSlice(
67 FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,
68 3600, FileSpec())
69 .Fail());
70}
71
72TEST_F(PlatformAndroidTest, DownloadModuleSliceWithNormalFile) {
73 auto sync_service = new MockSyncService();
74 EXPECT_CALL(*sync_service, Stat(FileSpec("/system/lib64/libc.so"), _, _, _))
75 .Times(n: 1)
76 .WillOnce(once_action: DoAll(action: SetArgReferee<1>(1), action: Return(value: Status())));
77 EXPECT_CALL(*sync_service, PullFile(FileSpec("/system/lib64/libc.so"), _))
78 .Times(n: 1)
79 .WillOnce(once_action: Return(value: Status()));
80
81 auto adb_client = new MockAdbClient();
82 EXPECT_CALL(*adb_client, GetSyncService(_))
83 .Times(n: 1)
84 .WillOnce(once_action: Return(value: ByMove(x: SyncServiceUP(sync_service))));
85
86 EXPECT_CALL(*this, GetAdbClient(_))
87 .Times(n: 1)
88 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client))));
89
90 EXPECT_TRUE(
91 DownloadModuleSlice(FileSpec("/system/lib64/libc.so"), 0, 0, FileSpec())
92 .Success());
93}
94
95TEST_F(PlatformAndroidTest, DownloadModuleSliceWithZipFile) {
96 auto adb_client = new MockAdbClient();
97 EXPECT_CALL(*adb_client,
98 ShellToFile(StrEq("dd if='/system/app/Test/Test.apk' "
99 "iflag=skip_bytes,count_bytes "
100 "skip=4096 count=3600 status=none"),
101 _, _))
102 .Times(n: 1)
103 .WillOnce(once_action: Return(value: Status()));
104
105 EXPECT_CALL(*this, GetAdbClient(_))
106 .Times(n: 1)
107 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client))));
108
109 EXPECT_TRUE(
110 DownloadModuleSlice(
111 FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,
112 3600, FileSpec())
113 .Success());
114}
115
116TEST_F(PlatformAndroidTest, DownloadModuleSliceWithZipFileAndRunAs) {
117 auto adb_client = new MockAdbClient();
118 EXPECT_CALL(*adb_client,
119 ShellToFile(StrEq("run-as 'com.example.test' "
120 "dd if='/system/app/Test/Test.apk' "
121 "iflag=skip_bytes,count_bytes "
122 "skip=4096 count=3600 status=none"),
123 _, _))
124 .Times(n: 1)
125 .WillOnce(once_action: Return(value: Status()));
126
127 EXPECT_CALL(*this, GetPropertyPackageName())
128 .Times(n: 1)
129 .WillOnce(once_action: Return(value: llvm::StringRef("com.example.test")));
130
131 EXPECT_CALL(*this, GetAdbClient(_))
132 .Times(n: 1)
133 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client))));
134
135 EXPECT_TRUE(
136 DownloadModuleSlice(
137 FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,
138 3600, FileSpec())
139 .Success());
140}
141
142TEST_F(PlatformAndroidTest, GetFileWithNormalFile) {
143 auto sync_service = new MockSyncService();
144 EXPECT_CALL(*sync_service, Stat(FileSpec("/data/local/tmp/test"), _, _, _))
145 .Times(n: 1)
146 .WillOnce(once_action: DoAll(action: SetArgReferee<1>(1), action: Return(value: Status())));
147 EXPECT_CALL(*sync_service, PullFile(FileSpec("/data/local/tmp/test"), _))
148 .Times(n: 1)
149 .WillOnce(once_action: Return(value: Status()));
150
151 auto adb_client = new MockAdbClient();
152 EXPECT_CALL(*adb_client, GetSyncService(_))
153 .Times(n: 1)
154 .WillOnce(once_action: Return(value: ByMove(x: SyncServiceUP(sync_service))));
155
156 EXPECT_CALL(*this, GetAdbClient(_))
157 .Times(n: 1)
158 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client))));
159
160 EXPECT_TRUE(GetFile(FileSpec("/data/local/tmp/test"), FileSpec()).Success());
161}
162
163TEST_F(PlatformAndroidTest, GetFileWithCatFallback) {
164 auto sync_service = new MockSyncService();
165 EXPECT_CALL(
166 *sync_service,
167 Stat(FileSpec("/data/data/com.example.app/lib-main/libtest.so"), _, _, _))
168 .Times(n: 1)
169 .WillOnce(once_action: DoAll(action: SetArgReferee<1>(0), action: Return(value: Status())));
170
171 auto adb_client0 = new MockAdbClient();
172 EXPECT_CALL(*adb_client0, GetSyncService(_))
173 .Times(n: 1)
174 .WillOnce(once_action: Return(value: ByMove(x: SyncServiceUP(sync_service))));
175
176 auto adb_client1 = new MockAdbClient();
177 EXPECT_CALL(
178 *adb_client1,
179 ShellToFile(StrEq("cat '/data/data/com.example.app/lib-main/libtest.so'"),
180 _, _))
181 .Times(n: 1)
182 .WillOnce(once_action: Return(value: Status()));
183
184 EXPECT_CALL(*this, GetAdbClient(_))
185 .Times(n: 2)
186 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client0))))
187 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client1))));
188
189 EXPECT_TRUE(
190 GetFile(FileSpec("/data/data/com.example.app/lib-main/libtest.so"),
191 FileSpec())
192 .Success());
193}
194
195TEST_F(PlatformAndroidTest, GetFileWithCatFallbackAndRunAs) {
196 auto sync_service = new MockSyncService();
197 EXPECT_CALL(
198 *sync_service,
199 Stat(FileSpec("/data/data/com.example.app/lib-main/libtest.so"), _, _, _))
200 .Times(n: 1)
201 .WillOnce(once_action: DoAll(action: SetArgReferee<1>(0), action: Return(value: Status())));
202
203 auto adb_client0 = new MockAdbClient();
204 EXPECT_CALL(*adb_client0, GetSyncService(_))
205 .Times(n: 1)
206 .WillOnce(once_action: Return(value: ByMove(x: SyncServiceUP(sync_service))));
207
208 auto adb_client1 = new MockAdbClient();
209 EXPECT_CALL(
210 *adb_client1,
211 ShellToFile(StrEq("run-as 'com.example.app' "
212 "cat '/data/data/com.example.app/lib-main/libtest.so'"),
213 _, _))
214 .Times(n: 1)
215 .WillOnce(once_action: Return(value: Status()));
216
217 EXPECT_CALL(*this, GetPropertyPackageName())
218 .Times(n: 1)
219 .WillOnce(once_action: Return(value: llvm::StringRef("com.example.app")));
220
221 EXPECT_CALL(*this, GetAdbClient(_))
222 .Times(n: 2)
223 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client0))))
224 .WillOnce(once_action: Return(value: ByMove(x: AdbClientUP(adb_client1))));
225
226 EXPECT_TRUE(
227 GetFile(FileSpec("/data/data/com.example.app/lib-main/libtest.so"),
228 FileSpec())
229 .Success());
230}
231

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