summaryrefslogtreecommitdiffhomepage
path: root/talpid-ipc/tests/ipc-client-server.rs
blob: 6be834948739ea92bf97e8affc0bcea5511368b1 (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
// TODO fix these tests on Windows
#![cfg(not(windows))]

use assert_matches::assert_matches;
use futures::{sync::oneshot, Future};

use jsonrpc_client_core::{Error as ClientError, Transport};
use jsonrpc_core::{Error, IoHandler};
use jsonrpc_macros::build_rpc_trait;
use std::{
    sync::{mpsc, Mutex},
    time::Duration,
};

build_rpc_trait! {
    pub trait TestApi {
        #[rpc(name = "foo")]
        fn foo(&self, i64) -> Result<(), Error>;
    }
}

struct ApiImpl {
    tx: Mutex<mpsc::Sender<i64>>,
}

impl TestApi for ApiImpl {
    fn foo(&self, i: i64) -> Result<(), Error> {
        self.tx.lock().unwrap().send(i).unwrap();
        Ok(())
    }
}

#[test]
fn can_call_rpcs_on_server() {
    env_logger::init();

    let (server, rx) = create_server();
    let server_path = server.path().to_owned();
    let client = create_client(server_path);

    let _result: () = client.call_method("foo", &[97]).wait().unwrap();
    assert_eq!(Ok(97), rx.recv_timeout(Duration::from_millis(500)));

    let result: Result<(), ClientError> = client.call_method("invalid_method", &[0]).wait();
    assert_matches!(result, Err(_));
    server.close_handle().close();
}

#[test]
#[should_panic]
fn ipc_client_invalid_url() {
    let _client = create_client("INVALID ID".to_owned());
}

fn create_server() -> (talpid_ipc::IpcServer, mpsc::Receiver<i64>) {
    let (tx, rx) = mpsc::channel();
    let rpc = ApiImpl { tx: Mutex::new(tx) };
    let mut io = IoHandler::new();
    io.extend_with(rpc.to_delegate());

    let uuid = uuid::Uuid::new_v4().to_string();
    let ipc_path = if cfg!(windows) {
        format!(r"\\.\pipe\ipc-test-{}", uuid)
    } else {
        format!("/tmp/ipc-test-{}", uuid)
    };
    let server = talpid_ipc::IpcServer::start(io.into(), &ipc_path).unwrap();
    (server, rx)
}

fn create_client(ipc_path: String) -> jsonrpc_client_core::ClientHandle {
    use std::thread;
    let (tx, rx) = oneshot::channel();

    thread::spawn(move || {
        let (client, client_handle) =
            jsonrpc_client_ipc::IpcTransport::new(&ipc_path, &tokio::reactor::Handle::default())
                .expect("failed to construct a transport")
                .into_client();
        tx.send(client_handle).unwrap();
        client.wait().unwrap();
    });

    rx.wait().expect("Failed to construct a valid client")
}