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("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 | |
72 | TEST_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 | |
95 | TEST_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 | |
116 | TEST_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 | |
142 | TEST_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 | |
163 | TEST_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 | |
195 | TEST_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 | |