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 | |
16 | using namespace lldb; |
17 | using namespace lldb_private; |
18 | using namespace lldb_private::platform_android; |
19 | using namespace testing; |
20 | |
21 | namespace { |
22 | |
23 | class MockSyncService : public AdbClient::SyncService { |
24 | public: |
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 | |
33 | typedef std::unique_ptr<AdbClient::SyncService> SyncServiceUP; |
34 | |
35 | class MockAdbClient : public AdbClient { |
36 | public: |
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 | |
45 | class PlatformAndroidTest : public PlatformAndroid, public ::testing::Test { |
46 | public: |
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 | |
57 | TEST_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 | |
73 | TEST_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 | |
96 | TEST_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 | |
117 | TEST_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 | |
143 | TEST_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 | |
164 | TEST_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 | |
196 | TEST_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 | |