1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/files/file_enumerator.h"
6 
7 #include <utility>
8 #include <vector>
9 
10 #include "base/containers/circular_deque.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 using testing::ElementsAre;
18 using testing::IsEmpty;
19 using testing::UnorderedElementsAre;
20 
21 namespace base {
22 namespace {
23 
24 const FilePath::StringType kEmptyPattern;
25 
26 const std::vector<FileEnumerator::FolderSearchPolicy> kFolderSearchPolicies{
27     FileEnumerator::FolderSearchPolicy::MATCH_ONLY,
28     FileEnumerator::FolderSearchPolicy::ALL};
29 
RunEnumerator(const FilePath & root_path,bool recursive,int file_type,const FilePath::StringType & pattern,FileEnumerator::FolderSearchPolicy folder_search_policy)30 circular_deque<FilePath> RunEnumerator(
31     const FilePath& root_path,
32     bool recursive,
33     int file_type,
34     const FilePath::StringType& pattern,
35     FileEnumerator::FolderSearchPolicy folder_search_policy) {
36   circular_deque<FilePath> rv;
37   FileEnumerator enumerator(root_path, recursive, file_type, pattern,
38                             folder_search_policy);
39   for (auto file = enumerator.Next(); !file.empty(); file = enumerator.Next())
40     rv.emplace_back(std::move(file));
41   return rv;
42 }
43 
CreateDummyFile(const FilePath & path)44 bool CreateDummyFile(const FilePath& path) {
45   return WriteFile(path, "42", sizeof("42")) == sizeof("42");
46 }
47 
48 }  // namespace
49 
TEST(FileEnumerator,NotExistingPath)50 TEST(FileEnumerator, NotExistingPath) {
51   const FilePath path = FilePath::FromUTF8Unsafe("some_not_existing_path");
52   ASSERT_FALSE(PathExists(path));
53 
54   for (auto policy : kFolderSearchPolicies) {
55     const auto files = RunEnumerator(
56         path, true, FileEnumerator::FILES & FileEnumerator::DIRECTORIES,
57         FILE_PATH_LITERAL(""), policy);
58     EXPECT_THAT(files, IsEmpty());
59   }
60 }
61 
TEST(FileEnumerator,EmptyFolder)62 TEST(FileEnumerator, EmptyFolder) {
63   ScopedTempDir temp_dir;
64   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
65 
66   for (auto policy : kFolderSearchPolicies) {
67     const auto files =
68         RunEnumerator(temp_dir.GetPath(), true,
69                       FileEnumerator::FILES & FileEnumerator::DIRECTORIES,
70                       kEmptyPattern, policy);
71     EXPECT_THAT(files, IsEmpty());
72   }
73 }
74 
TEST(FileEnumerator,SingleFileInFolderForFileSearch)75 TEST(FileEnumerator, SingleFileInFolderForFileSearch) {
76   ScopedTempDir temp_dir;
77   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
78 
79   const FilePath& path = temp_dir.GetPath();
80   const FilePath file = path.AppendASCII("test.txt");
81   ASSERT_TRUE(CreateDummyFile(file));
82 
83   for (auto policy : kFolderSearchPolicies) {
84     const auto files = RunEnumerator(
85         temp_dir.GetPath(), true, FileEnumerator::FILES, kEmptyPattern, policy);
86     EXPECT_THAT(files, ElementsAre(file));
87   }
88 }
89 
TEST(FileEnumerator,SingleFileInFolderForDirSearch)90 TEST(FileEnumerator, SingleFileInFolderForDirSearch) {
91   ScopedTempDir temp_dir;
92   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
93 
94   const FilePath& path = temp_dir.GetPath();
95   ASSERT_TRUE(CreateDummyFile(path.AppendASCII("test.txt")));
96 
97   for (auto policy : kFolderSearchPolicies) {
98     const auto files = RunEnumerator(path, true, FileEnumerator::DIRECTORIES,
99                                      kEmptyPattern, policy);
100     EXPECT_THAT(files, IsEmpty());
101   }
102 }
103 
TEST(FileEnumerator,SingleFileInFolderWithFiltering)104 TEST(FileEnumerator, SingleFileInFolderWithFiltering) {
105   ScopedTempDir temp_dir;
106   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
107 
108   const FilePath& path = temp_dir.GetPath();
109   const FilePath file = path.AppendASCII("test.txt");
110   ASSERT_TRUE(CreateDummyFile(file));
111 
112   for (auto policy : kFolderSearchPolicies) {
113     auto files = RunEnumerator(path, true, FileEnumerator::FILES,
114                                FILE_PATH_LITERAL("*.txt"), policy);
115     EXPECT_THAT(files, ElementsAre(file));
116 
117     files = RunEnumerator(path, true, FileEnumerator::FILES,
118                           FILE_PATH_LITERAL("*.pdf"), policy);
119     EXPECT_THAT(files, IsEmpty());
120   }
121 }
122 
TEST(FileEnumerator,TwoFilesInFolder)123 TEST(FileEnumerator, TwoFilesInFolder) {
124   ScopedTempDir temp_dir;
125   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
126 
127   const FilePath& path = temp_dir.GetPath();
128   const FilePath foo_txt = path.AppendASCII("foo.txt");
129   const FilePath bar_txt = path.AppendASCII("bar.txt");
130   ASSERT_TRUE(CreateDummyFile(foo_txt));
131   ASSERT_TRUE(CreateDummyFile(bar_txt));
132 
133   for (auto policy : kFolderSearchPolicies) {
134     auto files = RunEnumerator(path, true, FileEnumerator::FILES,
135                                FILE_PATH_LITERAL("*.txt"), policy);
136     EXPECT_THAT(files, UnorderedElementsAre(foo_txt, bar_txt));
137 
138     files = RunEnumerator(path, true, FileEnumerator::FILES,
139                           FILE_PATH_LITERAL("foo*"), policy);
140     EXPECT_THAT(files, ElementsAre(foo_txt));
141 
142     files = RunEnumerator(path, true, FileEnumerator::FILES,
143                           FILE_PATH_LITERAL("*.pdf"), policy);
144     EXPECT_THAT(files, IsEmpty());
145 
146     files =
147         RunEnumerator(path, true, FileEnumerator::FILES, kEmptyPattern, policy);
148     EXPECT_THAT(files, UnorderedElementsAre(foo_txt, bar_txt));
149   }
150 }
151 
TEST(FileEnumerator,SingleFolderInFolderForFileSearch)152 TEST(FileEnumerator, SingleFolderInFolderForFileSearch) {
153   ScopedTempDir temp_dir;
154   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
155 
156   const FilePath& path = temp_dir.GetPath();
157 
158   ScopedTempDir temp_subdir;
159   ASSERT_TRUE(temp_subdir.CreateUniqueTempDirUnderPath(path));
160 
161   for (auto policy : kFolderSearchPolicies) {
162     const auto files =
163         RunEnumerator(path, true, FileEnumerator::FILES, kEmptyPattern, policy);
164     EXPECT_THAT(files, IsEmpty());
165   }
166 }
167 
TEST(FileEnumerator,SingleFolderInFolderForDirSearch)168 TEST(FileEnumerator, SingleFolderInFolderForDirSearch) {
169   ScopedTempDir temp_dir;
170   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
171 
172   const FilePath& path = temp_dir.GetPath();
173 
174   ScopedTempDir temp_subdir;
175   ASSERT_TRUE(temp_subdir.CreateUniqueTempDirUnderPath(path));
176 
177   for (auto policy : kFolderSearchPolicies) {
178     const auto files = RunEnumerator(path, true, FileEnumerator::DIRECTORIES,
179                                      kEmptyPattern, policy);
180     EXPECT_THAT(files, ElementsAre(temp_subdir.GetPath()));
181   }
182 }
183 
TEST(FileEnumerator,TwoFoldersInFolder)184 TEST(FileEnumerator, TwoFoldersInFolder) {
185   ScopedTempDir temp_dir;
186   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
187 
188   const FilePath& path = temp_dir.GetPath();
189 
190   const FilePath subdir_foo = path.AppendASCII("foo");
191   const FilePath subdir_bar = path.AppendASCII("bar");
192   ASSERT_TRUE(CreateDirectory(subdir_foo));
193   ASSERT_TRUE(CreateDirectory(subdir_bar));
194 
195   for (auto policy : kFolderSearchPolicies) {
196     auto files = RunEnumerator(path, true, FileEnumerator::DIRECTORIES,
197                                kEmptyPattern, policy);
198     EXPECT_THAT(files, UnorderedElementsAre(subdir_foo, subdir_bar));
199 
200     files = RunEnumerator(path, true, FileEnumerator::DIRECTORIES,
201                           FILE_PATH_LITERAL("foo"), policy);
202     EXPECT_THAT(files, ElementsAre(subdir_foo));
203   }
204 }
205 
TEST(FileEnumerator,FolderAndFileInFolder)206 TEST(FileEnumerator, FolderAndFileInFolder) {
207   ScopedTempDir temp_dir;
208   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
209 
210   const FilePath& path = temp_dir.GetPath();
211 
212   ScopedTempDir temp_subdir;
213   ASSERT_TRUE(temp_subdir.CreateUniqueTempDirUnderPath(path));
214   const FilePath file = path.AppendASCII("test.txt");
215   ASSERT_TRUE(CreateDummyFile(file));
216 
217   for (auto policy : kFolderSearchPolicies) {
218     auto files =
219         RunEnumerator(path, true, FileEnumerator::FILES, kEmptyPattern, policy);
220     EXPECT_THAT(files, ElementsAre(file));
221 
222     files = RunEnumerator(path, true, FileEnumerator::DIRECTORIES,
223                           kEmptyPattern, policy);
224     EXPECT_THAT(files, ElementsAre(temp_subdir.GetPath()));
225 
226     files = RunEnumerator(path, true,
227                           FileEnumerator::FILES | FileEnumerator::DIRECTORIES,
228                           kEmptyPattern, policy);
229     EXPECT_THAT(files, UnorderedElementsAre(file, temp_subdir.GetPath()));
230   }
231 }
232 
TEST(FileEnumerator,FilesInParentFolderAlwaysFirst)233 TEST(FileEnumerator, FilesInParentFolderAlwaysFirst) {
234   ScopedTempDir temp_dir;
235   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
236 
237   const FilePath& path = temp_dir.GetPath();
238 
239   ScopedTempDir temp_subdir;
240   ASSERT_TRUE(temp_subdir.CreateUniqueTempDirUnderPath(path));
241   const FilePath foo_txt = path.AppendASCII("foo.txt");
242   const FilePath bar_txt = temp_subdir.GetPath().AppendASCII("bar.txt");
243   ASSERT_TRUE(CreateDummyFile(foo_txt));
244   ASSERT_TRUE(CreateDummyFile(bar_txt));
245 
246   for (auto policy : kFolderSearchPolicies) {
247     const auto files =
248         RunEnumerator(path, true, FileEnumerator::FILES, kEmptyPattern, policy);
249     EXPECT_THAT(files, ElementsAre(foo_txt, bar_txt));
250   }
251 }
252 
TEST(FileEnumerator,FileInSubfolder)253 TEST(FileEnumerator, FileInSubfolder) {
254   ScopedTempDir temp_dir;
255   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
256 
257   const FilePath subdir = temp_dir.GetPath().AppendASCII("subdir");
258   ASSERT_TRUE(CreateDirectory(subdir));
259 
260   const FilePath file = subdir.AppendASCII("test.txt");
261   ASSERT_TRUE(CreateDummyFile(file));
262 
263   for (auto policy : kFolderSearchPolicies) {
264     auto files = RunEnumerator(temp_dir.GetPath(), true, FileEnumerator::FILES,
265                                kEmptyPattern, policy);
266     EXPECT_THAT(files, ElementsAre(file));
267 
268     files = RunEnumerator(temp_dir.GetPath(), false, FileEnumerator::FILES,
269                           kEmptyPattern, policy);
270     EXPECT_THAT(files, IsEmpty());
271   }
272 }
273 
TEST(FileEnumerator,FilesInSubfoldersWithFiltering)274 TEST(FileEnumerator, FilesInSubfoldersWithFiltering) {
275   ScopedTempDir temp_dir;
276   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
277 
278   const FilePath test_txt = temp_dir.GetPath().AppendASCII("test.txt");
279   const FilePath subdir_foo = temp_dir.GetPath().AppendASCII("foo_subdir");
280   const FilePath subdir_bar = temp_dir.GetPath().AppendASCII("bar_subdir");
281   const FilePath foo_test = subdir_foo.AppendASCII("test.txt");
282   const FilePath foo_foo = subdir_foo.AppendASCII("foo.txt");
283   const FilePath foo_bar = subdir_foo.AppendASCII("bar.txt");
284   const FilePath bar_test = subdir_bar.AppendASCII("test.txt");
285   const FilePath bar_foo = subdir_bar.AppendASCII("foo.txt");
286   const FilePath bar_bar = subdir_bar.AppendASCII("bar.txt");
287   ASSERT_TRUE(CreateDummyFile(test_txt));
288   ASSERT_TRUE(CreateDirectory(subdir_foo));
289   ASSERT_TRUE(CreateDirectory(subdir_bar));
290   ASSERT_TRUE(CreateDummyFile(foo_test));
291   ASSERT_TRUE(CreateDummyFile(foo_foo));
292   ASSERT_TRUE(CreateDummyFile(foo_bar));
293   ASSERT_TRUE(CreateDummyFile(bar_test));
294   ASSERT_TRUE(CreateDummyFile(bar_foo));
295   ASSERT_TRUE(CreateDummyFile(bar_bar));
296 
297   auto files =
298       RunEnumerator(temp_dir.GetPath(), true,
299                     FileEnumerator::FILES | FileEnumerator::DIRECTORIES,
300                     FILE_PATH_LITERAL("foo*"),
301                     FileEnumerator::FolderSearchPolicy::MATCH_ONLY);
302   EXPECT_THAT(files,
303               UnorderedElementsAre(subdir_foo, foo_test, foo_foo, foo_bar));
304 
305   files = RunEnumerator(temp_dir.GetPath(), true,
306                         FileEnumerator::FILES | FileEnumerator::DIRECTORIES,
307                         FILE_PATH_LITERAL("foo*"),
308                         FileEnumerator::FolderSearchPolicy::ALL);
309   EXPECT_THAT(files, UnorderedElementsAre(subdir_foo, foo_foo, bar_foo));
310 }
311 
312 }  // namespace base
313