blob: 9c916b7a97876cc114dae03a07db1b989f32e52e [file] [log] [blame]
Jerry Zhang487be612016-10-24 12:10:41 -07001/*
2 * Copyright 2016 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#define LOG_TAG "MtpFfsHandle_test.cpp"
17
18#include <android-base/unique_fd.h>
19#include <android-base/test_utils.h>
20#include <fcntl.h>
21#include <gtest/gtest.h>
22#include <memory>
Jerry Zhang8542fee2017-02-06 15:12:17 -080023#include <random>
Jerry Zhang487be612016-10-24 12:10:41 -070024#include <string>
25#include <unistd.h>
26#include <utils/Log.h>
27
Jerry Zhang69b74502017-10-02 16:26:37 -070028#include "MtpDescriptors.h"
Jerry Zhang487be612016-10-24 12:10:41 -070029#include "MtpFfsHandle.h"
Jerry Zhangdf69dd32017-05-03 17:17:49 -070030#include "MtpFfsCompatHandle.h"
Jerry Zhang487be612016-10-24 12:10:41 -070031
32namespace android {
33
Jerry Zhangdf69dd32017-05-03 17:17:49 -070034constexpr int TEST_PACKET_SIZE = 500;
Jerry Zhang487be612016-10-24 12:10:41 -070035constexpr int SMALL_MULT = 30;
36constexpr int MED_MULT = 510;
37
38static const std::string dummyDataStr =
39 "/*\n * Copyright 2015 The Android Open Source Project\n *\n * Licensed un"
40 "der the Apache License, Version 2.0 (the \"License\");\n * you may not us"
41 "e this file except in compliance with the License.\n * You may obtain a c"
42 "opy of the License at\n *\n * http://www.apache.org/licenses/LICENSE"
43 "-2.0\n *\n * Unless required by applicable law or agreed to in writing, s"
44 "oftware\n * distributed under the License is distributed on an \"AS IS\" "
45 "BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express o"
Jerry Zhangdf69dd32017-05-03 17:17:49 -070046 "r im";
Jerry Zhang487be612016-10-24 12:10:41 -070047
Jerry Zhang8542fee2017-02-06 15:12:17 -080048/**
49 * Functional tests for the MtpFfsHandle class. Ensures header and data integrity
50 * by mocking ffs endpoints as pipes to capture input / output.
51 */
Jerry Zhangdf69dd32017-05-03 17:17:49 -070052template <class T>
Jerry Zhang487be612016-10-24 12:10:41 -070053class MtpFfsHandleTest : public ::testing::Test {
54protected:
Jerry Zhangdf69dd32017-05-03 17:17:49 -070055 std::unique_ptr<MtpFfsHandle> handle;
Jerry Zhang487be612016-10-24 12:10:41 -070056
57 // Pipes for reading endpoint data
Jerry Zhangdf69dd32017-05-03 17:17:49 -070058 android::base::unique_fd control;
Jerry Zhang487be612016-10-24 12:10:41 -070059 android::base::unique_fd bulk_in;
60 android::base::unique_fd bulk_out;
61 android::base::unique_fd intr;
62
63 TemporaryFile dummy_file;
64
65 MtpFfsHandleTest() {
66 int fd[2];
Jerry Zhangdf69dd32017-05-03 17:17:49 -070067 handle = std::make_unique<T>();
68
69 EXPECT_EQ(pipe(fd), 0);
Jerry Zhang69b74502017-10-02 16:26:37 -070070 control.reset(fd[0]);
71 handle->mControl.reset(fd[1]);
Jerry Zhang487be612016-10-24 12:10:41 -070072
73 EXPECT_EQ(pipe(fd), 0);
74 EXPECT_EQ(fcntl(fd[0], F_SETPIPE_SZ, 1048576), 1048576);
75 bulk_in.reset(fd[0]);
Jerry Zhangdf69dd32017-05-03 17:17:49 -070076 handle->mBulkIn.reset(fd[1]);
Jerry Zhang487be612016-10-24 12:10:41 -070077
78 EXPECT_EQ(pipe(fd), 0);
79 EXPECT_EQ(fcntl(fd[0], F_SETPIPE_SZ, 1048576), 1048576);
80 bulk_out.reset(fd[1]);
Jerry Zhangdf69dd32017-05-03 17:17:49 -070081 handle->mBulkOut.reset(fd[0]);
Jerry Zhang487be612016-10-24 12:10:41 -070082
83 EXPECT_EQ(pipe(fd), 0);
84 intr.reset(fd[0]);
Jerry Zhangdf69dd32017-05-03 17:17:49 -070085 handle->mIntr.reset(fd[1]);
Jerry Zhang8542fee2017-02-06 15:12:17 -080086
Jerry Zhang69b74502017-10-02 16:26:37 -070087 EXPECT_EQ(handle->start(), 0);
Jerry Zhang487be612016-10-24 12:10:41 -070088 }
89
Jerry Zhangdf69dd32017-05-03 17:17:49 -070090 ~MtpFfsHandleTest() {
91 handle->close();
92 }
Jerry Zhang487be612016-10-24 12:10:41 -070093};
94
Jerry Zhangdf69dd32017-05-03 17:17:49 -070095typedef ::testing::Types<MtpFfsHandle, MtpFfsCompatHandle> mtpHandles;
96TYPED_TEST_CASE(MtpFfsHandleTest, mtpHandles);
97
Jerry Zhang69b74502017-10-02 16:26:37 -070098TYPED_TEST(MtpFfsHandleTest, testControl) {
99 EXPECT_TRUE(this->handle->writeDescriptors());
100 struct desc_v2 desc;
101 struct functionfs_strings strings;
102 EXPECT_EQ(read(this->control, &desc, sizeof(desc)), (long)sizeof(desc));
103 EXPECT_EQ(read(this->control, &strings, sizeof(strings)), (long)sizeof(strings));
104 EXPECT_TRUE(std::memcmp(&desc, &mtp_desc_v2, sizeof(desc)) == 0);
105 EXPECT_TRUE(std::memcmp(&strings, &mtp_strings, sizeof(strings)) == 0);
106}
107
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700108TYPED_TEST(MtpFfsHandleTest, testRead) {
109 EXPECT_EQ(write(this->bulk_out, dummyDataStr.c_str(), TEST_PACKET_SIZE), TEST_PACKET_SIZE);
Jerry Zhang487be612016-10-24 12:10:41 -0700110 char buf[TEST_PACKET_SIZE + 1];
111 buf[TEST_PACKET_SIZE] = '\0';
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700112 EXPECT_EQ(this->handle->read(buf, TEST_PACKET_SIZE), TEST_PACKET_SIZE);
Jerry Zhang487be612016-10-24 12:10:41 -0700113 EXPECT_STREQ(buf, dummyDataStr.c_str());
114}
115
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700116TYPED_TEST(MtpFfsHandleTest, testWrite) {
Jerry Zhang487be612016-10-24 12:10:41 -0700117 char buf[TEST_PACKET_SIZE + 1];
118 buf[TEST_PACKET_SIZE] = '\0';
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700119 EXPECT_EQ(this->handle->write(dummyDataStr.c_str(), TEST_PACKET_SIZE), TEST_PACKET_SIZE);
120 EXPECT_EQ(read(this->bulk_in, buf, TEST_PACKET_SIZE), TEST_PACKET_SIZE);
Jerry Zhang487be612016-10-24 12:10:41 -0700121 EXPECT_STREQ(buf, dummyDataStr.c_str());
122}
123
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700124TYPED_TEST(MtpFfsHandleTest, testReceiveFileEmpty) {
125 std::stringstream ss;
126 mtp_file_range mfr;
127 int size = 0;
128 char buf[size + 1];
129 buf[size] = '\0';
130
131 mfr.offset = 0;
132 mfr.length = size;
133 mfr.fd = this->dummy_file.fd;
134
135 EXPECT_EQ(write(this->bulk_out, ss.str().c_str(), size), size);
136 EXPECT_EQ(this->handle->receiveFile(mfr, false), 0);
137
138 EXPECT_EQ(read(this->dummy_file.fd, buf, size), size);
139}
140
141TYPED_TEST(MtpFfsHandleTest, testReceiveFileSmall) {
Jerry Zhang487be612016-10-24 12:10:41 -0700142 std::stringstream ss;
143 mtp_file_range mfr;
144 int size = TEST_PACKET_SIZE * SMALL_MULT;
145 char buf[size + 1];
146 buf[size] = '\0';
147
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700148 mfr.offset = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700149 mfr.length = size;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700150 mfr.fd = this->dummy_file.fd;
Jerry Zhang487be612016-10-24 12:10:41 -0700151 for (int i = 0; i < SMALL_MULT; i++)
152 ss << dummyDataStr;
153
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700154 EXPECT_EQ(write(this->bulk_out, ss.str().c_str(), size), size);
155 EXPECT_EQ(this->handle->receiveFile(mfr, false), 0);
Jerry Zhang487be612016-10-24 12:10:41 -0700156
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700157 EXPECT_EQ(read(this->dummy_file.fd, buf, size), size);
Jerry Zhang487be612016-10-24 12:10:41 -0700158
159 EXPECT_STREQ(buf, ss.str().c_str());
160}
161
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700162TYPED_TEST(MtpFfsHandleTest, testReceiveFileMed) {
Jerry Zhang487be612016-10-24 12:10:41 -0700163 std::stringstream ss;
164 mtp_file_range mfr;
165 int size = TEST_PACKET_SIZE * MED_MULT;
166 char buf[size + 1];
167 buf[size] = '\0';
168
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700169 mfr.offset = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700170 mfr.length = size;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700171 mfr.fd = this->dummy_file.fd;
Jerry Zhang487be612016-10-24 12:10:41 -0700172 for (int i = 0; i < MED_MULT; i++)
173 ss << dummyDataStr;
174
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700175 EXPECT_EQ(write(this->bulk_out, ss.str().c_str(), size), size);
176 EXPECT_EQ(this->handle->receiveFile(mfr, false), 0);
Jerry Zhang487be612016-10-24 12:10:41 -0700177
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700178 EXPECT_EQ(read(this->dummy_file.fd, buf, size), size);
Jerry Zhang487be612016-10-24 12:10:41 -0700179
180 EXPECT_STREQ(buf, ss.str().c_str());
181}
182
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700183TYPED_TEST(MtpFfsHandleTest, testReceiveFileMedPartial) {
184 std::stringstream ss;
185 mtp_file_range mfr;
186 int size = TEST_PACKET_SIZE * MED_MULT;
187 char buf[size + 1];
188 buf[size] = '\0';
189
190 mfr.fd = this->dummy_file.fd;
191 for (int i = 0; i < MED_MULT; i++)
192 ss << dummyDataStr;
193
194 EXPECT_EQ(write(this->bulk_out, ss.str().c_str(), size), size);
195
196 std::random_device rd;
197 std::mt19937 gen(rd());
198 std::uniform_int_distribution<> dis(1, TEST_PACKET_SIZE);
199 int offset = 0;
200 while (offset != size) {
201 mfr.offset = offset;
202 int length = std::min(size - offset, dis(gen));
203 mfr.length = length;
204
205 EXPECT_EQ(this->handle->receiveFile(mfr, false), 0);
206 offset += length;
207 }
208
209 EXPECT_EQ(read(this->dummy_file.fd, buf, size), size);
210
211 EXPECT_STREQ(buf, ss.str().c_str());
212}
213
214TYPED_TEST(MtpFfsHandleTest, testSendFileSmall) {
Jerry Zhang487be612016-10-24 12:10:41 -0700215 std::stringstream ss;
216 mtp_file_range mfr;
217 mfr.command = 42;
218 mfr.transaction_id = 1337;
Jerry Zhang8542fee2017-02-06 15:12:17 -0800219 mfr.offset = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700220 int size = TEST_PACKET_SIZE * SMALL_MULT;
221 char buf[size + sizeof(mtp_data_header) + 1];
222 buf[size + sizeof(mtp_data_header)] = '\0';
223
224 mfr.length = size;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700225 mfr.fd = this->dummy_file.fd;
Jerry Zhang487be612016-10-24 12:10:41 -0700226 for (int i = 0; i < SMALL_MULT; i++)
227 ss << dummyDataStr;
228
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700229 EXPECT_EQ(write(this->dummy_file.fd, ss.str().c_str(), size), size);
230 EXPECT_EQ(this->handle->sendFile(mfr), 0);
Jerry Zhang487be612016-10-24 12:10:41 -0700231
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700232 EXPECT_EQ(read(this->bulk_in, buf, size + sizeof(mtp_data_header)),
Jerry Zhang487be612016-10-24 12:10:41 -0700233 static_cast<long>(size + sizeof(mtp_data_header)));
234
235 struct mtp_data_header *header = reinterpret_cast<struct mtp_data_header*>(buf);
236 EXPECT_STREQ(buf + sizeof(mtp_data_header), ss.str().c_str());
237 EXPECT_EQ(header->length, static_cast<unsigned int>(size + sizeof(mtp_data_header)));
238 EXPECT_EQ(header->type, static_cast<unsigned int>(2));
239 EXPECT_EQ(header->command, static_cast<unsigned int>(42));
240 EXPECT_EQ(header->transaction_id, static_cast<unsigned int>(1337));
241}
242
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700243TYPED_TEST(MtpFfsHandleTest, testSendFileMed) {
Jerry Zhang487be612016-10-24 12:10:41 -0700244 std::stringstream ss;
245 mtp_file_range mfr;
246 mfr.command = 42;
247 mfr.transaction_id = 1337;
Jerry Zhang8542fee2017-02-06 15:12:17 -0800248 mfr.offset = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700249 int size = TEST_PACKET_SIZE * MED_MULT;
250 char buf[size + sizeof(mtp_data_header) + 1];
251 buf[size + sizeof(mtp_data_header)] = '\0';
252
253 mfr.length = size;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700254 mfr.fd = this->dummy_file.fd;
Jerry Zhang487be612016-10-24 12:10:41 -0700255 for (int i = 0; i < MED_MULT; i++)
256 ss << dummyDataStr;
257
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700258 EXPECT_EQ(write(this->dummy_file.fd, ss.str().c_str(), size), size);
259 EXPECT_EQ(this->handle->sendFile(mfr), 0);
Jerry Zhang487be612016-10-24 12:10:41 -0700260
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700261 EXPECT_EQ(read(this->bulk_in, buf, size + sizeof(mtp_data_header)),
Jerry Zhang487be612016-10-24 12:10:41 -0700262 static_cast<long>(size + sizeof(mtp_data_header)));
263
264 struct mtp_data_header *header = reinterpret_cast<struct mtp_data_header*>(buf);
265 EXPECT_STREQ(buf + sizeof(mtp_data_header), ss.str().c_str());
266 EXPECT_EQ(header->length, static_cast<unsigned int>(size + sizeof(mtp_data_header)));
267 EXPECT_EQ(header->type, static_cast<unsigned int>(2));
268 EXPECT_EQ(header->command, static_cast<unsigned int>(42));
269 EXPECT_EQ(header->transaction_id, static_cast<unsigned int>(1337));
270}
271
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700272TYPED_TEST(MtpFfsHandleTest, testSendFileMedPartial) {
Jerry Zhang8542fee2017-02-06 15:12:17 -0800273 std::stringstream ss;
274 mtp_file_range mfr;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700275 mfr.fd = this->dummy_file.fd;
Jerry Zhang8542fee2017-02-06 15:12:17 -0800276 mfr.command = 42;
277 mfr.transaction_id = 1337;
278 int size = TEST_PACKET_SIZE * MED_MULT;
279 char buf[size + 1];
280 buf[size] = '\0';
281
282 for (int i = 0; i < MED_MULT; i++)
283 ss << dummyDataStr;
284
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700285 EXPECT_EQ(write(this->dummy_file.fd, ss.str().c_str(), size), size);
Jerry Zhang8542fee2017-02-06 15:12:17 -0800286
287 std::random_device rd;
288 std::mt19937 gen(rd());
289 std::uniform_int_distribution<> dis(1, TEST_PACKET_SIZE);
290 int offset = 0;
291 while (offset != size) {
292 mfr.offset = offset;
293 int length = std::min(size - offset, dis(gen));
294 mfr.length = length;
295 char temp_buf[length + sizeof(mtp_data_header)];
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700296 EXPECT_EQ(this->handle->sendFile(mfr), 0);
Jerry Zhang8542fee2017-02-06 15:12:17 -0800297
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700298 EXPECT_EQ(read(this->bulk_in, temp_buf, length + sizeof(mtp_data_header)),
Jerry Zhang8542fee2017-02-06 15:12:17 -0800299 static_cast<long>(length + sizeof(mtp_data_header)));
300
301 struct mtp_data_header *header = reinterpret_cast<struct mtp_data_header*>(temp_buf);
302 EXPECT_EQ(header->length, static_cast<unsigned int>(length + sizeof(mtp_data_header)));
303 EXPECT_EQ(header->type, static_cast<unsigned int>(2));
304 EXPECT_EQ(header->command, static_cast<unsigned int>(42));
305 EXPECT_EQ(header->transaction_id, static_cast<unsigned int>(1337));
306 memcpy(buf + offset, temp_buf + sizeof(mtp_data_header), length);
307 offset += length;
308 }
309 EXPECT_STREQ(buf, ss.str().c_str());
310}
311
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700312TYPED_TEST(MtpFfsHandleTest, testSendFileEmpty) {
Jerry Zhang8542fee2017-02-06 15:12:17 -0800313 mtp_file_range mfr;
314 mfr.command = 42;
315 mfr.transaction_id = 1337;
316 mfr.offset = 0;
317 int size = 0;
318 char buf[size + sizeof(mtp_data_header) + 1];
319 buf[size + sizeof(mtp_data_header)] = '\0';
320
321 mfr.length = size;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700322 mfr.fd = this->dummy_file.fd;
Jerry Zhang8542fee2017-02-06 15:12:17 -0800323
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700324 EXPECT_EQ(this->handle->sendFile(mfr), 0);
Jerry Zhang8542fee2017-02-06 15:12:17 -0800325
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700326 EXPECT_EQ(read(this->bulk_in, buf, size + sizeof(mtp_data_header)),
Jerry Zhang8542fee2017-02-06 15:12:17 -0800327 static_cast<long>(size + sizeof(mtp_data_header)));
328
329 struct mtp_data_header *header = reinterpret_cast<struct mtp_data_header*>(buf);
330 EXPECT_EQ(header->length, static_cast<unsigned int>(size + sizeof(mtp_data_header)));
331 EXPECT_EQ(header->type, static_cast<unsigned int>(2));
332 EXPECT_EQ(header->command, static_cast<unsigned int>(42));
333 EXPECT_EQ(header->transaction_id, static_cast<unsigned int>(1337));
334}
335
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700336TYPED_TEST(MtpFfsHandleTest, testSendEvent) {
Jerry Zhang487be612016-10-24 12:10:41 -0700337 struct mtp_event event;
338 event.length = TEST_PACKET_SIZE;
339 event.data = const_cast<char*>(dummyDataStr.c_str());
340 char buf[TEST_PACKET_SIZE + 1];
341 buf[TEST_PACKET_SIZE] = '\0';
342
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700343 this->handle->sendEvent(event);
344 read(this->intr, buf, TEST_PACKET_SIZE);
Jerry Zhang487be612016-10-24 12:10:41 -0700345 EXPECT_STREQ(buf, dummyDataStr.c_str());
346}
347
348} // namespace android