1 /* 2 * Copyright (C) 2013 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 17 #include "ziparchive/zip_archive.h" 18 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <getopt.h> 22 #include <stdio.h> 23 #include <unistd.h> 24 #include <vector> 25 26 #include <base/file.h> 27 #include <gtest/gtest.h> 28 29 static std::string test_data_dir; 30 31 static const std::string kMissingZip = "missing.zip"; 32 static const std::string kValidZip = "valid.zip"; 33 34 static const uint8_t kATxtContents[] = { 35 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 36 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 37 '\n' 38 }; 39 40 static const uint8_t kBTxtContents[] = { 41 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 42 '\n' 43 }; 44 45 static const uint16_t kATxtNameLength = 5; 46 static const uint16_t kBTxtNameLength = 5; 47 static const uint16_t kNonexistentTxtNameLength = 15; 48 static const uint16_t kEmptyTxtNameLength = 9; 49 50 static const uint8_t kATxtName[kATxtNameLength] = { 51 'a', '.', 't', 'x', 't' 52 }; 53 54 static const uint8_t kBTxtName[kBTxtNameLength] = { 55 'b', '.', 't', 'x', 't' 56 }; 57 58 static const uint8_t kNonexistentTxtName[kNonexistentTxtNameLength] = { 59 'n', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 't', 'x' ,'t' 60 }; 61 62 static const uint8_t kEmptyTxtName[kEmptyTxtNameLength] = { 63 'e', 'm', 'p', 't', 'y', '.', 't', 'x', 't' 64 }; 65 66 static int32_t OpenArchiveWrapper(const std::string& name, 67 ZipArchiveHandle* handle) { 68 const std::string abs_path = test_data_dir + "/" + name; 69 return OpenArchive(abs_path.c_str(), handle); 70 } 71 72 static void AssertNameEquals(const std::string& name_str, 73 const ZipEntryName& name) { 74 ASSERT_EQ(name_str.size(), name.name_length); 75 ASSERT_EQ(0, memcmp(name_str.c_str(), name.name, name.name_length)); 76 } 77 78 TEST(ziparchive, Open) { 79 ZipArchiveHandle handle; 80 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); 81 82 CloseArchive(handle); 83 } 84 85 TEST(ziparchive, OpenMissing) { 86 ZipArchiveHandle handle; 87 ASSERT_NE(0, OpenArchiveWrapper(kMissingZip, &handle)); 88 89 // Confirm the file descriptor is not going to be mistaken for a valid one. 90 ASSERT_EQ(-1, GetFileDescriptor(handle)); 91 } 92 93 TEST(ziparchive, OpenAssumeFdOwnership) { 94 int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY); 95 ASSERT_NE(-1, fd); 96 ZipArchiveHandle handle; 97 ASSERT_EQ(0, OpenArchiveFd(fd, "OpenWithAssumeFdOwnership", &handle)); 98 CloseArchive(handle); 99 ASSERT_EQ(-1, lseek(fd, 0, SEEK_SET)); 100 ASSERT_EQ(EBADF, errno); 101 } 102 103 TEST(ziparchive, OpenDoNotAssumeFdOwnership) { 104 int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY); 105 ASSERT_NE(-1, fd); 106 ZipArchiveHandle handle; 107 ASSERT_EQ(0, OpenArchiveFd(fd, "OpenWithAssumeFdOwnership", &handle, false)); 108 CloseArchive(handle); 109 ASSERT_EQ(0, lseek(fd, 0, SEEK_SET)); 110 close(fd); 111 } 112 113 TEST(ziparchive, Iteration) { 114 ZipArchiveHandle handle; 115 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); 116 117 void* iteration_cookie; 118 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL, NULL)); 119 120 ZipEntry data; 121 ZipEntryName name; 122 123 // b/c.txt 124 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 125 AssertNameEquals("b/c.txt", name); 126 127 // b/d.txt 128 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 129 AssertNameEquals("b/d.txt", name); 130 131 // a.txt 132 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 133 AssertNameEquals("a.txt", name); 134 135 // b.txt 136 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 137 AssertNameEquals("b.txt", name); 138 139 // b/ 140 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 141 AssertNameEquals("b/", name); 142 143 // End of iteration. 144 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name)); 145 146 CloseArchive(handle); 147 } 148 149 TEST(ziparchive, IterationWithPrefix) { 150 ZipArchiveHandle handle; 151 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); 152 153 void* iteration_cookie; 154 ZipEntryName prefix("b/"); 155 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, &prefix, NULL)); 156 157 ZipEntry data; 158 ZipEntryName name; 159 160 // b/c.txt 161 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 162 AssertNameEquals("b/c.txt", name); 163 164 // b/d.txt 165 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 166 AssertNameEquals("b/d.txt", name); 167 168 // b/ 169 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 170 AssertNameEquals("b/", name); 171 172 // End of iteration. 173 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name)); 174 175 CloseArchive(handle); 176 } 177 178 TEST(ziparchive, IterationWithSuffix) { 179 ZipArchiveHandle handle; 180 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); 181 182 void* iteration_cookie; 183 ZipEntryName suffix(".txt"); 184 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL, &suffix)); 185 186 ZipEntry data; 187 ZipEntryName name; 188 189 // b/c.txt 190 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 191 AssertNameEquals("b/c.txt", name); 192 193 // b/d.txt 194 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 195 AssertNameEquals("b/d.txt", name); 196 197 // a.txt 198 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 199 AssertNameEquals("a.txt", name); 200 201 // b.txt 202 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 203 AssertNameEquals("b.txt", name); 204 205 // End of iteration. 206 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name)); 207 208 CloseArchive(handle); 209 } 210 211 TEST(ziparchive, IterationWithPrefixAndSuffix) { 212 ZipArchiveHandle handle; 213 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); 214 215 void* iteration_cookie; 216 ZipEntryName prefix("b"); 217 ZipEntryName suffix(".txt"); 218 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, &prefix, &suffix)); 219 220 ZipEntry data; 221 ZipEntryName name; 222 223 // b/c.txt 224 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 225 AssertNameEquals("b/c.txt", name); 226 227 // b/d.txt 228 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 229 AssertNameEquals("b/d.txt", name); 230 231 // b.txt 232 ASSERT_EQ(0, Next(iteration_cookie, &data, &name)); 233 AssertNameEquals("b.txt", name); 234 235 // End of iteration. 236 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name)); 237 238 CloseArchive(handle); 239 } 240 241 TEST(ziparchive, IterationWithBadPrefixAndSuffix) { 242 ZipArchiveHandle handle; 243 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); 244 245 void* iteration_cookie; 246 ZipEntryName prefix("x"); 247 ZipEntryName suffix("y"); 248 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, &prefix, &suffix)); 249 250 ZipEntry data; 251 ZipEntryName name; 252 253 // End of iteration. 254 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name)); 255 256 CloseArchive(handle); 257 } 258 259 TEST(ziparchive, FindEntry) { 260 ZipArchiveHandle handle; 261 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); 262 263 ZipEntry data; 264 ZipEntryName name; 265 name.name = kATxtName; 266 name.name_length = kATxtNameLength; 267 ASSERT_EQ(0, FindEntry(handle, name, &data)); 268 269 // Known facts about a.txt, from zipinfo -v. 270 ASSERT_EQ(63, data.offset); 271 ASSERT_EQ(kCompressDeflated, data.method); 272 ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length); 273 ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length); 274 ASSERT_EQ(0x950821c5, data.crc32); 275 276 // An entry that doesn't exist. Should be a negative return code. 277 ZipEntryName absent_name; 278 absent_name.name = kNonexistentTxtName; 279 absent_name.name_length = kNonexistentTxtNameLength; 280 ASSERT_LT(FindEntry(handle, absent_name, &data), 0); 281 282 CloseArchive(handle); 283 } 284 285 TEST(ziparchive, TestInvalidDeclaredLength) { 286 ZipArchiveHandle handle; 287 ASSERT_EQ(0, OpenArchiveWrapper("declaredlength.zip", &handle)); 288 289 void* iteration_cookie; 290 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL)); 291 292 ZipEntryName name; 293 ZipEntry data; 294 295 ASSERT_EQ(Next(iteration_cookie, &data, &name), 0); 296 ASSERT_EQ(Next(iteration_cookie, &data, &name), 0); 297 298 CloseArchive(handle); 299 } 300 301 TEST(ziparchive, ExtractToMemory) { 302 ZipArchiveHandle handle; 303 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); 304 305 // An entry that's deflated. 306 ZipEntry data; 307 ZipEntryName a_name; 308 a_name.name = kATxtName; 309 a_name.name_length = kATxtNameLength; 310 ASSERT_EQ(0, FindEntry(handle, a_name, &data)); 311 const uint32_t a_size = data.uncompressed_length; 312 ASSERT_EQ(a_size, sizeof(kATxtContents)); 313 uint8_t* buffer = new uint8_t[a_size]; 314 ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, a_size)); 315 ASSERT_EQ(0, memcmp(buffer, kATxtContents, a_size)); 316 delete[] buffer; 317 318 // An entry that's stored. 319 ZipEntryName b_name; 320 b_name.name = kBTxtName; 321 b_name.name_length = kBTxtNameLength; 322 ASSERT_EQ(0, FindEntry(handle, b_name, &data)); 323 const uint32_t b_size = data.uncompressed_length; 324 ASSERT_EQ(b_size, sizeof(kBTxtContents)); 325 buffer = new uint8_t[b_size]; 326 ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, b_size)); 327 ASSERT_EQ(0, memcmp(buffer, kBTxtContents, b_size)); 328 delete[] buffer; 329 330 CloseArchive(handle); 331 } 332 333 static const uint32_t kEmptyEntriesZip[] = { 334 0x04034b50, 0x0000000a, 0x63600000, 0x00004438, 0x00000000, 0x00000000, 335 0x00090000, 0x6d65001c, 0x2e797470, 0x55747874, 0x03000954, 0x52e25c13, 336 0x52e25c24, 0x000b7875, 0x42890401, 0x88040000, 0x50000013, 0x1e02014b, 337 0x00000a03, 0x60000000, 0x00443863, 0x00000000, 0x00000000, 0x09000000, 338 0x00001800, 0x00000000, 0xa0000000, 0x00000081, 0x706d6500, 0x742e7974, 339 0x54557478, 0x13030005, 0x7552e25c, 0x01000b78, 0x00428904, 0x13880400, 340 0x4b500000, 0x00000605, 0x00010000, 0x004f0001, 0x00430000, 0x00000000 }; 341 342 // This is a zip file containing a single entry (ab.txt) that contains 343 // 90072 repetitions of the string "ab\n" and has an uncompressed length 344 // of 270216 bytes. 345 static const uint16_t kAbZip[] = { 346 0x4b50, 0x0403, 0x0014, 0x0000, 0x0008, 0x51d2, 0x4698, 0xc4b0, 347 0x2cda, 0x011b, 0x0000, 0x1f88, 0x0004, 0x0006, 0x001c, 0x6261, 348 0x742e, 0x7478, 0x5455, 0x0009, 0x7c03, 0x3a09, 0x7c55, 0x3a09, 349 0x7555, 0x0b78, 0x0100, 0x8904, 0x0042, 0x0400, 0x1388, 0x0000, 350 0xc2ed, 0x0d31, 0x0000, 0x030c, 0x7fa0, 0x3b2e, 0x22ff, 0xa2aa, 351 0x841f, 0x45fc, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 352 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 353 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 354 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 355 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 356 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 357 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 358 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 359 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 360 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 361 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 362 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 363 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 364 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 365 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 366 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 367 0x5555, 0x5555, 0x5555, 0x5555, 0xdd55, 0x502c, 0x014b, 0x1e02, 368 0x1403, 0x0000, 0x0800, 0xd200, 0x9851, 0xb046, 0xdac4, 0x1b2c, 369 0x0001, 0x8800, 0x041f, 0x0600, 0x1800, 0x0000, 0x0000, 0x0100, 370 0x0000, 0xa000, 0x0081, 0x0000, 0x6100, 0x2e62, 0x7874, 0x5574, 371 0x0554, 0x0300, 0x097c, 0x553a, 0x7875, 0x000b, 0x0401, 0x4289, 372 0x0000, 0x8804, 0x0013, 0x5000, 0x054b, 0x0006, 0x0000, 0x0100, 373 0x0100, 0x4c00, 0x0000, 0x5b00, 0x0001, 0x0000, 0x0000 374 }; 375 376 static const uint8_t kAbTxtName[] = { 'a', 'b', '.', 't', 'x', 't' }; 377 static const uint16_t kAbTxtNameLength = sizeof(kAbTxtName); 378 static const size_t kAbUncompressedSize = 270216; 379 380 static int make_temporary_file(const char* file_name_pattern) { 381 char full_path[1024]; 382 // Account for differences between the host and the target. 383 // 384 // TODO: Maybe reuse bionic/tests/TemporaryFile.h. 385 snprintf(full_path, sizeof(full_path), "/data/local/tmp/%s", file_name_pattern); 386 int fd = mkstemp(full_path); 387 if (fd == -1) { 388 snprintf(full_path, sizeof(full_path), "/tmp/%s", file_name_pattern); 389 fd = mkstemp(full_path); 390 } 391 392 return fd; 393 } 394 395 TEST(ziparchive, EmptyEntries) { 396 char temp_file_pattern[] = "empty_entries_test_XXXXXX"; 397 int fd = make_temporary_file(temp_file_pattern); 398 ASSERT_NE(-1, fd); 399 const ssize_t file_size = sizeof(kEmptyEntriesZip); 400 ASSERT_EQ(file_size, TEMP_FAILURE_RETRY(write(fd, kEmptyEntriesZip, file_size))); 401 402 ZipArchiveHandle handle; 403 ASSERT_EQ(0, OpenArchiveFd(fd, "EmptyEntriesTest", &handle)); 404 405 ZipEntry entry; 406 ZipEntryName empty_name; 407 empty_name.name = kEmptyTxtName; 408 empty_name.name_length = kEmptyTxtNameLength; 409 ASSERT_EQ(0, FindEntry(handle, empty_name, &entry)); 410 ASSERT_EQ(static_cast<uint32_t>(0), entry.uncompressed_length); 411 uint8_t buffer[1]; 412 ASSERT_EQ(0, ExtractToMemory(handle, &entry, buffer, 1)); 413 414 char output_file_pattern[] = "empty_entries_output_XXXXXX"; 415 int output_fd = make_temporary_file(output_file_pattern); 416 ASSERT_NE(-1, output_fd); 417 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, output_fd)); 418 419 struct stat stat_buf; 420 ASSERT_EQ(0, fstat(output_fd, &stat_buf)); 421 ASSERT_EQ(0, stat_buf.st_size); 422 423 close(fd); 424 close(output_fd); 425 } 426 427 TEST(ziparchive, EntryLargerThan32K) { 428 char temp_file_pattern[] = "entry_larger_than_32k_test_XXXXXX"; 429 int fd = make_temporary_file(temp_file_pattern); 430 ASSERT_NE(-1, fd); 431 ASSERT_TRUE(android::base::WriteFully(fd, reinterpret_cast<const uint8_t*>(kAbZip), 432 sizeof(kAbZip) - 1)); 433 ZipArchiveHandle handle; 434 ASSERT_EQ(0, OpenArchiveFd(fd, "EntryLargerThan32KTest", &handle)); 435 436 ZipEntry entry; 437 ZipEntryName ab_name; 438 ab_name.name = kAbTxtName; 439 ab_name.name_length = kAbTxtNameLength; 440 ASSERT_EQ(0, FindEntry(handle, ab_name, &entry)); 441 ASSERT_EQ(kAbUncompressedSize, entry.uncompressed_length); 442 443 // Extract the entry to memory. 444 std::vector<uint8_t> buffer(kAbUncompressedSize); 445 ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], buffer.size())); 446 447 // Extract the entry to a file. 448 char output_file_pattern[] = "entry_larger_than_32k_test_output_XXXXXX"; 449 int output_fd = make_temporary_file(output_file_pattern); 450 ASSERT_NE(-1, output_fd); 451 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, output_fd)); 452 453 // Make sure the extracted file size is as expected. 454 struct stat stat_buf; 455 ASSERT_EQ(0, fstat(output_fd, &stat_buf)); 456 ASSERT_EQ(kAbUncompressedSize, static_cast<size_t>(stat_buf.st_size)); 457 458 // Read the file back to a buffer and make sure the contents are 459 // the same as the memory buffer we extracted directly to. 460 std::vector<uint8_t> file_contents(kAbUncompressedSize); 461 ASSERT_EQ(0, lseek64(output_fd, 0, SEEK_SET)); 462 ASSERT_TRUE(android::base::ReadFully(output_fd, &file_contents[0], file_contents.size())); 463 ASSERT_EQ(file_contents, buffer); 464 465 for (int i = 0; i < 90072; ++i) { 466 const uint8_t* line = &file_contents[0] + (3 * i); 467 ASSERT_EQ('a', line[0]); 468 ASSERT_EQ('b', line[1]); 469 ASSERT_EQ('\n', line[2]); 470 } 471 472 close(fd); 473 close(output_fd); 474 } 475 476 TEST(ziparchive, TrailerAfterEOCD) { 477 char temp_file_pattern[] = "trailer_after_eocd_test_XXXXXX"; 478 int fd = make_temporary_file(temp_file_pattern); 479 ASSERT_NE(-1, fd); 480 481 // Create a file with 8 bytes of random garbage. 482 static const uint8_t trailer[] = { 'A' ,'n', 'd', 'r', 'o', 'i', 'd', 'z' }; 483 const ssize_t file_size = sizeof(kEmptyEntriesZip); 484 const ssize_t trailer_size = sizeof(trailer); 485 ASSERT_EQ(file_size, TEMP_FAILURE_RETRY(write(fd, kEmptyEntriesZip, file_size))); 486 ASSERT_EQ(trailer_size, TEMP_FAILURE_RETRY(write(fd, trailer, trailer_size))); 487 488 ZipArchiveHandle handle; 489 ASSERT_GT(0, OpenArchiveFd(fd, "EmptyEntriesTest", &handle)); 490 } 491 492 TEST(ziparchive, ExtractToFile) { 493 char kTempFilePattern[] = "zip_archive_input_XXXXXX"; 494 int fd = make_temporary_file(kTempFilePattern); 495 ASSERT_NE(-1, fd); 496 const uint8_t data[8] = { '1', '2', '3', '4', '5', '6', '7', '8' }; 497 const ssize_t data_size = sizeof(data); 498 499 ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(write(fd, data, data_size))); 500 501 ZipArchiveHandle handle; 502 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); 503 504 ZipEntry entry; 505 ZipEntryName name; 506 name.name = kATxtName; 507 name.name_length = kATxtNameLength; 508 ASSERT_EQ(0, FindEntry(handle, name, &entry)); 509 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, fd)); 510 511 512 // Assert that the first 8 bytes of the file haven't been clobbered. 513 uint8_t read_buffer[data_size]; 514 ASSERT_EQ(0, lseek64(fd, 0, SEEK_SET)); 515 ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(read(fd, read_buffer, data_size))); 516 ASSERT_EQ(0, memcmp(read_buffer, data, data_size)); 517 518 // Assert that the remainder of the file contains the incompressed data. 519 std::vector<uint8_t> uncompressed_data(entry.uncompressed_length); 520 ASSERT_EQ(static_cast<ssize_t>(entry.uncompressed_length), 521 TEMP_FAILURE_RETRY( 522 read(fd, &uncompressed_data[0], entry.uncompressed_length))); 523 ASSERT_EQ(0, memcmp(&uncompressed_data[0], kATxtContents, 524 sizeof(kATxtContents))); 525 526 // Assert that the total length of the file is sane 527 ASSERT_EQ(data_size + static_cast<ssize_t>(sizeof(kATxtContents)), 528 lseek64(fd, 0, SEEK_END)); 529 530 close(fd); 531 } 532 533 int main(int argc, char** argv) { 534 ::testing::InitGoogleTest(&argc, argv); 535 536 static struct option options[] = { 537 { "test_data_dir", required_argument, NULL, 't' }, 538 { NULL, 0, NULL, 0 } 539 }; 540 541 while (true) { 542 int option_index; 543 const int c = getopt_long_only(argc, argv, "", options, &option_index); 544 if (c == -1) { 545 break; 546 } 547 548 if (c == 't') { 549 test_data_dir = optarg; 550 } 551 } 552 553 if (test_data_dir.size() == 0) { 554 printf("Test data flag (--test_data_dir) required\n\n"); 555 return -1; 556 } 557 558 if (test_data_dir[0] != '/') { 559 printf("Test data must be an absolute path, was %s\n\n", 560 test_data_dir.c_str()); 561 return -2; 562 } 563 564 return RUN_ALL_TESTS(); 565 } 566