1
use std::{
2
    env,
3
    error::Error,
4
    fs,
5
    sync::{Arc, RwLock},
6
};
7

            
8
use conjure_cp::parse::tree_sitter::{parse_essence_file, parse_essence_file_native};
9
use conjure_cp::settings::Parser;
10
use conjure_cp::{
11
    Model, ast::ExprInfo, context::Context, parse::tree_sitter::errors::ParseErrorCollection,
12
};
13
use tests_integration::TestConfig;
14

            
15
/// Parser function used by expression domain tests.
16
type ParseFn = fn(&str, Arc<RwLock<Context<'static>>>) -> Result<Model, Box<ParseErrorCollection>>;
17

            
18
/// Runs a test for one model using each configured parser
19
fn expression_domain_test(
20
    path: &str,
21
    filename: &str,
22
    extension: &str,
23
) -> Result<(), Box<dyn Error>> {
24
    let accept = env::var("ACCEPT").unwrap_or("false".to_string()) == "true";
25

            
26
    let file_config: TestConfig =
27
        if let Ok(config_contents) = fs::read_to_string(format!("{path}/config.toml")) {
28
            toml::from_str(&config_contents).unwrap()
29
        } else {
30
            Default::default()
31
        };
32

            
33
    if accept {
34
        clean_test_dir_for_accept(path)?;
35
    }
36

            
37
    let parsers = file_config
38
        .configured_parsers()
39
        .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err))?;
40

            
41
    for parser in parsers {
42
        let case_name = parser.to_string();
43
        let parse = match parser {
44
            Parser::TreeSitter => parse_essence_file_native,
45
            Parser::ViaConjure => parse_essence_file,
46
        };
47
        expression_domain_test_inner(path, filename, &case_name, extension, parse)?;
48
    }
49

            
50
    Ok(())
51
}
52

            
53
fn expression_domain_test_inner(
54
    path: &str,
55
    input_filename: &str,
56
    case_name: &str,
57
    extension: &str,
58
    parse: ParseFn,
59
) -> Result<(), Box<dyn Error>> {
60
    unimplemented!()
61
}
62

            
63
fn clean_test_dir_for_accept(path: &str) -> Result<(), std::io::Error> {
64
    for entry in std::fs::read_dir(path)? {
65
        let entry = entry?;
66
        let file_name = entry.file_name();
67
        let file_name = file_name.to_string_lossy();
68
        let entry_path = entry.path();
69

            
70
        if entry_path.is_dir() {
71
            continue;
72
        }
73

            
74
        let keep = if file_name == "config.toml" {
75
            true
76
        } else {
77
            let is_model_file = entry_path
78
                .extension()
79
                .and_then(|ext| ext.to_str())
80
                .is_some_and(|ext| ext == "essence");
81
            let is_generated_or_expected =
82
                file_name.contains(".generated") || file_name.contains(".expected");
83
            is_model_file && !is_generated_or_expected
84
        };
85

            
86
        if keep {
87
            continue;
88
        }
89

            
90
        std::fs::remove_file(entry_path)?;
91
    }
92

            
93
    Ok(())
94
}
95

            
96
/// Returns the saved expression JSON path
97
fn expression_domains_json_path(path: &str, case_name: &str, file_type: &str) -> String {
98
    format!("{path}/{case_name}.{file_type}.serialised.json")
99
}
100

            
101
/// Reads and initialises a saved expression domains snapshot.
102
fn read_expression_domains_json(
103
    context: &Arc<RwLock<Context<'static>>>,
104
    path: &str,
105
    case_name: &str,
106
    file_type: &str,
107
) -> Result<Vec<ExprInfo>, std::io::Error> {
108
    let serialised = fs::read_to_string(expression_domains_json_path(path, case_name, file_type))?;
109
    let exprs: Vec<ExprInfo> = serde_json::from_str(&serialised).map_err(std::io::Error::other)?;
110

            
111
    Ok(exprs)
112
}
113

            
114
// include!(concat!(env!("OUT_DIR"), "/gen_tests_domain_tightening.rs"));