summaryrefslogtreecommitdiffhomepage
path: root/mullvad-ios/src/api_client/mock.rs
blob: 005a6c10c0496c20d61575f6ada4d441590512a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
use mockito::{Mock, ServerGuard};
use std::ffi::{c_char, c_void};

#[repr(C)]
pub struct SwiftServerMock {
    server_ptr: *const c_void,
    mock_ptr: *const c_void,
    port: u16,
}

impl SwiftServerMock {
    pub fn new(server: ServerGuard, mock: Mock) -> SwiftServerMock {
        let port = server.socket_address().port();
        let server_ptr = Box::into_raw(Box::new(server)) as *const c_void;
        let mock_ptr = Box::into_raw(Box::new(mock)) as *const c_void;

        SwiftServerMock {
            server_ptr,
            mock_ptr,
            port,
        }
    }
}

/// # Safety
///
/// `method` must be a pointer to a null terminated string representing the http method.
///
/// `path` must be a pointer to a null terminated string representing the url path.
///
/// `response_code` must be a usize representing the http response code.
///
/// `response_body` must be a pointer to a null terminated string representing the body.
///
/// This function is safe.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mullvad_api_mock_get(
    path: *const c_char,
    response_code: usize,
    response_body: *const u8,
) -> SwiftServerMock {
    // SAFETY: See notes above
    let path = unsafe { std::ffi::CStr::from_ptr(path.cast()) }
        .to_str()
        .unwrap();
    // SAFETY: See notes above
    let response_body = unsafe { std::ffi::CStr::from_ptr(response_body.cast()) }
        .to_str()
        .unwrap();
    let mut server = mockito::Server::new();
    let mock = server
        .mock("GET", path)
        .with_header("content-type", "application/json")
        .with_status(response_code)
        .with_body(response_body)
        .create();
    SwiftServerMock::new(server, mock)
}

/// # Safety
///
/// `path` must be a pointer to a null terminated string representing the url path.
///
/// `response_code` must be a usize representing the http response code.
///
/// `match_body` must be a pointer to a null terminated json string representing the body the server expects.
///
/// This function is safe.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mullvad_api_mock_post(
    path: *const c_char,
    response_code: usize,
    match_body: *const c_char,
) -> SwiftServerMock {
    // SAFETY: See notes above
    let path = unsafe { std::ffi::CStr::from_ptr(path.cast()) }
        .to_str()
        .unwrap();
    // SAFETY: See notes above
    let match_body = unsafe { std::ffi::CStr::from_ptr(match_body.cast()) }
        .to_str()
        .unwrap();
    let mut server = mockito::Server::new();
    let mock = server
        .mock("POST", path)
        .with_header("content-type", "application/json")
        .with_status(response_code)
        .match_body(mockito::Matcher::JsonString(match_body.to_string()))
        .create();
    SwiftServerMock::new(server, mock)
}

/// Called by the Swift side to signal that the Rust `SwiftServerMock` can be safely
/// dropped from memory.
///
/// # Safety
///
/// `mock_ptr` must be pointing to a valid instance of `SwiftServerMock`. This function
/// is not safe to call multiple times with the same `SwiftServerMock`.
#[unsafe(no_mangle)]
extern "C" fn mullvad_api_mock_drop(mock_ptr: SwiftServerMock) {
    if !mock_ptr.mock_ptr.is_null() {
        // SAFETY: See notes above
        unsafe { drop(Box::from_raw(mock_ptr.mock_ptr as *mut Mock)) };
    }
    if !mock_ptr.server_ptr.is_null() {
        // SAFETY: See notes above
        unsafe { drop(Box::from_raw(mock_ptr.server_ptr as *mut ServerGuard)) };
    }
}