use crate::error::*;
use crate::http::client::AbstractClient;
use crate::http::recording::{RecordedRequest, Recording, RecordingEntry};
use crate::http::types::{HttpData, ResponseMetadata};
use crate::lock;
use reqwest::Client as InnerClient;
use reqwest::{Request, RequestBuilder, Url};
use serde_json;
use std::collections::VecDeque;
use std::sync::Mutex;
pub struct TestStubClient {
inner: InnerClient,
recordings: Mutex<VecDeque<Recording>>,
}
impl TestStubClient {
pub fn new() -> Self {
TestStubClient {
inner: InnerClient::new(),
recordings: Mutex::new(VecDeque::new()),
}
}
pub fn push_recording(&self, recording: &[u8]) -> Result<&Self> {
lock(&self.recordings).push_back(serde_json::from_slice(recording)?);
Ok(self)
}
}
impl AbstractClient for TestStubClient {
fn execute(&self, request: Request) -> Result<(ResponseMetadata, Vec<u8>)> {
let entry: RecordingEntry;
let pop: bool;
let mut recordings = lock(&self.recordings);
{
let recording = match recordings.front_mut() {
None => {
panic!("Unexpected call to AbstractClient::execute (no more mock recordings)")
}
Some(recording) => recording,
};
entry = recording
.0
.pop_front()
.expect("TestStubClient: front recording was empty; test setup bug?");
pop = recording.0.is_empty();
}
if pop {
recordings.pop_front();
}
let assert_req = RecordedRequest::from(&request);
assert_eq!(
entry.req, assert_req,
"HTTP server expected {:#?}, got {:#?}",
entry.req, assert_req
);
Ok((
entry.res.metadata,
match entry.res.body {
HttpData::Text(text) => text.into_bytes(),
HttpData::Binary(bytes) => bytes,
},
))
}
fn get(&self, url: Url) -> RequestBuilder {
self.inner.get(url)
}
fn post(&self, url: Url) -> RequestBuilder {
self.inner.post(url)
}
fn put(&self, url: Url) -> RequestBuilder {
self.inner.put(url)
}
fn patch(&self, url: Url) -> RequestBuilder {
self.inner.patch(url)
}
fn delete(&self, url: Url) -> RequestBuilder {
self.inner.delete(url)
}
fn head(&self, url: Url) -> RequestBuilder {
self.inner.head(url)
}
}
impl Drop for TestStubClient {
fn drop(&mut self) {
if !::std::thread::panicking() {
let guard = lock(&self.recordings);
let empty = guard.is_empty();
drop(guard);
if !empty {
println!(
"Test failure / panic: test ended with mock HTTP client recordings still pending"
);
}
assert!(empty);
}
}
}