1
use crate::exit;
2
use std::path::PathBuf;
3
use std::sync::Arc;
4

            
5
use crate::cli::GlobalArgs;
6
use crate::solve::{self, init_solver};
7
use clap::ValueHint;
8
use conjure_cp::instantiate::{instantiate_model, validate_instantiation_conditions};
9
use conjure_cp_cli::utils::conjure::{
10
    get_solutions, get_solutions_from_conjure, solutions_to_json,
11
};
12
use conjure_cp_cli::utils::testing::normalize_solutions_for_comparison;
13

            
14
#[derive(Clone, Debug, clap::Args)]
15
pub struct Args {
16
    /// The input Essence problem file
17
    #[arg(value_name = "INPUT_ESSENCE",value_hint=ValueHint::FilePath)]
18
    pub input_file: PathBuf,
19

            
20
    /// The input Essence parameter file
21
    #[arg(value_name = "PARAM_ESSENCE", value_hint=ValueHint::FilePath)]
22
    pub param_file: Option<PathBuf>,
23
}
24

            
25
4
pub fn run_test_solve_command(global_args: GlobalArgs, local_args: Args) -> anyhow::Result<()> {
26
    // stealing most of the steps of the solve command, except the solver stuff.
27
4
    let input_file = local_args.input_file;
28
4
    let param_file = local_args.param_file;
29

            
30
    // each step is in its own method so that similar commands
31
    // (e.g. testsolve) can reuse some of these steps.
32

            
33
4
    let context = solve::init_context(&global_args, input_file.clone(), param_file.clone())?;
34

            
35
    // get input and param file name from context
36
4
    let ctx_lock = context.read().unwrap();
37
4
    let essence_file_name = ctx_lock
38
4
        .essence_file_name
39
4
        .as_ref()
40
4
        .expect("context should contain the problem input file");
41
4
    let param_file_name = ctx_lock.param_file_name.as_ref();
42

            
43
    // parse models
44
4
    let problem_model = solve::parse(&global_args, Arc::clone(&context), essence_file_name)?;
45

            
46
4
    let unified_model = match param_file_name {
47
        Some(param_file_name) => {
48
4
            let param_model = solve::parse(&global_args, Arc::clone(&context), param_file_name)?;
49
4
            instantiate_model(problem_model, param_model)?
50
        }
51
        None => {
52
            let mut problem_model = problem_model;
53
            validate_instantiation_conditions(&mut problem_model)?;
54
            problem_model
55
        }
56
    };
57

            
58
2
    drop(ctx_lock);
59

            
60
2
    let rewritten_model = solve::rewrite(unified_model, &global_args, Arc::clone(&context))?;
61

            
62
2
    let solver = init_solver(&global_args)?;
63

            
64
    // now we are stealing from the exhaustive tester
65

            
66
2
    let our_solutions = get_solutions(
67
2
        solver,
68
2
        rewritten_model,
69
2
        0,
70
2
        false,
71
2
        &global_args.save_solver_input_file,
72
2
        global_args.rule_trace_cdp,
73
2
    )?;
74

            
75
2
    let conjure_solutions = get_solutions_from_conjure(
76
2
        input_file.to_str().unwrap(),
77
2
        param_file.as_deref().map(|f| f.to_str().unwrap()),
78
2
        Arc::clone(&context),
79
    )?;
80

            
81
2
    let our_solutions = normalize_solutions_for_comparison(&our_solutions);
82
2
    let conjure_solutions = normalize_solutions_for_comparison(&conjure_solutions);
83

            
84
2
    let mut our_solutions_json = solutions_to_json(&our_solutions);
85
2
    let mut conjure_solutions_json = solutions_to_json(&conjure_solutions);
86

            
87
2
    our_solutions_json.sort_all_objects();
88
2
    conjure_solutions_json.sort_all_objects();
89

            
90
2
    if our_solutions_json == conjure_solutions_json {
91
2
        eprintln!("Success: solutions match!");
92
2
        exit(0);
93
    } else {
94
        eprintln!("=== our solutions:");
95
        eprintln!("{our_solutions_json}");
96
        eprintln!("=== conjure's solutions:");
97
        eprintln!("{conjure_solutions_json}");
98
        eprintln!("Failure: solutions do not match!");
99
        exit(1);
100
    }
101
2
}