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 |