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.
5 #include "third_party/zlib/google/zip_reader.h"
10 #include "base/bind.h"
11 #include "base/file_util.h"
12 #include "base/files/file.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/logging.h"
16 #include "base/path_service.h"
17 #include "base/run_loop.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/time/time.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "testing/platform_test.h"
23 #include "third_party/zlib/google/zip_internal.h"
27 const static std::string kQuuxExpectedMD5
= "d1ae4ac8a17a0e09317113ab284b57a6";
36 FileWrapper(const base::FilePath
& path
, AccessMode mode
) {
37 int flags
= base::File::FLAG_READ
;
38 if (mode
== READ_ONLY
)
39 flags
|= base::File::FLAG_OPEN
;
41 flags
|= base::File::FLAG_WRITE
| base::File::FLAG_CREATE_ALWAYS
;
43 file_
.Initialize(path
, flags
);
48 base::PlatformFile
platform_file() { return file_
.GetPlatformFile(); }
54 // A mock that provides methods that can be used as callbacks in asynchronous
55 // unzip functions. Tracks the number of calls and number of bytes reported.
56 // Assumes that progress callbacks will be executed in-order.
57 class MockUnzipListener
: public base::SupportsWeakPtr
<MockUnzipListener
> {
63 current_progress_(0) {
66 // Success callback for async functions.
67 void OnUnzipSuccess() {
71 // Failure callback for async functions.
72 void OnUnzipFailure() {
76 // Progress callback for async functions.
77 void OnUnzipProgress(int64 progress
) {
78 DCHECK(progress
> current_progress_
);
80 current_progress_
= progress
;
83 int success_calls() { return success_calls_
; }
84 int failure_calls() { return failure_calls_
; }
85 int progress_calls() { return progress_calls_
; }
86 int current_progress() { return current_progress_
; }
93 int64 current_progress_
;
100 // Make the test a PlatformTest to setup autorelease pools properly on Mac.
101 class ZipReaderTest
: public PlatformTest
{
103 virtual void SetUp() {
104 PlatformTest::SetUp();
106 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
107 test_dir_
= temp_dir_
.path();
109 ASSERT_TRUE(GetTestDataDirectory(&test_data_dir_
));
111 test_zip_file_
= test_data_dir_
.AppendASCII("test.zip");
112 evil_zip_file_
= test_data_dir_
.AppendASCII("evil.zip");
113 evil_via_invalid_utf8_zip_file_
= test_data_dir_
.AppendASCII(
114 "evil_via_invalid_utf8.zip");
115 evil_via_absolute_file_name_zip_file_
= test_data_dir_
.AppendASCII(
116 "evil_via_absolute_file_name.zip");
118 test_zip_contents_
.insert(base::FilePath(FILE_PATH_LITERAL("foo/")));
119 test_zip_contents_
.insert(base::FilePath(FILE_PATH_LITERAL("foo/bar/")));
120 test_zip_contents_
.insert(
121 base::FilePath(FILE_PATH_LITERAL("foo/bar/baz.txt")));
122 test_zip_contents_
.insert(
123 base::FilePath(FILE_PATH_LITERAL("foo/bar/quux.txt")));
124 test_zip_contents_
.insert(
125 base::FilePath(FILE_PATH_LITERAL("foo/bar.txt")));
126 test_zip_contents_
.insert(base::FilePath(FILE_PATH_LITERAL("foo.txt")));
127 test_zip_contents_
.insert(
128 base::FilePath(FILE_PATH_LITERAL("foo/bar/.hidden")));
131 virtual void TearDown() {
132 PlatformTest::TearDown();
135 bool GetTestDataDirectory(base::FilePath
* path
) {
136 bool success
= PathService::Get(base::DIR_SOURCE_ROOT
, path
);
137 EXPECT_TRUE(success
);
140 *path
= path
->AppendASCII("third_party");
141 *path
= path
->AppendASCII("zlib");
142 *path
= path
->AppendASCII("google");
143 *path
= path
->AppendASCII("test");
144 *path
= path
->AppendASCII("data");
148 bool CompareFileAndMD5(const base::FilePath
& path
,
149 const std::string expected_md5
) {
150 // Read the output file and compute the MD5.
152 if (!base::ReadFileToString(path
, &output
))
154 const std::string md5
= base::MD5String(output
);
155 return expected_md5
== md5
;
158 // The path to temporary directory used to contain the test operations.
159 base::FilePath test_dir_
;
160 // The path to the test data directory where test.zip etc. are located.
161 base::FilePath test_data_dir_
;
162 // The path to test.zip in the test data directory.
163 base::FilePath test_zip_file_
;
164 // The path to evil.zip in the test data directory.
165 base::FilePath evil_zip_file_
;
166 // The path to evil_via_invalid_utf8.zip in the test data directory.
167 base::FilePath evil_via_invalid_utf8_zip_file_
;
168 // The path to evil_via_absolute_file_name.zip in the test data directory.
169 base::FilePath evil_via_absolute_file_name_zip_file_
;
170 std::set
<base::FilePath
> test_zip_contents_
;
172 base::ScopedTempDir temp_dir_
;
174 base::MessageLoop message_loop_
;
177 TEST_F(ZipReaderTest
, Open_ValidZipFile
) {
179 ASSERT_TRUE(reader
.Open(test_zip_file_
));
182 TEST_F(ZipReaderTest
, Open_ValidZipPlatformFile
) {
184 FileWrapper
zip_fd_wrapper(test_zip_file_
, FileWrapper::READ_ONLY
);
185 ASSERT_TRUE(reader
.OpenFromPlatformFile(zip_fd_wrapper
.platform_file()));
188 TEST_F(ZipReaderTest
, Open_NonExistentFile
) {
190 ASSERT_FALSE(reader
.Open(test_data_dir_
.AppendASCII("nonexistent.zip")));
193 TEST_F(ZipReaderTest
, Open_ExistentButNonZipFile
) {
195 ASSERT_FALSE(reader
.Open(test_data_dir_
.AppendASCII("create_test_zip.sh")));
198 // Iterate through the contents in the test zip file, and compare that the
199 // contents collected from the zip reader matches the expected contents.
200 TEST_F(ZipReaderTest
, Iteration
) {
201 std::set
<base::FilePath
> actual_contents
;
203 ASSERT_TRUE(reader
.Open(test_zip_file_
));
204 while (reader
.HasMore()) {
205 ASSERT_TRUE(reader
.OpenCurrentEntryInZip());
206 actual_contents
.insert(reader
.current_entry_info()->file_path());
207 ASSERT_TRUE(reader
.AdvanceToNextEntry());
209 EXPECT_FALSE(reader
.AdvanceToNextEntry()); // Shouldn't go further.
210 EXPECT_EQ(test_zip_contents_
.size(),
211 static_cast<size_t>(reader
.num_entries()));
212 EXPECT_EQ(test_zip_contents_
.size(), actual_contents
.size());
213 EXPECT_EQ(test_zip_contents_
, actual_contents
);
216 // Open the test zip file from a file descriptor, iterate through its contents,
217 // and compare that they match the expected contents.
218 TEST_F(ZipReaderTest
, PlatformFileIteration
) {
219 std::set
<base::FilePath
> actual_contents
;
221 FileWrapper
zip_fd_wrapper(test_zip_file_
, FileWrapper::READ_ONLY
);
222 ASSERT_TRUE(reader
.OpenFromPlatformFile(zip_fd_wrapper
.platform_file()));
223 while (reader
.HasMore()) {
224 ASSERT_TRUE(reader
.OpenCurrentEntryInZip());
225 actual_contents
.insert(reader
.current_entry_info()->file_path());
226 ASSERT_TRUE(reader
.AdvanceToNextEntry());
228 EXPECT_FALSE(reader
.AdvanceToNextEntry()); // Shouldn't go further.
229 EXPECT_EQ(test_zip_contents_
.size(),
230 static_cast<size_t>(reader
.num_entries()));
231 EXPECT_EQ(test_zip_contents_
.size(), actual_contents
.size());
232 EXPECT_EQ(test_zip_contents_
, actual_contents
);
235 TEST_F(ZipReaderTest
, LocateAndOpenEntry_ValidFile
) {
236 std::set
<base::FilePath
> actual_contents
;
238 ASSERT_TRUE(reader
.Open(test_zip_file_
));
239 base::FilePath
target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
240 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
241 EXPECT_EQ(target_path
, reader
.current_entry_info()->file_path());
244 TEST_F(ZipReaderTest
, LocateAndOpenEntry_NonExistentFile
) {
245 std::set
<base::FilePath
> actual_contents
;
247 ASSERT_TRUE(reader
.Open(test_zip_file_
));
248 base::FilePath
target_path(FILE_PATH_LITERAL("nonexistent.txt"));
249 ASSERT_FALSE(reader
.LocateAndOpenEntry(target_path
));
250 EXPECT_EQ(NULL
, reader
.current_entry_info());
253 TEST_F(ZipReaderTest
, ExtractCurrentEntryToFilePath_RegularFile
) {
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 ASSERT_TRUE(reader
.ExtractCurrentEntryToFilePath(
259 test_dir_
.AppendASCII("quux.txt")));
260 // Read the output file ans compute the MD5.
262 ASSERT_TRUE(base::ReadFileToString(test_dir_
.AppendASCII("quux.txt"),
264 const std::string md5
= base::MD5String(output
);
265 EXPECT_EQ(kQuuxExpectedMD5
, md5
);
266 // quux.txt should be larger than kZipBufSize so that we can exercise
267 // the loop in ExtractCurrentEntry().
268 EXPECT_LT(static_cast<size_t>(internal::kZipBufSize
), output
.size());
271 TEST_F(ZipReaderTest
, PlatformFileExtractCurrentEntryToFilePath_RegularFile
) {
273 FileWrapper
zip_fd_wrapper(test_zip_file_
, FileWrapper::READ_ONLY
);
274 ASSERT_TRUE(reader
.OpenFromPlatformFile(zip_fd_wrapper
.platform_file()));
275 base::FilePath
target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
276 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
277 ASSERT_TRUE(reader
.ExtractCurrentEntryToFilePath(
278 test_dir_
.AppendASCII("quux.txt")));
279 // Read the output file and compute the MD5.
281 ASSERT_TRUE(base::ReadFileToString(test_dir_
.AppendASCII("quux.txt"),
283 const std::string md5
= base::MD5String(output
);
284 EXPECT_EQ(kQuuxExpectedMD5
, md5
);
285 // quux.txt should be larger than kZipBufSize so that we can exercise
286 // the loop in ExtractCurrentEntry().
287 EXPECT_LT(static_cast<size_t>(internal::kZipBufSize
), output
.size());
290 #if defined(OS_POSIX)
291 TEST_F(ZipReaderTest
, PlatformFileExtractCurrentEntryToFd_RegularFile
) {
293 FileWrapper
zip_fd_wrapper(test_zip_file_
, FileWrapper::READ_ONLY
);
294 ASSERT_TRUE(reader
.OpenFromPlatformFile(zip_fd_wrapper
.platform_file()));
295 base::FilePath
target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
296 base::FilePath out_path
= test_dir_
.AppendASCII("quux.txt");
297 FileWrapper
out_fd_w(out_path
, FileWrapper::READ_WRITE
);
298 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
299 ASSERT_TRUE(reader
.ExtractCurrentEntryToFd(out_fd_w
.platform_file()));
300 // Read the output file and compute the MD5.
302 ASSERT_TRUE(base::ReadFileToString(test_dir_
.AppendASCII("quux.txt"),
304 const std::string md5
= base::MD5String(output
);
305 EXPECT_EQ(kQuuxExpectedMD5
, md5
);
306 // quux.txt should be larger than kZipBufSize so that we can exercise
307 // the loop in ExtractCurrentEntry().
308 EXPECT_LT(static_cast<size_t>(internal::kZipBufSize
), output
.size());
312 TEST_F(ZipReaderTest
, ExtractCurrentEntryToFilePath_Directory
) {
314 ASSERT_TRUE(reader
.Open(test_zip_file_
));
315 base::FilePath
target_path(FILE_PATH_LITERAL("foo/"));
316 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
317 ASSERT_TRUE(reader
.ExtractCurrentEntryToFilePath(
318 test_dir_
.AppendASCII("foo")));
319 // The directory should be created.
320 ASSERT_TRUE(base::DirectoryExists(test_dir_
.AppendASCII("foo")));
323 TEST_F(ZipReaderTest
, ExtractCurrentEntryIntoDirectory_RegularFile
) {
325 ASSERT_TRUE(reader
.Open(test_zip_file_
));
326 base::FilePath
target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
327 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
328 ASSERT_TRUE(reader
.ExtractCurrentEntryIntoDirectory(test_dir_
));
329 // Sub directories should be created.
330 ASSERT_TRUE(base::DirectoryExists(test_dir_
.AppendASCII("foo/bar")));
331 // And the file should be created.
333 ASSERT_TRUE(base::ReadFileToString(
334 test_dir_
.AppendASCII("foo/bar/quux.txt"), &output
));
335 const std::string md5
= base::MD5String(output
);
336 EXPECT_EQ(kQuuxExpectedMD5
, md5
);
339 TEST_F(ZipReaderTest
, current_entry_info_RegularFile
) {
341 ASSERT_TRUE(reader
.Open(test_zip_file_
));
342 base::FilePath
target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
343 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
344 ZipReader::EntryInfo
* current_entry_info
= reader
.current_entry_info();
346 EXPECT_EQ(target_path
, current_entry_info
->file_path());
347 EXPECT_EQ(13527, current_entry_info
->original_size());
349 // The expected time stamp: 2009-05-29 06:22:20
350 base::Time::Exploded exploded
= {}; // Zero-clear.
351 current_entry_info
->last_modified().LocalExplode(&exploded
);
352 EXPECT_EQ(2009, exploded
.year
);
353 EXPECT_EQ(5, exploded
.month
);
354 EXPECT_EQ(29, exploded
.day_of_month
);
355 EXPECT_EQ(6, exploded
.hour
);
356 EXPECT_EQ(22, exploded
.minute
);
357 EXPECT_EQ(20, exploded
.second
);
358 EXPECT_EQ(0, exploded
.millisecond
);
360 EXPECT_FALSE(current_entry_info
->is_unsafe());
361 EXPECT_FALSE(current_entry_info
->is_directory());
364 TEST_F(ZipReaderTest
, current_entry_info_DotDotFile
) {
366 ASSERT_TRUE(reader
.Open(evil_zip_file_
));
367 base::FilePath
target_path(FILE_PATH_LITERAL(
368 "../levilevilevilevilevilevilevilevilevilevilevilevil"));
369 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
370 ZipReader::EntryInfo
* current_entry_info
= reader
.current_entry_info();
371 EXPECT_EQ(target_path
, current_entry_info
->file_path());
373 // This file is unsafe because of ".." in the file name.
374 EXPECT_TRUE(current_entry_info
->is_unsafe());
375 EXPECT_FALSE(current_entry_info
->is_directory());
378 TEST_F(ZipReaderTest
, current_entry_info_InvalidUTF8File
) {
380 ASSERT_TRUE(reader
.Open(evil_via_invalid_utf8_zip_file_
));
381 // The evil file is the 2nd file in the zip file.
382 // We cannot locate by the file name ".\x80.\\evil.txt",
383 // as FilePath may internally convert the string.
384 ASSERT_TRUE(reader
.AdvanceToNextEntry());
385 ASSERT_TRUE(reader
.OpenCurrentEntryInZip());
386 ZipReader::EntryInfo
* current_entry_info
= reader
.current_entry_info();
388 // This file is unsafe because of invalid UTF-8 in the file name.
389 EXPECT_TRUE(current_entry_info
->is_unsafe());
390 EXPECT_FALSE(current_entry_info
->is_directory());
393 TEST_F(ZipReaderTest
, current_entry_info_AbsoluteFile
) {
395 ASSERT_TRUE(reader
.Open(evil_via_absolute_file_name_zip_file_
));
396 base::FilePath
target_path(FILE_PATH_LITERAL("/evil.txt"));
397 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
398 ZipReader::EntryInfo
* current_entry_info
= reader
.current_entry_info();
399 EXPECT_EQ(target_path
, current_entry_info
->file_path());
401 // This file is unsafe because of the absolute file name.
402 EXPECT_TRUE(current_entry_info
->is_unsafe());
403 EXPECT_FALSE(current_entry_info
->is_directory());
406 TEST_F(ZipReaderTest
, current_entry_info_Directory
) {
408 ASSERT_TRUE(reader
.Open(test_zip_file_
));
409 base::FilePath
target_path(FILE_PATH_LITERAL("foo/bar/"));
410 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
411 ZipReader::EntryInfo
* current_entry_info
= reader
.current_entry_info();
413 EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("foo/bar/")),
414 current_entry_info
->file_path());
415 // The directory size should be zero.
416 EXPECT_EQ(0, current_entry_info
->original_size());
418 // The expected time stamp: 2009-05-31 15:49:52
419 base::Time::Exploded exploded
= {}; // Zero-clear.
420 current_entry_info
->last_modified().LocalExplode(&exploded
);
421 EXPECT_EQ(2009, exploded
.year
);
422 EXPECT_EQ(5, exploded
.month
);
423 EXPECT_EQ(31, exploded
.day_of_month
);
424 EXPECT_EQ(15, exploded
.hour
);
425 EXPECT_EQ(49, exploded
.minute
);
426 EXPECT_EQ(52, exploded
.second
);
427 EXPECT_EQ(0, exploded
.millisecond
);
429 EXPECT_FALSE(current_entry_info
->is_unsafe());
430 EXPECT_TRUE(current_entry_info
->is_directory());
433 // Verifies that the ZipReader class can extract a file from a zip archive
434 // stored in memory. This test opens a zip archive in a std::string object,
435 // extracts its content, and verifies the content is the same as the expected
437 TEST_F(ZipReaderTest
, OpenFromString
) {
438 // A zip archive consisting of one file "test.txt", which is a 16-byte text
439 // file that contains "This is a test.\n".
440 const char kTestData
[] =
441 "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\xa4\x66\x24\x41\x13\xe8"
442 "\xcb\x27\x10\x00\x00\x00\x10\x00\x00\x00\x08\x00\x1c\x00\x74\x65"
443 "\x73\x74\x2e\x74\x78\x74\x55\x54\x09\x00\x03\x34\x89\x45\x50\x34"
444 "\x89\x45\x50\x75\x78\x0b\x00\x01\x04\x8e\xf0\x00\x00\x04\x88\x13"
445 "\x00\x00\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74"
446 "\x2e\x0a\x50\x4b\x01\x02\x1e\x03\x0a\x00\x00\x00\x00\x00\xa4\x66"
447 "\x24\x41\x13\xe8\xcb\x27\x10\x00\x00\x00\x10\x00\x00\x00\x08\x00"
448 "\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa4\x81\x00\x00\x00\x00"
449 "\x74\x65\x73\x74\x2e\x74\x78\x74\x55\x54\x05\x00\x03\x34\x89\x45"
450 "\x50\x75\x78\x0b\x00\x01\x04\x8e\xf0\x00\x00\x04\x88\x13\x00\x00"
451 "\x50\x4b\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00\x4e\x00\x00\x00"
452 "\x52\x00\x00\x00\x00\x00";
453 std::string
data(kTestData
, arraysize(kTestData
));
455 ASSERT_TRUE(reader
.OpenFromString(data
));
456 base::FilePath
target_path(FILE_PATH_LITERAL("test.txt"));
457 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
458 ASSERT_TRUE(reader
.ExtractCurrentEntryToFilePath(
459 test_dir_
.AppendASCII("test.txt")));
462 ASSERT_TRUE(base::ReadFileToString(
463 test_dir_
.AppendASCII("test.txt"), &actual
));
464 EXPECT_EQ(std::string("This is a test.\n"), actual
);
467 // Verifies that the asynchronous extraction to a file works.
468 TEST_F(ZipReaderTest
, ExtractToFileAsync_RegularFile
) {
469 MockUnzipListener listener
;
472 base::FilePath target_file
= test_dir_
.AppendASCII("quux.txt");
473 base::FilePath
target_path(FILE_PATH_LITERAL("foo/bar/quux.txt"));
474 ASSERT_TRUE(reader
.Open(test_zip_file_
));
475 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
476 reader
.ExtractCurrentEntryToFilePathAsync(
478 base::Bind(&MockUnzipListener::OnUnzipSuccess
,
479 listener
.AsWeakPtr()),
480 base::Bind(&MockUnzipListener::OnUnzipFailure
,
481 listener
.AsWeakPtr()),
482 base::Bind(&MockUnzipListener::OnUnzipProgress
,
483 listener
.AsWeakPtr()));
485 EXPECT_EQ(0, listener
.success_calls());
486 EXPECT_EQ(0, listener
.failure_calls());
487 EXPECT_EQ(0, listener
.progress_calls());
489 base::RunLoop().RunUntilIdle();
491 EXPECT_EQ(1, listener
.success_calls());
492 EXPECT_EQ(0, listener
.failure_calls());
493 EXPECT_LE(1, listener
.progress_calls());
496 ASSERT_TRUE(base::ReadFileToString(test_dir_
.AppendASCII("quux.txt"),
498 const std::string md5
= base::MD5String(output
);
499 EXPECT_EQ(kQuuxExpectedMD5
, md5
);
502 ASSERT_TRUE(base::GetFileSize(target_file
, &file_size
));
504 EXPECT_EQ(file_size
, listener
.current_progress());
507 // Verifies that the asynchronous extraction to a file works.
508 TEST_F(ZipReaderTest
, ExtractToFileAsync_Directory
) {
509 MockUnzipListener listener
;
512 base::FilePath target_file
= test_dir_
.AppendASCII("foo");
513 base::FilePath
target_path(FILE_PATH_LITERAL("foo/"));
514 ASSERT_TRUE(reader
.Open(test_zip_file_
));
515 ASSERT_TRUE(reader
.LocateAndOpenEntry(target_path
));
516 reader
.ExtractCurrentEntryToFilePathAsync(
518 base::Bind(&MockUnzipListener::OnUnzipSuccess
,
519 listener
.AsWeakPtr()),
520 base::Bind(&MockUnzipListener::OnUnzipFailure
,
521 listener
.AsWeakPtr()),
522 base::Bind(&MockUnzipListener::OnUnzipProgress
,
523 listener
.AsWeakPtr()));
525 EXPECT_EQ(0, listener
.success_calls());
526 EXPECT_EQ(0, listener
.failure_calls());
527 EXPECT_EQ(0, listener
.progress_calls());
529 base::RunLoop().RunUntilIdle();
531 EXPECT_EQ(1, listener
.success_calls());
532 EXPECT_EQ(0, listener
.failure_calls());
533 EXPECT_GE(0, listener
.progress_calls());
535 ASSERT_TRUE(base::DirectoryExists(target_file
));
538 TEST_F(ZipReaderTest
, ExtractCurrentEntryToString
) {
539 // test_mismatch_size.zip contains files with names from 0.txt to 7.txt with
540 // sizes from 0 to 7 bytes respectively, being the contents of each file a
541 // substring of "0123456" starting at '0'.
542 base::FilePath test_zip_file
=
543 test_data_dir_
.AppendASCII("test_mismatch_size.zip");
546 std::string contents
;
547 ASSERT_TRUE(reader
.Open(test_zip_file
));
549 for (size_t i
= 0; i
< 8; i
++) {
550 SCOPED_TRACE(base::StringPrintf("Processing %d.txt", static_cast<int>(i
)));
552 base::FilePath file_name
= base::FilePath::FromUTF8Unsafe(
553 base::StringPrintf("%d.txt", static_cast<int>(i
)));
554 ASSERT_TRUE(reader
.LocateAndOpenEntry(file_name
));
557 // Off by one byte read limit: must fail.
558 EXPECT_FALSE(reader
.ExtractCurrentEntryToString(i
- 1, &contents
));
562 // Exact byte read limit: must pass.
563 EXPECT_TRUE(reader
.ExtractCurrentEntryToString(i
, &contents
));
564 EXPECT_EQ(i
, contents
.size());
565 EXPECT_EQ(0, memcmp(contents
.c_str(), "0123456", i
));
568 // More than necessary byte read limit: must pass.
569 EXPECT_TRUE(reader
.ExtractCurrentEntryToString(16, &contents
));
570 EXPECT_EQ(i
, contents
.size());
571 EXPECT_EQ(0, memcmp(contents
.c_str(), "0123456", i
));