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