simple test harness
This commit is contained in:
@@ -9,8 +9,9 @@
|
|||||||
- [x] Header handling
|
- [x] Header handling
|
||||||
- [x] Transfer-Encoding: chunked
|
- [x] Transfer-Encoding: chunked
|
||||||
- [x] Ergonomic JSON handling
|
- [x] Ergonomic JSON handling
|
||||||
- [ ] Auth headers
|
|
||||||
- [ ] Test harness for end-to-end tests
|
- [ ] Test harness for end-to-end tests
|
||||||
|
- [ ] Limit read length on Content-Size
|
||||||
|
- [ ] Auth headers
|
||||||
- [ ] Cookie jar in agent
|
- [ ] Cookie jar in agent
|
||||||
- [ ] Forms with application/x-www-form-urlencoded
|
- [ ] Forms with application/x-www-form-urlencoded
|
||||||
- [ ] multipart/form-data
|
- [ ] multipart/form-data
|
||||||
|
|||||||
12
src/conn.rs
12
src/conn.rs
@@ -33,6 +33,7 @@ impl ConnectionPool {
|
|||||||
let mut stream = match url.scheme() {
|
let mut stream = match url.scheme() {
|
||||||
"http" => connect_http(request, &url),
|
"http" => connect_http(request, &url),
|
||||||
"https" => connect_https(request, &url),
|
"https" => connect_https(request, &url),
|
||||||
|
"test" => connect_test(request, &url),
|
||||||
_ => Err(Error::UnknownScheme(url.scheme().to_string())),
|
_ => Err(Error::UnknownScheme(url.scheme().to_string())),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
@@ -191,3 +192,14 @@ where
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
fn connect_test(_request: &Request, url: &Url) -> Result<Stream, Error> {
|
||||||
|
Err(Error::UnknownScheme(url.scheme().to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn connect_test(request: &Request, url: &Url) -> Result<Stream, Error> {
|
||||||
|
use test;
|
||||||
|
test::resolve_handler(request, url)
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ mod header;
|
|||||||
mod stream;
|
mod stream;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test;
|
||||||
|
|
||||||
pub use agent::{Agent, Request, Response};
|
pub use agent::{Agent, Request, Response};
|
||||||
pub use header::Header;
|
pub use header::Header;
|
||||||
|
|
||||||
@@ -125,7 +128,7 @@ where
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
//#[test]
|
||||||
fn connect_http_google() {
|
fn connect_http_google() {
|
||||||
let resp = get("http://www.google.com/").call();
|
let resp = get("http://www.google.com/").call();
|
||||||
println!("{:?}", resp);
|
println!("{:?}", resp);
|
||||||
@@ -133,7 +136,7 @@ mod tests {
|
|||||||
assert_eq!("text/html", resp.content_type());
|
assert_eq!("text/html", resp.content_type());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
//#[test]
|
||||||
fn connect_https_google() {
|
fn connect_https_google() {
|
||||||
let resp = get("https://www.google.com/").call();
|
let resp = get("https://www.google.com/").call();
|
||||||
println!("{:?}", resp);
|
println!("{:?}", resp);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use std::net::TcpStream;
|
|||||||
pub enum Stream {
|
pub enum Stream {
|
||||||
Http(TcpStream),
|
Http(TcpStream),
|
||||||
Https(rustls::ClientSession, TcpStream),
|
Https(rustls::ClientSession, TcpStream),
|
||||||
|
#[cfg(test)] Test(Box<Read + Send>, Box<Write + Send>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Read for Stream {
|
impl Read for Stream {
|
||||||
@@ -14,6 +15,7 @@ impl Read for Stream {
|
|||||||
match self {
|
match self {
|
||||||
Stream::Http(sock) => sock.read(buf),
|
Stream::Http(sock) => sock.read(buf),
|
||||||
Stream::Https(sess, sock) => rustls::Stream::new(sess, sock).read(buf),
|
Stream::Https(sess, sock) => rustls::Stream::new(sess, sock).read(buf),
|
||||||
|
#[cfg(test)] Stream::Test(reader, _) => reader.read(buf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,12 +25,14 @@ impl Write for Stream {
|
|||||||
match self {
|
match self {
|
||||||
Stream::Http(sock) => sock.write(buf),
|
Stream::Http(sock) => sock.write(buf),
|
||||||
Stream::Https(sess, sock) => rustls::Stream::new(sess, sock).write(buf),
|
Stream::Https(sess, sock) => rustls::Stream::new(sess, sock).write(buf),
|
||||||
|
#[cfg(test)] Stream::Test(_, writer) => writer.write(buf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn flush(&mut self) -> Result<()> {
|
fn flush(&mut self) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Stream::Http(sock) => sock.flush(),
|
Stream::Http(sock) => sock.flush(),
|
||||||
Stream::Https(sess, sock) => rustls::Stream::new(sess, sock).flush(),
|
Stream::Https(sess, sock) => rustls::Stream::new(sess, sock).flush(),
|
||||||
|
#[cfg(test)] Stream::Test(_, writer) => writer.flush(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
52
src/test/mod.rs
Normal file
52
src/test/mod.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
use agent::Request;
|
||||||
|
use error::Error;
|
||||||
|
use header::Header;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use stream::Stream;
|
||||||
|
use url::Url;
|
||||||
|
use util::vecread::VecRead;
|
||||||
|
|
||||||
|
mod simple;
|
||||||
|
|
||||||
|
type RequestHandler = Fn(&Request, &Url) -> Result<Stream, Error> + Send + 'static;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref TEST_HANDLERS: Arc<Mutex<HashMap<String, Box<RequestHandler>>>> =
|
||||||
|
{ Arc::new(Mutex::new(HashMap::new())) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_handler<H>(path: &str, handler: H)
|
||||||
|
where
|
||||||
|
H: Fn(&Request, &Url) -> Result<Stream, Error> + Send + 'static,
|
||||||
|
{
|
||||||
|
let mut handlers = TEST_HANDLERS.lock().unwrap();
|
||||||
|
handlers.insert(path.to_string(), Box::new(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_stream(
|
||||||
|
status: u16,
|
||||||
|
status_text: &str,
|
||||||
|
headers: Vec<&str>,
|
||||||
|
mut body: Vec<u8>,
|
||||||
|
) -> Result<Stream, Error> {
|
||||||
|
let mut buf: Vec<u8> = vec![];
|
||||||
|
write!(&mut buf, "HTTP/1.1 {} {}\r\n", status, status_text).ok();
|
||||||
|
for hstr in headers.iter() {
|
||||||
|
let header = hstr.parse::<Header>().unwrap();
|
||||||
|
write!(&mut buf, "{}: {}\r\n", header.name(), header.value()).ok();
|
||||||
|
}
|
||||||
|
write!(&mut buf, "\r\n").ok();
|
||||||
|
buf.append(&mut body);
|
||||||
|
let read = VecRead::from_vec(buf);
|
||||||
|
let write: Vec<u8> = vec![];
|
||||||
|
Ok(Stream::Test(Box::new(read), Box::new(write)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_handler(req: &Request, url: &Url) -> Result<Stream, Error> {
|
||||||
|
let mut handlers = TEST_HANDLERS.lock().unwrap();
|
||||||
|
let path = url.path();
|
||||||
|
let handler = handlers.remove(path).unwrap();
|
||||||
|
handler(req, url)
|
||||||
|
}
|
||||||
25
src/test/simple.rs
Normal file
25
src/test/simple.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
use super::super::*;
|
||||||
|
use test;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn header_passing() {
|
||||||
|
test::set_handler("/header_passing", |req, _url| {
|
||||||
|
assert!(req.has("X-Foo"));
|
||||||
|
assert_eq!(req.get("X-Foo").unwrap(), "bar");
|
||||||
|
test::make_stream(200, "OK", vec!["X-Bar: foo"], vec![])
|
||||||
|
});
|
||||||
|
let resp = get("test://host/header_passing").set("X-Foo", "bar").call();
|
||||||
|
assert_eq!(*resp.status(), 200);
|
||||||
|
assert!(resp.has("X-Bar"));
|
||||||
|
assert_eq!(resp.get("X-Bar").unwrap(), "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn body_as_text() {
|
||||||
|
test::set_handler("/body_as_text", |_req, _url| {
|
||||||
|
test::make_stream(200, "OK", vec![], "Hello World!".to_string().into_bytes())
|
||||||
|
});
|
||||||
|
let resp = get("test://host/body_as_text").call();
|
||||||
|
let text = resp.into_string().unwrap();
|
||||||
|
assert_eq!(text, "Hello World!");
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
mod macros;
|
mod macros;
|
||||||
mod serde_macros;
|
mod serde_macros;
|
||||||
mod vecread;
|
pub mod vecread;
|
||||||
|
|
||||||
use base64;
|
use base64;
|
||||||
use mime_guess::get_mime_type_str;
|
use mime_guess::get_mime_type_str;
|
||||||
|
|||||||
Reference in New Issue
Block a user