1
use std::fs;
2
use std::io;
3
use std::path::{Path, PathBuf};
4

            
5
use serde::Serialize;
6

            
7
/// Gitignored directory inside each exhaustive test case for debugging failed runs.
8
pub const DIAGNOSTICS_DIR: &str = "diagnostics";
9

            
10
#[derive(Debug, Serialize)]
11
pub struct FailureRecord {
12
    pub stage: String,
13
    pub message: String,
14
    #[serde(skip_serializing_if = "Option::is_none")]
15
    pub run_label: Option<String>,
16
}
17

            
18
1773
pub fn diagnostics_dir(test_dir: &Path) -> PathBuf {
19
1773
    test_dir.join(DIAGNOSTICS_DIR)
20
1773
}
21

            
22
pub fn conjure_artifacts_dir(test_dir: &Path) -> PathBuf {
23
    diagnostics_dir(test_dir).join("conjure")
24
}
25

            
26
pub fn oxide_artifacts_dir(test_dir: &Path) -> PathBuf {
27
    diagnostics_dir(test_dir).join("oxide")
28
}
29

            
30
/// Removes diagnostics after a passing run.
31
1773
pub fn clear_diagnostics(test_dir: &Path) -> io::Result<()> {
32
1773
    let dir = diagnostics_dir(test_dir);
33
1773
    if dir.is_dir() {
34
        fs::remove_dir_all(dir)?;
35
1773
    }
36
1773
    Ok(())
37
1773
}
38

            
39
/// Writes `failure.json` under `diagnostics/`.
40
pub fn write_failure_record(test_dir: &Path, record: &FailureRecord) -> io::Result<()> {
41
    fs::create_dir_all(diagnostics_dir(test_dir))?;
42
    let failure_json = serde_json::to_string_pretty(record).map_err(io::Error::other)?;
43
    fs::write(
44
        diagnostics_dir(test_dir).join("failure.json"),
45
        format!("{failure_json}\n"),
46
    )
47
}
48

            
49
pub fn copy_file_if_exists(from: &Path, to: &Path) -> io::Result<()> {
50
    if from.is_file() {
51
        if let Some(parent) = to.parent() {
52
            fs::create_dir_all(parent)?;
53
        }
54
        fs::copy(from, to)?;
55
    }
56
    Ok(())
57
}
58

            
59
pub fn write_oxide_failure_text(test_dir: &Path, run_label: &str, message: &str) -> io::Result<()> {
60
    let path = oxide_artifacts_dir(test_dir).join(format!("{run_label}.txt"));
61
    if let Some(parent) = path.parent() {
62
        fs::create_dir_all(parent)?;
63
    }
64
    fs::write(path, format!("{message}\n"))
65
}