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