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