1// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11// ignore-windows TempDir may cause IoError on windows: #10462
12
13#![cfg_attr(test, deny(warnings))]
14
15extern crate glob;
16extern crate tempdir;
17
18use glob::glob;
19use std::env;
20use std::fs;
21use std::path::PathBuf;
22use tempdir::TempDir;
23
24#[test]
25fn main() {
26 fn mk_file(path: &str, directory: bool) {
27 if directory {
28 fs::create_dir(path).unwrap();
29 } else {
30 fs::File::create(path).unwrap();
31 }
32 }
33
34 fn glob_vec(pattern: &str) -> Vec<PathBuf> {
35 glob(pattern).unwrap().map(|r| r.unwrap()).collect()
36 }
37
38 let root = TempDir::new("glob-tests");
39 let root = root.ok().expect("Should have created a temp directory");
40 assert!(env::set_current_dir(root.path()).is_ok());
41
42 mk_file("aaa", true);
43 mk_file("aaa/apple", true);
44 mk_file("aaa/orange", true);
45 mk_file("aaa/tomato", true);
46 mk_file("aaa/tomato/tomato.txt", false);
47 mk_file("aaa/tomato/tomoto.txt", false);
48 mk_file("bbb", true);
49 mk_file("bbb/specials", true);
50 mk_file("bbb/specials/!", false);
51
52 // windows does not allow `*` or `?` characters to exist in filenames
53 if env::consts::FAMILY != "windows" {
54 mk_file("bbb/specials/*", false);
55 mk_file("bbb/specials/?", false);
56 }
57
58 mk_file("bbb/specials/[", false);
59 mk_file("bbb/specials/]", false);
60 mk_file("ccc", true);
61 mk_file("xyz", true);
62 mk_file("xyz/x", false);
63 mk_file("xyz/y", false);
64 mk_file("xyz/z", false);
65
66 mk_file("r", true);
67 mk_file("r/current_dir.md", false);
68 mk_file("r/one", true);
69 mk_file("r/one/a.md", false);
70 mk_file("r/one/another", true);
71 mk_file("r/one/another/a.md", false);
72 mk_file("r/one/another/deep", true);
73 mk_file("r/one/another/deep/spelunking.md", false);
74 mk_file("r/another", true);
75 mk_file("r/another/a.md", false);
76 mk_file("r/two", true);
77 mk_file("r/two/b.md", false);
78 mk_file("r/three", true);
79 mk_file("r/three/c.md", false);
80
81 // all recursive entities
82 assert_eq!(
83 glob_vec("r/**"),
84 vec!(
85 PathBuf::from("r/another"),
86 PathBuf::from("r/one"),
87 PathBuf::from("r/one/another"),
88 PathBuf::from("r/one/another/deep"),
89 PathBuf::from("r/three"),
90 PathBuf::from("r/two")
91 )
92 );
93
94 // collapse consecutive recursive patterns
95 assert_eq!(
96 glob_vec("r/**/**"),
97 vec!(
98 PathBuf::from("r/another"),
99 PathBuf::from("r/one"),
100 PathBuf::from("r/one/another"),
101 PathBuf::from("r/one/another/deep"),
102 PathBuf::from("r/three"),
103 PathBuf::from("r/two")
104 )
105 );
106
107 assert_eq!(
108 glob_vec("r/**/*"),
109 vec!(
110 PathBuf::from("r/another"),
111 PathBuf::from("r/another/a.md"),
112 PathBuf::from("r/current_dir.md"),
113 PathBuf::from("r/one"),
114 PathBuf::from("r/one/a.md"),
115 PathBuf::from("r/one/another"),
116 PathBuf::from("r/one/another/a.md"),
117 PathBuf::from("r/one/another/deep"),
118 PathBuf::from("r/one/another/deep/spelunking.md"),
119 PathBuf::from("r/three"),
120 PathBuf::from("r/three/c.md"),
121 PathBuf::from("r/two"),
122 PathBuf::from("r/two/b.md")
123 )
124 );
125
126 // followed by a wildcard
127 assert_eq!(
128 glob_vec("r/**/*.md"),
129 vec!(
130 PathBuf::from("r/another/a.md"),
131 PathBuf::from("r/current_dir.md"),
132 PathBuf::from("r/one/a.md"),
133 PathBuf::from("r/one/another/a.md"),
134 PathBuf::from("r/one/another/deep/spelunking.md"),
135 PathBuf::from("r/three/c.md"),
136 PathBuf::from("r/two/b.md")
137 )
138 );
139
140 // followed by a precise pattern
141 assert_eq!(
142 glob_vec("r/one/**/a.md"),
143 vec!(
144 PathBuf::from("r/one/a.md"),
145 PathBuf::from("r/one/another/a.md")
146 )
147 );
148
149 // followed by another recursive pattern
150 // collapses consecutive recursives into one
151 assert_eq!(
152 glob_vec("r/one/**/**/a.md"),
153 vec!(
154 PathBuf::from("r/one/a.md"),
155 PathBuf::from("r/one/another/a.md")
156 )
157 );
158
159 // followed by two precise patterns
160 assert_eq!(
161 glob_vec("r/**/another/a.md"),
162 vec!(
163 PathBuf::from("r/another/a.md"),
164 PathBuf::from("r/one/another/a.md")
165 )
166 );
167
168 assert_eq!(glob_vec(""), Vec::<PathBuf>::new());
169 assert_eq!(glob_vec("."), vec!(PathBuf::from(".")));
170 assert_eq!(glob_vec(".."), vec!(PathBuf::from("..")));
171
172 assert_eq!(glob_vec("aaa"), vec!(PathBuf::from("aaa")));
173 assert_eq!(glob_vec("aaa/"), vec!(PathBuf::from("aaa")));
174 assert_eq!(glob_vec("a"), Vec::<PathBuf>::new());
175 assert_eq!(glob_vec("aa"), Vec::<PathBuf>::new());
176 assert_eq!(glob_vec("aaaa"), Vec::<PathBuf>::new());
177
178 assert_eq!(glob_vec("aaa/apple"), vec!(PathBuf::from("aaa/apple")));
179 assert_eq!(glob_vec("aaa/apple/nope"), Vec::<PathBuf>::new());
180
181 // windows should support both / and \ as directory separators
182 if env::consts::FAMILY == "windows" {
183 assert_eq!(glob_vec("aaa\\apple"), vec!(PathBuf::from("aaa/apple")));
184 }
185
186 assert_eq!(
187 glob_vec("???/"),
188 vec!(
189 PathBuf::from("aaa"),
190 PathBuf::from("bbb"),
191 PathBuf::from("ccc"),
192 PathBuf::from("xyz")
193 )
194 );
195
196 assert_eq!(
197 glob_vec("aaa/tomato/tom?to.txt"),
198 vec!(
199 PathBuf::from("aaa/tomato/tomato.txt"),
200 PathBuf::from("aaa/tomato/tomoto.txt")
201 )
202 );
203
204 assert_eq!(
205 glob_vec("xyz/?"),
206 vec!(
207 PathBuf::from("xyz/x"),
208 PathBuf::from("xyz/y"),
209 PathBuf::from("xyz/z")
210 )
211 );
212
213 assert_eq!(glob_vec("a*"), vec!(PathBuf::from("aaa")));
214 assert_eq!(glob_vec("*a*"), vec!(PathBuf::from("aaa")));
215 assert_eq!(glob_vec("a*a"), vec!(PathBuf::from("aaa")));
216 assert_eq!(glob_vec("aaa*"), vec!(PathBuf::from("aaa")));
217 assert_eq!(glob_vec("*aaa"), vec!(PathBuf::from("aaa")));
218 assert_eq!(glob_vec("*aaa*"), vec!(PathBuf::from("aaa")));
219 assert_eq!(glob_vec("*a*a*a*"), vec!(PathBuf::from("aaa")));
220 assert_eq!(glob_vec("aaa*/"), vec!(PathBuf::from("aaa")));
221
222 assert_eq!(
223 glob_vec("aaa/*"),
224 vec!(
225 PathBuf::from("aaa/apple"),
226 PathBuf::from("aaa/orange"),
227 PathBuf::from("aaa/tomato")
228 )
229 );
230
231 assert_eq!(
232 glob_vec("aaa/*a*"),
233 vec!(
234 PathBuf::from("aaa/apple"),
235 PathBuf::from("aaa/orange"),
236 PathBuf::from("aaa/tomato")
237 )
238 );
239
240 assert_eq!(
241 glob_vec("*/*/*.txt"),
242 vec!(
243 PathBuf::from("aaa/tomato/tomato.txt"),
244 PathBuf::from("aaa/tomato/tomoto.txt")
245 )
246 );
247
248 assert_eq!(
249 glob_vec("*/*/t[aob]m?to[.]t[!y]t"),
250 vec!(
251 PathBuf::from("aaa/tomato/tomato.txt"),
252 PathBuf::from("aaa/tomato/tomoto.txt")
253 )
254 );
255
256 assert_eq!(glob_vec("./aaa"), vec!(PathBuf::from("aaa")));
257 assert_eq!(glob_vec("./*"), glob_vec("*"));
258 assert_eq!(glob_vec("*/..").pop().unwrap(), PathBuf::from("xyz/.."));
259 assert_eq!(glob_vec("aaa/../bbb"), vec!(PathBuf::from("aaa/../bbb")));
260 assert_eq!(glob_vec("nonexistent/../bbb"), Vec::<PathBuf>::new());
261 assert_eq!(glob_vec("aaa/tomato/tomato.txt/.."), Vec::<PathBuf>::new());
262
263 assert_eq!(glob_vec("aaa/tomato/tomato.txt/"), Vec::<PathBuf>::new());
264
265 assert_eq!(glob_vec("aa[a]"), vec!(PathBuf::from("aaa")));
266 assert_eq!(glob_vec("aa[abc]"), vec!(PathBuf::from("aaa")));
267 assert_eq!(glob_vec("a[bca]a"), vec!(PathBuf::from("aaa")));
268 assert_eq!(glob_vec("aa[b]"), Vec::<PathBuf>::new());
269 assert_eq!(glob_vec("aa[xyz]"), Vec::<PathBuf>::new());
270 assert_eq!(glob_vec("aa[]]"), Vec::<PathBuf>::new());
271
272 assert_eq!(glob_vec("aa[!b]"), vec!(PathBuf::from("aaa")));
273 assert_eq!(glob_vec("aa[!bcd]"), vec!(PathBuf::from("aaa")));
274 assert_eq!(glob_vec("a[!bcd]a"), vec!(PathBuf::from("aaa")));
275 assert_eq!(glob_vec("aa[!a]"), Vec::<PathBuf>::new());
276 assert_eq!(glob_vec("aa[!abc]"), Vec::<PathBuf>::new());
277
278 assert_eq!(
279 glob_vec("bbb/specials/[[]"),
280 vec!(PathBuf::from("bbb/specials/["))
281 );
282 assert_eq!(
283 glob_vec("bbb/specials/!"),
284 vec!(PathBuf::from("bbb/specials/!"))
285 );
286 assert_eq!(
287 glob_vec("bbb/specials/[]]"),
288 vec!(PathBuf::from("bbb/specials/]"))
289 );
290
291 if env::consts::FAMILY != "windows" {
292 assert_eq!(
293 glob_vec("bbb/specials/[*]"),
294 vec!(PathBuf::from("bbb/specials/*"))
295 );
296 assert_eq!(
297 glob_vec("bbb/specials/[?]"),
298 vec!(PathBuf::from("bbb/specials/?"))
299 );
300 }
301
302 if env::consts::FAMILY == "windows" {
303 assert_eq!(
304 glob_vec("bbb/specials/[![]"),
305 vec!(
306 PathBuf::from("bbb/specials/!"),
307 PathBuf::from("bbb/specials/]")
308 )
309 );
310
311 assert_eq!(
312 glob_vec("bbb/specials/[!]]"),
313 vec!(
314 PathBuf::from("bbb/specials/!"),
315 PathBuf::from("bbb/specials/[")
316 )
317 );
318
319 assert_eq!(
320 glob_vec("bbb/specials/[!!]"),
321 vec!(
322 PathBuf::from("bbb/specials/["),
323 PathBuf::from("bbb/specials/]")
324 )
325 );
326 } else {
327 assert_eq!(
328 glob_vec("bbb/specials/[![]"),
329 vec!(
330 PathBuf::from("bbb/specials/!"),
331 PathBuf::from("bbb/specials/*"),
332 PathBuf::from("bbb/specials/?"),
333 PathBuf::from("bbb/specials/]")
334 )
335 );
336
337 assert_eq!(
338 glob_vec("bbb/specials/[!]]"),
339 vec!(
340 PathBuf::from("bbb/specials/!"),
341 PathBuf::from("bbb/specials/*"),
342 PathBuf::from("bbb/specials/?"),
343 PathBuf::from("bbb/specials/[")
344 )
345 );
346
347 assert_eq!(
348 glob_vec("bbb/specials/[!!]"),
349 vec!(
350 PathBuf::from("bbb/specials/*"),
351 PathBuf::from("bbb/specials/?"),
352 PathBuf::from("bbb/specials/["),
353 PathBuf::from("bbb/specials/]")
354 )
355 );
356
357 assert_eq!(
358 glob_vec("bbb/specials/[!*]"),
359 vec!(
360 PathBuf::from("bbb/specials/!"),
361 PathBuf::from("bbb/specials/?"),
362 PathBuf::from("bbb/specials/["),
363 PathBuf::from("bbb/specials/]")
364 )
365 );
366
367 assert_eq!(
368 glob_vec("bbb/specials/[!?]"),
369 vec!(
370 PathBuf::from("bbb/specials/!"),
371 PathBuf::from("bbb/specials/*"),
372 PathBuf::from("bbb/specials/["),
373 PathBuf::from("bbb/specials/]")
374 )
375 );
376 }
377}
378