1
#![allow(warnings)]
2

            
3
use std::ffi::CString;
4
use std::sync::atomic::{AtomicI32, Ordering};
5
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
6

            
7
#[cfg(test)]
8
mod tests {
9
    use std::ffi::CString;
10

            
11
    use super::*;
12

            
13
    // solutions
14
    static X_VAL: AtomicI32 = AtomicI32::new(0);
15
    static Y_VAL: AtomicI32 = AtomicI32::new(0);
16
    static Z_VAL: AtomicI32 = AtomicI32::new(0);
17

            
18
    #[unsafe(no_mangle)]
19
1
    pub extern "C" fn hello_from_rust() -> bool {
20
        unsafe {
21
1
            X_VAL.store(printMatrix_getValue(0) as _, Ordering::Relaxed);
22
1
            Y_VAL.store(printMatrix_getValue(1) as _, Ordering::Relaxed);
23
1
            Z_VAL.store(printMatrix_getValue(2) as _, Ordering::Relaxed);
24
1
            return true;
25
        }
26
1
    }
27

            
28
    #[test]
29
1
    fn xyz_raw() {
30
        // A simple constraints model, manually written using FFI functions.
31
        // Testing to see if it does not segfault.
32
        // Results can be manually inspected in the outputted minion logs.
33
        unsafe {
34
            // See https://rust-lang.github.io/rust-bindgen/cpp.html
35
1
            let options = searchOptions_new();
36
1
            let args = searchMethod_new();
37
1
            let instance = instance_new();
38

            
39
1
            let x_str = CString::new("x").expect("bad x");
40
1
            let y_str = CString::new("y").expect("bad y");
41
1
            let z_str = CString::new("z").expect("bad z");
42

            
43
1
            newVar_ffi(instance, x_str.as_ptr() as _, VariableType_VAR_BOUND, 1, 3);
44
1
            newVar_ffi(instance, y_str.as_ptr() as _, VariableType_VAR_BOUND, 2, 4);
45
1
            newVar_ffi(instance, z_str.as_ptr() as _, VariableType_VAR_BOUND, 1, 5);
46

            
47
1
            let x = getVarByName(instance, x_str.as_ptr() as _);
48
1
            let y = getVarByName(instance, y_str.as_ptr() as _);
49
1
            let z = getVarByName(instance, z_str.as_ptr() as _);
50

            
51
            // PRINT
52
1
            printMatrix_addVar(instance, x);
53
1
            printMatrix_addVar(instance, y);
54
1
            printMatrix_addVar(instance, z);
55

            
56
            // VARORDER
57
1
            let search_vars = vec_var_new();
58
1
            vec_var_push_back(search_vars as _, x);
59
1
            vec_var_push_back(search_vars as _, y);
60
1
            vec_var_push_back(search_vars as _, z);
61
1
            let search_order = searchOrder_new(search_vars as _, VarOrderEnum_ORDER_STATIC, false);
62
1
            instance_addSearchOrder(instance, search_order);
63

            
64
            // CONSTRAINTS
65
1
            let leq = constraint_new(ConstraintType_CT_LEQSUM);
66
1
            let geq = constraint_new(ConstraintType_CT_GEQSUM);
67
1
            let ineq = constraint_new(ConstraintType_CT_INEQ);
68

            
69
1
            let rhs_vars = vec_var_new();
70
1
            vec_var_push_back(rhs_vars, constantAsVar(4));
71

            
72
            // leq / geq : [var] [var]
73
1
            constraint_addList(leq, search_vars as _);
74
1
            constraint_addList(leq, rhs_vars as _);
75

            
76
1
            constraint_addList(geq, search_vars as _);
77
1
            constraint_addList(geq, rhs_vars as _);
78

            
79
            // ineq: [var] [var] [const]
80
1
            let x_vec = vec_var_new();
81
1
            vec_var_push_back(x_vec, x);
82

            
83
1
            let y_vec = vec_var_new();
84
1
            vec_var_push_back(y_vec, y);
85

            
86
1
            let const_vec = vec_int_new();
87
1
            vec_int_push_back(const_vec, -1);
88

            
89
1
            constraint_addList(ineq, x_vec as _);
90
1
            constraint_addList(ineq, y_vec as _);
91
1
            constraint_addConstantList(ineq, const_vec as _);
92

            
93
1
            instance_addConstraint(instance, leq);
94
1
            instance_addConstraint(instance, geq);
95
1
            instance_addConstraint(instance, ineq);
96

            
97
1
            let res = runMinion(options, args, instance, Some(hello_from_rust));
98

            
99
            // does it get this far?
100
1
            assert_eq!(res, 0);
101

            
102
            // test if solutions are correct
103
1
            assert_eq!(X_VAL.load(Ordering::Relaxed), 1);
104
1
            assert_eq!(Y_VAL.load(Ordering::Relaxed), 2);
105
1
            assert_eq!(Z_VAL.load(Ordering::Relaxed), 1);
106
        }
107
1
    }
108
}