1/* 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> 23#include <random> 24#include <string> 25#include <unistd.h> 26#include <utils/Log.h> 27 28#include "MtpFfsHandle.h" 29 30namespace android { 31 32constexpr int MAX_FILE_CHUNK_SIZE = 3 * 1024 * 1024; 33 34constexpr int TEST_PACKET_SIZE = 512; 35constexpr 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" 46 "r implied.\n * Se"; 47 48/** 49 * Functional tests for the MtpFfsHandle class. Ensures header and data integrity 50 * by mocking ffs endpoints as pipes to capture input / output. 51 */ 52class MtpFfsHandleTest : public ::testing::Test { 53protected: 54 std::unique_ptr<IMtpHandle> handle; 55 56 // Pipes for reading endpoint data 57 android::base::unique_fd bulk_in; 58 android::base::unique_fd bulk_out; 59 android::base::unique_fd intr; 60 61 TemporaryFile dummy_file; 62 63 MtpFfsHandleTest() { 64 int fd[2]; 65 handle = std::unique_ptr<IMtpHandle>(get_ffs_handle()); 66 MtpFfsHandle *ffs_handle = static_cast<MtpFfsHandle*>(handle.get()); 67 EXPECT_TRUE(ffs_handle != NULL); 68 69 EXPECT_EQ(pipe(fd), 0); 70 EXPECT_EQ(fcntl(fd[0], F_SETPIPE_SZ, 1048576), 1048576); 71 bulk_in.reset(fd[0]); 72 ffs_handle->mBulkIn.reset(fd[1]); 73 74 EXPECT_EQ(pipe(fd), 0); 75 EXPECT_EQ(fcntl(fd[0], F_SETPIPE_SZ, 1048576), 1048576); 76 bulk_out.reset(fd[1]); 77 ffs_handle->mBulkOut.reset(fd[0]); 78 79 EXPECT_EQ(pipe(fd), 0); 80 intr.reset(fd[0]); 81 ffs_handle->mIntr.reset(fd[1]); 82 83 ffs_handle->mBuffer1.resize(MAX_FILE_CHUNK_SIZE); 84 ffs_handle->mBuffer2.resize(MAX_FILE_CHUNK_SIZE); 85 } 86 87 ~MtpFfsHandleTest() {} 88}; 89 90TEST_F(MtpFfsHandleTest, testRead) { 91 EXPECT_EQ(write(bulk_out, dummyDataStr.c_str(), TEST_PACKET_SIZE), TEST_PACKET_SIZE); 92 char buf[TEST_PACKET_SIZE + 1]; 93 buf[TEST_PACKET_SIZE] = '\0'; 94 EXPECT_EQ(handle->read(buf, TEST_PACKET_SIZE), TEST_PACKET_SIZE); 95 EXPECT_STREQ(buf, dummyDataStr.c_str()); 96} 97 98TEST_F(MtpFfsHandleTest, testWrite) { 99 char buf[TEST_PACKET_SIZE + 1]; 100 buf[TEST_PACKET_SIZE] = '\0'; 101 EXPECT_EQ(handle->write(dummyDataStr.c_str(), TEST_PACKET_SIZE), TEST_PACKET_SIZE); 102 EXPECT_EQ(read(bulk_in, buf, TEST_PACKET_SIZE), TEST_PACKET_SIZE); 103 EXPECT_STREQ(buf, dummyDataStr.c_str()); 104} 105 106TEST_F(MtpFfsHandleTest, testReceiveFileSmall) { 107 std::stringstream ss; 108 mtp_file_range mfr; 109 int size = TEST_PACKET_SIZE * SMALL_MULT; 110 char buf[size + 1]; 111 buf[size] = '\0'; 112 113 mfr.length = size; 114 mfr.fd = dummy_file.fd; 115 for (int i = 0; i < SMALL_MULT; i++) 116 ss << dummyDataStr; 117 118 EXPECT_EQ(write(bulk_out, ss.str().c_str(), size), size); 119 EXPECT_EQ(handle->receiveFile(mfr, false), 0); 120 121 EXPECT_EQ(read(dummy_file.fd, buf, size), size); 122 123 EXPECT_STREQ(buf, ss.str().c_str()); 124} 125 126TEST_F(MtpFfsHandleTest, testReceiveFileMed) { 127 std::stringstream ss; 128 mtp_file_range mfr; 129 int size = TEST_PACKET_SIZE * MED_MULT; 130 char buf[size + 1]; 131 buf[size] = '\0'; 132 133 mfr.length = size; 134 mfr.fd = dummy_file.fd; 135 for (int i = 0; i < MED_MULT; i++) 136 ss << dummyDataStr; 137 138 EXPECT_EQ(write(bulk_out, ss.str().c_str(), size), size); 139 EXPECT_EQ(handle->receiveFile(mfr, false), 0); 140 141 EXPECT_EQ(read(dummy_file.fd, buf, size), size); 142 143 EXPECT_STREQ(buf, ss.str().c_str()); 144} 145 146TEST_F(MtpFfsHandleTest, testSendFileSmall) { 147 std::stringstream ss; 148 mtp_file_range mfr; 149 mfr.command = 42; 150 mfr.transaction_id = 1337; 151 mfr.offset = 0; 152 int size = TEST_PACKET_SIZE * SMALL_MULT; 153 char buf[size + sizeof(mtp_data_header) + 1]; 154 buf[size + sizeof(mtp_data_header)] = '\0'; 155 156 mfr.length = size; 157 mfr.fd = dummy_file.fd; 158 for (int i = 0; i < SMALL_MULT; i++) 159 ss << dummyDataStr; 160 161 EXPECT_EQ(write(dummy_file.fd, ss.str().c_str(), size), size); 162 EXPECT_EQ(handle->sendFile(mfr), 0); 163 164 EXPECT_EQ(read(bulk_in, buf, size + sizeof(mtp_data_header)), 165 static_cast<long>(size + sizeof(mtp_data_header))); 166 167 struct mtp_data_header *header = reinterpret_cast<struct mtp_data_header*>(buf); 168 EXPECT_STREQ(buf + sizeof(mtp_data_header), ss.str().c_str()); 169 EXPECT_EQ(header->length, static_cast<unsigned int>(size + sizeof(mtp_data_header))); 170 EXPECT_EQ(header->type, static_cast<unsigned int>(2)); 171 EXPECT_EQ(header->command, static_cast<unsigned int>(42)); 172 EXPECT_EQ(header->transaction_id, static_cast<unsigned int>(1337)); 173} 174 175TEST_F(MtpFfsHandleTest, testSendFileMed) { 176 std::stringstream ss; 177 mtp_file_range mfr; 178 mfr.command = 42; 179 mfr.transaction_id = 1337; 180 mfr.offset = 0; 181 int size = TEST_PACKET_SIZE * MED_MULT; 182 char buf[size + sizeof(mtp_data_header) + 1]; 183 buf[size + sizeof(mtp_data_header)] = '\0'; 184 185 mfr.length = size; 186 mfr.fd = dummy_file.fd; 187 for (int i = 0; i < MED_MULT; i++) 188 ss << dummyDataStr; 189 190 EXPECT_EQ(write(dummy_file.fd, ss.str().c_str(), size), size); 191 EXPECT_EQ(handle->sendFile(mfr), 0); 192 193 EXPECT_EQ(read(bulk_in, buf, size + sizeof(mtp_data_header)), 194 static_cast<long>(size + sizeof(mtp_data_header))); 195 196 struct mtp_data_header *header = reinterpret_cast<struct mtp_data_header*>(buf); 197 EXPECT_STREQ(buf + sizeof(mtp_data_header), ss.str().c_str()); 198 EXPECT_EQ(header->length, static_cast<unsigned int>(size + sizeof(mtp_data_header))); 199 EXPECT_EQ(header->type, static_cast<unsigned int>(2)); 200 EXPECT_EQ(header->command, static_cast<unsigned int>(42)); 201 EXPECT_EQ(header->transaction_id, static_cast<unsigned int>(1337)); 202} 203 204TEST_F(MtpFfsHandleTest, testSendFileMedPartial) { 205 std::stringstream ss; 206 mtp_file_range mfr; 207 mfr.fd = dummy_file.fd; 208 mfr.command = 42; 209 mfr.transaction_id = 1337; 210 int size = TEST_PACKET_SIZE * MED_MULT; 211 char buf[size + 1]; 212 buf[size] = '\0'; 213 214 for (int i = 0; i < MED_MULT; i++) 215 ss << dummyDataStr; 216 217 EXPECT_EQ(write(dummy_file.fd, ss.str().c_str(), size), size); 218 219 std::random_device rd; 220 std::mt19937 gen(rd()); 221 std::uniform_int_distribution<> dis(1, TEST_PACKET_SIZE); 222 int offset = 0; 223 while (offset != size) { 224 mfr.offset = offset; 225 int length = std::min(size - offset, dis(gen)); 226 mfr.length = length; 227 char temp_buf[length + sizeof(mtp_data_header)]; 228 EXPECT_EQ(handle->sendFile(mfr), 0); 229 230 EXPECT_EQ(read(bulk_in, temp_buf, length + sizeof(mtp_data_header)), 231 static_cast<long>(length + sizeof(mtp_data_header))); 232 233 struct mtp_data_header *header = reinterpret_cast<struct mtp_data_header*>(temp_buf); 234 EXPECT_EQ(header->length, static_cast<unsigned int>(length + sizeof(mtp_data_header))); 235 EXPECT_EQ(header->type, static_cast<unsigned int>(2)); 236 EXPECT_EQ(header->command, static_cast<unsigned int>(42)); 237 EXPECT_EQ(header->transaction_id, static_cast<unsigned int>(1337)); 238 memcpy(buf + offset, temp_buf + sizeof(mtp_data_header), length); 239 offset += length; 240 } 241 EXPECT_STREQ(buf, ss.str().c_str()); 242} 243 244TEST_F(MtpFfsHandleTest, testSendFileEmpty) { 245 mtp_file_range mfr; 246 mfr.command = 42; 247 mfr.transaction_id = 1337; 248 mfr.offset = 0; 249 int size = 0; 250 char buf[size + sizeof(mtp_data_header) + 1]; 251 buf[size + sizeof(mtp_data_header)] = '\0'; 252 253 mfr.length = size; 254 mfr.fd = dummy_file.fd; 255 256 EXPECT_EQ(handle->sendFile(mfr), 0); 257 258 EXPECT_EQ(read(bulk_in, buf, size + sizeof(mtp_data_header)), 259 static_cast<long>(size + sizeof(mtp_data_header))); 260 261 struct mtp_data_header *header = reinterpret_cast<struct mtp_data_header*>(buf); 262 EXPECT_EQ(header->length, static_cast<unsigned int>(size + sizeof(mtp_data_header))); 263 EXPECT_EQ(header->type, static_cast<unsigned int>(2)); 264 EXPECT_EQ(header->command, static_cast<unsigned int>(42)); 265 EXPECT_EQ(header->transaction_id, static_cast<unsigned int>(1337)); 266} 267 268TEST_F(MtpFfsHandleTest, testSendEvent) { 269 struct mtp_event event; 270 event.length = TEST_PACKET_SIZE; 271 event.data = const_cast<char*>(dummyDataStr.c_str()); 272 char buf[TEST_PACKET_SIZE + 1]; 273 buf[TEST_PACKET_SIZE] = '\0'; 274 275 handle->sendEvent(event); 276 read(intr, buf, TEST_PACKET_SIZE); 277 EXPECT_STREQ(buf, dummyDataStr.c_str()); 278} 279 280} // namespace android 281