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
    pub extern "C" fn hello_from_rust() -> bool {
20
        unsafe {
21
            X_VAL.store(printMatrix_getValue(0) as _, Ordering::Relaxed);
22
            Y_VAL.store(printMatrix_getValue(1) as _, Ordering::Relaxed);
23
            Z_VAL.store(printMatrix_getValue(2) as _, Ordering::Relaxed);
24
            return true;
25
        }
26
    }
27

            
28
    #[test]
29
    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
            let options = searchOptions_new();
36
            let args = searchMethod_new();
37
            let instance = instance_new();
38

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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