1use crate::error::{Error, Result};
2use crate::manifest::Name;
3use crate::Test;
4use std::collections::BTreeMap as Map;
5use std::path::PathBuf;
6
7#[derive(Debug)]
8pub(crate) struct ExpandedTest {
9 pub name: Name,
10 pub test: Test,
11 pub error: Option<Error>,
12 is_from_glob: bool,
13}
14
15pub(crate) fn expand_globs(tests: &[Test]) -> Vec<ExpandedTest> {
16 let mut set = ExpandedTestSet::new();
17
18 for test in tests {
19 match test.path.to_str() {
20 Some(utf8) if utf8.contains('*') => match glob(utf8) {
21 Ok(paths) => {
22 let expected = test.expected;
23 for path in paths {
24 set.insert(Test { path, expected }, None, true);
25 }
26 }
27 Err(error) => set.insert(test.clone(), Some(error), false),
28 },
29 _ => set.insert(test.clone(), None, false),
30 }
31 }
32
33 set.vec
34}
35
36struct ExpandedTestSet {
37 vec: Vec<ExpandedTest>,
38 path_to_index: Map<PathBuf, usize>,
39}
40
41impl ExpandedTestSet {
42 fn new() -> Self {
43 ExpandedTestSet {
44 vec: Vec::new(),
45 path_to_index: Map::new(),
46 }
47 }
48
49 fn insert(&mut self, test: Test, error: Option<Error>, is_from_glob: bool) {
50 if let Some(&i) = self.path_to_index.get(&test.path) {
51 let prev = &mut self.vec[i];
52 if prev.is_from_glob {
53 prev.test.expected = test.expected;
54 return;
55 }
56 }
57
58 let index = self.vec.len();
59 let name = Name(format!("trybuild{:03}", index));
60 self.path_to_index.insert(test.path.clone(), index);
61 self.vec.push(ExpandedTest {
62 name,
63 test,
64 error,
65 is_from_glob,
66 });
67 }
68}
69
70fn glob(pattern: &str) -> Result<Vec<PathBuf>> {
71 let mut paths = glob::glob(pattern)?
72 .map(|entry| entry.map_err(Error::from))
73 .collect::<Result<Vec<PathBuf>>>()?;
74 paths.sort();
75 Ok(paths)
76}
77