1
use pretty_assertions::assert_eq;
2
use std::borrow::Cow;
3
use std::collections::BTreeSet;
4
use std::env;
5
use std::error::Error;
6
use std::fs;
7
use std::path::Path;
8
use std::path::PathBuf;
9
use std::process::Command;
10
use tests_integration::golden_files::assert_no_redundant_expected_files;
11

            
12
37
pub fn custom_test(test_dir: &str) -> Result<(), Box<dyn Error>> {
13
37
    let accept = env::var("ACCEPT").unwrap_or("false".to_string()) == "true";
14

            
15
    // Convert test directory to a PathBuf
16
37
    let test_path = PathBuf::from(test_dir);
17
37
    assert!(
18
37
        test_path.exists(),
19
        "Test directory not found: {test_path:?}"
20
    );
21

            
22
    // Get paths
23
37
    let script_path = test_path.join("run.sh");
24
37
    assert!(
25
37
        script_path.exists(),
26
        "Test script not found: {script_path:?}"
27
    );
28
37
    let expected_output_path = test_path.join("stdout.expected");
29
37
    let expected_error_path = test_path.join("stderr.expected");
30

            
31
    // Execute the test script in the correct directory
32
37
    let output = Command::new("sh")
33
37
        .arg("run.sh")
34
37
        .current_dir(&test_path)
35
37
        .output()?;
36

            
37
    // Convert captured output/error to string
38
37
    let actual_output = String::from_utf8_lossy(&output.stdout);
39
37
    let actual_error = String::from_utf8_lossy(&output.stderr);
40

            
41
37
    if accept {
42
        // Overwrite expected files
43
        update_file(expected_output_path, &actual_output)?;
44
        update_file(expected_error_path, &actual_error)?;
45
    } else {
46
        // Compare results
47
37
        let expected_output = if expected_output_path.exists() {
48
30
            fs::read_to_string(&expected_output_path)?
49
        } else {
50
7
            String::new()
51
        };
52
37
        let expected_error = if expected_error_path.exists() {
53
21
            fs::read_to_string(&expected_error_path)?
54
        } else {
55
16
            String::new()
56
        };
57

            
58
37
        assert_eq!(expected_error, actual_error, "Standard error mismatch");
59
37
        assert_eq!(expected_output, actual_output, "Standard output mismatch");
60
    }
61

            
62
37
    let allowed_expected_files = expected_custom_files_for_case(&actual_output, &actual_error);
63
37
    assert_no_redundant_expected_files(Path::new(&test_path), &allowed_expected_files, None)?;
64

            
65
37
    Ok(())
66
37
}
67

            
68
fn update_file(
69
    expected_file_path: PathBuf,
70
    actual_output: &Cow<'_, str>,
71
) -> Result<(), Box<dyn Error>> {
72
    if expected_file_path.exists() {
73
        fs::remove_file(&expected_file_path)?;
74
    }
75
    if !actual_output.trim().is_empty() {
76
        fs::File::create(&expected_file_path)?;
77
        fs::write(&expected_file_path, actual_output.as_bytes())?;
78
    }
79
    Ok(())
80
}
81

            
82
/// Returns the expected snapshot files for the observed custom test output.
83
37
fn expected_custom_files_for_case(
84
37
    stdout: &Cow<'_, str>,
85
37
    stderr: &Cow<'_, str>,
86
37
) -> BTreeSet<String> {
87
37
    let mut expected_files = BTreeSet::new();
88
37
    if !stdout.trim().is_empty() {
89
30
        expected_files.insert("stdout.expected".to_string());
90
30
    }
91
37
    if !stderr.trim().is_empty() {
92
21
        expected_files.insert("stderr.expected".to_string());
93
21
    }
94
37
    expected_files
95
37
}
96

            
97
#[test]
98
1
fn assert_conjure_present() {
99
1
    conjure_cp_cli::find_conjure::conjure_executable().unwrap();
100
1
}
101

            
102
include!(concat!(env!("OUT_DIR"), "/gen_tests_custom.rs"));