xref: /aosp_15_r20/external/zlib/google/zip_unittest.cc (revision 86ee64e75fa5f8bce2c8c356138035642429cd05)
1*86ee64e7SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*86ee64e7SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*86ee64e7SAndroid Build Coastguard Worker // found in the LICENSE file.
4*86ee64e7SAndroid Build Coastguard Worker 
5*86ee64e7SAndroid Build Coastguard Worker #include <stddef.h>
6*86ee64e7SAndroid Build Coastguard Worker #include <stdint.h>
7*86ee64e7SAndroid Build Coastguard Worker 
8*86ee64e7SAndroid Build Coastguard Worker #include <iomanip>
9*86ee64e7SAndroid Build Coastguard Worker #include <limits>
10*86ee64e7SAndroid Build Coastguard Worker #include <string>
11*86ee64e7SAndroid Build Coastguard Worker #include <unordered_map>
12*86ee64e7SAndroid Build Coastguard Worker #include <unordered_set>
13*86ee64e7SAndroid Build Coastguard Worker #include <vector>
14*86ee64e7SAndroid Build Coastguard Worker 
15*86ee64e7SAndroid Build Coastguard Worker #include "base/files/file.h"
16*86ee64e7SAndroid Build Coastguard Worker #include "base/files/file_enumerator.h"
17*86ee64e7SAndroid Build Coastguard Worker #include "base/files/file_path.h"
18*86ee64e7SAndroid Build Coastguard Worker #include "base/files/file_util.h"
19*86ee64e7SAndroid Build Coastguard Worker #include "base/files/scoped_temp_dir.h"
20*86ee64e7SAndroid Build Coastguard Worker #include "base/functional/bind.h"
21*86ee64e7SAndroid Build Coastguard Worker #include "base/logging.h"
22*86ee64e7SAndroid Build Coastguard Worker #include "base/path_service.h"
23*86ee64e7SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
24*86ee64e7SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
25*86ee64e7SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
26*86ee64e7SAndroid Build Coastguard Worker #include "base/test/bind.h"
27*86ee64e7SAndroid Build Coastguard Worker #include "base/time/time.h"
28*86ee64e7SAndroid Build Coastguard Worker #include "build/build_config.h"
29*86ee64e7SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
30*86ee64e7SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
31*86ee64e7SAndroid Build Coastguard Worker #include "testing/platform_test.h"
32*86ee64e7SAndroid Build Coastguard Worker #include "third_party/zlib/google/zip.h"
33*86ee64e7SAndroid Build Coastguard Worker #include "third_party/zlib/google/zip_internal.h"
34*86ee64e7SAndroid Build Coastguard Worker #include "third_party/zlib/google/zip_reader.h"
35*86ee64e7SAndroid Build Coastguard Worker 
36*86ee64e7SAndroid Build Coastguard Worker // Convenience macro to create a file path from a string literal.
37*86ee64e7SAndroid Build Coastguard Worker #define FP(path) base::FilePath(FILE_PATH_LITERAL(path))
38*86ee64e7SAndroid Build Coastguard Worker 
39*86ee64e7SAndroid Build Coastguard Worker namespace {
40*86ee64e7SAndroid Build Coastguard Worker 
41*86ee64e7SAndroid Build Coastguard Worker using testing::UnorderedElementsAre;
42*86ee64e7SAndroid Build Coastguard Worker using testing::UnorderedElementsAreArray;
43*86ee64e7SAndroid Build Coastguard Worker 
GetRelativePaths(const base::FilePath & dir,base::FileEnumerator::FileType type)44*86ee64e7SAndroid Build Coastguard Worker std::vector<std::string> GetRelativePaths(const base::FilePath& dir,
45*86ee64e7SAndroid Build Coastguard Worker                                           base::FileEnumerator::FileType type) {
46*86ee64e7SAndroid Build Coastguard Worker   std::vector<std::string> got_paths;
47*86ee64e7SAndroid Build Coastguard Worker   base::FileEnumerator files(dir, true, type);
48*86ee64e7SAndroid Build Coastguard Worker   for (base::FilePath path = files.Next(); !path.empty(); path = files.Next()) {
49*86ee64e7SAndroid Build Coastguard Worker     base::FilePath relative;
50*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(dir.AppendRelativePath(path, &relative));
51*86ee64e7SAndroid Build Coastguard Worker     got_paths.push_back(relative.NormalizePathSeparatorsTo('/').AsUTF8Unsafe());
52*86ee64e7SAndroid Build Coastguard Worker   }
53*86ee64e7SAndroid Build Coastguard Worker 
54*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(base::File::FILE_OK, files.GetError());
55*86ee64e7SAndroid Build Coastguard Worker   return got_paths;
56*86ee64e7SAndroid Build Coastguard Worker }
57*86ee64e7SAndroid Build Coastguard Worker 
CreateFile(const std::string & content,base::FilePath * file_path,base::File * file)58*86ee64e7SAndroid Build Coastguard Worker bool CreateFile(const std::string& content,
59*86ee64e7SAndroid Build Coastguard Worker                 base::FilePath* file_path,
60*86ee64e7SAndroid Build Coastguard Worker                 base::File* file) {
61*86ee64e7SAndroid Build Coastguard Worker   if (!base::CreateTemporaryFile(file_path))
62*86ee64e7SAndroid Build Coastguard Worker     return false;
63*86ee64e7SAndroid Build Coastguard Worker 
64*86ee64e7SAndroid Build Coastguard Worker   if (base::WriteFile(*file_path, content.data(), content.size()) == -1)
65*86ee64e7SAndroid Build Coastguard Worker     return false;
66*86ee64e7SAndroid Build Coastguard Worker 
67*86ee64e7SAndroid Build Coastguard Worker   *file = base::File(
68*86ee64e7SAndroid Build Coastguard Worker       *file_path, base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ);
69*86ee64e7SAndroid Build Coastguard Worker   return file->IsValid();
70*86ee64e7SAndroid Build Coastguard Worker }
71*86ee64e7SAndroid Build Coastguard Worker 
72*86ee64e7SAndroid Build Coastguard Worker // A WriterDelegate that logs progress once per second.
73*86ee64e7SAndroid Build Coastguard Worker class ProgressWriterDelegate : public zip::WriterDelegate {
74*86ee64e7SAndroid Build Coastguard Worker  public:
ProgressWriterDelegate(int64_t expected_size)75*86ee64e7SAndroid Build Coastguard Worker   explicit ProgressWriterDelegate(int64_t expected_size)
76*86ee64e7SAndroid Build Coastguard Worker       : expected_size_(expected_size) {
77*86ee64e7SAndroid Build Coastguard Worker     CHECK_GT(expected_size_, 0);
78*86ee64e7SAndroid Build Coastguard Worker   }
79*86ee64e7SAndroid Build Coastguard Worker 
WriteBytes(const char * data,int num_bytes)80*86ee64e7SAndroid Build Coastguard Worker   bool WriteBytes(const char* data, int num_bytes) override {
81*86ee64e7SAndroid Build Coastguard Worker     received_bytes_ += num_bytes;
82*86ee64e7SAndroid Build Coastguard Worker     LogProgressIfNecessary();
83*86ee64e7SAndroid Build Coastguard Worker     return true;
84*86ee64e7SAndroid Build Coastguard Worker   }
85*86ee64e7SAndroid Build Coastguard Worker 
SetTimeModified(const base::Time & time)86*86ee64e7SAndroid Build Coastguard Worker   void SetTimeModified(const base::Time& time) override { LogProgress(); }
87*86ee64e7SAndroid Build Coastguard Worker 
received_bytes() const88*86ee64e7SAndroid Build Coastguard Worker   int64_t received_bytes() const { return received_bytes_; }
89*86ee64e7SAndroid Build Coastguard Worker 
90*86ee64e7SAndroid Build Coastguard Worker  private:
LogProgressIfNecessary()91*86ee64e7SAndroid Build Coastguard Worker   void LogProgressIfNecessary() {
92*86ee64e7SAndroid Build Coastguard Worker     const base::TimeTicks now = base::TimeTicks::Now();
93*86ee64e7SAndroid Build Coastguard Worker     if (next_progress_report_time_ > now)
94*86ee64e7SAndroid Build Coastguard Worker       return;
95*86ee64e7SAndroid Build Coastguard Worker 
96*86ee64e7SAndroid Build Coastguard Worker     next_progress_report_time_ = now + progress_period_;
97*86ee64e7SAndroid Build Coastguard Worker     LogProgress();
98*86ee64e7SAndroid Build Coastguard Worker   }
99*86ee64e7SAndroid Build Coastguard Worker 
LogProgress() const100*86ee64e7SAndroid Build Coastguard Worker   void LogProgress() const {
101*86ee64e7SAndroid Build Coastguard Worker     LOG(INFO) << "Unzipping... " << std::setw(3)
102*86ee64e7SAndroid Build Coastguard Worker               << (100 * received_bytes_ / expected_size_) << "%";
103*86ee64e7SAndroid Build Coastguard Worker   }
104*86ee64e7SAndroid Build Coastguard Worker 
105*86ee64e7SAndroid Build Coastguard Worker   const base::TimeDelta progress_period_ = base::Seconds(1);
106*86ee64e7SAndroid Build Coastguard Worker   base::TimeTicks next_progress_report_time_ =
107*86ee64e7SAndroid Build Coastguard Worker       base::TimeTicks::Now() + progress_period_;
108*86ee64e7SAndroid Build Coastguard Worker   const uint64_t expected_size_;
109*86ee64e7SAndroid Build Coastguard Worker   int64_t received_bytes_ = 0;
110*86ee64e7SAndroid Build Coastguard Worker };
111*86ee64e7SAndroid Build Coastguard Worker 
112*86ee64e7SAndroid Build Coastguard Worker // A virtual file system containing:
113*86ee64e7SAndroid Build Coastguard Worker // /test
114*86ee64e7SAndroid Build Coastguard Worker // /test/foo.txt
115*86ee64e7SAndroid Build Coastguard Worker // /test/bar/bar1.txt
116*86ee64e7SAndroid Build Coastguard Worker // /test/bar/bar2.txt
117*86ee64e7SAndroid Build Coastguard Worker // Used to test providing a custom zip::FileAccessor when unzipping.
118*86ee64e7SAndroid Build Coastguard Worker class VirtualFileSystem : public zip::FileAccessor {
119*86ee64e7SAndroid Build Coastguard Worker  public:
120*86ee64e7SAndroid Build Coastguard Worker   static constexpr char kFooContent[] = "This is foo.";
121*86ee64e7SAndroid Build Coastguard Worker   static constexpr char kBar1Content[] = "This is bar.";
122*86ee64e7SAndroid Build Coastguard Worker   static constexpr char kBar2Content[] = "This is bar too.";
123*86ee64e7SAndroid Build Coastguard Worker 
VirtualFileSystem()124*86ee64e7SAndroid Build Coastguard Worker   VirtualFileSystem() {
125*86ee64e7SAndroid Build Coastguard Worker     base::FilePath test_dir;
126*86ee64e7SAndroid Build Coastguard Worker     base::FilePath foo_txt_path = test_dir.AppendASCII("foo.txt");
127*86ee64e7SAndroid Build Coastguard Worker 
128*86ee64e7SAndroid Build Coastguard Worker     base::FilePath file_path;
129*86ee64e7SAndroid Build Coastguard Worker     base::File file;
130*86ee64e7SAndroid Build Coastguard Worker     bool success = CreateFile(kFooContent, &file_path, &file);
131*86ee64e7SAndroid Build Coastguard Worker     DCHECK(success);
132*86ee64e7SAndroid Build Coastguard Worker     files_[foo_txt_path] = std::move(file);
133*86ee64e7SAndroid Build Coastguard Worker 
134*86ee64e7SAndroid Build Coastguard Worker     base::FilePath bar_dir = test_dir.AppendASCII("bar");
135*86ee64e7SAndroid Build Coastguard Worker     base::FilePath bar1_txt_path = bar_dir.AppendASCII("bar1.txt");
136*86ee64e7SAndroid Build Coastguard Worker     success = CreateFile(kBar1Content, &file_path, &file);
137*86ee64e7SAndroid Build Coastguard Worker     DCHECK(success);
138*86ee64e7SAndroid Build Coastguard Worker     files_[bar1_txt_path] = std::move(file);
139*86ee64e7SAndroid Build Coastguard Worker 
140*86ee64e7SAndroid Build Coastguard Worker     base::FilePath bar2_txt_path = bar_dir.AppendASCII("bar2.txt");
141*86ee64e7SAndroid Build Coastguard Worker     success = CreateFile(kBar2Content, &file_path, &file);
142*86ee64e7SAndroid Build Coastguard Worker     DCHECK(success);
143*86ee64e7SAndroid Build Coastguard Worker     files_[bar2_txt_path] = std::move(file);
144*86ee64e7SAndroid Build Coastguard Worker 
145*86ee64e7SAndroid Build Coastguard Worker     file_tree_[base::FilePath()] = {{foo_txt_path}, {bar_dir}};
146*86ee64e7SAndroid Build Coastguard Worker     file_tree_[bar_dir] = {{bar1_txt_path, bar2_txt_path}};
147*86ee64e7SAndroid Build Coastguard Worker     file_tree_[foo_txt_path] = {};
148*86ee64e7SAndroid Build Coastguard Worker     file_tree_[bar1_txt_path] = {};
149*86ee64e7SAndroid Build Coastguard Worker     file_tree_[bar2_txt_path] = {};
150*86ee64e7SAndroid Build Coastguard Worker   }
151*86ee64e7SAndroid Build Coastguard Worker 
152*86ee64e7SAndroid Build Coastguard Worker   VirtualFileSystem(const VirtualFileSystem&) = delete;
153*86ee64e7SAndroid Build Coastguard Worker   VirtualFileSystem& operator=(const VirtualFileSystem&) = delete;
154*86ee64e7SAndroid Build Coastguard Worker 
155*86ee64e7SAndroid Build Coastguard Worker   ~VirtualFileSystem() override = default;
156*86ee64e7SAndroid Build Coastguard Worker 
157*86ee64e7SAndroid Build Coastguard Worker  private:
Open(const zip::Paths paths,std::vector<base::File> * const files)158*86ee64e7SAndroid Build Coastguard Worker   bool Open(const zip::Paths paths,
159*86ee64e7SAndroid Build Coastguard Worker             std::vector<base::File>* const files) override {
160*86ee64e7SAndroid Build Coastguard Worker     DCHECK(files);
161*86ee64e7SAndroid Build Coastguard Worker     files->reserve(files->size() + paths.size());
162*86ee64e7SAndroid Build Coastguard Worker 
163*86ee64e7SAndroid Build Coastguard Worker     for (const base::FilePath& path : paths) {
164*86ee64e7SAndroid Build Coastguard Worker       const auto it = files_.find(path);
165*86ee64e7SAndroid Build Coastguard Worker       if (it == files_.end()) {
166*86ee64e7SAndroid Build Coastguard Worker         files->emplace_back();
167*86ee64e7SAndroid Build Coastguard Worker       } else {
168*86ee64e7SAndroid Build Coastguard Worker         EXPECT_TRUE(it->second.IsValid());
169*86ee64e7SAndroid Build Coastguard Worker         files->push_back(std::move(it->second));
170*86ee64e7SAndroid Build Coastguard Worker       }
171*86ee64e7SAndroid Build Coastguard Worker     }
172*86ee64e7SAndroid Build Coastguard Worker 
173*86ee64e7SAndroid Build Coastguard Worker     return true;
174*86ee64e7SAndroid Build Coastguard Worker   }
175*86ee64e7SAndroid Build Coastguard Worker 
List(const base::FilePath & path,std::vector<base::FilePath> * const files,std::vector<base::FilePath> * const subdirs)176*86ee64e7SAndroid Build Coastguard Worker   bool List(const base::FilePath& path,
177*86ee64e7SAndroid Build Coastguard Worker             std::vector<base::FilePath>* const files,
178*86ee64e7SAndroid Build Coastguard Worker             std::vector<base::FilePath>* const subdirs) override {
179*86ee64e7SAndroid Build Coastguard Worker     DCHECK(!path.IsAbsolute());
180*86ee64e7SAndroid Build Coastguard Worker     DCHECK(files);
181*86ee64e7SAndroid Build Coastguard Worker     DCHECK(subdirs);
182*86ee64e7SAndroid Build Coastguard Worker 
183*86ee64e7SAndroid Build Coastguard Worker     const auto it = file_tree_.find(path);
184*86ee64e7SAndroid Build Coastguard Worker     if (it == file_tree_.end())
185*86ee64e7SAndroid Build Coastguard Worker       return false;
186*86ee64e7SAndroid Build Coastguard Worker 
187*86ee64e7SAndroid Build Coastguard Worker     for (const base::FilePath& file : it->second.files) {
188*86ee64e7SAndroid Build Coastguard Worker       DCHECK(!file.empty());
189*86ee64e7SAndroid Build Coastguard Worker       files->push_back(file);
190*86ee64e7SAndroid Build Coastguard Worker     }
191*86ee64e7SAndroid Build Coastguard Worker 
192*86ee64e7SAndroid Build Coastguard Worker     for (const base::FilePath& subdir : it->second.subdirs) {
193*86ee64e7SAndroid Build Coastguard Worker       DCHECK(!subdir.empty());
194*86ee64e7SAndroid Build Coastguard Worker       subdirs->push_back(subdir);
195*86ee64e7SAndroid Build Coastguard Worker     }
196*86ee64e7SAndroid Build Coastguard Worker 
197*86ee64e7SAndroid Build Coastguard Worker     return true;
198*86ee64e7SAndroid Build Coastguard Worker   }
199*86ee64e7SAndroid Build Coastguard Worker 
GetInfo(const base::FilePath & path,Info * const info)200*86ee64e7SAndroid Build Coastguard Worker   bool GetInfo(const base::FilePath& path, Info* const info) override {
201*86ee64e7SAndroid Build Coastguard Worker     DCHECK(!path.IsAbsolute());
202*86ee64e7SAndroid Build Coastguard Worker     DCHECK(info);
203*86ee64e7SAndroid Build Coastguard Worker 
204*86ee64e7SAndroid Build Coastguard Worker     if (!file_tree_.count(path))
205*86ee64e7SAndroid Build Coastguard Worker       return false;
206*86ee64e7SAndroid Build Coastguard Worker 
207*86ee64e7SAndroid Build Coastguard Worker     info->is_directory = !files_.count(path);
208*86ee64e7SAndroid Build Coastguard Worker     info->last_modified =
209*86ee64e7SAndroid Build Coastguard Worker         base::Time::FromSecondsSinceUnixEpoch(172097977);  // Some random date.
210*86ee64e7SAndroid Build Coastguard Worker 
211*86ee64e7SAndroid Build Coastguard Worker     return true;
212*86ee64e7SAndroid Build Coastguard Worker   }
213*86ee64e7SAndroid Build Coastguard Worker 
214*86ee64e7SAndroid Build Coastguard Worker   struct DirContents {
215*86ee64e7SAndroid Build Coastguard Worker     std::vector<base::FilePath> files, subdirs;
216*86ee64e7SAndroid Build Coastguard Worker   };
217*86ee64e7SAndroid Build Coastguard Worker 
218*86ee64e7SAndroid Build Coastguard Worker   std::unordered_map<base::FilePath, DirContents> file_tree_;
219*86ee64e7SAndroid Build Coastguard Worker   std::unordered_map<base::FilePath, base::File> files_;
220*86ee64e7SAndroid Build Coastguard Worker };
221*86ee64e7SAndroid Build Coastguard Worker 
222*86ee64e7SAndroid Build Coastguard Worker // static
223*86ee64e7SAndroid Build Coastguard Worker constexpr char VirtualFileSystem::kFooContent[];
224*86ee64e7SAndroid Build Coastguard Worker constexpr char VirtualFileSystem::kBar1Content[];
225*86ee64e7SAndroid Build Coastguard Worker constexpr char VirtualFileSystem::kBar2Content[];
226*86ee64e7SAndroid Build Coastguard Worker 
227*86ee64e7SAndroid Build Coastguard Worker // Make the test a PlatformTest to setup autorelease pools properly on Mac.
228*86ee64e7SAndroid Build Coastguard Worker class ZipTest : public PlatformTest {
229*86ee64e7SAndroid Build Coastguard Worker  protected:
230*86ee64e7SAndroid Build Coastguard Worker   enum ValidYearType { VALID_YEAR, INVALID_YEAR };
231*86ee64e7SAndroid Build Coastguard Worker 
SetUp()232*86ee64e7SAndroid Build Coastguard Worker   virtual void SetUp() {
233*86ee64e7SAndroid Build Coastguard Worker     PlatformTest::SetUp();
234*86ee64e7SAndroid Build Coastguard Worker 
235*86ee64e7SAndroid Build Coastguard Worker     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
236*86ee64e7SAndroid Build Coastguard Worker     test_dir_ = temp_dir_.GetPath();
237*86ee64e7SAndroid Build Coastguard Worker 
238*86ee64e7SAndroid Build Coastguard Worker     base::FilePath zip_path(test_dir_);
239*86ee64e7SAndroid Build Coastguard Worker     zip_contents_.insert(zip_path.AppendASCII("foo.txt"));
240*86ee64e7SAndroid Build Coastguard Worker     zip_path = zip_path.AppendASCII("foo");
241*86ee64e7SAndroid Build Coastguard Worker     zip_contents_.insert(zip_path);
242*86ee64e7SAndroid Build Coastguard Worker     zip_contents_.insert(zip_path.AppendASCII("bar.txt"));
243*86ee64e7SAndroid Build Coastguard Worker     zip_path = zip_path.AppendASCII("bar");
244*86ee64e7SAndroid Build Coastguard Worker     zip_contents_.insert(zip_path);
245*86ee64e7SAndroid Build Coastguard Worker     zip_contents_.insert(zip_path.AppendASCII("baz.txt"));
246*86ee64e7SAndroid Build Coastguard Worker     zip_contents_.insert(zip_path.AppendASCII("quux.txt"));
247*86ee64e7SAndroid Build Coastguard Worker     zip_contents_.insert(zip_path.AppendASCII(".hidden"));
248*86ee64e7SAndroid Build Coastguard Worker 
249*86ee64e7SAndroid Build Coastguard Worker     // Include a subset of files in |zip_file_list_| to test ZipFiles().
250*86ee64e7SAndroid Build Coastguard Worker     zip_file_list_.push_back(FP("foo.txt"));
251*86ee64e7SAndroid Build Coastguard Worker     zip_file_list_.push_back(FP("foo/bar/quux.txt"));
252*86ee64e7SAndroid Build Coastguard Worker     zip_file_list_.push_back(FP("foo/bar/.hidden"));
253*86ee64e7SAndroid Build Coastguard Worker   }
254*86ee64e7SAndroid Build Coastguard Worker 
TearDown()255*86ee64e7SAndroid Build Coastguard Worker   virtual void TearDown() { PlatformTest::TearDown(); }
256*86ee64e7SAndroid Build Coastguard Worker 
GetDataDirectory()257*86ee64e7SAndroid Build Coastguard Worker   static base::FilePath GetDataDirectory() {
258*86ee64e7SAndroid Build Coastguard Worker     base::FilePath path;
259*86ee64e7SAndroid Build Coastguard Worker     bool success = base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &path);
260*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(success);
261*86ee64e7SAndroid Build Coastguard Worker     return std::move(path)
262*86ee64e7SAndroid Build Coastguard Worker         .AppendASCII("third_party")
263*86ee64e7SAndroid Build Coastguard Worker         .AppendASCII("zlib")
264*86ee64e7SAndroid Build Coastguard Worker         .AppendASCII("google")
265*86ee64e7SAndroid Build Coastguard Worker         .AppendASCII("test")
266*86ee64e7SAndroid Build Coastguard Worker         .AppendASCII("data");
267*86ee64e7SAndroid Build Coastguard Worker   }
268*86ee64e7SAndroid Build Coastguard Worker 
TestUnzipFile(const base::FilePath::StringType & filename,bool expect_hidden_files)269*86ee64e7SAndroid Build Coastguard Worker   void TestUnzipFile(const base::FilePath::StringType& filename,
270*86ee64e7SAndroid Build Coastguard Worker                      bool expect_hidden_files) {
271*86ee64e7SAndroid Build Coastguard Worker     TestUnzipFile(GetDataDirectory().Append(filename), expect_hidden_files);
272*86ee64e7SAndroid Build Coastguard Worker   }
273*86ee64e7SAndroid Build Coastguard Worker 
TestUnzipFile(const base::FilePath & path,bool expect_hidden_files)274*86ee64e7SAndroid Build Coastguard Worker   void TestUnzipFile(const base::FilePath& path, bool expect_hidden_files) {
275*86ee64e7SAndroid Build Coastguard Worker     ASSERT_TRUE(base::PathExists(path)) << "no file " << path;
276*86ee64e7SAndroid Build Coastguard Worker     ASSERT_TRUE(zip::Unzip(path, test_dir_));
277*86ee64e7SAndroid Build Coastguard Worker 
278*86ee64e7SAndroid Build Coastguard Worker     base::FilePath original_dir = GetDataDirectory().AppendASCII("test");
279*86ee64e7SAndroid Build Coastguard Worker 
280*86ee64e7SAndroid Build Coastguard Worker     base::FileEnumerator files(
281*86ee64e7SAndroid Build Coastguard Worker         test_dir_, true,
282*86ee64e7SAndroid Build Coastguard Worker         base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
283*86ee64e7SAndroid Build Coastguard Worker 
284*86ee64e7SAndroid Build Coastguard Worker     size_t count = 0;
285*86ee64e7SAndroid Build Coastguard Worker     for (base::FilePath unzipped_entry_path = files.Next();
286*86ee64e7SAndroid Build Coastguard Worker          !unzipped_entry_path.empty(); unzipped_entry_path = files.Next()) {
287*86ee64e7SAndroid Build Coastguard Worker       EXPECT_EQ(zip_contents_.count(unzipped_entry_path), 1U)
288*86ee64e7SAndroid Build Coastguard Worker           << "Couldn't find " << unzipped_entry_path;
289*86ee64e7SAndroid Build Coastguard Worker       count++;
290*86ee64e7SAndroid Build Coastguard Worker 
291*86ee64e7SAndroid Build Coastguard Worker       if (base::PathExists(unzipped_entry_path) &&
292*86ee64e7SAndroid Build Coastguard Worker           !base::DirectoryExists(unzipped_entry_path)) {
293*86ee64e7SAndroid Build Coastguard Worker         // It's a file, check its contents are what we zipped.
294*86ee64e7SAndroid Build Coastguard Worker         base::FilePath relative_path;
295*86ee64e7SAndroid Build Coastguard Worker         ASSERT_TRUE(
296*86ee64e7SAndroid Build Coastguard Worker             test_dir_.AppendRelativePath(unzipped_entry_path, &relative_path))
297*86ee64e7SAndroid Build Coastguard Worker             << "Cannot append relative path failed, params: '" << test_dir_
298*86ee64e7SAndroid Build Coastguard Worker             << "' and '" << unzipped_entry_path << "'";
299*86ee64e7SAndroid Build Coastguard Worker         base::FilePath original_path = original_dir.Append(relative_path);
300*86ee64e7SAndroid Build Coastguard Worker         EXPECT_TRUE(base::ContentsEqual(original_path, unzipped_entry_path))
301*86ee64e7SAndroid Build Coastguard Worker             << "Original file '" << original_path << "' and unzipped file '"
302*86ee64e7SAndroid Build Coastguard Worker             << unzipped_entry_path << "' have different contents";
303*86ee64e7SAndroid Build Coastguard Worker       }
304*86ee64e7SAndroid Build Coastguard Worker     }
305*86ee64e7SAndroid Build Coastguard Worker     EXPECT_EQ(base::File::FILE_OK, files.GetError());
306*86ee64e7SAndroid Build Coastguard Worker 
307*86ee64e7SAndroid Build Coastguard Worker     size_t expected_count = 0;
308*86ee64e7SAndroid Build Coastguard Worker     for (const base::FilePath& path : zip_contents_) {
309*86ee64e7SAndroid Build Coastguard Worker       if (expect_hidden_files || path.BaseName().value()[0] != '.')
310*86ee64e7SAndroid Build Coastguard Worker         ++expected_count;
311*86ee64e7SAndroid Build Coastguard Worker     }
312*86ee64e7SAndroid Build Coastguard Worker 
313*86ee64e7SAndroid Build Coastguard Worker     EXPECT_EQ(expected_count, count);
314*86ee64e7SAndroid Build Coastguard Worker   }
315*86ee64e7SAndroid Build Coastguard Worker 
316*86ee64e7SAndroid Build Coastguard Worker   // This function does the following:
317*86ee64e7SAndroid Build Coastguard Worker   // 1) Creates a test.txt file with the given last modification timestamp
318*86ee64e7SAndroid Build Coastguard Worker   // 2) Zips test.txt and extracts it back into a different location.
319*86ee64e7SAndroid Build Coastguard Worker   // 3) Confirms that test.txt in the output directory has the specified
320*86ee64e7SAndroid Build Coastguard Worker   //    last modification timestamp if it is valid (|valid_year| is true).
321*86ee64e7SAndroid Build Coastguard Worker   //    If the timestamp is not supported by the zip format, the last
322*86ee64e7SAndroid Build Coastguard Worker   //    modification defaults to the current time.
TestTimeStamp(const char * date_time,ValidYearType valid_year)323*86ee64e7SAndroid Build Coastguard Worker   void TestTimeStamp(const char* date_time, ValidYearType valid_year) {
324*86ee64e7SAndroid Build Coastguard Worker     SCOPED_TRACE(std::string("TestTimeStamp(") + date_time + ")");
325*86ee64e7SAndroid Build Coastguard Worker     base::ScopedTempDir temp_dir;
326*86ee64e7SAndroid Build Coastguard Worker     ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
327*86ee64e7SAndroid Build Coastguard Worker 
328*86ee64e7SAndroid Build Coastguard Worker     base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
329*86ee64e7SAndroid Build Coastguard Worker     base::FilePath src_dir = temp_dir.GetPath().AppendASCII("input");
330*86ee64e7SAndroid Build Coastguard Worker     base::FilePath out_dir = temp_dir.GetPath().AppendASCII("output");
331*86ee64e7SAndroid Build Coastguard Worker 
332*86ee64e7SAndroid Build Coastguard Worker     base::FilePath src_file = src_dir.AppendASCII("test.txt");
333*86ee64e7SAndroid Build Coastguard Worker     base::FilePath out_file = out_dir.AppendASCII("test.txt");
334*86ee64e7SAndroid Build Coastguard Worker 
335*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(base::CreateDirectory(src_dir));
336*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(base::CreateDirectory(out_dir));
337*86ee64e7SAndroid Build Coastguard Worker 
338*86ee64e7SAndroid Build Coastguard Worker     base::Time test_mtime;
339*86ee64e7SAndroid Build Coastguard Worker     ASSERT_TRUE(base::Time::FromString(date_time, &test_mtime));
340*86ee64e7SAndroid Build Coastguard Worker 
341*86ee64e7SAndroid Build Coastguard Worker     // Adjusting the current timestamp to the resolution that the zip file
342*86ee64e7SAndroid Build Coastguard Worker     // supports, which is 2 seconds. Note that between this call to Time::Now()
343*86ee64e7SAndroid Build Coastguard Worker     // and zip::Zip() the clock can advance a bit, hence the use of EXPECT_GE.
344*86ee64e7SAndroid Build Coastguard Worker     base::Time::Exploded now_parts;
345*86ee64e7SAndroid Build Coastguard Worker     base::Time::Now().UTCExplode(&now_parts);
346*86ee64e7SAndroid Build Coastguard Worker     now_parts.second = now_parts.second & ~1;
347*86ee64e7SAndroid Build Coastguard Worker     now_parts.millisecond = 0;
348*86ee64e7SAndroid Build Coastguard Worker     base::Time now_time;
349*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(base::Time::FromUTCExploded(now_parts, &now_time));
350*86ee64e7SAndroid Build Coastguard Worker 
351*86ee64e7SAndroid Build Coastguard Worker     EXPECT_EQ(1, base::WriteFile(src_file, "1", 1));
352*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(base::TouchFile(src_file, base::Time::Now(), test_mtime));
353*86ee64e7SAndroid Build Coastguard Worker 
354*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(zip::Zip(src_dir, zip_file, true));
355*86ee64e7SAndroid Build Coastguard Worker     ASSERT_TRUE(zip::Unzip(zip_file, out_dir));
356*86ee64e7SAndroid Build Coastguard Worker 
357*86ee64e7SAndroid Build Coastguard Worker     base::File::Info file_info;
358*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(base::GetFileInfo(out_file, &file_info));
359*86ee64e7SAndroid Build Coastguard Worker     EXPECT_EQ(file_info.size, 1);
360*86ee64e7SAndroid Build Coastguard Worker 
361*86ee64e7SAndroid Build Coastguard Worker     if (valid_year == VALID_YEAR) {
362*86ee64e7SAndroid Build Coastguard Worker       EXPECT_EQ(file_info.last_modified, test_mtime);
363*86ee64e7SAndroid Build Coastguard Worker     } else {
364*86ee64e7SAndroid Build Coastguard Worker       // Invalid date means the modification time will default to 'now'.
365*86ee64e7SAndroid Build Coastguard Worker       EXPECT_GE(file_info.last_modified, now_time);
366*86ee64e7SAndroid Build Coastguard Worker     }
367*86ee64e7SAndroid Build Coastguard Worker   }
368*86ee64e7SAndroid Build Coastguard Worker 
369*86ee64e7SAndroid Build Coastguard Worker   // The path to temporary directory used to contain the test operations.
370*86ee64e7SAndroid Build Coastguard Worker   base::FilePath test_dir_;
371*86ee64e7SAndroid Build Coastguard Worker 
372*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir_;
373*86ee64e7SAndroid Build Coastguard Worker 
374*86ee64e7SAndroid Build Coastguard Worker   // Hard-coded contents of a known zip file.
375*86ee64e7SAndroid Build Coastguard Worker   std::unordered_set<base::FilePath> zip_contents_;
376*86ee64e7SAndroid Build Coastguard Worker 
377*86ee64e7SAndroid Build Coastguard Worker   // Hard-coded list of relative paths for a zip file created with ZipFiles.
378*86ee64e7SAndroid Build Coastguard Worker   std::vector<base::FilePath> zip_file_list_;
379*86ee64e7SAndroid Build Coastguard Worker };
380*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipNoSuchFile)381*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipNoSuchFile) {
382*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(zip::Unzip(GetDataDirectory().AppendASCII("No Such File.zip"),
383*86ee64e7SAndroid Build Coastguard Worker                           test_dir_));
384*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
385*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
386*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre());
387*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
388*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::DIRECTORIES),
389*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre());
390*86ee64e7SAndroid Build Coastguard Worker }
391*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,Unzip)392*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, Unzip) {
393*86ee64e7SAndroid Build Coastguard Worker   TestUnzipFile(FILE_PATH_LITERAL("test.zip"), true);
394*86ee64e7SAndroid Build Coastguard Worker }
395*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipUncompressed)396*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipUncompressed) {
397*86ee64e7SAndroid Build Coastguard Worker   TestUnzipFile(FILE_PATH_LITERAL("test_nocompress.zip"), true);
398*86ee64e7SAndroid Build Coastguard Worker }
399*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipEvil)400*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipEvil) {
401*86ee64e7SAndroid Build Coastguard Worker   base::FilePath path = GetDataDirectory().AppendASCII("evil.zip");
402*86ee64e7SAndroid Build Coastguard Worker   // Unzip the zip file into a sub directory of test_dir_ so evil.zip
403*86ee64e7SAndroid Build Coastguard Worker   // won't create a persistent file outside test_dir_ in case of a
404*86ee64e7SAndroid Build Coastguard Worker   // failure.
405*86ee64e7SAndroid Build Coastguard Worker   base::FilePath output_dir = test_dir_.AppendASCII("out");
406*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Unzip(path, output_dir));
407*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::PathExists(output_dir.AppendASCII(
408*86ee64e7SAndroid Build Coastguard Worker       "UP/levilevilevilevilevilevilevilevilevilevilevilevil")));
409*86ee64e7SAndroid Build Coastguard Worker }
410*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipEvil2)411*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipEvil2) {
412*86ee64e7SAndroid Build Coastguard Worker   // The ZIP file contains a file with invalid UTF-8 in its file name.
413*86ee64e7SAndroid Build Coastguard Worker   base::FilePath path =
414*86ee64e7SAndroid Build Coastguard Worker       GetDataDirectory().AppendASCII("evil_via_invalid_utf8.zip");
415*86ee64e7SAndroid Build Coastguard Worker   // See the comment at UnzipEvil() for why we do this.
416*86ee64e7SAndroid Build Coastguard Worker   base::FilePath output_dir = test_dir_.AppendASCII("out");
417*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(zip::Unzip(path, output_dir));
418*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::PathExists(
419*86ee64e7SAndroid Build Coastguard Worker       output_dir.Append(base::FilePath::FromUTF8Unsafe(".�.�evil.txt"))));
420*86ee64e7SAndroid Build Coastguard Worker   ASSERT_FALSE(base::PathExists(output_dir.AppendASCII("../evil.txt")));
421*86ee64e7SAndroid Build Coastguard Worker }
422*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipWithFilter)423*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipWithFilter) {
424*86ee64e7SAndroid Build Coastguard Worker   auto filter = base::BindRepeating([](const base::FilePath& path) {
425*86ee64e7SAndroid Build Coastguard Worker     return path.BaseName().MaybeAsASCII() == "foo.txt";
426*86ee64e7SAndroid Build Coastguard Worker   });
427*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(zip::Unzip(GetDataDirectory().AppendASCII("test.zip"), test_dir_,
428*86ee64e7SAndroid Build Coastguard Worker                          {.filter = std::move(filter)}));
429*86ee64e7SAndroid Build Coastguard Worker   // Only foo.txt should have been extracted.
430*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
431*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
432*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("foo.txt"));
433*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
434*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::DIRECTORIES),
435*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre());
436*86ee64e7SAndroid Build Coastguard Worker }
437*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipEncryptedWithRightPassword)438*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipEncryptedWithRightPassword) {
439*86ee64e7SAndroid Build Coastguard Worker   // TODO(crbug.com/1296838) Also check the AES-encrypted files.
440*86ee64e7SAndroid Build Coastguard Worker   auto filter = base::BindRepeating([](const base::FilePath& path) {
441*86ee64e7SAndroid Build Coastguard Worker     return !base::StartsWith(path.MaybeAsASCII(), "Encrypted AES");
442*86ee64e7SAndroid Build Coastguard Worker   });
443*86ee64e7SAndroid Build Coastguard Worker 
444*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(zip::Unzip(
445*86ee64e7SAndroid Build Coastguard Worker       GetDataDirectory().AppendASCII("Different Encryptions.zip"), test_dir_,
446*86ee64e7SAndroid Build Coastguard Worker       {.filter = std::move(filter), .password = "password"}));
447*86ee64e7SAndroid Build Coastguard Worker 
448*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
449*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("ClearText.txt"),
450*86ee64e7SAndroid Build Coastguard Worker                                      &contents));
451*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("This is not encrypted.\n", contents);
452*86ee64e7SAndroid Build Coastguard Worker 
453*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::ReadFileToString(
454*86ee64e7SAndroid Build Coastguard Worker       test_dir_.AppendASCII("Encrypted ZipCrypto.txt"), &contents));
455*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("This is encrypted with ZipCrypto.\n", contents);
456*86ee64e7SAndroid Build Coastguard Worker }
457*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipEncryptedWithWrongPassword)458*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipEncryptedWithWrongPassword) {
459*86ee64e7SAndroid Build Coastguard Worker   // TODO(crbug.com/1296838) Also check the AES-encrypted files.
460*86ee64e7SAndroid Build Coastguard Worker   auto filter = base::BindRepeating([](const base::FilePath& path) {
461*86ee64e7SAndroid Build Coastguard Worker     return !base::StartsWith(path.MaybeAsASCII(), "Encrypted AES");
462*86ee64e7SAndroid Build Coastguard Worker   });
463*86ee64e7SAndroid Build Coastguard Worker 
464*86ee64e7SAndroid Build Coastguard Worker   ASSERT_FALSE(zip::Unzip(
465*86ee64e7SAndroid Build Coastguard Worker       GetDataDirectory().AppendASCII("Different Encryptions.zip"), test_dir_,
466*86ee64e7SAndroid Build Coastguard Worker       {.filter = std::move(filter), .password = "wrong"}));
467*86ee64e7SAndroid Build Coastguard Worker 
468*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
469*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("ClearText.txt"),
470*86ee64e7SAndroid Build Coastguard Worker                                      &contents));
471*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("This is not encrypted.\n", contents);
472*86ee64e7SAndroid Build Coastguard Worker 
473*86ee64e7SAndroid Build Coastguard Worker   // No rubbish file should be left behind.
474*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
475*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
476*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("ClearText.txt"));
477*86ee64e7SAndroid Build Coastguard Worker }
478*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipEncryptedWithNoPassword)479*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipEncryptedWithNoPassword) {
480*86ee64e7SAndroid Build Coastguard Worker   // TODO(crbug.com/1296838) Also check the AES-encrypted files.
481*86ee64e7SAndroid Build Coastguard Worker   auto filter = base::BindRepeating([](const base::FilePath& path) {
482*86ee64e7SAndroid Build Coastguard Worker     return !base::StartsWith(path.MaybeAsASCII(), "Encrypted AES");
483*86ee64e7SAndroid Build Coastguard Worker   });
484*86ee64e7SAndroid Build Coastguard Worker 
485*86ee64e7SAndroid Build Coastguard Worker   ASSERT_FALSE(
486*86ee64e7SAndroid Build Coastguard Worker       zip::Unzip(GetDataDirectory().AppendASCII("Different Encryptions.zip"),
487*86ee64e7SAndroid Build Coastguard Worker                  test_dir_, {.filter = std::move(filter)}));
488*86ee64e7SAndroid Build Coastguard Worker 
489*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
490*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("ClearText.txt"),
491*86ee64e7SAndroid Build Coastguard Worker                                      &contents));
492*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("This is not encrypted.\n", contents);
493*86ee64e7SAndroid Build Coastguard Worker 
494*86ee64e7SAndroid Build Coastguard Worker   // No rubbish file should be left behind.
495*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
496*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
497*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("ClearText.txt"));
498*86ee64e7SAndroid Build Coastguard Worker }
499*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipEncryptedContinueOnError)500*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipEncryptedContinueOnError) {
501*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(
502*86ee64e7SAndroid Build Coastguard Worker       zip::Unzip(GetDataDirectory().AppendASCII("Different Encryptions.zip"),
503*86ee64e7SAndroid Build Coastguard Worker                  test_dir_, {.continue_on_error = true}));
504*86ee64e7SAndroid Build Coastguard Worker 
505*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
506*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("ClearText.txt"),
507*86ee64e7SAndroid Build Coastguard Worker                                      &contents));
508*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("This is not encrypted.\n", contents);
509*86ee64e7SAndroid Build Coastguard Worker 
510*86ee64e7SAndroid Build Coastguard Worker   // No rubbish file should be left behind.
511*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
512*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
513*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("ClearText.txt"));
514*86ee64e7SAndroid Build Coastguard Worker }
515*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipWrongCrc)516*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipWrongCrc) {
517*86ee64e7SAndroid Build Coastguard Worker   ASSERT_FALSE(
518*86ee64e7SAndroid Build Coastguard Worker       zip::Unzip(GetDataDirectory().AppendASCII("Wrong CRC.zip"), test_dir_));
519*86ee64e7SAndroid Build Coastguard Worker 
520*86ee64e7SAndroid Build Coastguard Worker   // No rubbish file should be left behind.
521*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
522*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
523*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre());
524*86ee64e7SAndroid Build Coastguard Worker }
525*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipRepeatedDirName)526*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipRepeatedDirName) {
527*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Unzip(
528*86ee64e7SAndroid Build Coastguard Worker       GetDataDirectory().AppendASCII("Repeated Dir Name.zip"), test_dir_));
529*86ee64e7SAndroid Build Coastguard Worker 
530*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
531*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
532*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre());
533*86ee64e7SAndroid Build Coastguard Worker 
534*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
535*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::DIRECTORIES),
536*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("repeated"));
537*86ee64e7SAndroid Build Coastguard Worker }
538*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipRepeatedFileName)539*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipRepeatedFileName) {
540*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(zip::Unzip(
541*86ee64e7SAndroid Build Coastguard Worker       GetDataDirectory().AppendASCII("Repeated File Name.zip"), test_dir_));
542*86ee64e7SAndroid Build Coastguard Worker 
543*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
544*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
545*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("repeated"));
546*86ee64e7SAndroid Build Coastguard Worker 
547*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
548*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(
549*86ee64e7SAndroid Build Coastguard Worker       base::ReadFileToString(test_dir_.AppendASCII("repeated"), &contents));
550*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("First file", contents);
551*86ee64e7SAndroid Build Coastguard Worker }
552*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipCannotCreateEmptyDir)553*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipCannotCreateEmptyDir) {
554*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(zip::Unzip(
555*86ee64e7SAndroid Build Coastguard Worker       GetDataDirectory().AppendASCII("Empty Dir Same Name As File.zip"),
556*86ee64e7SAndroid Build Coastguard Worker       test_dir_));
557*86ee64e7SAndroid Build Coastguard Worker 
558*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
559*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
560*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("repeated"));
561*86ee64e7SAndroid Build Coastguard Worker 
562*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
563*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::DIRECTORIES),
564*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre());
565*86ee64e7SAndroid Build Coastguard Worker 
566*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
567*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(
568*86ee64e7SAndroid Build Coastguard Worker       base::ReadFileToString(test_dir_.AppendASCII("repeated"), &contents));
569*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("First file", contents);
570*86ee64e7SAndroid Build Coastguard Worker }
571*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipCannotCreateParentDir)572*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipCannotCreateParentDir) {
573*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(zip::Unzip(
574*86ee64e7SAndroid Build Coastguard Worker       GetDataDirectory().AppendASCII("Parent Dir Same Name As File.zip"),
575*86ee64e7SAndroid Build Coastguard Worker       test_dir_));
576*86ee64e7SAndroid Build Coastguard Worker 
577*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
578*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
579*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("repeated"));
580*86ee64e7SAndroid Build Coastguard Worker 
581*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
582*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::DIRECTORIES),
583*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre());
584*86ee64e7SAndroid Build Coastguard Worker 
585*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
586*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(
587*86ee64e7SAndroid Build Coastguard Worker       base::ReadFileToString(test_dir_.AppendASCII("repeated"), &contents));
588*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("First file", contents);
589*86ee64e7SAndroid Build Coastguard Worker }
590*86ee64e7SAndroid Build Coastguard Worker 
591*86ee64e7SAndroid Build Coastguard Worker // TODO(crbug.com/1311140) Detect and rename reserved file names on Windows.
TEST_F(ZipTest,UnzipWindowsSpecialNames)592*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipWindowsSpecialNames) {
593*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(
594*86ee64e7SAndroid Build Coastguard Worker       zip::Unzip(GetDataDirectory().AppendASCII("Windows Special Names.zip"),
595*86ee64e7SAndroid Build Coastguard Worker                  test_dir_, {.continue_on_error = true}));
596*86ee64e7SAndroid Build Coastguard Worker 
597*86ee64e7SAndroid Build Coastguard Worker   std::unordered_set<std::string> want_paths = {
598*86ee64e7SAndroid Build Coastguard Worker       "First",
599*86ee64e7SAndroid Build Coastguard Worker       "Last",
600*86ee64e7SAndroid Build Coastguard Worker       "CLOCK$",
601*86ee64e7SAndroid Build Coastguard Worker       " NUL.txt",
602*86ee64e7SAndroid Build Coastguard Worker #ifndef OS_WIN
603*86ee64e7SAndroid Build Coastguard Worker       "NUL",
604*86ee64e7SAndroid Build Coastguard Worker       "NUL ",
605*86ee64e7SAndroid Build Coastguard Worker       "NUL.",
606*86ee64e7SAndroid Build Coastguard Worker       "NUL .",
607*86ee64e7SAndroid Build Coastguard Worker       "NUL.txt",
608*86ee64e7SAndroid Build Coastguard Worker       "NUL.tar.gz",
609*86ee64e7SAndroid Build Coastguard Worker       "NUL..txt",
610*86ee64e7SAndroid Build Coastguard Worker       "NUL...txt",
611*86ee64e7SAndroid Build Coastguard Worker       "NUL .txt",
612*86ee64e7SAndroid Build Coastguard Worker       "NUL  .txt",
613*86ee64e7SAndroid Build Coastguard Worker       "NUL  ..txt",
614*86ee64e7SAndroid Build Coastguard Worker #ifndef OS_APPLE
615*86ee64e7SAndroid Build Coastguard Worker       "Nul.txt",
616*86ee64e7SAndroid Build Coastguard Worker #endif
617*86ee64e7SAndroid Build Coastguard Worker       "nul.very long extension",
618*86ee64e7SAndroid Build Coastguard Worker       "a/NUL",
619*86ee64e7SAndroid Build Coastguard Worker       "CON",
620*86ee64e7SAndroid Build Coastguard Worker       "PRN",
621*86ee64e7SAndroid Build Coastguard Worker       "AUX",
622*86ee64e7SAndroid Build Coastguard Worker       "COM1",
623*86ee64e7SAndroid Build Coastguard Worker       "COM2",
624*86ee64e7SAndroid Build Coastguard Worker       "COM3",
625*86ee64e7SAndroid Build Coastguard Worker       "COM4",
626*86ee64e7SAndroid Build Coastguard Worker       "COM5",
627*86ee64e7SAndroid Build Coastguard Worker       "COM6",
628*86ee64e7SAndroid Build Coastguard Worker       "COM7",
629*86ee64e7SAndroid Build Coastguard Worker       "COM8",
630*86ee64e7SAndroid Build Coastguard Worker       "COM9",
631*86ee64e7SAndroid Build Coastguard Worker       "LPT1",
632*86ee64e7SAndroid Build Coastguard Worker       "LPT2",
633*86ee64e7SAndroid Build Coastguard Worker       "LPT3",
634*86ee64e7SAndroid Build Coastguard Worker       "LPT4",
635*86ee64e7SAndroid Build Coastguard Worker       "LPT5",
636*86ee64e7SAndroid Build Coastguard Worker       "LPT6",
637*86ee64e7SAndroid Build Coastguard Worker       "LPT7",
638*86ee64e7SAndroid Build Coastguard Worker       "LPT8",
639*86ee64e7SAndroid Build Coastguard Worker       "LPT9",
640*86ee64e7SAndroid Build Coastguard Worker #endif
641*86ee64e7SAndroid Build Coastguard Worker   };
642*86ee64e7SAndroid Build Coastguard Worker 
643*86ee64e7SAndroid Build Coastguard Worker   const std::vector<std::string> got_paths =
644*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES);
645*86ee64e7SAndroid Build Coastguard Worker 
646*86ee64e7SAndroid Build Coastguard Worker   for (const std::string& path : got_paths) {
647*86ee64e7SAndroid Build Coastguard Worker     const bool ok = want_paths.erase(path);
648*86ee64e7SAndroid Build Coastguard Worker 
649*86ee64e7SAndroid Build Coastguard Worker #ifdef OS_WIN
650*86ee64e7SAndroid Build Coastguard Worker     if (!ok) {
651*86ee64e7SAndroid Build Coastguard Worker       // See crbug.com/1313991: Different versions of Windows treat these
652*86ee64e7SAndroid Build Coastguard Worker       // filenames differently. No hard error here if there is an unexpected
653*86ee64e7SAndroid Build Coastguard Worker       // file.
654*86ee64e7SAndroid Build Coastguard Worker       LOG(WARNING) << "Found unexpected file: " << std::quoted(path);
655*86ee64e7SAndroid Build Coastguard Worker       continue;
656*86ee64e7SAndroid Build Coastguard Worker     }
657*86ee64e7SAndroid Build Coastguard Worker #else
658*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(ok) << "Found unexpected file: " << std::quoted(path);
659*86ee64e7SAndroid Build Coastguard Worker #endif
660*86ee64e7SAndroid Build Coastguard Worker 
661*86ee64e7SAndroid Build Coastguard Worker     std::string contents;
662*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(base::ReadFileToString(test_dir_.AppendASCII(path), &contents));
663*86ee64e7SAndroid Build Coastguard Worker     EXPECT_EQ(base::StrCat({"This is: ", path}), contents);
664*86ee64e7SAndroid Build Coastguard Worker   }
665*86ee64e7SAndroid Build Coastguard Worker 
666*86ee64e7SAndroid Build Coastguard Worker   for (const std::string& path : want_paths) {
667*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(false) << "Cannot find expected file: " << std::quoted(path);
668*86ee64e7SAndroid Build Coastguard Worker   }
669*86ee64e7SAndroid Build Coastguard Worker }
670*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipDifferentCases)671*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipDifferentCases) {
672*86ee64e7SAndroid Build Coastguard Worker #if defined(OS_WIN) || defined(OS_APPLE)
673*86ee64e7SAndroid Build Coastguard Worker   // Only the first file (with mixed case) is extracted.
674*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(zip::Unzip(GetDataDirectory().AppendASCII(
675*86ee64e7SAndroid Build Coastguard Worker                               "Repeated File Name With Different Cases.zip"),
676*86ee64e7SAndroid Build Coastguard Worker                           test_dir_));
677*86ee64e7SAndroid Build Coastguard Worker 
678*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
679*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
680*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("Case"));
681*86ee64e7SAndroid Build Coastguard Worker 
682*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
683*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("Case"), &contents));
684*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("Mixed case 111", contents);
685*86ee64e7SAndroid Build Coastguard Worker #else
686*86ee64e7SAndroid Build Coastguard Worker   // All the files are extracted.
687*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Unzip(GetDataDirectory().AppendASCII(
688*86ee64e7SAndroid Build Coastguard Worker                              "Repeated File Name With Different Cases.zip"),
689*86ee64e7SAndroid Build Coastguard Worker                          test_dir_));
690*86ee64e7SAndroid Build Coastguard Worker 
691*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
692*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
693*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("Case", "case", "CASE"));
694*86ee64e7SAndroid Build Coastguard Worker 
695*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
696*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("Case"), &contents));
697*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("Mixed case 111", contents);
698*86ee64e7SAndroid Build Coastguard Worker 
699*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("case"), &contents));
700*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("Lower case 22", contents);
701*86ee64e7SAndroid Build Coastguard Worker 
702*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("CASE"), &contents));
703*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("Upper case 3", contents);
704*86ee64e7SAndroid Build Coastguard Worker #endif
705*86ee64e7SAndroid Build Coastguard Worker }
706*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipDifferentCasesContinueOnError)707*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipDifferentCasesContinueOnError) {
708*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Unzip(GetDataDirectory().AppendASCII(
709*86ee64e7SAndroid Build Coastguard Worker                              "Repeated File Name With Different Cases.zip"),
710*86ee64e7SAndroid Build Coastguard Worker                          test_dir_, {.continue_on_error = true}));
711*86ee64e7SAndroid Build Coastguard Worker 
712*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
713*86ee64e7SAndroid Build Coastguard Worker 
714*86ee64e7SAndroid Build Coastguard Worker #if defined(OS_WIN) || defined(OS_APPLE)
715*86ee64e7SAndroid Build Coastguard Worker   // Only the first file (with mixed case) has been extracted.
716*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
717*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
718*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("Case"));
719*86ee64e7SAndroid Build Coastguard Worker 
720*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("Case"), &contents));
721*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("Mixed case 111", contents);
722*86ee64e7SAndroid Build Coastguard Worker #else
723*86ee64e7SAndroid Build Coastguard Worker   // All the files have been extracted.
724*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
725*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
726*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAre("Case", "case", "CASE"));
727*86ee64e7SAndroid Build Coastguard Worker 
728*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("Case"), &contents));
729*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("Mixed case 111", contents);
730*86ee64e7SAndroid Build Coastguard Worker 
731*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("case"), &contents));
732*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("Lower case 22", contents);
733*86ee64e7SAndroid Build Coastguard Worker 
734*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("CASE"), &contents));
735*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("Upper case 3", contents);
736*86ee64e7SAndroid Build Coastguard Worker #endif
737*86ee64e7SAndroid Build Coastguard Worker }
738*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipMixedPaths)739*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipMixedPaths) {
740*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Unzip(GetDataDirectory().AppendASCII("Mixed Paths.zip"),
741*86ee64e7SAndroid Build Coastguard Worker                          test_dir_, {.continue_on_error = true}));
742*86ee64e7SAndroid Build Coastguard Worker 
743*86ee64e7SAndroid Build Coastguard Worker   std::unordered_set<std::string> want_paths = {
744*86ee64e7SAndroid Build Coastguard Worker #ifdef OS_WIN
745*86ee64e7SAndroid Build Coastguard Worker       "Dot",     //
746*86ee64e7SAndroid Build Coastguard Worker       "Space→",  //
747*86ee64e7SAndroid Build Coastguard Worker #else
748*86ee64e7SAndroid Build Coastguard Worker       " ",                        //
749*86ee64e7SAndroid Build Coastguard Worker       "AUX",                      // Disappears on Windows
750*86ee64e7SAndroid Build Coastguard Worker       "COM1",                     // Disappears on Windows
751*86ee64e7SAndroid Build Coastguard Worker       "COM2",                     // Disappears on Windows
752*86ee64e7SAndroid Build Coastguard Worker       "COM3",                     // Disappears on Windows
753*86ee64e7SAndroid Build Coastguard Worker       "COM4",                     // Disappears on Windows
754*86ee64e7SAndroid Build Coastguard Worker       "COM5",                     // Disappears on Windows
755*86ee64e7SAndroid Build Coastguard Worker       "COM6",                     // Disappears on Windows
756*86ee64e7SAndroid Build Coastguard Worker       "COM7",                     // Disappears on Windows
757*86ee64e7SAndroid Build Coastguard Worker       "COM8",                     // Disappears on Windows
758*86ee64e7SAndroid Build Coastguard Worker       "COM9",                     // Disappears on Windows
759*86ee64e7SAndroid Build Coastguard Worker       "CON",                      // Disappears on Windows
760*86ee64e7SAndroid Build Coastguard Worker       "Dot .",                    //
761*86ee64e7SAndroid Build Coastguard Worker       "LPT1",                     // Disappears on Windows
762*86ee64e7SAndroid Build Coastguard Worker       "LPT2",                     // Disappears on Windows
763*86ee64e7SAndroid Build Coastguard Worker       "LPT3",                     // Disappears on Windows
764*86ee64e7SAndroid Build Coastguard Worker       "LPT4",                     // Disappears on Windows
765*86ee64e7SAndroid Build Coastguard Worker       "LPT5",                     // Disappears on Windows
766*86ee64e7SAndroid Build Coastguard Worker       "LPT6",                     // Disappears on Windows
767*86ee64e7SAndroid Build Coastguard Worker       "LPT7",                     // Disappears on Windows
768*86ee64e7SAndroid Build Coastguard Worker       "LPT8",                     // Disappears on Windows
769*86ee64e7SAndroid Build Coastguard Worker       "LPT9",                     // Disappears on Windows
770*86ee64e7SAndroid Build Coastguard Worker       "NUL  ..txt",               // Disappears on Windows
771*86ee64e7SAndroid Build Coastguard Worker       "NUL  .txt",                // Disappears on Windows
772*86ee64e7SAndroid Build Coastguard Worker       "NUL ",                     // Disappears on Windows
773*86ee64e7SAndroid Build Coastguard Worker       "NUL .",                    // Disappears on Windows
774*86ee64e7SAndroid Build Coastguard Worker       "NUL .txt",                 // Disappears on Windows
775*86ee64e7SAndroid Build Coastguard Worker       "NUL",                      // Disappears on Windows
776*86ee64e7SAndroid Build Coastguard Worker       "NUL.",                     // Disappears on Windows
777*86ee64e7SAndroid Build Coastguard Worker       "NUL...txt",                // Disappears on Windows
778*86ee64e7SAndroid Build Coastguard Worker       "NUL..txt",                 // Disappears on Windows
779*86ee64e7SAndroid Build Coastguard Worker       "NUL.tar.gz",               // Disappears on Windows
780*86ee64e7SAndroid Build Coastguard Worker       "NUL.txt",                  // Disappears on Windows
781*86ee64e7SAndroid Build Coastguard Worker       "PRN",                      // Disappears on Windows
782*86ee64e7SAndroid Build Coastguard Worker       "Space→ ",                  //
783*86ee64e7SAndroid Build Coastguard Worker       "c/NUL",                    // Disappears on Windows
784*86ee64e7SAndroid Build Coastguard Worker       "nul.very long extension",  // Disappears on Windows
785*86ee64e7SAndroid Build Coastguard Worker #ifndef OS_APPLE
786*86ee64e7SAndroid Build Coastguard Worker       "CASE",                     // Conflicts with "Case"
787*86ee64e7SAndroid Build Coastguard Worker       "case",                     // Conflicts with "Case"
788*86ee64e7SAndroid Build Coastguard Worker #endif
789*86ee64e7SAndroid Build Coastguard Worker #endif
790*86ee64e7SAndroid Build Coastguard Worker       " NUL.txt",                  //
791*86ee64e7SAndroid Build Coastguard Worker       " ←Space",                   //
792*86ee64e7SAndroid Build Coastguard Worker       "$HOME",                     //
793*86ee64e7SAndroid Build Coastguard Worker       "%TMP",                      //
794*86ee64e7SAndroid Build Coastguard Worker       "-",                         //
795*86ee64e7SAndroid Build Coastguard Worker       "...Three",                  //
796*86ee64e7SAndroid Build Coastguard Worker       "..Two",                     //
797*86ee64e7SAndroid Build Coastguard Worker       ".One",                      //
798*86ee64e7SAndroid Build Coastguard Worker       "Ampersand &",               //
799*86ee64e7SAndroid Build Coastguard Worker       "Angle ��",                  //
800*86ee64e7SAndroid Build Coastguard Worker       "At @",                      //
801*86ee64e7SAndroid Build Coastguard Worker       "Backslash1→�",              //
802*86ee64e7SAndroid Build Coastguard Worker       "Backslash3→�←Backslash4",   //
803*86ee64e7SAndroid Build Coastguard Worker       "Backspace �",               //
804*86ee64e7SAndroid Build Coastguard Worker       "Backtick `",                //
805*86ee64e7SAndroid Build Coastguard Worker       "Bell �",                    //
806*86ee64e7SAndroid Build Coastguard Worker       "CLOCK$",                    //
807*86ee64e7SAndroid Build Coastguard Worker       "Caret ^",                   //
808*86ee64e7SAndroid Build Coastguard Worker       "Carriage Return �",         //
809*86ee64e7SAndroid Build Coastguard Worker       "Case",                      //
810*86ee64e7SAndroid Build Coastguard Worker       "Colon �",                   //
811*86ee64e7SAndroid Build Coastguard Worker       "Comma ,",                   //
812*86ee64e7SAndroid Build Coastguard Worker       "Curly {}",                  //
813*86ee64e7SAndroid Build Coastguard Worker       "C�",                        //
814*86ee64e7SAndroid Build Coastguard Worker       "C��",                       //
815*86ee64e7SAndroid Build Coastguard Worker       "C��Temp",                   //
816*86ee64e7SAndroid Build Coastguard Worker       "C��Temp�",                  //
817*86ee64e7SAndroid Build Coastguard Worker       "C��Temp�File",              //
818*86ee64e7SAndroid Build Coastguard Worker       "Dash -",                    //
819*86ee64e7SAndroid Build Coastguard Worker       "Delete \x7F",               //
820*86ee64e7SAndroid Build Coastguard Worker       "Dollar $",                  //
821*86ee64e7SAndroid Build Coastguard Worker       "Double quote �",            //
822*86ee64e7SAndroid Build Coastguard Worker       "Equal =",                   //
823*86ee64e7SAndroid Build Coastguard Worker       "Escape �",                  //
824*86ee64e7SAndroid Build Coastguard Worker       "Euro €",                    //
825*86ee64e7SAndroid Build Coastguard Worker       "Exclamation !",             //
826*86ee64e7SAndroid Build Coastguard Worker       "FileOrDir",                 //
827*86ee64e7SAndroid Build Coastguard Worker       "First",                     //
828*86ee64e7SAndroid Build Coastguard Worker       "Hash #",                    //
829*86ee64e7SAndroid Build Coastguard Worker       "Last",                      //
830*86ee64e7SAndroid Build Coastguard Worker       "Line Feed �",               //
831*86ee64e7SAndroid Build Coastguard Worker       "Percent %",                 //
832*86ee64e7SAndroid Build Coastguard Worker       "Pipe �",                    //
833*86ee64e7SAndroid Build Coastguard Worker       "Plus +",                    //
834*86ee64e7SAndroid Build Coastguard Worker       "Question �",                //
835*86ee64e7SAndroid Build Coastguard Worker       "Quote '",                   //
836*86ee64e7SAndroid Build Coastguard Worker       "ROOT/At The Top",           //
837*86ee64e7SAndroid Build Coastguard Worker       "ROOT/UP/Over The Top",      //
838*86ee64e7SAndroid Build Coastguard Worker       "ROOT/dev/null",             //
839*86ee64e7SAndroid Build Coastguard Worker       "Round ()",                  //
840*86ee64e7SAndroid Build Coastguard Worker       "Semicolon ;",               //
841*86ee64e7SAndroid Build Coastguard Worker       "Smile \U0001F642",          //
842*86ee64e7SAndroid Build Coastguard Worker       "Square []",                 //
843*86ee64e7SAndroid Build Coastguard Worker       "Star �",                    //
844*86ee64e7SAndroid Build Coastguard Worker       "String Terminator \u009C",  //
845*86ee64e7SAndroid Build Coastguard Worker       "Tab �",                     //
846*86ee64e7SAndroid Build Coastguard Worker       "Tilde ~",                   //
847*86ee64e7SAndroid Build Coastguard Worker       "UP/One Level Up",           //
848*86ee64e7SAndroid Build Coastguard Worker       "UP/UP/Two Levels Up",       //
849*86ee64e7SAndroid Build Coastguard Worker       "Underscore _",              //
850*86ee64e7SAndroid Build Coastguard Worker       "a/DOT/b",                   //
851*86ee64e7SAndroid Build Coastguard Worker       "a/UP/b",                    //
852*86ee64e7SAndroid Build Coastguard Worker       "u/v/w/x/y/z",               //
853*86ee64e7SAndroid Build Coastguard Worker       "~",                         //
854*86ee64e7SAndroid Build Coastguard Worker       "�←Backslash2",              //
855*86ee64e7SAndroid Build Coastguard Worker       "��server�share�file",       //
856*86ee64e7SAndroid Build Coastguard Worker   };
857*86ee64e7SAndroid Build Coastguard Worker 
858*86ee64e7SAndroid Build Coastguard Worker   const std::vector<std::string> got_paths =
859*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES);
860*86ee64e7SAndroid Build Coastguard Worker 
861*86ee64e7SAndroid Build Coastguard Worker   for (const std::string& path : got_paths) {
862*86ee64e7SAndroid Build Coastguard Worker     const bool ok = want_paths.erase(path);
863*86ee64e7SAndroid Build Coastguard Worker #ifdef OS_WIN
864*86ee64e7SAndroid Build Coastguard Worker     // See crbug.com/1313991: Different versions of Windows treat reserved
865*86ee64e7SAndroid Build Coastguard Worker     // Windows filenames differently. No hard error here if there is an
866*86ee64e7SAndroid Build Coastguard Worker     // unexpected file.
867*86ee64e7SAndroid Build Coastguard Worker     LOG_IF(WARNING, !ok) << "Found unexpected file: " << std::quoted(path);
868*86ee64e7SAndroid Build Coastguard Worker #else
869*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(ok) << "Found unexpected file: " << std::quoted(path);
870*86ee64e7SAndroid Build Coastguard Worker #endif
871*86ee64e7SAndroid Build Coastguard Worker   }
872*86ee64e7SAndroid Build Coastguard Worker 
873*86ee64e7SAndroid Build Coastguard Worker   for (const std::string& path : want_paths) {
874*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(false) << "Cannot find expected file: " << std::quoted(path);
875*86ee64e7SAndroid Build Coastguard Worker   }
876*86ee64e7SAndroid Build Coastguard Worker 
877*86ee64e7SAndroid Build Coastguard Worker   EXPECT_THAT(
878*86ee64e7SAndroid Build Coastguard Worker       GetRelativePaths(test_dir_, base::FileEnumerator::FileType::DIRECTORIES),
879*86ee64e7SAndroid Build Coastguard Worker       UnorderedElementsAreArray({
880*86ee64e7SAndroid Build Coastguard Worker           "Empty",
881*86ee64e7SAndroid Build Coastguard Worker           "ROOT",
882*86ee64e7SAndroid Build Coastguard Worker           "ROOT/Empty",
883*86ee64e7SAndroid Build Coastguard Worker           "ROOT/UP",
884*86ee64e7SAndroid Build Coastguard Worker           "ROOT/dev",
885*86ee64e7SAndroid Build Coastguard Worker           "UP",
886*86ee64e7SAndroid Build Coastguard Worker           "UP/UP",
887*86ee64e7SAndroid Build Coastguard Worker           "a",
888*86ee64e7SAndroid Build Coastguard Worker           "a/DOT",
889*86ee64e7SAndroid Build Coastguard Worker           "a/UP",
890*86ee64e7SAndroid Build Coastguard Worker           "c",
891*86ee64e7SAndroid Build Coastguard Worker           "u",
892*86ee64e7SAndroid Build Coastguard Worker           "u/v",
893*86ee64e7SAndroid Build Coastguard Worker           "u/v/w",
894*86ee64e7SAndroid Build Coastguard Worker           "u/v/w/x",
895*86ee64e7SAndroid Build Coastguard Worker           "u/v/w/x/y",
896*86ee64e7SAndroid Build Coastguard Worker       }));
897*86ee64e7SAndroid Build Coastguard Worker }
898*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipWithDelegates)899*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipWithDelegates) {
900*86ee64e7SAndroid Build Coastguard Worker   auto dir_creator =
901*86ee64e7SAndroid Build Coastguard Worker       base::BindLambdaForTesting([this](const base::FilePath& entry_path) {
902*86ee64e7SAndroid Build Coastguard Worker         return base::CreateDirectory(test_dir_.Append(entry_path));
903*86ee64e7SAndroid Build Coastguard Worker       });
904*86ee64e7SAndroid Build Coastguard Worker   auto writer =
905*86ee64e7SAndroid Build Coastguard Worker       base::BindLambdaForTesting([this](const base::FilePath& entry_path)
906*86ee64e7SAndroid Build Coastguard Worker                                      -> std::unique_ptr<zip::WriterDelegate> {
907*86ee64e7SAndroid Build Coastguard Worker         return std::make_unique<zip::FilePathWriterDelegate>(
908*86ee64e7SAndroid Build Coastguard Worker             test_dir_.Append(entry_path));
909*86ee64e7SAndroid Build Coastguard Worker       });
910*86ee64e7SAndroid Build Coastguard Worker 
911*86ee64e7SAndroid Build Coastguard Worker   base::File file(GetDataDirectory().AppendASCII("test.zip"),
912*86ee64e7SAndroid Build Coastguard Worker                   base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ);
913*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Unzip(file.GetPlatformFile(), writer, dir_creator));
914*86ee64e7SAndroid Build Coastguard Worker   base::FilePath dir = test_dir_;
915*86ee64e7SAndroid Build Coastguard Worker   base::FilePath dir_foo = dir.AppendASCII("foo");
916*86ee64e7SAndroid Build Coastguard Worker   base::FilePath dir_foo_bar = dir_foo.AppendASCII("bar");
917*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::PathExists(dir.AppendASCII("foo.txt")));
918*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::DirectoryExists(dir_foo));
919*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::PathExists(dir_foo.AppendASCII("bar.txt")));
920*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::DirectoryExists(dir_foo_bar));
921*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::PathExists(dir_foo_bar.AppendASCII(".hidden")));
922*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::PathExists(dir_foo_bar.AppendASCII("baz.txt")));
923*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::PathExists(dir_foo_bar.AppendASCII("quux.txt")));
924*86ee64e7SAndroid Build Coastguard Worker }
925*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipOnlyDirectories)926*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipOnlyDirectories) {
927*86ee64e7SAndroid Build Coastguard Worker   auto dir_creator =
928*86ee64e7SAndroid Build Coastguard Worker       base::BindLambdaForTesting([this](const base::FilePath& entry_path) {
929*86ee64e7SAndroid Build Coastguard Worker         return base::CreateDirectory(test_dir_.Append(entry_path));
930*86ee64e7SAndroid Build Coastguard Worker       });
931*86ee64e7SAndroid Build Coastguard Worker 
932*86ee64e7SAndroid Build Coastguard Worker   // Always return a null WriterDelegate.
933*86ee64e7SAndroid Build Coastguard Worker   auto writer =
934*86ee64e7SAndroid Build Coastguard Worker       base::BindLambdaForTesting([](const base::FilePath& entry_path) {
935*86ee64e7SAndroid Build Coastguard Worker         return std::unique_ptr<zip::WriterDelegate>();
936*86ee64e7SAndroid Build Coastguard Worker       });
937*86ee64e7SAndroid Build Coastguard Worker 
938*86ee64e7SAndroid Build Coastguard Worker   base::File file(GetDataDirectory().AppendASCII("test.zip"),
939*86ee64e7SAndroid Build Coastguard Worker                   base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ);
940*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Unzip(file.GetPlatformFile(), writer, dir_creator,
941*86ee64e7SAndroid Build Coastguard Worker                          {.continue_on_error = true}));
942*86ee64e7SAndroid Build Coastguard Worker   base::FilePath dir = test_dir_;
943*86ee64e7SAndroid Build Coastguard Worker   base::FilePath dir_foo = dir.AppendASCII("foo");
944*86ee64e7SAndroid Build Coastguard Worker   base::FilePath dir_foo_bar = dir_foo.AppendASCII("bar");
945*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(base::PathExists(dir.AppendASCII("foo.txt")));
946*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::DirectoryExists(dir_foo));
947*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(base::PathExists(dir_foo.AppendASCII("bar.txt")));
948*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::DirectoryExists(dir_foo_bar));
949*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(base::PathExists(dir_foo_bar.AppendASCII(".hidden")));
950*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(base::PathExists(dir_foo_bar.AppendASCII("baz.txt")));
951*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(base::PathExists(dir_foo_bar.AppendASCII("quux.txt")));
952*86ee64e7SAndroid Build Coastguard Worker }
953*86ee64e7SAndroid Build Coastguard Worker 
954*86ee64e7SAndroid Build Coastguard Worker // Tests that a ZIP archive containing SJIS-encoded file names can be correctly
955*86ee64e7SAndroid Build Coastguard Worker // extracted if the encoding is specified.
TEST_F(ZipTest,UnzipSjis)956*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipSjis) {
957*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(zip::Unzip(GetDataDirectory().AppendASCII("SJIS Bug 846195.zip"),
958*86ee64e7SAndroid Build Coastguard Worker                          test_dir_, {.encoding = "Shift_JIS"}));
959*86ee64e7SAndroid Build Coastguard Worker 
960*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath dir =
961*86ee64e7SAndroid Build Coastguard Worker       test_dir_.Append(base::FilePath::FromUTF8Unsafe("新しいフォルダ"));
962*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::DirectoryExists(dir));
963*86ee64e7SAndroid Build Coastguard Worker 
964*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
965*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::ReadFileToString(
966*86ee64e7SAndroid Build Coastguard Worker       dir.Append(base::FilePath::FromUTF8Unsafe("SJIS_835C_ソ.txt")),
967*86ee64e7SAndroid Build Coastguard Worker       &contents));
968*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(
969*86ee64e7SAndroid Build Coastguard Worker       "This file's name contains 0x5c (backslash) as the 2nd byte of Japanese "
970*86ee64e7SAndroid Build Coastguard Worker       "characater \"\x83\x5c\" when encoded in Shift JIS.",
971*86ee64e7SAndroid Build Coastguard Worker       contents);
972*86ee64e7SAndroid Build Coastguard Worker 
973*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::ReadFileToString(dir.Append(base::FilePath::FromUTF8Unsafe(
974*86ee64e7SAndroid Build Coastguard Worker                                          "新しいテキスト ドキュメント.txt")),
975*86ee64e7SAndroid Build Coastguard Worker                                      &contents));
976*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("This file name is coded in Shift JIS in the archive.", contents);
977*86ee64e7SAndroid Build Coastguard Worker }
978*86ee64e7SAndroid Build Coastguard Worker 
979*86ee64e7SAndroid Build Coastguard Worker // Tests that a ZIP archive containing SJIS-encoded file names can be extracted
980*86ee64e7SAndroid Build Coastguard Worker // even if the encoding is not specified. In this case, file names are
981*86ee64e7SAndroid Build Coastguard Worker // interpreted as UTF-8, which leads to garbled names where invalid UTF-8
982*86ee64e7SAndroid Build Coastguard Worker // sequences are replaced with the character �. Nevertheless, the files are
983*86ee64e7SAndroid Build Coastguard Worker // safely extracted and readable.
TEST_F(ZipTest,UnzipSjisAsUtf8)984*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipSjisAsUtf8) {
985*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(zip::Unzip(GetDataDirectory().AppendASCII("SJIS Bug 846195.zip"),
986*86ee64e7SAndroid Build Coastguard Worker                          test_dir_));
987*86ee64e7SAndroid Build Coastguard Worker 
988*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(base::DirectoryExists(
989*86ee64e7SAndroid Build Coastguard Worker       test_dir_.Append(base::FilePath::FromUTF8Unsafe("新しいフォルダ"))));
990*86ee64e7SAndroid Build Coastguard Worker 
991*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath dir =
992*86ee64e7SAndroid Build Coastguard Worker       test_dir_.Append(base::FilePath::FromUTF8Unsafe("�V�����t�H���_"));
993*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::DirectoryExists(dir));
994*86ee64e7SAndroid Build Coastguard Worker 
995*86ee64e7SAndroid Build Coastguard Worker   std::string contents;
996*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::ReadFileToString(
997*86ee64e7SAndroid Build Coastguard Worker       dir.Append(base::FilePath::FromUTF8Unsafe("SJIS_835C_��.txt")),
998*86ee64e7SAndroid Build Coastguard Worker       &contents));
999*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(
1000*86ee64e7SAndroid Build Coastguard Worker       "This file's name contains 0x5c (backslash) as the 2nd byte of Japanese "
1001*86ee64e7SAndroid Build Coastguard Worker       "characater \"\x83\x5c\" when encoded in Shift JIS.",
1002*86ee64e7SAndroid Build Coastguard Worker       contents);
1003*86ee64e7SAndroid Build Coastguard Worker 
1004*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::ReadFileToString(dir.Append(base::FilePath::FromUTF8Unsafe(
1005*86ee64e7SAndroid Build Coastguard Worker                                          "�V�����e�L�X�g �h�L�������g.txt")),
1006*86ee64e7SAndroid Build Coastguard Worker                                      &contents));
1007*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ("This file name is coded in Shift JIS in the archive.", contents);
1008*86ee64e7SAndroid Build Coastguard Worker }
1009*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,Zip)1010*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, Zip) {
1011*86ee64e7SAndroid Build Coastguard Worker   base::FilePath src_dir = GetDataDirectory().AppendASCII("test");
1012*86ee64e7SAndroid Build Coastguard Worker 
1013*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir;
1014*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1015*86ee64e7SAndroid Build Coastguard Worker   base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
1016*86ee64e7SAndroid Build Coastguard Worker 
1017*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Zip(src_dir, zip_file, /*include_hidden_files=*/true));
1018*86ee64e7SAndroid Build Coastguard Worker   TestUnzipFile(zip_file, true);
1019*86ee64e7SAndroid Build Coastguard Worker }
1020*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,ZipIgnoreHidden)1021*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, ZipIgnoreHidden) {
1022*86ee64e7SAndroid Build Coastguard Worker   base::FilePath src_dir = GetDataDirectory().AppendASCII("test");
1023*86ee64e7SAndroid Build Coastguard Worker 
1024*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir;
1025*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1026*86ee64e7SAndroid Build Coastguard Worker   base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
1027*86ee64e7SAndroid Build Coastguard Worker 
1028*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Zip(src_dir, zip_file, /*include_hidden_files=*/false));
1029*86ee64e7SAndroid Build Coastguard Worker   TestUnzipFile(zip_file, false);
1030*86ee64e7SAndroid Build Coastguard Worker }
1031*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,ZipNonASCIIDir)1032*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, ZipNonASCIIDir) {
1033*86ee64e7SAndroid Build Coastguard Worker   base::FilePath src_dir = GetDataDirectory().AppendASCII("test");
1034*86ee64e7SAndroid Build Coastguard Worker 
1035*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir;
1036*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1037*86ee64e7SAndroid Build Coastguard Worker   // Append 'Тест' (in cyrillic).
1038*86ee64e7SAndroid Build Coastguard Worker   base::FilePath src_dir_russian = temp_dir.GetPath().Append(
1039*86ee64e7SAndroid Build Coastguard Worker       base::FilePath::FromUTF8Unsafe("\xD0\xA2\xD0\xB5\xD1\x81\xD1\x82"));
1040*86ee64e7SAndroid Build Coastguard Worker   base::CopyDirectory(src_dir, src_dir_russian, true);
1041*86ee64e7SAndroid Build Coastguard Worker   base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out_russian.zip");
1042*86ee64e7SAndroid Build Coastguard Worker 
1043*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Zip(src_dir_russian, zip_file, true));
1044*86ee64e7SAndroid Build Coastguard Worker   TestUnzipFile(zip_file, true);
1045*86ee64e7SAndroid Build Coastguard Worker }
1046*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,ZipTimeStamp)1047*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, ZipTimeStamp) {
1048*86ee64e7SAndroid Build Coastguard Worker   // The dates tested are arbitrary, with some constraints. The zip format can
1049*86ee64e7SAndroid Build Coastguard Worker   // only store years from 1980 to 2107 and an even number of seconds, due to it
1050*86ee64e7SAndroid Build Coastguard Worker   // using the ms dos date format.
1051*86ee64e7SAndroid Build Coastguard Worker 
1052*86ee64e7SAndroid Build Coastguard Worker   // Valid arbitrary date.
1053*86ee64e7SAndroid Build Coastguard Worker   TestTimeStamp("23 Oct 1997 23:22:20", VALID_YEAR);
1054*86ee64e7SAndroid Build Coastguard Worker 
1055*86ee64e7SAndroid Build Coastguard Worker   // Date before 1980, zip format limitation, must default to unix epoch.
1056*86ee64e7SAndroid Build Coastguard Worker   TestTimeStamp("29 Dec 1979 21:00:10", INVALID_YEAR);
1057*86ee64e7SAndroid Build Coastguard Worker 
1058*86ee64e7SAndroid Build Coastguard Worker   // Despite the minizip headers telling the maximum year should be 2044, it
1059*86ee64e7SAndroid Build Coastguard Worker   // can actually go up to 2107. Beyond that, the dos date format cannot store
1060*86ee64e7SAndroid Build Coastguard Worker   // the year (2107-1980=127). To test that limit, the input file needs to be
1061*86ee64e7SAndroid Build Coastguard Worker   // touched, but the code that modifies the file access and modification times
1062*86ee64e7SAndroid Build Coastguard Worker   // relies on time_t which is defined as long, therefore being in many
1063*86ee64e7SAndroid Build Coastguard Worker   // platforms just a 4-byte integer, like 32-bit Mac OSX or linux. As such, it
1064*86ee64e7SAndroid Build Coastguard Worker   // suffers from the year-2038 bug. Therefore 2038 is the highest we can test
1065*86ee64e7SAndroid Build Coastguard Worker   // in all platforms reliably.
1066*86ee64e7SAndroid Build Coastguard Worker   TestTimeStamp("02 Jan 2038 23:59:58", VALID_YEAR);
1067*86ee64e7SAndroid Build Coastguard Worker }
1068*86ee64e7SAndroid Build Coastguard Worker 
1069*86ee64e7SAndroid Build Coastguard Worker #if defined(OS_POSIX) || defined(OS_FUCHSIA)
TEST_F(ZipTest,ZipFiles)1070*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, ZipFiles) {
1071*86ee64e7SAndroid Build Coastguard Worker   base::FilePath src_dir = GetDataDirectory().AppendASCII("test");
1072*86ee64e7SAndroid Build Coastguard Worker 
1073*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir;
1074*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1075*86ee64e7SAndroid Build Coastguard Worker   base::FilePath zip_name = temp_dir.GetPath().AppendASCII("out.zip");
1076*86ee64e7SAndroid Build Coastguard Worker 
1077*86ee64e7SAndroid Build Coastguard Worker   base::File zip_file(zip_name,
1078*86ee64e7SAndroid Build Coastguard Worker                       base::File::FLAG_CREATE | base::File::FLAG_WRITE);
1079*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(zip_file.IsValid());
1080*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(
1081*86ee64e7SAndroid Build Coastguard Worker       zip::ZipFiles(src_dir, zip_file_list_, zip_file.GetPlatformFile()));
1082*86ee64e7SAndroid Build Coastguard Worker   zip_file.Close();
1083*86ee64e7SAndroid Build Coastguard Worker 
1084*86ee64e7SAndroid Build Coastguard Worker   zip::ZipReader reader;
1085*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Open(zip_name));
1086*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(zip_file_list_.size(), static_cast<size_t>(reader.num_entries()));
1087*86ee64e7SAndroid Build Coastguard Worker   for (size_t i = 0; i < zip_file_list_.size(); ++i) {
1088*86ee64e7SAndroid Build Coastguard Worker     const zip::ZipReader::Entry* const entry = reader.Next();
1089*86ee64e7SAndroid Build Coastguard Worker     ASSERT_TRUE(entry);
1090*86ee64e7SAndroid Build Coastguard Worker     EXPECT_EQ(entry->path, zip_file_list_[i]);
1091*86ee64e7SAndroid Build Coastguard Worker   }
1092*86ee64e7SAndroid Build Coastguard Worker }
1093*86ee64e7SAndroid Build Coastguard Worker #endif  // defined(OS_POSIX) || defined(OS_FUCHSIA)
1094*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,UnzipFilesWithIncorrectSize)1095*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, UnzipFilesWithIncorrectSize) {
1096*86ee64e7SAndroid Build Coastguard Worker   // test_mismatch_size.zip contains files with names from 0.txt to 7.txt with
1097*86ee64e7SAndroid Build Coastguard Worker   // sizes from 0 to 7 bytes respectively, but the metadata in the zip file says
1098*86ee64e7SAndroid Build Coastguard Worker   // the uncompressed size is 3 bytes. The ZipReader and minizip code needs to
1099*86ee64e7SAndroid Build Coastguard Worker   // be clever enough to get all the data out.
1100*86ee64e7SAndroid Build Coastguard Worker   base::FilePath test_zip_file =
1101*86ee64e7SAndroid Build Coastguard Worker       GetDataDirectory().AppendASCII("test_mismatch_size.zip");
1102*86ee64e7SAndroid Build Coastguard Worker 
1103*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir scoped_temp_dir;
1104*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
1105*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath& temp_dir = scoped_temp_dir.GetPath();
1106*86ee64e7SAndroid Build Coastguard Worker 
1107*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(zip::Unzip(test_zip_file, temp_dir));
1108*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::DirectoryExists(temp_dir.AppendASCII("d")));
1109*86ee64e7SAndroid Build Coastguard Worker 
1110*86ee64e7SAndroid Build Coastguard Worker   for (int i = 0; i < 8; i++) {
1111*86ee64e7SAndroid Build Coastguard Worker     SCOPED_TRACE(base::StringPrintf("Processing %d.txt", i));
1112*86ee64e7SAndroid Build Coastguard Worker     base::FilePath file_path =
1113*86ee64e7SAndroid Build Coastguard Worker         temp_dir.AppendASCII(base::StringPrintf("%d.txt", i));
1114*86ee64e7SAndroid Build Coastguard Worker     int64_t file_size = -1;
1115*86ee64e7SAndroid Build Coastguard Worker     EXPECT_TRUE(base::GetFileSize(file_path, &file_size));
1116*86ee64e7SAndroid Build Coastguard Worker     EXPECT_EQ(static_cast<int64_t>(i), file_size);
1117*86ee64e7SAndroid Build Coastguard Worker   }
1118*86ee64e7SAndroid Build Coastguard Worker }
1119*86ee64e7SAndroid Build Coastguard Worker 
TEST_F(ZipTest,ZipWithFileAccessor)1120*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, ZipWithFileAccessor) {
1121*86ee64e7SAndroid Build Coastguard Worker   base::FilePath zip_file;
1122*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::CreateTemporaryFile(&zip_file));
1123*86ee64e7SAndroid Build Coastguard Worker   VirtualFileSystem file_accessor;
1124*86ee64e7SAndroid Build Coastguard Worker   const zip::ZipParams params{.file_accessor = &file_accessor,
1125*86ee64e7SAndroid Build Coastguard Worker                               .dest_file = zip_file};
1126*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(zip::Zip(params));
1127*86ee64e7SAndroid Build Coastguard Worker 
1128*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir scoped_temp_dir;
1129*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
1130*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath& temp_dir = scoped_temp_dir.GetPath();
1131*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(zip::Unzip(zip_file, temp_dir));
1132*86ee64e7SAndroid Build Coastguard Worker   base::FilePath bar_dir = temp_dir.AppendASCII("bar");
1133*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::DirectoryExists(bar_dir));
1134*86ee64e7SAndroid Build Coastguard Worker   std::string file_content;
1135*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(
1136*86ee64e7SAndroid Build Coastguard Worker       base::ReadFileToString(temp_dir.AppendASCII("foo.txt"), &file_content));
1137*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(VirtualFileSystem::kFooContent, file_content);
1138*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(
1139*86ee64e7SAndroid Build Coastguard Worker       base::ReadFileToString(bar_dir.AppendASCII("bar1.txt"), &file_content));
1140*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(VirtualFileSystem::kBar1Content, file_content);
1141*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(
1142*86ee64e7SAndroid Build Coastguard Worker       base::ReadFileToString(bar_dir.AppendASCII("bar2.txt"), &file_content));
1143*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(VirtualFileSystem::kBar2Content, file_content);
1144*86ee64e7SAndroid Build Coastguard Worker }
1145*86ee64e7SAndroid Build Coastguard Worker 
1146*86ee64e7SAndroid Build Coastguard Worker // Tests progress reporting while zipping files.
TEST_F(ZipTest,ZipProgress)1147*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, ZipProgress) {
1148*86ee64e7SAndroid Build Coastguard Worker   base::FilePath src_dir = GetDataDirectory().AppendASCII("test");
1149*86ee64e7SAndroid Build Coastguard Worker 
1150*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir;
1151*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1152*86ee64e7SAndroid Build Coastguard Worker   base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
1153*86ee64e7SAndroid Build Coastguard Worker 
1154*86ee64e7SAndroid Build Coastguard Worker   int progress_count = 0;
1155*86ee64e7SAndroid Build Coastguard Worker   zip::Progress last_progress;
1156*86ee64e7SAndroid Build Coastguard Worker 
1157*86ee64e7SAndroid Build Coastguard Worker   zip::ProgressCallback progress_callback =
1158*86ee64e7SAndroid Build Coastguard Worker       base::BindLambdaForTesting([&](const zip::Progress& progress) {
1159*86ee64e7SAndroid Build Coastguard Worker         progress_count++;
1160*86ee64e7SAndroid Build Coastguard Worker         LOG(INFO) << "Progress #" << progress_count << ": " << progress;
1161*86ee64e7SAndroid Build Coastguard Worker 
1162*86ee64e7SAndroid Build Coastguard Worker         // Progress should only go forwards.
1163*86ee64e7SAndroid Build Coastguard Worker         EXPECT_GE(progress.bytes, last_progress.bytes);
1164*86ee64e7SAndroid Build Coastguard Worker         EXPECT_GE(progress.files, last_progress.files);
1165*86ee64e7SAndroid Build Coastguard Worker         EXPECT_GE(progress.directories, last_progress.directories);
1166*86ee64e7SAndroid Build Coastguard Worker 
1167*86ee64e7SAndroid Build Coastguard Worker         last_progress = progress;
1168*86ee64e7SAndroid Build Coastguard Worker         return true;
1169*86ee64e7SAndroid Build Coastguard Worker       });
1170*86ee64e7SAndroid Build Coastguard Worker 
1171*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Zip({.src_dir = src_dir,
1172*86ee64e7SAndroid Build Coastguard Worker                         .dest_file = zip_file,
1173*86ee64e7SAndroid Build Coastguard Worker                         .progress_callback = std::move(progress_callback)}));
1174*86ee64e7SAndroid Build Coastguard Worker 
1175*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(progress_count, 14);
1176*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(last_progress.bytes, 13546);
1177*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(last_progress.files, 5);
1178*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(last_progress.directories, 2);
1179*86ee64e7SAndroid Build Coastguard Worker 
1180*86ee64e7SAndroid Build Coastguard Worker   TestUnzipFile(zip_file, true);
1181*86ee64e7SAndroid Build Coastguard Worker }
1182*86ee64e7SAndroid Build Coastguard Worker 
1183*86ee64e7SAndroid Build Coastguard Worker // Tests throttling of progress reporting while zipping files.
TEST_F(ZipTest,ZipProgressPeriod)1184*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, ZipProgressPeriod) {
1185*86ee64e7SAndroid Build Coastguard Worker   base::FilePath src_dir = GetDataDirectory().AppendASCII("test");
1186*86ee64e7SAndroid Build Coastguard Worker 
1187*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir;
1188*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1189*86ee64e7SAndroid Build Coastguard Worker   base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
1190*86ee64e7SAndroid Build Coastguard Worker 
1191*86ee64e7SAndroid Build Coastguard Worker   int progress_count = 0;
1192*86ee64e7SAndroid Build Coastguard Worker   zip::Progress last_progress;
1193*86ee64e7SAndroid Build Coastguard Worker 
1194*86ee64e7SAndroid Build Coastguard Worker   zip::ProgressCallback progress_callback =
1195*86ee64e7SAndroid Build Coastguard Worker       base::BindLambdaForTesting([&](const zip::Progress& progress) {
1196*86ee64e7SAndroid Build Coastguard Worker         progress_count++;
1197*86ee64e7SAndroid Build Coastguard Worker         LOG(INFO) << "Progress #" << progress_count << ": " << progress;
1198*86ee64e7SAndroid Build Coastguard Worker 
1199*86ee64e7SAndroid Build Coastguard Worker         // Progress should only go forwards.
1200*86ee64e7SAndroid Build Coastguard Worker         EXPECT_GE(progress.bytes, last_progress.bytes);
1201*86ee64e7SAndroid Build Coastguard Worker         EXPECT_GE(progress.files, last_progress.files);
1202*86ee64e7SAndroid Build Coastguard Worker         EXPECT_GE(progress.directories, last_progress.directories);
1203*86ee64e7SAndroid Build Coastguard Worker 
1204*86ee64e7SAndroid Build Coastguard Worker         last_progress = progress;
1205*86ee64e7SAndroid Build Coastguard Worker         return true;
1206*86ee64e7SAndroid Build Coastguard Worker       });
1207*86ee64e7SAndroid Build Coastguard Worker 
1208*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Zip({.src_dir = src_dir,
1209*86ee64e7SAndroid Build Coastguard Worker                         .dest_file = zip_file,
1210*86ee64e7SAndroid Build Coastguard Worker                         .progress_callback = std::move(progress_callback),
1211*86ee64e7SAndroid Build Coastguard Worker                         .progress_period = base::Hours(1)}));
1212*86ee64e7SAndroid Build Coastguard Worker 
1213*86ee64e7SAndroid Build Coastguard Worker   // We expect only 2 progress reports: the first one, and the last one.
1214*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(progress_count, 2);
1215*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(last_progress.bytes, 13546);
1216*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(last_progress.files, 5);
1217*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(last_progress.directories, 2);
1218*86ee64e7SAndroid Build Coastguard Worker 
1219*86ee64e7SAndroid Build Coastguard Worker   TestUnzipFile(zip_file, true);
1220*86ee64e7SAndroid Build Coastguard Worker }
1221*86ee64e7SAndroid Build Coastguard Worker 
1222*86ee64e7SAndroid Build Coastguard Worker // Tests cancellation while zipping files.
TEST_F(ZipTest,ZipCancel)1223*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, ZipCancel) {
1224*86ee64e7SAndroid Build Coastguard Worker   base::FilePath src_dir = GetDataDirectory().AppendASCII("test");
1225*86ee64e7SAndroid Build Coastguard Worker 
1226*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir;
1227*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1228*86ee64e7SAndroid Build Coastguard Worker   base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
1229*86ee64e7SAndroid Build Coastguard Worker 
1230*86ee64e7SAndroid Build Coastguard Worker   // First: establish the number of possible interruption points.
1231*86ee64e7SAndroid Build Coastguard Worker   int progress_count = 0;
1232*86ee64e7SAndroid Build Coastguard Worker 
1233*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Zip({.src_dir = src_dir,
1234*86ee64e7SAndroid Build Coastguard Worker                         .dest_file = zip_file,
1235*86ee64e7SAndroid Build Coastguard Worker                         .progress_callback = base::BindLambdaForTesting(
1236*86ee64e7SAndroid Build Coastguard Worker                             [&progress_count](const zip::Progress&) {
1237*86ee64e7SAndroid Build Coastguard Worker                               progress_count++;
1238*86ee64e7SAndroid Build Coastguard Worker                               return true;
1239*86ee64e7SAndroid Build Coastguard Worker                             })}));
1240*86ee64e7SAndroid Build Coastguard Worker 
1241*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(progress_count, 14);
1242*86ee64e7SAndroid Build Coastguard Worker 
1243*86ee64e7SAndroid Build Coastguard Worker   // Second: exercise each and every interruption point.
1244*86ee64e7SAndroid Build Coastguard Worker   for (int i = progress_count; i > 0; i--) {
1245*86ee64e7SAndroid Build Coastguard Worker     int j = 0;
1246*86ee64e7SAndroid Build Coastguard Worker     EXPECT_FALSE(zip::Zip({.src_dir = src_dir,
1247*86ee64e7SAndroid Build Coastguard Worker                            .dest_file = zip_file,
1248*86ee64e7SAndroid Build Coastguard Worker                            .progress_callback = base::BindLambdaForTesting(
1249*86ee64e7SAndroid Build Coastguard Worker                                [i, &j](const zip::Progress&) {
1250*86ee64e7SAndroid Build Coastguard Worker                                  j++;
1251*86ee64e7SAndroid Build Coastguard Worker                                  // Callback shouldn't be called again after
1252*86ee64e7SAndroid Build Coastguard Worker                                  // having returned false once.
1253*86ee64e7SAndroid Build Coastguard Worker                                  EXPECT_LE(j, i);
1254*86ee64e7SAndroid Build Coastguard Worker                                  return j < i;
1255*86ee64e7SAndroid Build Coastguard Worker                                })}));
1256*86ee64e7SAndroid Build Coastguard Worker 
1257*86ee64e7SAndroid Build Coastguard Worker     EXPECT_EQ(j, i);
1258*86ee64e7SAndroid Build Coastguard Worker   }
1259*86ee64e7SAndroid Build Coastguard Worker }
1260*86ee64e7SAndroid Build Coastguard Worker 
1261*86ee64e7SAndroid Build Coastguard Worker // Tests zip::internal::GetCompressionMethod()
TEST_F(ZipTest,GetCompressionMethod)1262*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, GetCompressionMethod) {
1263*86ee64e7SAndroid Build Coastguard Worker   using zip::internal::GetCompressionMethod;
1264*86ee64e7SAndroid Build Coastguard Worker   using zip::internal::kDeflated;
1265*86ee64e7SAndroid Build Coastguard Worker   using zip::internal::kStored;
1266*86ee64e7SAndroid Build Coastguard Worker 
1267*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("")), kDeflated);
1268*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("NoExtension")), kDeflated);
1269*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("Folder.zip").Append(FP("NoExtension"))),
1270*86ee64e7SAndroid Build Coastguard Worker             kDeflated);
1271*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("Name.txt")), kDeflated);
1272*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("Name.zip")), kStored);
1273*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("Name....zip")), kStored);
1274*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("Name.zip")), kStored);
1275*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("NAME.ZIP")), kStored);
1276*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("Name.gz")), kStored);
1277*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("Name.tar.gz")), kStored);
1278*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP("Name.tar")), kDeflated);
1279*86ee64e7SAndroid Build Coastguard Worker 
1280*86ee64e7SAndroid Build Coastguard Worker   // This one is controversial.
1281*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(GetCompressionMethod(FP(".zip")), kStored);
1282*86ee64e7SAndroid Build Coastguard Worker }
1283*86ee64e7SAndroid Build Coastguard Worker 
1284*86ee64e7SAndroid Build Coastguard Worker // Tests that files put inside a ZIP are effectively compressed.
TEST_F(ZipTest,Compressed)1285*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, Compressed) {
1286*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir;
1287*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1288*86ee64e7SAndroid Build Coastguard Worker 
1289*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath src_dir = temp_dir.GetPath().AppendASCII("input");
1290*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::CreateDirectory(src_dir));
1291*86ee64e7SAndroid Build Coastguard Worker 
1292*86ee64e7SAndroid Build Coastguard Worker   // Create some dummy source files.
1293*86ee64e7SAndroid Build Coastguard Worker   for (const base::StringPiece s : {"foo", "bar.txt", ".hidden"}) {
1294*86ee64e7SAndroid Build Coastguard Worker     base::File f(src_dir.AppendASCII(s),
1295*86ee64e7SAndroid Build Coastguard Worker                  base::File::FLAG_CREATE | base::File::FLAG_WRITE);
1296*86ee64e7SAndroid Build Coastguard Worker     ASSERT_TRUE(f.SetLength(5000));
1297*86ee64e7SAndroid Build Coastguard Worker   }
1298*86ee64e7SAndroid Build Coastguard Worker 
1299*86ee64e7SAndroid Build Coastguard Worker   // Zip the source files.
1300*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath dest_file = temp_dir.GetPath().AppendASCII("dest.zip");
1301*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Zip({.src_dir = src_dir,
1302*86ee64e7SAndroid Build Coastguard Worker                         .dest_file = dest_file,
1303*86ee64e7SAndroid Build Coastguard Worker                         .include_hidden_files = true}));
1304*86ee64e7SAndroid Build Coastguard Worker 
1305*86ee64e7SAndroid Build Coastguard Worker   // Since the source files compress well, the destination ZIP file should be
1306*86ee64e7SAndroid Build Coastguard Worker   // smaller than the source files.
1307*86ee64e7SAndroid Build Coastguard Worker   int64_t dest_file_size;
1308*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::GetFileSize(dest_file, &dest_file_size));
1309*86ee64e7SAndroid Build Coastguard Worker   EXPECT_GT(dest_file_size, 300);
1310*86ee64e7SAndroid Build Coastguard Worker   EXPECT_LT(dest_file_size, 1000);
1311*86ee64e7SAndroid Build Coastguard Worker }
1312*86ee64e7SAndroid Build Coastguard Worker 
1313*86ee64e7SAndroid Build Coastguard Worker // Tests that a ZIP put inside a ZIP is simply stored instead of being
1314*86ee64e7SAndroid Build Coastguard Worker // compressed.
TEST_F(ZipTest,NestedZip)1315*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, NestedZip) {
1316*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir;
1317*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1318*86ee64e7SAndroid Build Coastguard Worker 
1319*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath src_dir = temp_dir.GetPath().AppendASCII("input");
1320*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::CreateDirectory(src_dir));
1321*86ee64e7SAndroid Build Coastguard Worker 
1322*86ee64e7SAndroid Build Coastguard Worker   // Create a dummy ZIP file. This is not a valid ZIP file, but for the purpose
1323*86ee64e7SAndroid Build Coastguard Worker   // of this test, it doesn't really matter.
1324*86ee64e7SAndroid Build Coastguard Worker   const int64_t src_size = 5000;
1325*86ee64e7SAndroid Build Coastguard Worker 
1326*86ee64e7SAndroid Build Coastguard Worker   {
1327*86ee64e7SAndroid Build Coastguard Worker     base::File f(src_dir.AppendASCII("src.zip"),
1328*86ee64e7SAndroid Build Coastguard Worker                  base::File::FLAG_CREATE | base::File::FLAG_WRITE);
1329*86ee64e7SAndroid Build Coastguard Worker     ASSERT_TRUE(f.SetLength(src_size));
1330*86ee64e7SAndroid Build Coastguard Worker   }
1331*86ee64e7SAndroid Build Coastguard Worker 
1332*86ee64e7SAndroid Build Coastguard Worker   // Zip the dummy ZIP file.
1333*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath dest_file = temp_dir.GetPath().AppendASCII("dest.zip");
1334*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Zip({.src_dir = src_dir, .dest_file = dest_file}));
1335*86ee64e7SAndroid Build Coastguard Worker 
1336*86ee64e7SAndroid Build Coastguard Worker   // Since the dummy source (inner) ZIP file should simply be stored in the
1337*86ee64e7SAndroid Build Coastguard Worker   // destination (outer) ZIP file, the destination file should be bigger than
1338*86ee64e7SAndroid Build Coastguard Worker   // the source file, but not much bigger.
1339*86ee64e7SAndroid Build Coastguard Worker   int64_t dest_file_size;
1340*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::GetFileSize(dest_file, &dest_file_size));
1341*86ee64e7SAndroid Build Coastguard Worker   EXPECT_GT(dest_file_size, src_size + 100);
1342*86ee64e7SAndroid Build Coastguard Worker   EXPECT_LT(dest_file_size, src_size + 300);
1343*86ee64e7SAndroid Build Coastguard Worker }
1344*86ee64e7SAndroid Build Coastguard Worker 
1345*86ee64e7SAndroid Build Coastguard Worker // Tests that there is no 2GB or 4GB limits. Tests that big files can be zipped
1346*86ee64e7SAndroid Build Coastguard Worker // (crbug.com/1207737) and that big ZIP files can be created
1347*86ee64e7SAndroid Build Coastguard Worker // (crbug.com/1221447). Tests that the big ZIP can be opened, that its entries
1348*86ee64e7SAndroid Build Coastguard Worker // are correctly enumerated (crbug.com/1298347), and that the big file can be
1349*86ee64e7SAndroid Build Coastguard Worker // extracted.
1350*86ee64e7SAndroid Build Coastguard Worker //
1351*86ee64e7SAndroid Build Coastguard Worker // Because this test is dealing with big files, it tends to take a lot of disk
1352*86ee64e7SAndroid Build Coastguard Worker // space and time (crbug.com/1299736). Therefore, it only gets run on a few bots
1353*86ee64e7SAndroid Build Coastguard Worker // (ChromeOS and Windows).
1354*86ee64e7SAndroid Build Coastguard Worker //
1355*86ee64e7SAndroid Build Coastguard Worker // This test is too slow with TSAN.
1356*86ee64e7SAndroid Build Coastguard Worker // OS Fuchsia does not seem to support large files.
1357*86ee64e7SAndroid Build Coastguard Worker // Some 32-bit Android waterfall and CQ try bots are running out of space when
1358*86ee64e7SAndroid Build Coastguard Worker // performing this test (android-asan, android-11-x86-rel,
1359*86ee64e7SAndroid Build Coastguard Worker // android-marshmallow-x86-rel-non-cq).
1360*86ee64e7SAndroid Build Coastguard Worker // Some Mac, Linux and Debug (dbg) bots tend to time out when performing this
1361*86ee64e7SAndroid Build Coastguard Worker // test (crbug.com/1299736, crbug.com/1300448, crbug.com/1369958).
1362*86ee64e7SAndroid Build Coastguard Worker #if defined(THREAD_SANITIZER) || BUILDFLAG(IS_FUCHSIA) ||                \
1363*86ee64e7SAndroid Build Coastguard Worker     BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
1364*86ee64e7SAndroid Build Coastguard Worker     BUILDFLAG(IS_CHROMEOS) || !defined(NDEBUG)
TEST_F(ZipTest,DISABLED_BigFile)1365*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, DISABLED_BigFile) {
1366*86ee64e7SAndroid Build Coastguard Worker #else
1367*86ee64e7SAndroid Build Coastguard Worker TEST_F(ZipTest, BigFile) {
1368*86ee64e7SAndroid Build Coastguard Worker #endif
1369*86ee64e7SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir;
1370*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1371*86ee64e7SAndroid Build Coastguard Worker 
1372*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath src_dir = temp_dir.GetPath().AppendASCII("input");
1373*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(base::CreateDirectory(src_dir));
1374*86ee64e7SAndroid Build Coastguard Worker 
1375*86ee64e7SAndroid Build Coastguard Worker   // Create a big dummy ZIP file. This is not a valid ZIP file, but for the
1376*86ee64e7SAndroid Build Coastguard Worker   // purpose of this test, it doesn't really matter.
1377*86ee64e7SAndroid Build Coastguard Worker   const int64_t src_size = 5'000'000'000;
1378*86ee64e7SAndroid Build Coastguard Worker 
1379*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath src_file = src_dir.AppendASCII("src.zip");
1380*86ee64e7SAndroid Build Coastguard Worker   LOG(INFO) << "Creating big file " << src_file;
1381*86ee64e7SAndroid Build Coastguard Worker   {
1382*86ee64e7SAndroid Build Coastguard Worker     base::File f(src_file, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
1383*86ee64e7SAndroid Build Coastguard Worker     ASSERT_TRUE(f.SetLength(src_size));
1384*86ee64e7SAndroid Build Coastguard Worker   }
1385*86ee64e7SAndroid Build Coastguard Worker 
1386*86ee64e7SAndroid Build Coastguard Worker   // Zip the dummy ZIP file.
1387*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath dest_file = temp_dir.GetPath().AppendASCII("dest.zip");
1388*86ee64e7SAndroid Build Coastguard Worker   LOG(INFO) << "Zipping big file into " << dest_file;
1389*86ee64e7SAndroid Build Coastguard Worker   zip::ProgressCallback progress_callback =
1390*86ee64e7SAndroid Build Coastguard Worker       base::BindLambdaForTesting([&](const zip::Progress& progress) {
1391*86ee64e7SAndroid Build Coastguard Worker         LOG(INFO) << "Zipping... " << std::setw(3)
1392*86ee64e7SAndroid Build Coastguard Worker                   << (100 * progress.bytes / src_size) << "%";
1393*86ee64e7SAndroid Build Coastguard Worker         return true;
1394*86ee64e7SAndroid Build Coastguard Worker       });
1395*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(zip::Zip({.src_dir = src_dir,
1396*86ee64e7SAndroid Build Coastguard Worker                         .dest_file = dest_file,
1397*86ee64e7SAndroid Build Coastguard Worker                         .progress_callback = std::move(progress_callback),
1398*86ee64e7SAndroid Build Coastguard Worker                         .progress_period = base::Seconds(1)}));
1399*86ee64e7SAndroid Build Coastguard Worker 
1400*86ee64e7SAndroid Build Coastguard Worker   // Since the dummy source (inner) ZIP file should simply be stored in the
1401*86ee64e7SAndroid Build Coastguard Worker   // destination (outer) ZIP file, the destination file should be bigger than
1402*86ee64e7SAndroid Build Coastguard Worker   // the source file, but not much bigger.
1403*86ee64e7SAndroid Build Coastguard Worker   int64_t dest_file_size;
1404*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(base::GetFileSize(dest_file, &dest_file_size));
1405*86ee64e7SAndroid Build Coastguard Worker   EXPECT_GT(dest_file_size, src_size + 100);
1406*86ee64e7SAndroid Build Coastguard Worker   EXPECT_LT(dest_file_size, src_size + 300);
1407*86ee64e7SAndroid Build Coastguard Worker 
1408*86ee64e7SAndroid Build Coastguard Worker   LOG(INFO) << "Reading big ZIP " << dest_file;
1409*86ee64e7SAndroid Build Coastguard Worker   zip::ZipReader reader;
1410*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(reader.Open(dest_file));
1411*86ee64e7SAndroid Build Coastguard Worker 
1412*86ee64e7SAndroid Build Coastguard Worker   const zip::ZipReader::Entry* const entry = reader.Next();
1413*86ee64e7SAndroid Build Coastguard Worker   ASSERT_TRUE(entry);
1414*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(FP("src.zip"), entry->path);
1415*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(src_size, entry->original_size);
1416*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(entry->is_directory);
1417*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(entry->is_encrypted);
1418*86ee64e7SAndroid Build Coastguard Worker 
1419*86ee64e7SAndroid Build Coastguard Worker   ProgressWriterDelegate writer(src_size);
1420*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.ExtractCurrentEntry(&writer,
1421*86ee64e7SAndroid Build Coastguard Worker                                          std::numeric_limits<uint64_t>::max()));
1422*86ee64e7SAndroid Build Coastguard Worker   EXPECT_EQ(src_size, writer.received_bytes());
1423*86ee64e7SAndroid Build Coastguard Worker 
1424*86ee64e7SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.Next());
1425*86ee64e7SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.ok());
1426*86ee64e7SAndroid Build Coastguard Worker }
1427*86ee64e7SAndroid Build Coastguard Worker 
1428*86ee64e7SAndroid Build Coastguard Worker }  // namespace
1429