1
use std::collections::BTreeSet;
2
use std::path::Path;
3

            
4
use crate::AcceptMode;
5

            
6
/// Returns whether a file name represents an expected golden artifact.
7
39135
fn is_expected_golden_file(file_name: &str) -> bool {
8
39135
    file_name.contains(".expected") || file_name.contains("-expected-")
9
39135
}
10

            
11
/// Lists expected snapshot files in `path` that are not present in `allowed_expected_files`.
12
1617
pub fn find_redundant_expected_files(
13
1617
    path: &Path,
14
1617
    allowed_expected_files: &BTreeSet<String>,
15
1617
) -> Result<Vec<String>, std::io::Error> {
16
1617
    let mut redundant = Vec::new();
17

            
18
39138
    for entry in std::fs::read_dir(path)? {
19
39138
        let entry = entry?;
20
39138
        if !entry.path().is_file() {
21
3
            continue;
22
39135
        }
23

            
24
39135
        let file_name = entry.file_name();
25
39135
        let file_name = file_name.to_string_lossy().to_string();
26

            
27
39135
        if is_expected_golden_file(&file_name) && !allowed_expected_files.contains(&file_name) {
28
            redundant.push(file_name);
29
39135
        }
30
    }
31

            
32
1617
    redundant.sort();
33
1617
    Ok(redundant)
34
1617
}
35

            
36
/// Builds a standardised error describing redundant golden files for a test directory.
37
pub fn redundant_golden_files_error(
38
    path: &Path,
39
    redundant_files: Vec<String>,
40
    context: Option<&str>,
41
) -> std::io::Error {
42
    let file_list = redundant_files
43
        .into_iter()
44
        .map(|file| format!("  - {file}"))
45
        .collect::<Vec<_>>()
46
        .join("\n");
47

            
48
    let context = context.map_or(String::new(), |context| format!(" {context}"));
49

            
50
    std::io::Error::other(format!(
51
        "Redundant golden files detected in {}{context}:\n{file_list}\n{} to refresh snapshots.",
52
        path.display(),
53
        AcceptMode::refresh_hint()
54
    ))
55
}
56

            
57
/// Fails when `path` contains any expected snapshot file not listed in `allowed_expected_files`.
58
1617
pub fn assert_no_redundant_expected_files(
59
1617
    path: &Path,
60
1617
    allowed_expected_files: &BTreeSet<String>,
61
1617
    context: Option<&str>,
62
1617
) -> Result<(), std::io::Error> {
63
1617
    let redundant = find_redundant_expected_files(path, allowed_expected_files)?;
64
1617
    if redundant.is_empty() {
65
1617
        return Ok(());
66
    }
67

            
68
    Err(redundant_golden_files_error(path, redundant, context))
69
1617
}