• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stddef.h>
6 #include <stdint.h>
7 
8 #include <map>
9 #include <set>
10 #include <string>
11 #include <vector>
12 
13 #include "base/bind.h"
14 #include "base/files/file.h"
15 #include "base/files/file_enumerator.h"
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/files/scoped_temp_dir.h"
19 #include "base/macros.h"
20 #include "base/path_service.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "build/build_config.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "testing/platform_test.h"
26 #include "third_party/zlib/google/zip.h"
27 #include "third_party/zlib/google/zip_reader.h"
28 
29 namespace {
30 
CreateFile(const std::string & content,base::FilePath * file_path,base::File * file)31 bool CreateFile(const std::string& content,
32                 base::FilePath* file_path,
33                 base::File* file) {
34   if (!base::CreateTemporaryFile(file_path))
35     return false;
36 
37   if (base::WriteFile(*file_path, content.data(), content.size()) == -1)
38     return false;
39 
40   *file = base::File(
41       *file_path, base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ);
42   return file->IsValid();
43 }
44 
45 // A virtual file system containing:
46 // /test
47 // /test/foo.txt
48 // /test/bar/bar1.txt
49 // /test/bar/bar2.txt
50 // Used to test providing a custom zip::FileAccessor when unzipping.
51 class VirtualFileSystem : public zip::FileAccessor {
52  public:
53   static constexpr char kFooContent[] = "This is foo.";
54   static constexpr char kBar1Content[] = "This is bar.";
55   static constexpr char kBar2Content[] = "This is bar too.";
56 
VirtualFileSystem()57   VirtualFileSystem() {
58     base::FilePath test_dir(FILE_PATH_LITERAL("/test"));
59     base::FilePath foo_txt_path = test_dir.Append(FILE_PATH_LITERAL("foo.txt"));
60 
61     base::FilePath file_path;
62     base::File file;
63     bool success = CreateFile(kFooContent, &file_path, &file);
64     DCHECK(success);
65     files_[foo_txt_path] = std::move(file);
66 
67     base::FilePath bar_dir = test_dir.Append(FILE_PATH_LITERAL("bar"));
68     base::FilePath bar1_txt_path =
69         bar_dir.Append(FILE_PATH_LITERAL("bar1.txt"));
70     success = CreateFile(kBar1Content, &file_path, &file);
71     DCHECK(success);
72     files_[bar1_txt_path] = std::move(file);
73 
74     base::FilePath bar2_txt_path =
75         bar_dir.Append(FILE_PATH_LITERAL("bar2.txt"));
76     success = CreateFile(kBar2Content, &file_path, &file);
77     DCHECK(success);
78     files_[bar2_txt_path] = std::move(file);
79 
80     file_tree_[test_dir] = std::vector<DirectoryContentEntry>{
81         DirectoryContentEntry(foo_txt_path, /*is_dir=*/false),
82         DirectoryContentEntry(bar_dir, /*is_dir=*/true)};
83     file_tree_[bar_dir] = std::vector<DirectoryContentEntry>{
84         DirectoryContentEntry(bar1_txt_path, /*is_dir=*/false),
85         DirectoryContentEntry(bar2_txt_path, /*is_dir=*/false)};
86   }
87   ~VirtualFileSystem() override = default;
88 
89  private:
OpenFilesForReading(const std::vector<base::FilePath> & paths)90   std::vector<base::File> OpenFilesForReading(
91       const std::vector<base::FilePath>& paths) override {
92     std::vector<base::File> files;
93     for (const auto& path : paths) {
94       auto iter = files_.find(path);
95       files.push_back(iter == files_.end() ? base::File()
96                                            : std::move(iter->second));
97     }
98     return files;
99   }
100 
DirectoryExists(const base::FilePath & file)101   bool DirectoryExists(const base::FilePath& file) override {
102     return file_tree_.count(file) == 1 && files_.count(file) == 0;
103   }
104 
ListDirectoryContent(const base::FilePath & dir)105   std::vector<DirectoryContentEntry> ListDirectoryContent(
106       const base::FilePath& dir) override {
107     auto iter = file_tree_.find(dir);
108     if (iter == file_tree_.end()) {
109       NOTREACHED();
110       return std::vector<DirectoryContentEntry>();
111     }
112     return iter->second;
113   }
114 
GetLastModifiedTime(const base::FilePath & path)115   base::Time GetLastModifiedTime(const base::FilePath& path) override {
116     return base::Time::FromDoubleT(172097977);  // Some random date.
117   }
118 
119   std::map<base::FilePath, std::vector<DirectoryContentEntry>> file_tree_;
120   std::map<base::FilePath, base::File> files_;
121 
122   DISALLOW_COPY_AND_ASSIGN(VirtualFileSystem);
123 };
124 
125 // static
126 constexpr char VirtualFileSystem::kFooContent[];
127 constexpr char VirtualFileSystem::kBar1Content[];
128 constexpr char VirtualFileSystem::kBar2Content[];
129 
130 // Make the test a PlatformTest to setup autorelease pools properly on Mac.
131 class ZipTest : public PlatformTest {
132  protected:
133   enum ValidYearType {
134     VALID_YEAR,
135     INVALID_YEAR
136   };
137 
SetUp()138   virtual void SetUp() {
139     PlatformTest::SetUp();
140 
141     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
142     test_dir_ = temp_dir_.GetPath();
143 
144     base::FilePath zip_path(test_dir_);
145     zip_contents_.insert(zip_path.Append(FILE_PATH_LITERAL("foo.txt")));
146     zip_path = zip_path.Append(FILE_PATH_LITERAL("foo"));
147     zip_contents_.insert(zip_path);
148     zip_contents_.insert(zip_path.Append(FILE_PATH_LITERAL("bar.txt")));
149     zip_path = zip_path.Append(FILE_PATH_LITERAL("bar"));
150     zip_contents_.insert(zip_path);
151     zip_contents_.insert(zip_path.Append(FILE_PATH_LITERAL("baz.txt")));
152     zip_contents_.insert(zip_path.Append(FILE_PATH_LITERAL("quux.txt")));
153     zip_contents_.insert(zip_path.Append(FILE_PATH_LITERAL(".hidden")));
154 
155     // Include a subset of files in |zip_file_list_| to test ZipFiles().
156     zip_file_list_.push_back(base::FilePath(FILE_PATH_LITERAL("foo.txt")));
157     zip_file_list_.push_back(
158         base::FilePath(FILE_PATH_LITERAL("foo/bar/quux.txt")));
159     zip_file_list_.push_back(
160         base::FilePath(FILE_PATH_LITERAL("foo/bar/.hidden")));
161   }
162 
TearDown()163   virtual void TearDown() {
164     PlatformTest::TearDown();
165   }
166 
GetTestDataDirectory(base::FilePath * path)167   bool GetTestDataDirectory(base::FilePath* path) {
168     bool success = base::PathService::Get(base::DIR_SOURCE_ROOT, path);
169     EXPECT_TRUE(success);
170     if (!success)
171       return false;
172     *path = path->AppendASCII("third_party");
173     *path = path->AppendASCII("zlib");
174     *path = path->AppendASCII("google");
175     *path = path->AppendASCII("test");
176     *path = path->AppendASCII("data");
177     return true;
178   }
179 
TestUnzipFile(const base::FilePath::StringType & filename,bool expect_hidden_files)180   void TestUnzipFile(const base::FilePath::StringType& filename,
181                      bool expect_hidden_files) {
182     base::FilePath test_dir;
183     ASSERT_TRUE(GetTestDataDirectory(&test_dir));
184     TestUnzipFile(test_dir.Append(filename), expect_hidden_files);
185   }
186 
TestUnzipFile(const base::FilePath & path,bool expect_hidden_files)187   void TestUnzipFile(const base::FilePath& path, bool expect_hidden_files) {
188     ASSERT_TRUE(base::PathExists(path)) << "no file " << path.value();
189     ASSERT_TRUE(zip::Unzip(path, test_dir_));
190 
191     base::FilePath original_dir;
192     ASSERT_TRUE(GetTestDataDirectory(&original_dir));
193     original_dir = original_dir.AppendASCII("test");
194 
195     base::FileEnumerator files(test_dir_, true,
196         base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
197     base::FilePath unzipped_entry_path = files.Next();
198     size_t count = 0;
199     while (!unzipped_entry_path.value().empty()) {
200       EXPECT_EQ(zip_contents_.count(unzipped_entry_path), 1U)
201           << "Couldn't find " << unzipped_entry_path.value();
202       count++;
203 
204       if (base::PathExists(unzipped_entry_path) &&
205           !base::DirectoryExists(unzipped_entry_path)) {
206         // It's a file, check its contents are what we zipped.
207         // TODO(774156): figure out why the commented out EXPECT_TRUE below
208         // fails on the build bots (but not on the try-bots).
209         base::FilePath relative_path;
210         bool append_relative_path_success =
211             test_dir_.AppendRelativePath(unzipped_entry_path, &relative_path);
212         if (!append_relative_path_success) {
213           LOG(ERROR) << "Append relative path failed, params: "
214                      << test_dir_.value() << " and "
215                      << unzipped_entry_path.value();
216         }
217         base::FilePath original_path = original_dir.Append(relative_path);
218         LOG(ERROR) << "Comparing original " << original_path.value()
219                    << " and unzipped file " << unzipped_entry_path.value()
220                    << " result: "
221                    << base::ContentsEqual(original_path, unzipped_entry_path);
222         // EXPECT_TRUE(base::ContentsEqual(original_path, unzipped_entry_path))
223         //    << "Contents differ between original " << original_path.value()
224         //    << " and unzipped file " << unzipped_entry_path.value();
225       }
226       unzipped_entry_path = files.Next();
227     }
228 
229     size_t expected_count = 0;
230     for (std::set<base::FilePath>::iterator iter = zip_contents_.begin();
231          iter != zip_contents_.end(); ++iter) {
232       if (expect_hidden_files || iter->BaseName().value()[0] != '.')
233         ++expected_count;
234     }
235 
236     EXPECT_EQ(expected_count, count);
237   }
238 
239   // This function does the following:
240   // 1) Creates a test.txt file with the given last modification timestamp
241   // 2) Zips test.txt and extracts it back into a different location.
242   // 3) Confirms that test.txt in the output directory has the specified
243   //    last modification timestamp if it is valid (|valid_year| is true).
244   //    If the timestamp is not supported by the zip format, the last
245   //    modification defaults to the current time.
TestTimeStamp(const char * date_time,ValidYearType valid_year)246   void TestTimeStamp(const char* date_time, ValidYearType valid_year) {
247     SCOPED_TRACE(std::string("TestTimeStamp(") + date_time + ")");
248     base::ScopedTempDir temp_dir;
249     ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
250 
251     base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
252     base::FilePath src_dir = temp_dir.GetPath().AppendASCII("input");
253     base::FilePath out_dir = temp_dir.GetPath().AppendASCII("output");
254 
255     base::FilePath src_file = src_dir.AppendASCII("test.txt");
256     base::FilePath out_file = out_dir.AppendASCII("test.txt");
257 
258     EXPECT_TRUE(base::CreateDirectory(src_dir));
259     EXPECT_TRUE(base::CreateDirectory(out_dir));
260 
261     base::Time test_mtime;
262     ASSERT_TRUE(base::Time::FromString(date_time, &test_mtime));
263 
264     // Adjusting the current timestamp to the resolution that the zip file
265     // supports, which is 2 seconds. Note that between this call to Time::Now()
266     // and zip::Zip() the clock can advance a bit, hence the use of EXPECT_GE.
267     base::Time::Exploded now_parts;
268     base::Time::Now().LocalExplode(&now_parts);
269     now_parts.second = now_parts.second & ~1;
270     now_parts.millisecond = 0;
271     base::Time now_time;
272     EXPECT_TRUE(base::Time::FromLocalExploded(now_parts, &now_time));
273 
274     EXPECT_EQ(1, base::WriteFile(src_file, "1", 1));
275     EXPECT_TRUE(base::TouchFile(src_file, base::Time::Now(), test_mtime));
276 
277     EXPECT_TRUE(zip::Zip(src_dir, zip_file, true));
278     ASSERT_TRUE(zip::Unzip(zip_file, out_dir));
279 
280     base::File::Info file_info;
281     EXPECT_TRUE(base::GetFileInfo(out_file, &file_info));
282     EXPECT_EQ(file_info.size, 1);
283 
284     if (valid_year == VALID_YEAR) {
285       EXPECT_EQ(file_info.last_modified, test_mtime);
286     } else {
287       // Invalid date means the modification time will default to 'now'.
288       EXPECT_GE(file_info.last_modified, now_time);
289     }
290   }
291 
292   // The path to temporary directory used to contain the test operations.
293   base::FilePath test_dir_;
294 
295   base::ScopedTempDir temp_dir_;
296 
297   // Hard-coded contents of a known zip file.
298   std::set<base::FilePath> zip_contents_;
299 
300   // Hard-coded list of relative paths for a zip file created with ZipFiles.
301   std::vector<base::FilePath> zip_file_list_;
302 };
303 
TEST_F(ZipTest,Unzip)304 TEST_F(ZipTest, Unzip) {
305   TestUnzipFile(FILE_PATH_LITERAL("test.zip"), true);
306 }
307 
TEST_F(ZipTest,UnzipUncompressed)308 TEST_F(ZipTest, UnzipUncompressed) {
309   TestUnzipFile(FILE_PATH_LITERAL("test_nocompress.zip"), true);
310 }
311 
TEST_F(ZipTest,UnzipEvil)312 TEST_F(ZipTest, UnzipEvil) {
313   base::FilePath path;
314   ASSERT_TRUE(GetTestDataDirectory(&path));
315   path = path.AppendASCII("evil.zip");
316   // Unzip the zip file into a sub directory of test_dir_ so evil.zip
317   // won't create a persistent file outside test_dir_ in case of a
318   // failure.
319   base::FilePath output_dir = test_dir_.AppendASCII("out");
320   ASSERT_FALSE(zip::Unzip(path, output_dir));
321   base::FilePath evil_file = output_dir;
322   evil_file = evil_file.AppendASCII(
323       "../levilevilevilevilevilevilevilevilevilevilevilevil");
324   ASSERT_FALSE(base::PathExists(evil_file));
325 }
326 
TEST_F(ZipTest,UnzipEvil2)327 TEST_F(ZipTest, UnzipEvil2) {
328   base::FilePath path;
329   ASSERT_TRUE(GetTestDataDirectory(&path));
330   // The zip file contains an evil file with invalid UTF-8 in its file
331   // name.
332   path = path.AppendASCII("evil_via_invalid_utf8.zip");
333   // See the comment at UnzipEvil() for why we do this.
334   base::FilePath output_dir = test_dir_.AppendASCII("out");
335   // This should fail as it contains an evil file.
336   ASSERT_FALSE(zip::Unzip(path, output_dir));
337   base::FilePath evil_file = output_dir;
338   evil_file = evil_file.AppendASCII("../evil.txt");
339   ASSERT_FALSE(base::PathExists(evil_file));
340 }
341 
TEST_F(ZipTest,UnzipWithFilter)342 TEST_F(ZipTest, UnzipWithFilter) {
343   auto filter = base::BindRepeating([](const base::FilePath& path) {
344     return path.BaseName().MaybeAsASCII() == "foo.txt";
345   });
346   base::FilePath path;
347   ASSERT_TRUE(GetTestDataDirectory(&path));
348   ASSERT_TRUE(zip::UnzipWithFilterCallback(path.AppendASCII("test.zip"),
349                                            test_dir_, filter, false));
350   // Only foo.txt should have been extracted. The following paths should not
351   // be extracted:
352   //   foo/
353   //   foo/bar.txt
354   //   foo/bar/
355   //   foo/bar/.hidden
356   //   foo/bar/baz.txt
357   //   foo/bar/quux.txt
358   ASSERT_TRUE(base::PathExists(test_dir_.AppendASCII("foo.txt")));
359   base::FileEnumerator extractedFiles(
360       test_dir_,
361       false,  // Do not enumerate recursively - the file must be in the root.
362       base::FileEnumerator::FileType::FILES);
363   int extracted_count = 0;
364   while (!extractedFiles.Next().empty())
365     ++extracted_count;
366   ASSERT_EQ(1, extracted_count);
367 
368   base::FileEnumerator extractedDirs(
369       test_dir_,
370       false,  // Do not enumerate recursively - we require zero directories.
371       base::FileEnumerator::FileType::DIRECTORIES);
372   extracted_count = 0;
373   while (!extractedDirs.Next().empty())
374     ++extracted_count;
375   ASSERT_EQ(0, extracted_count);
376 }
377 
TEST_F(ZipTest,UnzipWithDelegates)378 TEST_F(ZipTest, UnzipWithDelegates) {
379   auto filter =
380       base::BindRepeating([](const base::FilePath& path) { return true; });
381   auto dir_creator = base::BindRepeating(
382       [](const base::FilePath& extract_dir, const base::FilePath& entry_path) {
383         return base::CreateDirectory(extract_dir.Append(entry_path));
384       },
385       test_dir_);
386   auto writer = base::BindRepeating(
387       [](const base::FilePath& extract_dir, const base::FilePath& entry_path)
388           -> std::unique_ptr<zip::WriterDelegate> {
389         return std::make_unique<zip::FilePathWriterDelegate>(
390             extract_dir.Append(entry_path));
391       },
392       test_dir_);
393   base::FilePath path;
394   ASSERT_TRUE(GetTestDataDirectory(&path));
395   base::File file(path.AppendASCII("test.zip"),
396                   base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ);
397   ASSERT_TRUE(zip::UnzipWithFilterAndWriters(file.GetPlatformFile(), writer,
398                                              dir_creator, filter, false));
399   base::FilePath dir = test_dir_;
400   base::FilePath dir_foo = dir.AppendASCII("foo");
401   base::FilePath dir_foo_bar = dir_foo.AppendASCII("bar");
402   ASSERT_TRUE(base::PathExists(dir.AppendASCII("foo.txt")));
403   ASSERT_TRUE(base::PathExists(dir_foo));
404   ASSERT_TRUE(base::PathExists(dir_foo.AppendASCII("bar.txt")));
405   ASSERT_TRUE(base::PathExists(dir_foo_bar));
406   ASSERT_TRUE(base::PathExists(dir_foo_bar.AppendASCII(".hidden")));
407   ASSERT_TRUE(base::PathExists(dir_foo_bar.AppendASCII("baz.txt")));
408   ASSERT_TRUE(base::PathExists(dir_foo_bar.AppendASCII("quux.txt")));
409 }
410 
TEST_F(ZipTest,Zip)411 TEST_F(ZipTest, Zip) {
412   base::FilePath src_dir;
413   ASSERT_TRUE(GetTestDataDirectory(&src_dir));
414   src_dir = src_dir.AppendASCII("test");
415 
416   base::ScopedTempDir temp_dir;
417   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
418   base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
419 
420   EXPECT_TRUE(zip::Zip(src_dir, zip_file, /*include_hidden_files=*/true));
421   TestUnzipFile(zip_file, true);
422 }
423 
TEST_F(ZipTest,ZipIgnoreHidden)424 TEST_F(ZipTest, ZipIgnoreHidden) {
425   base::FilePath src_dir;
426   ASSERT_TRUE(GetTestDataDirectory(&src_dir));
427   src_dir = src_dir.AppendASCII("test");
428 
429   base::ScopedTempDir temp_dir;
430   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
431   base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
432 
433   EXPECT_TRUE(zip::Zip(src_dir, zip_file, /*include_hidden_files=*/false));
434   TestUnzipFile(zip_file, false);
435 }
436 
TEST_F(ZipTest,ZipNonASCIIDir)437 TEST_F(ZipTest, ZipNonASCIIDir) {
438   base::FilePath src_dir;
439   ASSERT_TRUE(GetTestDataDirectory(&src_dir));
440   src_dir = src_dir.AppendASCII("test");
441 
442   base::ScopedTempDir temp_dir;
443   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
444   // Append 'Тест' (in cyrillic).
445   base::FilePath src_dir_russian = temp_dir.GetPath().Append(
446       base::FilePath::FromUTF8Unsafe("\xD0\xA2\xD0\xB5\xD1\x81\xD1\x82"));
447   base::CopyDirectory(src_dir, src_dir_russian, true);
448   base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out_russian.zip");
449 
450   EXPECT_TRUE(zip::Zip(src_dir_russian, zip_file, true));
451   TestUnzipFile(zip_file, true);
452 }
453 
TEST_F(ZipTest,ZipTimeStamp)454 TEST_F(ZipTest, ZipTimeStamp) {
455   // The dates tested are arbitrary, with some constraints. The zip format can
456   // only store years from 1980 to 2107 and an even number of seconds, due to it
457   // using the ms dos date format.
458 
459   // Valid arbitrary date.
460   TestTimeStamp("23 Oct 1997 23:22:20", VALID_YEAR);
461 
462   // Date before 1980, zip format limitation, must default to unix epoch.
463   TestTimeStamp("29 Dec 1979 21:00:10", INVALID_YEAR);
464 
465   // Despite the minizip headers telling the maximum year should be 2044, it
466   // can actually go up to 2107. Beyond that, the dos date format cannot store
467   // the year (2107-1980=127). To test that limit, the input file needs to be
468   // touched, but the code that modifies the file access and modification times
469   // relies on time_t which is defined as long, therefore being in many
470   // platforms just a 4-byte integer, like 32-bit Mac OSX or linux. As such, it
471   // suffers from the year-2038 bug. Therefore 2038 is the highest we can test
472   // in all platforms reliably.
473   TestTimeStamp("02 Jan 2038 23:59:58", VALID_YEAR);
474 }
475 
476 #if defined(OS_POSIX)
TEST_F(ZipTest,ZipFiles)477 TEST_F(ZipTest, ZipFiles) {
478   base::FilePath src_dir;
479   ASSERT_TRUE(GetTestDataDirectory(&src_dir));
480   src_dir = src_dir.AppendASCII("test");
481 
482   base::ScopedTempDir temp_dir;
483   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
484   base::FilePath zip_name = temp_dir.GetPath().AppendASCII("out.zip");
485 
486   base::File zip_file(zip_name,
487                       base::File::FLAG_CREATE | base::File::FLAG_WRITE);
488   ASSERT_TRUE(zip_file.IsValid());
489   EXPECT_TRUE(zip::ZipFiles(src_dir, zip_file_list_,
490                             zip_file.GetPlatformFile()));
491   zip_file.Close();
492 
493   zip::ZipReader reader;
494   EXPECT_TRUE(reader.Open(zip_name));
495   EXPECT_EQ(zip_file_list_.size(), static_cast<size_t>(reader.num_entries()));
496   for (size_t i = 0; i < zip_file_list_.size(); ++i) {
497     EXPECT_TRUE(reader.HasMore());
498     EXPECT_TRUE(reader.OpenCurrentEntryInZip());
499     const zip::ZipReader::EntryInfo* entry_info = reader.current_entry_info();
500     EXPECT_EQ(entry_info->file_path(), zip_file_list_[i]);
501     reader.AdvanceToNextEntry();
502   }
503 }
504 #endif  // defined(OS_POSIX)
505 
TEST_F(ZipTest,UnzipFilesWithIncorrectSize)506 TEST_F(ZipTest, UnzipFilesWithIncorrectSize) {
507   base::FilePath test_data_folder;
508   ASSERT_TRUE(GetTestDataDirectory(&test_data_folder));
509 
510   // test_mismatch_size.zip contains files with names from 0.txt to 7.txt with
511   // sizes from 0 to 7 bytes respectively, but the metadata in the zip file says
512   // the uncompressed size is 3 bytes. The ZipReader and minizip code needs to
513   // be clever enough to get all the data out.
514   base::FilePath test_zip_file =
515       test_data_folder.AppendASCII("test_mismatch_size.zip");
516 
517   base::ScopedTempDir scoped_temp_dir;
518   ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
519   const base::FilePath& temp_dir = scoped_temp_dir.GetPath();
520 
521   ASSERT_TRUE(zip::Unzip(test_zip_file, temp_dir));
522   EXPECT_TRUE(base::DirectoryExists(temp_dir.AppendASCII("d")));
523 
524   for (int i = 0; i < 8; i++) {
525     SCOPED_TRACE(base::StringPrintf("Processing %d.txt", i));
526     base::FilePath file_path = temp_dir.AppendASCII(
527         base::StringPrintf("%d.txt", i));
528     int64_t file_size = -1;
529     EXPECT_TRUE(base::GetFileSize(file_path, &file_size));
530     EXPECT_EQ(static_cast<int64_t>(i), file_size);
531   }
532 }
533 
TEST_F(ZipTest,ZipWithFileAccessor)534 TEST_F(ZipTest, ZipWithFileAccessor) {
535   base::FilePath zip_file;
536   ASSERT_TRUE(base::CreateTemporaryFile(&zip_file));
537   zip::ZipParams params(base::FilePath(FILE_PATH_LITERAL("/test")), zip_file);
538   params.set_file_accessor(std::make_unique<VirtualFileSystem>());
539   ASSERT_TRUE(zip::Zip(params));
540 
541   base::ScopedTempDir scoped_temp_dir;
542   ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
543   const base::FilePath& temp_dir = scoped_temp_dir.GetPath();
544   ASSERT_TRUE(zip::Unzip(zip_file, temp_dir));
545   base::FilePath bar_dir = temp_dir.Append(FILE_PATH_LITERAL("bar"));
546   EXPECT_TRUE(base::DirectoryExists(bar_dir));
547   std::string file_content;
548   EXPECT_TRUE(base::ReadFileToString(
549       temp_dir.Append(FILE_PATH_LITERAL("foo.txt")), &file_content));
550   EXPECT_EQ(VirtualFileSystem::kFooContent, file_content);
551   EXPECT_TRUE(base::ReadFileToString(
552       bar_dir.Append(FILE_PATH_LITERAL("bar1.txt")), &file_content));
553   EXPECT_EQ(VirtualFileSystem::kBar1Content, file_content);
554   EXPECT_TRUE(base::ReadFileToString(
555       bar_dir.Append(FILE_PATH_LITERAL("bar2.txt")), &file_content));
556   EXPECT_EQ(VirtualFileSystem::kBar2Content, file_content);
557 }
558 
559 }  // namespace
560