Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / utility / safe_browsing / mac / hfs_unittest.cc
blob4ef93165ceceb9be078041a0d020bb30094d444d
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/utility/safe_browsing/mac/hfs.h"
7 #include "base/files/file.h"
8 #include "base/logging.h"
9 #include "base/strings/string_piece.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/utility/safe_browsing/mac/dmg_test_utils.h"
13 #include "chrome/utility/safe_browsing/mac/read_stream.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace safe_browsing {
17 namespace dmg {
18 namespace {
20 class HFSIteratorTest : public testing::Test {
21 public:
22 void GetTargetFiles(bool case_sensitive,
23 std::set<base::string16>* files,
24 std::set<base::string16>* dirs) {
25 const char* kBaseFiles[] = {
26 "first/second/third/fourth/fifth/random",
27 "first/second/third/fourth/Hello World",
28 "first/second/third/symlink-random",
29 "first/second/goat-output.txt",
30 "first/unicode_name",
31 "README.txt",
32 ".metadata_never_index",
35 const char* kBaseDirs[] = {
36 "first/second/third/fourth/fifth",
37 "first/second/third/fourth",
38 "first/second/third",
39 "first/second",
40 "first",
41 ".Trashes",
44 const base::string16 dmg_name = base::ASCIIToUTF16("SafeBrowsingDMG/");
46 for (size_t i = 0; i < arraysize(kBaseFiles); ++i)
47 files->insert(dmg_name + base::ASCIIToUTF16(kBaseFiles[i]));
49 files->insert(dmg_name + base::ASCIIToUTF16("first/second/") +
50 base::UTF8ToUTF16("Te\xCC\x86st\xCC\x88 \xF0\x9F\x90\x90 "));
52 dirs->insert(dmg_name.substr(0, dmg_name.size() - 1));
53 for (size_t i = 0; i < arraysize(kBaseDirs); ++i)
54 dirs->insert(dmg_name + base::ASCIIToUTF16(kBaseDirs[i]));
56 if (case_sensitive) {
57 files->insert(base::ASCIIToUTF16(
58 "SafeBrowsingDMG/first/second/third/fourth/hEllo wOrld"));
62 void TestTargetFiles(safe_browsing::dmg::HFSIterator* hfs_reader,
63 bool case_sensitive) {
64 std::set<base::string16> files, dirs;
65 GetTargetFiles(case_sensitive, &files, &dirs);
67 ASSERT_TRUE(hfs_reader->Open());
68 while (hfs_reader->Next()) {
69 base::string16 path = hfs_reader->GetPath();
70 // Skip over .fseventsd files.
71 if (path.find(base::ASCIIToUTF16("SafeBrowsingDMG/.fseventsd")) !=
72 base::string16::npos) {
73 continue;
75 if (hfs_reader->IsDirectory())
76 EXPECT_TRUE(dirs.erase(path)) << path;
77 else
78 EXPECT_TRUE(files.erase(path)) << path;
81 EXPECT_EQ(0u, files.size());
82 for (const auto& file : files) {
83 ADD_FAILURE() << "Unexpected missing file " << file;
88 TEST_F(HFSIteratorTest, HFSPlus) {
89 base::File file;
90 ASSERT_NO_FATAL_FAILURE(test::GetTestFile("hfs_plus.img", &file));
92 FileReadStream stream(file.GetPlatformFile());
93 HFSIterator hfs_reader(&stream);
94 TestTargetFiles(&hfs_reader, false);
97 TEST_F(HFSIteratorTest, HFSXCaseSensitive) {
98 base::File file;
99 ASSERT_NO_FATAL_FAILURE(test::GetTestFile("hfsx_case_sensitive.img", &file));
101 FileReadStream stream(file.GetPlatformFile());
102 HFSIterator hfs_reader(&stream);
103 TestTargetFiles(&hfs_reader, true);
106 class HFSFileReadTest : public testing::TestWithParam<const char*> {
107 protected:
108 void SetUp() override {
109 ASSERT_NO_FATAL_FAILURE(test::GetTestFile(GetParam(), &hfs_file_));
111 hfs_stream_.reset(new FileReadStream(hfs_file_.GetPlatformFile()));
112 hfs_reader_.reset(new HFSIterator(hfs_stream_.get()));
113 ASSERT_TRUE(hfs_reader_->Open());
116 bool GoToFile(const char* name) {
117 while (hfs_reader_->Next()) {
118 if (EndsWith(hfs_reader_->GetPath(), base::ASCIIToUTF16(name),
119 base::CompareCase::SENSITIVE)) {
120 return true;
123 return false;
126 HFSIterator* hfs_reader() { return hfs_reader_.get(); }
128 private:
129 base::File hfs_file_;
130 scoped_ptr<FileReadStream> hfs_stream_;
131 scoped_ptr<HFSIterator> hfs_reader_;
134 TEST_P(HFSFileReadTest, ReadReadme) {
135 ASSERT_TRUE(GoToFile("README.txt"));
137 scoped_ptr<ReadStream> stream = hfs_reader()->GetReadStream();
138 ASSERT_TRUE(stream.get());
140 EXPECT_FALSE(hfs_reader()->IsSymbolicLink());
141 EXPECT_FALSE(hfs_reader()->IsHardLink());
142 EXPECT_FALSE(hfs_reader()->IsDecmpfsCompressed());
144 std::vector<uint8_t> buffer(4, 0);
146 // Read the first four bytes.
147 EXPECT_TRUE(stream->ReadExact(&buffer[0], buffer.size()));
148 const uint8_t expected[] = { 'T', 'h', 'i', 's' };
149 EXPECT_EQ(0, memcmp(expected, &buffer[0], sizeof(expected)));
150 buffer.clear();
152 // Rewind back to the start.
153 EXPECT_EQ(0, stream->Seek(0, SEEK_SET));
155 // Read the entire file now.
156 EXPECT_TRUE(test::ReadEntireStream(stream.get(), &buffer));
157 EXPECT_EQ("This is a test HFS+ filesystem generated by "
158 "chrome/test/data/safe_browsing/dmg/make_hfs.sh.\n",
159 base::StringPiece(reinterpret_cast<const char*>(&buffer[0]),
160 buffer.size()));
161 EXPECT_EQ(92u, buffer.size());
164 TEST_P(HFSFileReadTest, ReadRandom) {
165 ASSERT_TRUE(GoToFile("fifth/random"));
167 scoped_ptr<ReadStream> stream = hfs_reader()->GetReadStream();
168 ASSERT_TRUE(stream.get());
170 EXPECT_FALSE(hfs_reader()->IsSymbolicLink());
171 EXPECT_FALSE(hfs_reader()->IsHardLink());
172 EXPECT_FALSE(hfs_reader()->IsDecmpfsCompressed());
174 std::vector<uint8_t> buffer;
175 EXPECT_TRUE(test::ReadEntireStream(stream.get(), &buffer));
176 EXPECT_EQ(768u, buffer.size());
179 TEST_P(HFSFileReadTest, Symlink) {
180 ASSERT_TRUE(GoToFile("symlink-random"));
182 scoped_ptr<ReadStream> stream = hfs_reader()->GetReadStream();
183 ASSERT_TRUE(stream.get());
185 EXPECT_TRUE(hfs_reader()->IsSymbolicLink());
186 EXPECT_FALSE(hfs_reader()->IsHardLink());
187 EXPECT_FALSE(hfs_reader()->IsDecmpfsCompressed());
189 std::vector<uint8_t> buffer;
190 EXPECT_TRUE(test::ReadEntireStream(stream.get(), &buffer));
192 EXPECT_EQ("fourth/fifth/random",
193 base::StringPiece(reinterpret_cast<const char*>(&buffer[0]),
194 buffer.size()));
197 TEST_P(HFSFileReadTest, HardLink) {
198 ASSERT_TRUE(GoToFile("unicode_name"));
200 EXPECT_FALSE(hfs_reader()->IsSymbolicLink());
201 EXPECT_TRUE(hfs_reader()->IsHardLink());
202 EXPECT_FALSE(hfs_reader()->IsDecmpfsCompressed());
205 TEST_P(HFSFileReadTest, DecmpfsFile) {
206 ASSERT_TRUE(GoToFile("first/second/goat-output.txt"));
208 scoped_ptr<ReadStream> stream = hfs_reader()->GetReadStream();
209 ASSERT_TRUE(stream.get());
211 EXPECT_FALSE(hfs_reader()->IsSymbolicLink());
212 EXPECT_FALSE(hfs_reader()->IsHardLink());
213 EXPECT_TRUE(hfs_reader()->IsDecmpfsCompressed());
215 std::vector<uint8_t> buffer;
216 EXPECT_TRUE(test::ReadEntireStream(stream.get(), &buffer));
217 EXPECT_EQ(0u, buffer.size());
220 INSTANTIATE_TEST_CASE_P(HFSIteratorTest,
221 HFSFileReadTest,
222 testing::Values(
223 "hfs_plus.img",
224 "hfsx_case_sensitive.img"));
226 } // namespace
227 } // namespace dmg
228 } // namespace safe_browsing