| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2009, Google Inc. | 2 * Copyright 2009, Google Inc. |
| 3 * All rights reserved. | 3 * All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 7 * met: | 7 * met: |
| 8 * | 8 * |
| 9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 const int kUserIDOffset = 108; | 56 const int kUserIDOffset = 108; |
| 57 const int kGroupIDOffset = 116; | 57 const int kGroupIDOffset = 116; |
| 58 const int kFileSizeOffset = 124; | 58 const int kFileSizeOffset = 124; |
| 59 const int kModifyTimeOffset = 136; | 59 const int kModifyTimeOffset = 136; |
| 60 const int kHeaderCheckSumOffset = 148; | 60 const int kHeaderCheckSumOffset = 148; |
| 61 const int kLinkFlagOffset = 156; | 61 const int kLinkFlagOffset = 156; |
| 62 const int kMagicOffset = 257; | 62 const int kMagicOffset = 257; |
| 63 const int kUserNameOffset = 265; | 63 const int kUserNameOffset = 265; |
| 64 const int kGroupNameOffset = 297; | 64 const int kGroupNameOffset = 297; |
| 65 | 65 |
| 66 const char *kLongLink = "././@LongLink"; |
| 66 const char *kDirName1 = "test/apples/"; | 67 const char *kDirName1 = "test/apples/"; |
| 67 const char *kDirName2 = "test/oranges/"; | 68 const char *kDirName2 = "test/oranges/"; |
| 68 const char *kFileName1 = "test/apples/file1"; | 69 const char *kFileName1 = "test/apples/file1"; |
| 69 const char *kFileName2 = "test/apples/file2"; | 70 const char *kFileName2 = "test/apples/file2"; |
| 70 const char *kFileName3 = "test/oranges/file3"; | 71 const char *kFileName3 = "test/oranges/file3"; |
| 72 const char *kFileName4 = |
| 73 "ThisIsAFilenameLongerThen100CharsThisIsAFilenameLongerThen100Chars" |
| 74 "ThisIsAFilenameLongerThen100CharsThisIsAFilenameLongerThen100Chars"; |
| 71 | 75 |
| 72 // The first file is less than one block in size | 76 // The first file is less than one block in size |
| 73 const char *kFileContents1 = | 77 const char *kFileContents1 = |
| 74 "The cellphone is the world’s most ubiquitous computer.\n" | 78 "The cellphone is the world most ubiquitous computer.\n" |
| 75 "The four billion cellphones in use around the globe carry personal\n" | 79 "The four billion cellphones in use around the globe carry personal\n" |
| 76 "information, provide access to the Web and are being used more and more\n" | 80 "information, provide access to the Web and are being used more and more\n" |
| 77 "to navigate the real world. And as cellphones change how we live,\n" | 81 "to navigate the real world. And as cellphones change how we live,\n" |
| 78 "computer scientists say, they are also changing\n" | 82 "computer scientists say, they are also changing\n" |
| 79 "how we think about information\n"; | 83 "how we think about information\n"; |
| 80 | 84 |
| 81 // The 2nd file takes two blocks | 85 // The 2nd file takes two blocks |
| 82 const char *kFileContents2 = | 86 const char *kFileContents2 = |
| 83 "From Hong Kong to eastern Europe to Wall Street, financial gloom was\n" | 87 "From Hong Kong to eastern Europe to Wall Street, financial gloom was\n" |
| 84 "everywhere on Tuesday.\n" | 88 "everywhere on Tuesday.\n" |
| 85 "Stock markets around the world staggered lower. In New York,\n" | 89 "Stock markets around the world staggered lower. In New York,\n" |
| 86 "the Dow fell more than 3 percent, coming within sight of its worst\n" | 90 "the Dow fell more than 3 percent, coming within sight of its worst\n" |
| 87 "levels since the credit crisis erupted. Financial shares were battered.\n" | 91 "levels since the credit crisis erupted. Financial shares were battered.\n" |
| 88 "And rattled investors clamored to buy rainy-day investments like gold\n" | 92 "And rattled investors clamored to buy rainy-day investments like gold\n" |
| 89 "and Treasury debt. It was a global wave of selling spurred by rising\n" | 93 "and Treasury debt. It was a global wave of selling spurred by rising\n" |
| 90 "worries about how banks, automakers — entire countries — would fare\n" | 94 "worries about how banks, automakers entire countries would fare\n" |
| 91 "in a deepening global downturn.\n" | 95 "in a deepening global downturn.\n" |
| 92 "'Nobody believes it’s going get better yet,' said Howard Silverblatt,\n" | 96 "'Nobody believes it&'s going get better yet,' said Howard Silverblatt,\n" |
| 93 "senior index analyst at Standard & Poor’s. 'Do you see that light at\n" | 97 "senior index analyst at Standard & Poors. 'Do you see that light at\n" |
| 94 "the end of the tunnel? Any kind of light? Right now, it’s not there'\n" | 98 "the end of the tunnel? Any kind of light? Right now, it's not there'\n" |
| 95 "yet.\n"; | 99 "yet.\n"; |
| 96 | 100 |
| 97 // The 3rd file takes one block | 101 // The 3rd file takes one block |
| 98 const char *kFileContents3 = "nothing much here...\n"; | 102 const char *kFileContents3 = "nothing much here...\n"; |
| 99 | 103 |
| 100 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 104 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 101 // Receives the tar bytestream from the TarGenerator. | 105 // Receives the tar bytestream from the TarGenerator. |
| 102 // We validate the bytestream as it comes in... | 106 // We validate the bytestream as it comes in... |
| 103 // | 107 // |
| 104 class CallbackClient : public StreamProcessor { | 108 class CallbackClient : public StreamProcessor { |
| 105 public: | 109 public: |
| 106 // states for state machine, with each state representing one | 110 // states for state machine, with each state representing one |
| 107 // received block of the tar stream. | 111 // received block of the tar stream. |
| 108 // The blocks can be either headers (for directories and files) | 112 // The blocks can be either headers (for directories and files) |
| 109 // or data blocks (zero padded at the end to make a full block) | 113 // or data blocks (zero padded at the end to make a full block) |
| 110 enum ValidationState { | 114 enum ValidationState { |
| 111 VALIDATE_DIRECTORY_HEADER1, // header 1 is directory so no file data | 115 VALIDATE_DIRECTORY_HEADER1, // header 1 is directory so no file data |
| 112 VALIDATE_FILE_HEADER1, | 116 VALIDATE_FILE_HEADER1, |
| 113 VALIDATE_FILE_DATA1, // 1st file takes one block | 117 VALIDATE_FILE_DATA1, // 1st file takes one block |
| 114 VALIDATE_FILE_HEADER2, | 118 VALIDATE_FILE_HEADER2, |
| 115 VALIDATE_FILE_DATA2_BLOCK1, // 2nd file takes two blocks | 119 VALIDATE_FILE_DATA2_BLOCK1, // 2nd file takes two blocks |
| 116 VALIDATE_FILE_DATA2_BLOCK2, | 120 VALIDATE_FILE_DATA2_BLOCK2, |
| 117 VALIDATE_DIRECTORY_HEADER2, // 3rd file is in another directory | 121 VALIDATE_DIRECTORY_HEADER2, // 3rd file is in another directory |
| 118 VALIDATE_FILE_HEADER3, | 122 VALIDATE_FILE_HEADER3, |
| 119 VALIDATE_FILE_DATA3, | 123 VALIDATE_FILE_DATA3, |
| 124 VALIDATE_FILE_LONGNAME_HEADER4, // 4th file has a long name. |
| 125 VALIDATE_FILE_LONGNAME_DATA4, |
| 126 VALIDATE_FILE_HEADER4, |
| 127 VALIDATE_FILE_DATA4, |
| 120 FINISHED | 128 FINISHED |
| 121 }; | 129 }; |
| 122 | 130 |
| 123 CallbackClient() | 131 CallbackClient() |
| 124 : state_(VALIDATE_DIRECTORY_HEADER1), | 132 : state_(VALIDATE_DIRECTORY_HEADER1), |
| 125 total_bytes_received_(0), | 133 total_bytes_received_(0), |
| 126 memory_block_(kBlockSize), | 134 memory_block_(kBlockSize), |
| 127 write_stream_(memory_block_, kBlockSize) { | 135 write_stream_(memory_block_, kBlockSize) { |
| 128 } | 136 } |
| 129 | 137 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 break; | 214 break; |
| 207 | 215 |
| 208 case VALIDATE_FILE_HEADER3: | 216 case VALIDATE_FILE_HEADER3: |
| 209 ValidateHeader(memory_block_, kFileName3, strlen(kFileContents3)); | 217 ValidateHeader(memory_block_, kFileName3, strlen(kFileContents3)); |
| 210 break; | 218 break; |
| 211 | 219 |
| 212 case VALIDATE_FILE_DATA3: | 220 case VALIDATE_FILE_DATA3: |
| 213 ValidateData(memory_block_, kFileContents3); | 221 ValidateData(memory_block_, kFileContents3); |
| 214 break; | 222 break; |
| 215 | 223 |
| 224 case VALIDATE_FILE_LONGNAME_HEADER4: |
| 225 ValidateHeader(memory_block_, kLongLink, strlen(kFileName4)); |
| 226 break; |
| 227 |
| 228 case VALIDATE_FILE_LONGNAME_DATA4: |
| 229 ValidateData(memory_block_, kFileName4); |
| 230 break; |
| 231 |
| 232 case VALIDATE_FILE_HEADER4: { |
| 233 String first_99_chars(kFileName4, 99); |
| 234 ValidateHeader(memory_block_, first_99_chars.c_str(), |
| 235 strlen(kFileContents3)); |
| 236 break; |
| 237 } |
| 238 |
| 239 case VALIDATE_FILE_DATA4: |
| 240 ValidateData(memory_block_, kFileContents3); |
| 241 break; |
| 242 |
| 216 case FINISHED: | 243 case FINISHED: |
| 217 break; | 244 break; |
| 218 } | 245 } |
| 219 | 246 |
| 220 // Advance to the next state | 247 // Advance to the next state |
| 221 ++state_; | 248 ++state_; |
| 222 | 249 |
| 223 // So next time we write, we start at beginning of buffer | 250 // So next time we write, we start at beginning of buffer |
| 224 write_stream_.Seek(0); | 251 write_stream_.Seek(0); |
| 225 } | 252 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 EXPECT_EQ(0, header[kFileSizeOffset + 11]); | 336 EXPECT_EQ(0, header[kFileSizeOffset + 11]); |
| 310 | 337 |
| 311 EXPECT_TRUE(IsOctalString(header + kModifyTimeOffset)); | 338 EXPECT_TRUE(IsOctalString(header + kModifyTimeOffset)); |
| 312 EXPECT_EQ(0, header[kModifyTimeOffset + 11]); | 339 EXPECT_EQ(0, header[kModifyTimeOffset + 11]); |
| 313 | 340 |
| 314 EXPECT_TRUE(IsOctalString(header + kHeaderCheckSumOffset)); | 341 EXPECT_TRUE(IsOctalString(header + kHeaderCheckSumOffset)); |
| 315 EXPECT_EQ(0, header[kHeaderCheckSumOffset + 6]); | 342 EXPECT_EQ(0, header[kHeaderCheckSumOffset + 6]); |
| 316 | 343 |
| 317 // For now we only have directories '5' or normal files '0' | 344 // For now we only have directories '5' or normal files '0' |
| 318 int link_flag = header[kLinkFlagOffset]; | 345 int link_flag = header[kLinkFlagOffset]; |
| 319 EXPECT_TRUE(link_flag == '0' || link_flag == '5'); | 346 EXPECT_TRUE(link_flag == '0' || link_flag == '5' || link_flag == 'L'); |
| 320 | 347 |
| 321 EXPECT_EQ(0, strcmp((const char*)header + kMagicOffset, "ustar ")); | 348 EXPECT_EQ(0, strcmp((const char*)header + kMagicOffset, "ustar ")); |
| 322 | 349 |
| 323 EXPECT_EQ(0, header[kUserNameOffset + 31]); | 350 EXPECT_EQ(0, header[kUserNameOffset + 31]); |
| 324 EXPECT_EQ(0, header[kGroupNameOffset + 31]); | 351 EXPECT_EQ(0, header[kGroupNameOffset + 31]); |
| 325 | 352 |
| 326 // Validate checksum | 353 // Validate checksum |
| 327 int checksum = ComputeCheckSum(header); | 354 int checksum = ComputeCheckSum(header); |
| 328 int header_checksum; | 355 int header_checksum; |
| 329 sscanf((const char*)header + kHeaderCheckSumOffset, "%o", &header_checksum); | 356 sscanf((const char*)header + kHeaderCheckSumOffset, "%o", &header_checksum); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 350 // Creates a tar file with three files in two directories | 377 // Creates a tar file with three files in two directories |
| 351 // | 378 // |
| 352 TEST_F(TarGeneratorTest, CreateSimpleArchive) { | 379 TEST_F(TarGeneratorTest, CreateSimpleArchive) { |
| 353 CallbackClient client; | 380 CallbackClient client; |
| 354 TarGenerator generator(&client); | 381 TarGenerator generator(&client); |
| 355 | 382 |
| 356 const int kFileLength1 = strlen(kFileContents1); | 383 const int kFileLength1 = strlen(kFileContents1); |
| 357 const int kFileLength2 = strlen(kFileContents2); | 384 const int kFileLength2 = strlen(kFileContents2); |
| 358 const int kFileLength3 = strlen(kFileContents3); | 385 const int kFileLength3 = strlen(kFileContents3); |
| 359 | 386 |
| 360 generator.AddFile(kFileName1, kFileLength1); | 387 EXPECT_TRUE(generator.AddFile(kFileName1, kFileLength1)); |
| 361 MemoryReadStream file1_stream(reinterpret_cast<const uint8*>(kFileContents1), | 388 MemoryReadStream file1_stream(reinterpret_cast<const uint8*>(kFileContents1), |
| 362 kFileLength1); | 389 kFileLength1); |
| 363 generator.AddFileBytes(&file1_stream, kFileLength1); | 390 generator.AddFileBytes(&file1_stream, kFileLength1); |
| 364 | 391 |
| 365 generator.AddFile(kFileName2, kFileLength2); | 392 EXPECT_TRUE(generator.AddFile(kFileName2, kFileLength2)); |
| 366 MemoryReadStream file2_stream(reinterpret_cast<const uint8*>(kFileContents2), | 393 MemoryReadStream file2_stream(reinterpret_cast<const uint8*>(kFileContents2), |
| 367 kFileLength2); | 394 kFileLength2); |
| 368 generator.AddFileBytes(&file2_stream, kFileLength2); | 395 generator.AddFileBytes(&file2_stream, kFileLength2); |
| 369 | 396 |
| 370 generator.AddFile(kFileName3, kFileLength3); | 397 EXPECT_TRUE(generator.AddFile(kFileName3, kFileLength3)); |
| 371 MemoryReadStream file3_stream(reinterpret_cast<const uint8*>(kFileContents3), | 398 MemoryReadStream file3_stream(reinterpret_cast<const uint8*>(kFileContents3), |
| 372 kFileLength3); | 399 kFileLength3); |
| 373 generator.AddFileBytes(&file3_stream, kFileLength3); | 400 generator.AddFileBytes(&file3_stream, kFileLength3); |
| 401 EXPECT_TRUE(generator.AddFile(kFileName4, kFileLength3)); |
| 402 MemoryReadStream file4_stream(reinterpret_cast<const uint8*>(kFileContents3), |
| 403 kFileLength3); |
| 404 generator.AddFileBytes(&file4_stream, kFileLength3); |
| 374 | 405 |
| 375 generator.Finalize(); | 406 generator.Finalize(); |
| 376 | 407 |
| 377 // Verify that the tar byte stream produced is exactly divisible by | 408 // Verify that the tar byte stream produced is exactly divisible by |
| 378 // the block size | 409 // the block size |
| 379 size_t bytes_received = client.GetTotalBytesReceived(); | 410 size_t bytes_received = client.GetTotalBytesReceived(); |
| 380 EXPECT_EQ(0, bytes_received % kBlockSize); | 411 EXPECT_EQ(0, bytes_received % kBlockSize); |
| 381 | 412 |
| 382 // Make sure the state machine is in the expected state | 413 // Make sure the state machine is in the expected state |
| 383 EXPECT_EQ(CallbackClient::FINISHED, client.GetState()); | 414 EXPECT_EQ(CallbackClient::FINISHED, client.GetState()); |
| 384 } | 415 } |
| 385 | 416 |
| 386 } // namespace | 417 } // namespace |
| OLD | NEW |