1
use std::path::PathBuf;
2
use std::process::exit;
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;
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
4
        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 => problem_model,
52
    };
53

            
54
2
    drop(ctx_lock);
55

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

            
58
2
    let solver = init_solver(&global_args);
59

            
60
    // now we are stealing from the integration tester
61

            
62
2
    let our_solutions = get_solutions(
63
2
        solver,
64
2
        rewritten_model,
65
        0,
66
2
        &global_args.save_solver_input_file,
67
    )?;
68

            
69
2
    let conjure_solutions = get_solutions_from_conjure(
70
2
        input_file.to_str().unwrap(),
71
2
        param_file.as_deref().map(|f| f.to_str().unwrap()),
72
2
        Arc::clone(&context),
73
    )?;
74

            
75
2
    let our_solutions = normalize_solutions_for_comparison(&our_solutions);
76
2
    let conjure_solutions = normalize_solutions_for_comparison(&conjure_solutions);
77

            
78
2
    let mut our_solutions_json = solutions_to_json(&our_solutions);
79
2
    let mut conjure_solutions_json = solutions_to_json(&conjure_solutions);
80

            
81
2
    our_solutions_json.sort_all_objects();
82
2
    conjure_solutions_json.sort_all_objects();
83

            
84
2
    if our_solutions_json == conjure_solutions_json {
85
2
        eprintln!("Success: solutions match!");
86
2
        exit(0);
87
    } else {
88
        eprintln!("=== our solutions:");
89
        eprintln!("{our_solutions_json}");
90
        eprintln!("=== conjure's solutions:");
91
        eprintln!("{conjure_solutions_json}");
92
        eprintln!("Failure: solutions do not match!");
93
        exit(1);
94
    }
95
2
}