Diff Coverage

Diff: upstream/main...HEAD, staged and unstaged changes

Source File Diff Coverage (%) Missing Lines
crates/conjure-cp-cli/src/pretty.rs 0.0% 31,35
crates/conjure-cp-cli/src/utils/testing.rs 0.0% 118-122
crates/conjure-cp-core/src/ast/model.rs 0.0% 564-567,569-574
tests-integration/tests/domain_tightening_tests.rs 0.0% 19-24,26-28,30,33-35,37-39,41-45,47,50-51,53-60,63-68,70-72,74-75,77-83,86-88,90,93-94,97-99,102-109,111-112
crates/conjure-cp-cli/src/pretty.rs
27
28
29
30
31
32
33
34
35
36
37
38
39

    // Running the correct method to acquire pretty string
    let output = match pretty_args.output_format.as_str() {
        "ast-json" => serialize_model(&model),
        "expression-domains" => serialize_domains(&model),
        // "add_new_flag" => method(),
        _ => {
            return Err(anyhow!(
                "Unknown output format {}; supports [ast-json, expression-domains]",
                &pretty_args.output_format
            ));
        }
    };
crates/conjure-cp-cli/src/utils/testing.rs
114
115
116
117
118
119
120
121
122
123
124
125
126
    // Serialize to pretty-printed string
    serde_json::to_string_pretty(&sorted_json)
}

pub fn serialize_domains(model: &ConjureModel) -> Result<String, JsonError> {
    let exprs: Vec<ExprInfo> = model.constraints().iter().map(ExprInfo::create).collect();
    serde_json::to_string_pretty(&exprs)
}

pub fn save_model_json(
    model: &ConjureModel,
    path: &str,
    test_name: &str,
crates/conjure-cp-core/src/ast/model.rs
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
    children: Vec<ExprInfo>,
}

impl ExprInfo {
    pub fn create(expr: &Expression) -> ExprInfo {
        let pretty = expr.to_string();
        let domain = expr.domain_of();
        let children = expr.children().iter().map(Self::create).collect();

        ExprInfo {
            pretty,
            domain,
            children,
        }
    }
}
tests-integration/tests/domain_tightening_tests.rs
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/// Parser function used by expression domain tests.
type ParseFn = fn(&str, Arc<RwLock<Context<'static>>>) -> Result<Model, Box<ParseErrorCollection>>;

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

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

    if accept {
        clean_test_dir_for_accept(path)?;
    }

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

    for parser in parsers {
        let case_name = parser.to_string();
        let parse = match parser {
            Parser::TreeSitter => parse_essence_file_native,
            Parser::ViaConjure => parse_essence_file,
        };
        expression_domain_test_inner(path, filename, &case_name, extension, parse)?;
    }

    Ok(())
}

fn expression_domain_test_inner(
    path: &str,
    input_filename: &str,
    case_name: &str,
    extension: &str,
    parse: ParseFn,
) -> Result<(), Box<dyn Error>> {
    unimplemented!()
}

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

        if entry_path.is_dir() {
            continue;
        }

        let keep = if file_name == "config.toml" {
            true
        } else {
            let is_model_file = entry_path
                .extension()
                .and_then(|ext| ext.to_str())
                .is_some_and(|ext| ext == "essence");
            let is_generated_or_expected =
                file_name.contains(".generated") || file_name.contains(".expected");
            is_model_file && !is_generated_or_expected
        };

        if keep {
            continue;
        }

        std::fs::remove_file(entry_path)?;
    }

    Ok(())
}

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

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

    Ok(exprs)
}

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