1 // Copyright 2017 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "util/file/directory_reader.h"
16 
17 #include <set>
18 
19 #include "base/files/file_path.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "gtest/gtest.h"
23 #include "test/filesystem.h"
24 #include "test/scoped_temp_dir.h"
25 #include "util/file/file_io.h"
26 #include "util/file/filesystem.h"
27 
28 namespace crashpad {
29 namespace test {
30 namespace {
31 
TEST(DirectoryReader,BadPaths)32 TEST(DirectoryReader, BadPaths) {
33   DirectoryReader reader;
34   EXPECT_FALSE(reader.Open(base::FilePath()));
35 
36   ScopedTempDir temp_dir;
37   base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
38   ASSERT_TRUE(CreateFile(file));
39   EXPECT_FALSE(reader.Open(file));
40 
41   EXPECT_FALSE(
42       reader.Open(temp_dir.path().Append(FILE_PATH_LITERAL("doesntexist"))));
43 }
44 
45 #if !defined(OS_FUCHSIA)
46 
TEST(DirectoryReader,BadPaths_SymbolicLinks)47 TEST(DirectoryReader, BadPaths_SymbolicLinks) {
48   if (!CanCreateSymbolicLinks()) {
49     GTEST_SKIP();
50   }
51 
52   ScopedTempDir temp_dir;
53   base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
54   ASSERT_TRUE(CreateFile(file));
55 
56   base::FilePath link(temp_dir.path().Append(FILE_PATH_LITERAL("link")));
57   ASSERT_TRUE(CreateSymbolicLink(file, link));
58 
59   DirectoryReader reader;
60   EXPECT_FALSE(reader.Open(link));
61 
62   ASSERT_TRUE(LoggingRemoveFile(file));
63   EXPECT_FALSE(reader.Open(link));
64 }
65 
66 #endif  // !OS_FUCHSIA
67 
TEST(DirectoryReader,EmptyDirectory)68 TEST(DirectoryReader, EmptyDirectory) {
69   ScopedTempDir temp_dir;
70   DirectoryReader reader;
71 
72   ASSERT_TRUE(reader.Open(temp_dir.path()));
73   base::FilePath filename;
74   EXPECT_EQ(reader.NextFile(&filename), DirectoryReader::Result::kNoMoreFiles);
75 }
76 
ExpectFiles(const std::set<base::FilePath> & files,const std::set<base::FilePath> & expected)77 void ExpectFiles(const std::set<base::FilePath>& files,
78                  const std::set<base::FilePath>& expected) {
79   EXPECT_EQ(files.size(), expected.size());
80 
81   for (const auto& filename : expected) {
82     SCOPED_TRACE(
83         base::StringPrintf("Filename: %" PRFilePath, filename.value().c_str()));
84     EXPECT_NE(files.find(filename), files.end());
85   }
86 }
87 
TestFilesAndDirectories(bool symbolic_links)88 void TestFilesAndDirectories(bool symbolic_links) {
89   ScopedTempDir temp_dir;
90   std::set<base::FilePath> expected_files;
91 
92   base::FilePath file(FILE_PATH_LITERAL("file"));
93   ASSERT_TRUE(CreateFile(temp_dir.path().Append(file)));
94   EXPECT_TRUE(expected_files.insert(file).second);
95 
96   base::FilePath directory(FILE_PATH_LITERAL("directory"));
97   ASSERT_TRUE(LoggingCreateDirectory(temp_dir.path().Append(directory),
98                                      FilePermissions::kWorldReadable,
99                                      false));
100   EXPECT_TRUE(expected_files.insert(directory).second);
101 
102   base::FilePath nested_file(FILE_PATH_LITERAL("nested_file"));
103   ASSERT_TRUE(
104       CreateFile(temp_dir.path().Append(directory).Append(nested_file)));
105 
106 #if !defined(OS_FUCHSIA)
107 
108   if (symbolic_links) {
109     base::FilePath link(FILE_PATH_LITERAL("link"));
110     ASSERT_TRUE(CreateSymbolicLink(temp_dir.path().Append(file),
111                                    temp_dir.path().Append(link)));
112     EXPECT_TRUE(expected_files.insert(link).second);
113 
114     base::FilePath dangling(FILE_PATH_LITERAL("dangling"));
115     ASSERT_TRUE(
116         CreateSymbolicLink(base::FilePath(FILE_PATH_LITERAL("not_a_file")),
117                            temp_dir.path().Append(dangling)));
118     EXPECT_TRUE(expected_files.insert(dangling).second);
119   }
120 
121 #endif  // !OS_FUCHSIA
122 
123   std::set<base::FilePath> files;
124   DirectoryReader reader;
125   ASSERT_TRUE(reader.Open(temp_dir.path()));
126   DirectoryReader::Result result;
127   base::FilePath filename;
128   while ((result = reader.NextFile(&filename)) ==
129          DirectoryReader::Result::kSuccess) {
130     EXPECT_TRUE(files.insert(filename).second);
131   }
132   EXPECT_EQ(result, DirectoryReader::Result::kNoMoreFiles);
133   EXPECT_EQ(reader.NextFile(&filename), DirectoryReader::Result::kNoMoreFiles);
134   ExpectFiles(files, expected_files);
135 }
136 
TEST(DirectoryReader,FilesAndDirectories)137 TEST(DirectoryReader, FilesAndDirectories) {
138   TestFilesAndDirectories(false);
139 }
140 
141 #if !defined(OS_FUCHSIA)
142 
TEST(DirectoryReader,FilesAndDirectories_SymbolicLinks)143 TEST(DirectoryReader, FilesAndDirectories_SymbolicLinks) {
144   if (!CanCreateSymbolicLinks()) {
145     GTEST_SKIP();
146   }
147 
148   TestFilesAndDirectories(true);
149 }
150 
151 #endif  // !OS_FUCHSIA
152 
153 }  // namespace
154 }  // namespace test
155 }  // namespace crashpad
156