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] |
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 | |