Skip to content

Commit

Permalink
Use speculate and mockito to make integration tests much more clean
Browse files Browse the repository at this point in the history
  • Loading branch information
sagebind committed Jul 20, 2019
1 parent 9bfc40a commit 821f8e4
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 148 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ optional = true

[dev-dependencies]
env_logger = "0.6"
mockito = "0.19"
rayon = "1"
rouille = "3"
speculate = "0.1"

[[example]]
name = "async"
Expand Down
3 changes: 2 additions & 1 deletion benchmarks/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[package]
name = "chttp-benchmarks"
version = "0.0.1"
version = "0.0.0"
edition = "2018"
publish = false

[dependencies.chttp]
path = ".."
Expand Down
105 changes: 60 additions & 45 deletions tests/redirects.rs
Original file line number Diff line number Diff line change
@@ -1,62 +1,77 @@
use chttp::config::RedirectPolicy;
use chttp::prelude::*;
use utilities::rouille;
use mockito::{mock, server_url};

mod utilities;
mod utils;

#[test]
fn response_301_no_follow() {
utilities::logging();
speculate::speculate! {
before {
utils::logging();
}

let server = utilities::server::spawn(|request| match request.raw_url() {
"/a" => rouille::Response::redirect_301("/b"),
_ => rouille::Response::text("ok"),
});
test "response 301 no follow" {
let m = mock("GET", "/")
.with_status(301)
.with_header("Location", "/b")
.create();

let response = chttp::get(&format!("{}/a", &server.endpoint())).unwrap();
let response = chttp::get(server_url()).unwrap();

assert_eq!(response.status(), 301);
}
assert_eq!(response.status(), 301);
assert_eq!(response.headers()["Location"], "/b");
m.assert();
}

#[test]
fn response_301_auto_follow() {
utilities::logging();
test "response 301 auto follow" {
let m1 = mock("GET", "/")
.with_status(301)
.with_header("Location", "/b")
.create();

let server = utilities::server::spawn(|request| match request.raw_url() {
"/a" => rouille::Response::redirect_301("/b"),
_ => rouille::Response::text("ok"),
});
let m2 = mock("GET", "/b")
.with_status(200)
.with_body("ok")
.create();

let mut response = Request::get(format!("{}/a", server.endpoint()))
.redirect_policy(RedirectPolicy::Follow)
.body(())
.map_err(Into::into)
.and_then(chttp::send)
.unwrap();
let mut response = Request::get(server_url())
.redirect_policy(RedirectPolicy::Follow)
.body(())
.unwrap()
.send()
.unwrap();

assert_eq!(response.status(), 200);
assert_eq!(response.text().unwrap(), "ok");
}
assert_eq!(response.status(), 200);
assert_eq!(response.text().unwrap(), "ok");

m1.assert();
m2.assert();
}

#[test]
fn redirect_limit_is_respected() {
utilities::logging();
test "redirect limit is respected" {
let m1 = mock("GET", "/")
.with_status(301)
.with_header("Location", "/b")
.create();

let server = utilities::server::spawn(|request| {
let count = request.raw_url()[1..].parse::<u32>().unwrap();
let m2 = mock("GET", "/b")
.with_status(301)
.with_header("Location", "/")
.create();

rouille::Response::redirect_301(format!("/{}", count + 1))
});
let result = Request::get(server_url())
.redirect_policy(RedirectPolicy::Limit(5))
.body(())
.unwrap()
.send();

let result = Request::get(format!("{}/0", server.endpoint()))
.redirect_policy(RedirectPolicy::Limit(5))
.body(())
.map_err(Into::into)
.and_then(chttp::send);
// Request should error with too many redirects.
assert!(match result {
Err(chttp::Error::TooManyRedirects) => true,
_ => false,
});

// Request should error with too many redirects.
assert!(match result {
Err(chttp::Error::TooManyRedirects) => true,
_ => false,
});
// After request (limit + 1) that returns a redirect should error.
m1.expect(3);
m2.expect(3);
}
}
45 changes: 27 additions & 18 deletions tests/response.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
use utilities::rouille;
use mockito::{mock, server_url};

mod utilities;
mod utils;

#[test]
fn simple_response_body() {
utilities::logging();
speculate::speculate! {
before {
utils::logging();
}

let server = utilities::server::spawn(|_| rouille::Response::text("hello world"));
test "simple response body" {
let mock = mock("GET", "/")
.with_body("hello world")
.create();

let mut response = chttp::get(server.endpoint()).unwrap();
let response_text = response.body_mut().text().unwrap();
assert_eq!(response_text, "hello world");
}
let mut response = chttp::get(server_url()).unwrap();
let response_text = response.body_mut().text().unwrap();
assert_eq!(response_text, "hello world");

mock.assert();
}

test "large response body" {
let body = "wow so large ".repeat(1000);

#[test]
fn large_response_body() {
utilities::logging();
let mock = mock("GET", "/")
.with_body(&body)
.create();

let server =
utilities::server::spawn(|_| rouille::Response::text("wow so large ".repeat(1000)));
let mut response = chttp::get(server_url()).unwrap();
let response_text = response.body_mut().text().unwrap();
assert_eq!(response_text, body);

let mut response = chttp::get(server.endpoint()).unwrap();
let response_text = response.body_mut().text().unwrap();
assert_eq!(response_text, "wow so large ".repeat(1000));
mock.assert();
}
}
53 changes: 30 additions & 23 deletions tests/timeouts.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
use chttp::prelude::*;
use std::thread;
use mockito::{mock, server_url};
use std::thread::sleep;
use std::time::Duration;
use utilities::rouille;

mod utilities;
mod utils;

/// Issue #3
#[test]
fn request_errors_if_read_timeout_is_reached() {
utilities::logging();
speculate::speculate! {
before {
utils::logging();
}

// Spawn a slow server.
let server = utilities::server::spawn(|_| {
thread::sleep(Duration::from_secs(3));
rouille::Response::text("hello world")
});
/// Issue #3
test "request errors if read timeout is reached" {
// Spawn a slow server.
let m = mock("POST", "/")
.with_body_from_fn(|_| {
sleep(Duration::from_millis(500));
Ok(())
})
.create();

// Send a request with a timeout.
let result = Request::post(server.endpoint())
.timeout(Duration::from_secs(2))
.body("hello world")
.map_err(Into::into)
.and_then(chttp::send);
// Send a request with a timeout.
let result = Request::post(server_url())
.timeout(Duration::from_millis(100))
.body("hello world")
.unwrap()
.send();

// Client should time-out.
assert!(match result {
Err(chttp::Error::Timeout) => true,
_ => false,
});
// Client should time-out.
assert!(match result {
Err(chttp::Error::Timeout) => true,
_ => false,
});

m.assert();
}
}
56 changes: 0 additions & 56 deletions tests/utilities/server.rs

This file was deleted.

4 changes: 0 additions & 4 deletions tests/utilities/mod.rs → tests/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
use std::env;
use std::sync::Once;

pub use rouille;

pub mod server;

pub fn logging() {
static ONCE: Once = Once::new();

Expand Down

0 comments on commit 821f8e4

Please sign in to comment.