Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(440)

Side by Side Diff: third_party/zlib/google/zip_reader_unittest.cc

Issue 2023703002: Beginning work on GN build (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Really add //build. Add dart_bootstrap rule. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/zlib/google/zip_reader.cc ('k') | third_party/zlib/google/zip_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/zlib/google/zip_reader.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <string.h>
10
11 #include <set>
12 #include <string>
13
14 #include "base/bind.h"
15 #include "base/files/file.h"
16 #include "base/files/file_util.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/logging.h"
19 #include "base/macros.h"
20 #include "base/md5.h"
21 #include "base/path_service.h"
22 #include "base/run_loop.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/time/time.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "testing/platform_test.h"
29 #include "third_party/zlib/google/zip_internal.h"
30
31 using ::testing::Return;
32 using ::testing::_;
33
34 namespace {
35
36 const static std::string kQuuxExpectedMD5 = "d1ae4ac8a17a0e09317113ab284b57a6";
37
38 class FileWrapper {
39 public:
40 typedef enum {
41 READ_ONLY,
42 READ_WRITE
43 } AccessMode;
44
45 FileWrapper(const base::FilePath& path, AccessMode mode) {
46 int flags = base::File::FLAG_READ;
47 if (mode == READ_ONLY)
48 flags |= base::File::FLAG_OPEN;
49 else
50 flags |= base::File::FLAG_WRITE | base::File::FLAG_CREATE_ALWAYS;
51
52 file_.Initialize(path, flags);
53 }
54
55 ~FileWrapper() {}
56
57 base::PlatformFile platform_file() { return file_.GetPlatformFile(); }
58
59 base::File* file() { return &file_; }
60
61 private:
62 base::File file_;
63 };
64
65 // A mock that provides methods that can be used as callbacks in asynchronous
66 // unzip functions. Tracks the number of calls and number of bytes reported.
67 // Assumes that progress callbacks will be executed in-order.
68 class MockUnzipListener : public base::SupportsWeakPtr<MockUnzipListener> {
69 public:
70 MockUnzipListener()
71 : success_calls_(0),
72 failure_calls_(0),
73 progress_calls_(0),
74 current_progress_(0) {
75 }
76
77 // Success callback for async functions.
78 void OnUnzipSuccess() {
79 success_calls_++;
80 }
81
82 // Failure callback for async functions.
83 void OnUnzipFailure() {
84 failure_calls_++;
85 }
86
87 // Progress callback for async functions.
88 void OnUnzipProgress(int64_t progress) {
89 DCHECK(progress > current_progress_);
90 progress_calls_++;
91 current_progress_ = progress;
92 }
93
94 int success_calls() { return success_calls_; }
95 int failure_calls() { return failure_calls_; }
96 int progress_calls() { return progress_calls_; }
97 int current_progress() { return current_progress_; }
98
99 private:
100 int success_calls_;
101 int failure_calls_;
102 int progress_calls_;
103
104 int64_t current_progress_;
105 };
106
107 class MockWriterDelegate : public zip::WriterDelegate {
108 public:
109 MOCK_METHOD0(PrepareOutput, bool());
110 MOCK_METHOD2(WriteBytes, bool(const char*, int));
111 };
112
113 } // namespace
114
115 namespace zip {
116
117 // Make the test a PlatformTest to setup autorelease pools properly on Mac.
118 class ZipReaderTest : public PlatformTest {
119 protected:
120 virtual void SetUp() {
121 PlatformTest::SetUp();
122
123 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
124 test_dir_ = temp_dir_.path();
125
126 ASSERT_TRUE(GetTestDataDirectory(&test_data_dir_));
127
128 test_zip_file_ = test_data_dir_.AppendASCII("test.zip");
129 evil_zip_file_ = test_data_dir_.AppendASCII("evil.zip");
130 evil_via_invalid_utf8_zip_file_ = test_data_dir_.AppendASCII(
131 "evil_via_invalid_utf8.zip");
132 evil_via_absolute_file_name_zip_file_ = test_data_dir_.AppendASCII(
133 "evil_via_absolute_file_name.zip");
134
135 test_zip_contents_.insert(base::FilePath(FILE_PATH_LITERAL("foo/")));
136 test_zip_contents_.insert(base::FilePath(FILE_PATH_LITERAL("foo/bar/")));
137 test_zip_contents_.insert(
138 base::FilePath(FILE_PATH_LITERAL("foo/bar/baz.txt")));
139 test_zip_contents_.insert(
140 base::FilePath(FILE_PATH_LITERAL("foo/bar/quux.txt")));
141 test_zip_contents_.insert(
142 base::FilePath(FILE_PATH_LITERAL("foo/bar.txt")));
143 test_zip_contents_.insert(base::FilePath(FILE_PATH_LITERAL("foo.txt")));
144 test_zip_contents_.insert(
145 base::FilePath(FILE_PATH_LITERAL("foo/bar/.hidden")));
146 }
147
148 virtual void TearDown() {
149 PlatformTest::TearDown();
150 }
151
152 bool GetTestDataDirectory(base::FilePath* path) {
153 bool success = PathService::Get(base::DIR_SOURCE_ROOT, path);
154 EXPECT_TRUE(success);
155 if (!success)
156 return false;
157 *path = path->AppendASCII("third_party");
158 *path = path->AppendASCII("zlib");
159 *path = path->AppendASCII("google");
160 *path = path->AppendASCII("test");
161 *path = path->AppendASCII("data");
162 return true;
163 }
164
165 bool CompareFileAndMD5(const base::FilePath& path,
166 const std::string expected_md5) {
167 // Read the output file and compute the MD5.
168 std::string output;
169 if (!base::ReadFileToString(path, &output))
170 return false;
171 const std::string md5 = base::MD5String(output);
172 return expected_md5 == md5;
173 }
174
175 // The path to temporary directory used to contain the test operations.
176 base::FilePath test_dir_;
177 // The path to the test data directory where test.zip etc. are located.
178 base::FilePath test_data_dir_;
179 // The path to test.zip in the test data directory.
180 base::FilePath test_zip_file_;
181 // The path to evil.zip in the test data directory.
182 base::FilePath evil_zip_file_;
183 // The path to evil_via_invalid_utf8.zip in the test data directory.
184 base::FilePath evil_via_invalid_utf8_zip_file_;
185 // The path to evil_via_absolute_file_name.zip in the test data directory.
186 base::FilePath evil_via_absolute_file_name_zip_file_;
187 std::set<base::FilePath> test_zip_contents_;
188
189 base::ScopedTempDir temp_dir_;
190
191 base::MessageLoop message_loop_;
192 };
193
194 TEST_F(ZipReaderTest, Open_ValidZipFile) {
195 ZipReader reader;
196 ASSERT_TRUE(reader.Open(test_zip_file_));
197 }
198
199 TEST_F(ZipReaderTest, Open_ValidZipPlatformFile) {
200 ZipReader reader;
201 FileWrapper zip_fd_wrapper(test_zip_file_, FileWrapper::READ_ONLY);
202 ASSERT_TRUE(reader.OpenFromPlatformFile(zip_fd_wrapper.platform_file()));
203 }
204
205 TEST_F(ZipReaderTest, Open_NonExistentFile) {
206 ZipReader reader;
207 ASSERT_FALSE(reader.Open(test_data_dir_.AppendASCII("nonexistent.zip")));
208 }
209
210 TEST_F(ZipReaderTest, Open_ExistentButNonZipFile) {
211 ZipReader reader;
212 ASSERT_FALSE(reader.Open(test_data_dir_.AppendASCII("create_test_zip.sh")));
213 }
214
215 // Iterate through the contents in the test zip file, and compare that the
216 // contents collected from the zip reader matches the expected contents.
217 TEST_F(ZipReaderTest, Iteration) {
218 std::set<base::FilePath> actual_contents;
219 ZipReader reader;
220 ASSERT_TRUE(reader.Open(test_zip_file_));
221 while (reader.HasMore()) {
222 ASSERT_TRUE(reader.OpenCurrentEntryInZip());
223 actual_contents.insert(reader.current_entry_info()->file_path());
224 ASSERT_TRUE(reader.AdvanceToNextEntry());
225 }
226 EXPECT_FALSE(reader.AdvanceToNextEntry()); // Shouldn't go further.
227 EXPECT_EQ(test_zip_contents_.size(),
228 static_cast<size_t>(reader.num_entries()));
229 EXPECT_EQ(test_zip_contents_.size(), actual_contents.size());
230 EXPECT_EQ(test_zip_contents_, actual_contents);
231 }
232
233 // Open the test zip file from a file descriptor, iterate through its contents,
234 // and compare that they match the expected contents.
235 TEST_F(ZipReaderTest, PlatformFileIteration) {
236 std::set<base::FilePath> actual_contents;
237 ZipReader reader;
238 FileWrapper zip_fd_wrapper(test_zip_file_, FileWrapper::READ_ONLY);
239 ASSERT_TRUE(reader.OpenFromPlatformFile(zip_fd_wrapper.platform_file()));
240 while (reader.HasMore()) {
241 ASSERT_TRUE(reader.OpenCurrentEntryInZip());
242 actual_contents.insert(reader.current_entry_info()->file_path());
243 ASSERT_TRUE(reader.AdvanceToNextEntry());
244 }
245 EXPECT_FALSE(reader.AdvanceToNextEntry()); // Shouldn't go further.
246 EXPECT_EQ(test_zip_contents_.size(),
247 static_cast<size_t>(reader.num_entries()));
248 EXPECT_EQ(test_zip_contents_.size(), actual_contents.size());
249 EXPECT_EQ(test_zip_contents_, actual_contents);
250 }
251
252 TEST_F(ZipReaderTest, LocateAndOpenEntry_ValidFile) {
253 std::set<base::FilePath> actual_contents;
254 ZipReader reader;
255 ASSERT_TRUE(reader.Open(test_zip_file_));
256 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
257 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
258 EXPECT_EQ(target_path, reader.current_entry_info()->file_path());
259 }
260
261 TEST_F(ZipReaderTest, LocateAndOpenEntry_NonExistentFile) {
262 std::set<base::FilePath> actual_contents;
263 ZipReader reader;
264 ASSERT_TRUE(reader.Open(test_zip_file_));
265 base::FilePath target_path(FILE_PATH_LITERAL("nonexistent.txt"));
266 ASSERT_FALSE(reader.LocateAndOpenEntry(target_path));
267 EXPECT_EQ(NULL, reader.current_entry_info());
268 }
269
270 TEST_F(ZipReaderTest, ExtractCurrentEntryToFilePath_RegularFile) {
271 ZipReader reader;
272 ASSERT_TRUE(reader.Open(test_zip_file_));
273 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
274 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
275 ASSERT_TRUE(reader.ExtractCurrentEntryToFilePath(
276 test_dir_.AppendASCII("quux.txt")));
277 // Read the output file ans compute the MD5.
278 std::string output;
279 ASSERT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("quux.txt"),
280 &output));
281 const std::string md5 = base::MD5String(output);
282 EXPECT_EQ(kQuuxExpectedMD5, md5);
283 // quux.txt should be larger than kZipBufSize so that we can exercise
284 // the loop in ExtractCurrentEntry().
285 EXPECT_LT(static_cast<size_t>(internal::kZipBufSize), output.size());
286 }
287
288 TEST_F(ZipReaderTest, PlatformFileExtractCurrentEntryToFilePath_RegularFile) {
289 ZipReader reader;
290 FileWrapper zip_fd_wrapper(test_zip_file_, FileWrapper::READ_ONLY);
291 ASSERT_TRUE(reader.OpenFromPlatformFile(zip_fd_wrapper.platform_file()));
292 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
293 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
294 ASSERT_TRUE(reader.ExtractCurrentEntryToFilePath(
295 test_dir_.AppendASCII("quux.txt")));
296 // Read the output file and compute the MD5.
297 std::string output;
298 ASSERT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("quux.txt"),
299 &output));
300 const std::string md5 = base::MD5String(output);
301 EXPECT_EQ(kQuuxExpectedMD5, md5);
302 // quux.txt should be larger than kZipBufSize so that we can exercise
303 // the loop in ExtractCurrentEntry().
304 EXPECT_LT(static_cast<size_t>(internal::kZipBufSize), output.size());
305 }
306
307 TEST_F(ZipReaderTest, PlatformFileExtractCurrentEntryToFile_RegularFile) {
308 ZipReader reader;
309 FileWrapper zip_fd_wrapper(test_zip_file_, FileWrapper::READ_ONLY);
310 ASSERT_TRUE(reader.OpenFromPlatformFile(zip_fd_wrapper.platform_file()));
311 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
312 base::FilePath out_path = test_dir_.AppendASCII("quux.txt");
313 FileWrapper out_fd_w(out_path, FileWrapper::READ_WRITE);
314 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
315 ASSERT_TRUE(reader.ExtractCurrentEntryToFile(out_fd_w.file()));
316 // Read the output file and compute the MD5.
317 std::string output;
318 ASSERT_TRUE(base::ReadFileToString(out_path, &output));
319 const std::string md5 = base::MD5String(output);
320 EXPECT_EQ(kQuuxExpectedMD5, md5);
321 // quux.txt should be larger than kZipBufSize so that we can exercise
322 // the loop in ExtractCurrentEntry().
323 EXPECT_LT(static_cast<size_t>(internal::kZipBufSize), output.size());
324 }
325
326 TEST_F(ZipReaderTest, ExtractCurrentEntryToFilePath_Directory) {
327 ZipReader reader;
328 ASSERT_TRUE(reader.Open(test_zip_file_));
329 base::FilePath target_path(FILE_PATH_LITERAL("foo/"));
330 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
331 ASSERT_TRUE(reader.ExtractCurrentEntryToFilePath(
332 test_dir_.AppendASCII("foo")));
333 // The directory should be created.
334 ASSERT_TRUE(base::DirectoryExists(test_dir_.AppendASCII("foo")));
335 }
336
337 TEST_F(ZipReaderTest, ExtractCurrentEntryIntoDirectory_RegularFile) {
338 ZipReader reader;
339 ASSERT_TRUE(reader.Open(test_zip_file_));
340 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
341 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
342 ASSERT_TRUE(reader.ExtractCurrentEntryIntoDirectory(test_dir_));
343 // Sub directories should be created.
344 ASSERT_TRUE(base::DirectoryExists(test_dir_.AppendASCII("foo/bar")));
345 // And the file should be created.
346 std::string output;
347 ASSERT_TRUE(base::ReadFileToString(
348 test_dir_.AppendASCII("foo/bar/quux.txt"), &output));
349 const std::string md5 = base::MD5String(output);
350 EXPECT_EQ(kQuuxExpectedMD5, md5);
351 }
352
353 TEST_F(ZipReaderTest, current_entry_info_RegularFile) {
354 ZipReader reader;
355 ASSERT_TRUE(reader.Open(test_zip_file_));
356 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
357 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
358 ZipReader::EntryInfo* current_entry_info = reader.current_entry_info();
359
360 EXPECT_EQ(target_path, current_entry_info->file_path());
361 EXPECT_EQ(13527, current_entry_info->original_size());
362
363 // The expected time stamp: 2009-05-29 06:22:20
364 base::Time::Exploded exploded = {}; // Zero-clear.
365 current_entry_info->last_modified().LocalExplode(&exploded);
366 EXPECT_EQ(2009, exploded.year);
367 EXPECT_EQ(5, exploded.month);
368 EXPECT_EQ(29, exploded.day_of_month);
369 EXPECT_EQ(6, exploded.hour);
370 EXPECT_EQ(22, exploded.minute);
371 EXPECT_EQ(20, exploded.second);
372 EXPECT_EQ(0, exploded.millisecond);
373
374 EXPECT_FALSE(current_entry_info->is_unsafe());
375 EXPECT_FALSE(current_entry_info->is_directory());
376 }
377
378 TEST_F(ZipReaderTest, current_entry_info_DotDotFile) {
379 ZipReader reader;
380 ASSERT_TRUE(reader.Open(evil_zip_file_));
381 base::FilePath target_path(FILE_PATH_LITERAL(
382 "../levilevilevilevilevilevilevilevilevilevilevilevil"));
383 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
384 ZipReader::EntryInfo* current_entry_info = reader.current_entry_info();
385 EXPECT_EQ(target_path, current_entry_info->file_path());
386
387 // This file is unsafe because of ".." in the file name.
388 EXPECT_TRUE(current_entry_info->is_unsafe());
389 EXPECT_FALSE(current_entry_info->is_directory());
390 }
391
392 TEST_F(ZipReaderTest, current_entry_info_InvalidUTF8File) {
393 ZipReader reader;
394 ASSERT_TRUE(reader.Open(evil_via_invalid_utf8_zip_file_));
395 // The evil file is the 2nd file in the zip file.
396 // We cannot locate by the file name ".\x80.\\evil.txt",
397 // as FilePath may internally convert the string.
398 ASSERT_TRUE(reader.AdvanceToNextEntry());
399 ASSERT_TRUE(reader.OpenCurrentEntryInZip());
400 ZipReader::EntryInfo* current_entry_info = reader.current_entry_info();
401
402 // This file is unsafe because of invalid UTF-8 in the file name.
403 EXPECT_TRUE(current_entry_info->is_unsafe());
404 EXPECT_FALSE(current_entry_info->is_directory());
405 }
406
407 TEST_F(ZipReaderTest, current_entry_info_AbsoluteFile) {
408 ZipReader reader;
409 ASSERT_TRUE(reader.Open(evil_via_absolute_file_name_zip_file_));
410 base::FilePath target_path(FILE_PATH_LITERAL("/evil.txt"));
411 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
412 ZipReader::EntryInfo* current_entry_info = reader.current_entry_info();
413 EXPECT_EQ(target_path, current_entry_info->file_path());
414
415 // This file is unsafe because of the absolute file name.
416 EXPECT_TRUE(current_entry_info->is_unsafe());
417 EXPECT_FALSE(current_entry_info->is_directory());
418 }
419
420 TEST_F(ZipReaderTest, current_entry_info_Directory) {
421 ZipReader reader;
422 ASSERT_TRUE(reader.Open(test_zip_file_));
423 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/"));
424 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
425 ZipReader::EntryInfo* current_entry_info = reader.current_entry_info();
426
427 EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("foo/bar/")),
428 current_entry_info->file_path());
429 // The directory size should be zero.
430 EXPECT_EQ(0, current_entry_info->original_size());
431
432 // The expected time stamp: 2009-05-31 15:49:52
433 base::Time::Exploded exploded = {}; // Zero-clear.
434 current_entry_info->last_modified().LocalExplode(&exploded);
435 EXPECT_EQ(2009, exploded.year);
436 EXPECT_EQ(5, exploded.month);
437 EXPECT_EQ(31, exploded.day_of_month);
438 EXPECT_EQ(15, exploded.hour);
439 EXPECT_EQ(49, exploded.minute);
440 EXPECT_EQ(52, exploded.second);
441 EXPECT_EQ(0, exploded.millisecond);
442
443 EXPECT_FALSE(current_entry_info->is_unsafe());
444 EXPECT_TRUE(current_entry_info->is_directory());
445 }
446
447 // Verifies that the ZipReader class can extract a file from a zip archive
448 // stored in memory. This test opens a zip archive in a std::string object,
449 // extracts its content, and verifies the content is the same as the expected
450 // text.
451 TEST_F(ZipReaderTest, OpenFromString) {
452 // A zip archive consisting of one file "test.txt", which is a 16-byte text
453 // file that contains "This is a test.\n".
454 const char kTestData[] =
455 "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\xa4\x66\x24\x41\x13\xe8"
456 "\xcb\x27\x10\x00\x00\x00\x10\x00\x00\x00\x08\x00\x1c\x00\x74\x65"
457 "\x73\x74\x2e\x74\x78\x74\x55\x54\x09\x00\x03\x34\x89\x45\x50\x34"
458 "\x89\x45\x50\x75\x78\x0b\x00\x01\x04\x8e\xf0\x00\x00\x04\x88\x13"
459 "\x00\x00\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74"
460 "\x2e\x0a\x50\x4b\x01\x02\x1e\x03\x0a\x00\x00\x00\x00\x00\xa4\x66"
461 "\x24\x41\x13\xe8\xcb\x27\x10\x00\x00\x00\x10\x00\x00\x00\x08\x00"
462 "\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa4\x81\x00\x00\x00\x00"
463 "\x74\x65\x73\x74\x2e\x74\x78\x74\x55\x54\x05\x00\x03\x34\x89\x45"
464 "\x50\x75\x78\x0b\x00\x01\x04\x8e\xf0\x00\x00\x04\x88\x13\x00\x00"
465 "\x50\x4b\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00\x4e\x00\x00\x00"
466 "\x52\x00\x00\x00\x00\x00";
467 std::string data(kTestData, arraysize(kTestData));
468 ZipReader reader;
469 ASSERT_TRUE(reader.OpenFromString(data));
470 base::FilePath target_path(FILE_PATH_LITERAL("test.txt"));
471 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
472 ASSERT_TRUE(reader.ExtractCurrentEntryToFilePath(
473 test_dir_.AppendASCII("test.txt")));
474
475 std::string actual;
476 ASSERT_TRUE(base::ReadFileToString(
477 test_dir_.AppendASCII("test.txt"), &actual));
478 EXPECT_EQ(std::string("This is a test.\n"), actual);
479 }
480
481 // Verifies that the asynchronous extraction to a file works.
482 TEST_F(ZipReaderTest, ExtractToFileAsync_RegularFile) {
483 MockUnzipListener listener;
484
485 ZipReader reader;
486 base::FilePath target_file = test_dir_.AppendASCII("quux.txt");
487 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
488 ASSERT_TRUE(reader.Open(test_zip_file_));
489 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
490 reader.ExtractCurrentEntryToFilePathAsync(
491 target_file,
492 base::Bind(&MockUnzipListener::OnUnzipSuccess,
493 listener.AsWeakPtr()),
494 base::Bind(&MockUnzipListener::OnUnzipFailure,
495 listener.AsWeakPtr()),
496 base::Bind(&MockUnzipListener::OnUnzipProgress,
497 listener.AsWeakPtr()));
498
499 EXPECT_EQ(0, listener.success_calls());
500 EXPECT_EQ(0, listener.failure_calls());
501 EXPECT_EQ(0, listener.progress_calls());
502
503 base::RunLoop().RunUntilIdle();
504
505 EXPECT_EQ(1, listener.success_calls());
506 EXPECT_EQ(0, listener.failure_calls());
507 EXPECT_LE(1, listener.progress_calls());
508
509 std::string output;
510 ASSERT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("quux.txt"),
511 &output));
512 const std::string md5 = base::MD5String(output);
513 EXPECT_EQ(kQuuxExpectedMD5, md5);
514
515 int64_t file_size = 0;
516 ASSERT_TRUE(base::GetFileSize(target_file, &file_size));
517
518 EXPECT_EQ(file_size, listener.current_progress());
519 }
520
521 // Verifies that the asynchronous extraction to a file works.
522 TEST_F(ZipReaderTest, ExtractToFileAsync_Directory) {
523 MockUnzipListener listener;
524
525 ZipReader reader;
526 base::FilePath target_file = test_dir_.AppendASCII("foo");
527 base::FilePath target_path(FILE_PATH_LITERAL("foo/"));
528 ASSERT_TRUE(reader.Open(test_zip_file_));
529 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
530 reader.ExtractCurrentEntryToFilePathAsync(
531 target_file,
532 base::Bind(&MockUnzipListener::OnUnzipSuccess,
533 listener.AsWeakPtr()),
534 base::Bind(&MockUnzipListener::OnUnzipFailure,
535 listener.AsWeakPtr()),
536 base::Bind(&MockUnzipListener::OnUnzipProgress,
537 listener.AsWeakPtr()));
538
539 EXPECT_EQ(0, listener.success_calls());
540 EXPECT_EQ(0, listener.failure_calls());
541 EXPECT_EQ(0, listener.progress_calls());
542
543 base::RunLoop().RunUntilIdle();
544
545 EXPECT_EQ(1, listener.success_calls());
546 EXPECT_EQ(0, listener.failure_calls());
547 EXPECT_GE(0, listener.progress_calls());
548
549 ASSERT_TRUE(base::DirectoryExists(target_file));
550 }
551
552 TEST_F(ZipReaderTest, ExtractCurrentEntryToString) {
553 // test_mismatch_size.zip contains files with names from 0.txt to 7.txt with
554 // sizes from 0 to 7 bytes respectively, being the contents of each file a
555 // substring of "0123456" starting at '0'.
556 base::FilePath test_zip_file =
557 test_data_dir_.AppendASCII("test_mismatch_size.zip");
558
559 ZipReader reader;
560 std::string contents;
561 ASSERT_TRUE(reader.Open(test_zip_file));
562
563 for (size_t i = 0; i < 8; i++) {
564 SCOPED_TRACE(base::StringPrintf("Processing %d.txt", static_cast<int>(i)));
565
566 base::FilePath file_name = base::FilePath::FromUTF8Unsafe(
567 base::StringPrintf("%d.txt", static_cast<int>(i)));
568 ASSERT_TRUE(reader.LocateAndOpenEntry(file_name));
569
570 if (i > 1) {
571 // Off by one byte read limit: must fail.
572 EXPECT_FALSE(reader.ExtractCurrentEntryToString(i - 1, &contents));
573 }
574
575 if (i > 0) {
576 // Exact byte read limit: must pass.
577 EXPECT_TRUE(reader.ExtractCurrentEntryToString(i, &contents));
578 EXPECT_EQ(i, contents.size());
579 EXPECT_EQ(0, memcmp(contents.c_str(), "0123456", i));
580 }
581
582 // More than necessary byte read limit: must pass.
583 EXPECT_TRUE(reader.ExtractCurrentEntryToString(16, &contents));
584 EXPECT_EQ(i, contents.size());
585 EXPECT_EQ(0, memcmp(contents.c_str(), "0123456", i));
586 }
587 reader.Close();
588 }
589
590 // This test exposes http://crbug.com/430959, at least on OS X
591 TEST_F(ZipReaderTest, DISABLED_LeakDetectionTest) {
592 for (int i = 0; i < 100000; ++i) {
593 FileWrapper zip_fd_wrapper(test_zip_file_, FileWrapper::READ_ONLY);
594 ZipReader reader;
595 ASSERT_TRUE(reader.OpenFromPlatformFile(zip_fd_wrapper.platform_file()));
596 }
597 }
598
599 // Test that when WriterDelegate::PrepareMock returns false, no other methods on
600 // the delegate are called and the extraction fails.
601 TEST_F(ZipReaderTest, ExtractCurrentEntryPrepareFailure) {
602 testing::StrictMock<MockWriterDelegate> mock_writer;
603
604 EXPECT_CALL(mock_writer, PrepareOutput())
605 .WillOnce(Return(false));
606
607 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
608 ZipReader reader;
609
610 ASSERT_TRUE(reader.Open(test_zip_file_));
611 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
612 ASSERT_FALSE(reader.ExtractCurrentEntry(&mock_writer));
613 }
614
615 // Test that when WriterDelegate::WriteBytes returns false, no other methods on
616 // the delegate are called and the extraction fails.
617 TEST_F(ZipReaderTest, ExtractCurrentEntryWriteBytesFailure) {
618 testing::StrictMock<MockWriterDelegate> mock_writer;
619
620 EXPECT_CALL(mock_writer, PrepareOutput())
621 .WillOnce(Return(true));
622 EXPECT_CALL(mock_writer, WriteBytes(_, _))
623 .WillOnce(Return(false));
624
625 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
626 ZipReader reader;
627
628 ASSERT_TRUE(reader.Open(test_zip_file_));
629 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
630 ASSERT_FALSE(reader.ExtractCurrentEntry(&mock_writer));
631 }
632
633 // Test that extraction succeeds when the writer delegate reports all is well.
634 TEST_F(ZipReaderTest, ExtractCurrentEntrySuccess) {
635 testing::StrictMock<MockWriterDelegate> mock_writer;
636
637 EXPECT_CALL(mock_writer, PrepareOutput())
638 .WillOnce(Return(true));
639 EXPECT_CALL(mock_writer, WriteBytes(_, _))
640 .WillRepeatedly(Return(true));
641
642 base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
643 ZipReader reader;
644
645 ASSERT_TRUE(reader.Open(test_zip_file_));
646 ASSERT_TRUE(reader.LocateAndOpenEntry(target_path));
647 ASSERT_TRUE(reader.ExtractCurrentEntry(&mock_writer));
648 }
649
650 class FileWriterDelegateTest : public ::testing::Test {
651 protected:
652 void SetUp() override {
653 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_));
654 file_.Initialize(temp_file_path_, (base::File::FLAG_CREATE_ALWAYS |
655 base::File::FLAG_READ |
656 base::File::FLAG_WRITE |
657 base::File::FLAG_TEMPORARY |
658 base::File::FLAG_DELETE_ON_CLOSE));
659 ASSERT_TRUE(file_.IsValid());
660 }
661
662 // Writes data to the file, leaving the current position at the end of the
663 // write.
664 void PopulateFile() {
665 static const char kSomeData[] = "this sure is some data.";
666 static const size_t kSomeDataLen = sizeof(kSomeData) - 1;
667 ASSERT_NE(-1LL, file_.Write(0LL, kSomeData, kSomeDataLen));
668 }
669
670 base::FilePath temp_file_path_;
671 base::File file_;
672 };
673
674 TEST_F(FileWriterDelegateTest, WriteToStartAndTruncate) {
675 // Write stuff and advance.
676 PopulateFile();
677
678 // This should rewind, write, then truncate.
679 static const char kSomeData[] = "short";
680 static const int kSomeDataLen = sizeof(kSomeData) - 1;
681 {
682 FileWriterDelegate writer(&file_);
683 ASSERT_TRUE(writer.PrepareOutput());
684 ASSERT_TRUE(writer.WriteBytes(kSomeData, kSomeDataLen));
685 }
686 ASSERT_EQ(kSomeDataLen, file_.GetLength());
687 char buf[kSomeDataLen] = {};
688 ASSERT_EQ(kSomeDataLen, file_.Read(0LL, buf, kSomeDataLen));
689 ASSERT_EQ(std::string(kSomeData), std::string(buf, kSomeDataLen));
690 }
691
692 } // namespace zip
OLDNEW
« no previous file with comments | « third_party/zlib/google/zip_reader.cc ('k') | third_party/zlib/google/zip_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698