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 
15 extern crate glob;
16 extern crate tempdir;
17 
18 use glob::glob;
19 use std::env;
20 use std::fs;
21 use std::path::PathBuf;
22 use tempdir::TempDir;
23 
24 #[test]
main()25 fn 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