1
use std::path::{Component, Path};
2

            
3
3011
pub(crate) fn is_roundtrip_model_input(path: &Path) -> bool {
4
3011
    path.extension().is_some_and(|ext| ext == "essence")
5
1158
        && path
6
1158
            .file_stem()
7
1158
            .and_then(|stem| stem.to_str())
8
1158
            .is_some_and(|stem| !stem.contains(".generated") && !stem.contains(".expected"))
9
3011
}
10

            
11
/// Returns whether a test-suite file can affect the generated Rust test list or attributes.
12
14880
pub(crate) fn is_compile_time_test_input(path: &Path) -> bool {
13
14880
    let Ok(relative) = path.strip_prefix("tests") else {
14
        return false;
15
    };
16
14880
    let mut components = relative.components();
17
14880
    let Some(Component::Normal(suite_or_file)) = components.next() else {
18
        return false;
19
    };
20
14880
    let file_name = path.file_name().and_then(|name| name.to_str());
21

            
22
14880
    if components.next().is_none() {
23
15
        return file_name.is_some_and(|name| name.ends_with("_test_template"));
24
14865
    }
25

            
26
14865
    match suite_or_file.to_str() {
27
        Some("exhaustive") => {
28
12380
            matches!(file_name, Some("config.toml" | "stats.toml"))
29
9554
                || path.extension().is_some_and(|ext| ext == "essence")
30
        }
31
1085
        Some("custom") => matches!(file_name, Some("config.toml" | "run.sh")),
32
1398
        Some("roundtrip") => file_name == Some("config.toml") || is_roundtrip_model_input(path),
33
2
        _ => false,
34
    }
35
14880
}
36

            
37
#[cfg(test)]
38
mod tests {
39
    use super::{is_compile_time_test_input, is_roundtrip_model_input};
40
    use std::path::Path;
41

            
42
    #[test]
43
1
    fn watches_files_used_to_generate_tests() {
44
1
        for path in [
45
1
            "tests/exhaustive/example/input.essence",
46
1
            "tests/exhaustive/example/config.toml",
47
1
            "tests/exhaustive/example/stats.toml",
48
1
            "tests/custom/example/run.sh",
49
1
            "tests/custom/example/config.toml",
50
1
            "tests/roundtrip/example/input.essence",
51
1
            "tests/roundtrip/example/config.toml",
52
1
            "tests/exhaustive_test_template",
53
1
            "tests/custom_test_template",
54
1
            "tests/roundtrip_test_template",
55
1
        ] {
56
10
            assert!(is_compile_time_test_input(Path::new(path)), "{path}");
57
        }
58
1
    }
59

            
60
    #[test]
61
1
    fn ignores_runtime_outputs() {
62
1
        for path in [
63
1
            "tests/exhaustive/example/input.param",
64
1
            "tests/exhaustive/example/model.expected.solutions",
65
1
            "tests/exhaustive/example/model-generated-rule-trace.txt",
66
1
            "tests/custom/example/expected-output",
67
1
            "tests/roundtrip/example/tree-sitter.generated.essence",
68
1
            "tests/roundtrip/example/tree-sitter.expected.essence",
69
1
            "tests/roundtrip/example/tree-sitter.generated.serialised.json",
70
1
            "tests/roundtrip/example/tree-sitter.expected.serialised.json",
71
1
        ] {
72
8
            assert!(!is_compile_time_test_input(Path::new(path)), "{path}");
73
        }
74
1
    }
75

            
76
    #[test]
77
1
    fn selects_only_roundtrip_source_models() {
78
1
        assert!(is_roundtrip_model_input(Path::new(
79
1
            "tests/roundtrip/example/input.essence"
80
1
        )));
81
1
        assert!(!is_roundtrip_model_input(Path::new(
82
1
            "tests/roundtrip/example/config.toml"
83
1
        )));
84
1
        assert!(!is_roundtrip_model_input(Path::new(
85
1
            "tests/roundtrip/example/tree-sitter.generated.essence"
86
1
        )));
87
1
        assert!(!is_roundtrip_model_input(Path::new(
88
1
            "tests/roundtrip/example/tree-sitter.expected.essence"
89
1
        )));
90
1
    }
91
}