1 // Copyright 2017 The xi-editor Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Types and helpers used for testing.
16 
17 use std::io::{self, Cursor, Write};
18 use std::sync::mpsc::{channel, Receiver, Sender};
19 use std::time::{Duration, Instant};
20 
21 use serde_json::{self, Value};
22 
23 use super::{Callback, Error, MessageReader, Peer, ReadError, Response, RpcObject};
24 
25 /// Wraps an instance of `mpsc::Sender`, implementing `Write`.
26 ///
27 /// This lets the tx side of an mpsc::channel serve as the destination
28 /// stream for an RPC loop.
29 pub struct DummyWriter(Sender<String>);
30 
31 /// Wraps an instance of `mpsc::Receiver`, providing convenience methods
32 /// for parsing received messages.
33 pub struct DummyReader(MessageReader, Receiver<String>);
34 
35 /// An Peer that doesn't do anything.
36 #[derive(Debug, Clone)]
37 pub struct DummyPeer;
38 
39 /// Returns a `(DummyWriter, DummyReader)` pair.
test_channel() -> (DummyWriter, DummyReader)40 pub fn test_channel() -> (DummyWriter, DummyReader) {
41     let (tx, rx) = channel();
42     (DummyWriter(tx), DummyReader(MessageReader::default(), rx))
43 }
44 
45 /// Given a string type, returns a `Cursor<Vec<u8>>`, which implements
46 /// `BufRead`.
make_reader<S: AsRef<str>>(s: S) -> Cursor<Vec<u8>>47 pub fn make_reader<S: AsRef<str>>(s: S) -> Cursor<Vec<u8>> {
48     Cursor::new(s.as_ref().as_bytes().to_vec())
49 }
50 
51 impl DummyReader {
52     /// Attempts to read a message, returning `None` if the wait exceeds
53     /// `timeout`.
54     ///
55     /// This method makes no assumptions about the contents of the
56     /// message, and does no error handling.
next_timeout(&mut self, timeout: Duration) -> Option<Result<RpcObject, ReadError>>57     pub fn next_timeout(&mut self, timeout: Duration) -> Option<Result<RpcObject, ReadError>> {
58         self.1.recv_timeout(timeout).ok().map(|s| self.0.parse(&s))
59     }
60 
61     /// Reads and parses a response object.
62     ///
63     /// # Panics
64     ///
65     /// Panics if a non-response message is received, or if no message
66     /// is received after a reasonable time.
expect_response(&mut self) -> Response67     pub fn expect_response(&mut self) -> Response {
68         let raw = self.next_timeout(Duration::from_secs(1)).expect("response should be received");
69         let val = raw.as_ref().ok().map(|v| serde_json::to_string(&v.0));
70         let resp = raw.map_err(|e| e.to_string()).and_then(|r| r.into_response());
71 
72         match resp {
73             Err(msg) => panic!("Bad response: {:?}. {}", val, msg),
74             Ok(resp) => resp,
75         }
76     }
77 
expect_object(&mut self) -> RpcObject78     pub fn expect_object(&mut self) -> RpcObject {
79         self.next_timeout(Duration::from_secs(1)).expect("expected object").unwrap()
80     }
81 
expect_rpc(&mut self, method: &str) -> RpcObject82     pub fn expect_rpc(&mut self, method: &str) -> RpcObject {
83         let obj = self
84             .next_timeout(Duration::from_secs(1))
85             .unwrap_or_else(|| panic!("expected rpc \"{}\"", method))
86             .unwrap();
87         assert_eq!(obj.get_method(), Some(method));
88         obj
89     }
90 
expect_nothing(&mut self)91     pub fn expect_nothing(&mut self) {
92         if let Some(thing) = self.next_timeout(Duration::from_millis(500)) {
93             panic!("unexpected something {:?}", thing);
94         }
95     }
96 }
97 
98 impl Write for DummyWriter {
write(&mut self, buf: &[u8]) -> io::Result<usize>99     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
100         let s = String::from_utf8(buf.to_vec()).unwrap();
101         self.0
102             .send(s)
103             .map_err(|err| io::Error::new(io::ErrorKind::Other, format!("{:?}", err)))
104             .map(|_| buf.len())
105     }
106 
flush(&mut self) -> io::Result<()>107     fn flush(&mut self) -> io::Result<()> {
108         Ok(())
109     }
110 }
111 
112 impl Peer for DummyPeer {
box_clone(&self) -> Box<dyn Peer>113     fn box_clone(&self) -> Box<dyn Peer> {
114         Box::new(self.clone())
115     }
send_rpc_notification(&self, _method: &str, _params: &Value)116     fn send_rpc_notification(&self, _method: &str, _params: &Value) {}
send_rpc_request_async(&self, _method: &str, _params: &Value, f: Box<dyn Callback>)117     fn send_rpc_request_async(&self, _method: &str, _params: &Value, f: Box<dyn Callback>) {
118         f.call(Ok("dummy peer".into()))
119     }
send_rpc_request(&self, _method: &str, _params: &Value) -> Result<Value, Error>120     fn send_rpc_request(&self, _method: &str, _params: &Value) -> Result<Value, Error> {
121         Ok("dummy peer".into())
122     }
request_is_pending(&self) -> bool123     fn request_is_pending(&self) -> bool {
124         false
125     }
schedule_idle(&self, _token: usize)126     fn schedule_idle(&self, _token: usize) {}
schedule_timer(&self, _time: Instant, _token: usize)127     fn schedule_timer(&self, _time: Instant, _token: usize) {}
128 }
129