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