1use log::debug;
30
31use std::collections::HashMap;
32use std::pin::Pin;
33use std::sync::Arc;
34use std::task::{Context, Poll};
35
36use futures;
37use futures::lock::Mutex;
38use futures::Future;
39use hyper::Uri;
40use tower_service::Service;
41
42mod streams;
43pub use crate::streams::MockPollStream;
44
45#[macro_export]
48macro_rules! mock_connector (
49 ($name:ident {
50 $($url:expr => $res:expr)*
51 }) => (
52 #[derive(Clone)]
53 pub struct $name($crate::HostToReplyConnector);
54
55 impl Default for $name {
56 fn default() -> Self {
57 let mut c = Self(Default::default());
58 $(c.0.m.insert($url.to_string(), $res.to_string());)*
59 c
60 }
61 }
62
63 impl tower_service::Service<hyper::Uri> for $name {
64 type Response = $crate::MockPollStream;
65 type Error = std::io::Error;
66 type Future = std::pin::Pin<Box<dyn std::future::Future<Output = Result<Self::Response, Self::Error>> + Send>>;
67
68 fn poll_ready(&mut self, cx: &mut std::task::Context<'_>) -> std::task::Poll<Result<(), Self::Error>> {
69 self.0.poll_ready(cx)
70 }
71
72 fn call(&mut self, req: hyper::Uri) -> Self::Future {
73 self.0.call(req)
74 }
75 }
76 )
77);
78
79#[derive(Default, Clone)]
84pub struct HostToReplyConnector {
85 pub m: HashMap<String, String>,
86}
87
88impl Service<Uri> for HostToReplyConnector {
89 type Response = crate::MockPollStream;
90 type Error = std::io::Error;
91 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
92
93 fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
94 Poll::Ready(Ok(()))
95 }
96
97 fn call(&mut self, req: Uri) -> Self::Future {
98 debug!("HostToReplyConnector::connect({:?})", req);
99
100 match (|| {
101 self.m.get(&format!("{}://{}", req.scheme()?, req.host()?))
103 })() {
104 Some(res) => Box::pin(futures::future::ok(MockPollStream::new(
105 res.clone().into_bytes(),
106 ))),
107 None => panic!("HostToReplyConnector doesn't know url {}", req),
108 }
109 }
110}
111
112#[macro_export]
115macro_rules! mock_connector_in_order (
116 ($name:ident {
117 $( $res:expr )*
118 }) => (
119 #[derive(Clone)]
120 pub struct $name($crate::SequentialConnector);
121
122 impl Default for $name {
123 fn default() -> $name {
124 Self($crate::SequentialConnector::new(vec![
125 $($res.to_string(),)*
126 ]))
127 }
128 }
129
130 impl tower_service::Service<hyper::Uri> for $name {
131 type Response = $crate::MockPollStream;
132 type Error = std::io::Error;
133 type Future = std::pin::Pin<Box<dyn std::future::Future<Output = Result<Self::Response, Self::Error>> + Send>>;
134
135 fn poll_ready(&mut self, cx: &mut std::task::Context<'_>) -> std::task::Poll<Result<(), Self::Error>> {
136 self.0.poll_ready(cx)
137 }
138
139 fn call(&mut self, req: hyper::Uri) -> Self::Future {
140 self.0.call(req)
141 }
142 }
143 )
144);
145
146#[derive(Clone)]
149pub struct SequentialConnector {
150 pub content: Arc<[String]>,
151 pub current: Arc<Mutex<usize>>,
152}
153
154impl SequentialConnector {
155 pub fn new(content: impl Into<Box<[String]>>) -> Self {
156 let content = content.into();
157 assert!(
158 content.len() != 0,
159 "Not a single streamer return value specified"
160 );
161
162 SequentialConnector {
163 content: content.into(),
164 current: Arc::new(Mutex::new(0)),
165 }
166 }
167}
168
169impl Service<Uri> for SequentialConnector {
170 type Response = crate::MockPollStream;
171 type Error = std::io::Error;
172 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
173
174 fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
175 Poll::Ready(Ok(()))
176 }
177
178 fn call(&mut self, req: Uri) -> Self::Future {
179 debug!("SequentialConnector::connect({:?})", req);
180
181 let content = self.content.clone();
182 let current = self.current.clone();
183 Box::pin(async move {
184 let mut current = current.lock().await;
185 let data = content[*current].clone().into_bytes();
186 *current = *current + 1;
187 Ok(MockPollStream::new(data))
188 })
189 }
190}