Skip to content

Commit

Permalink
doc(examples): flesh out the integration test example with a dummy da…
Browse files Browse the repository at this point in the history
…tabase
  • Loading branch information
Ryman committed May 18, 2016
1 parent 80f8a17 commit 28eb6e2
Showing 1 changed file with 95 additions and 12 deletions.
107 changes: 95 additions & 12 deletions examples/integration_testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,76 @@ use std::error::Error as StdError;
use std::{env, str};
use std::sync::atomic::{self, AtomicUsize};

// Example trait to allow custom databases to be used within the integration tests
// to test different behaviours without touching a real database.
trait Database : Send + Sync + 'static {
fn get_users(&self) -> Vec<String>;
}

impl Database for Vec<String> {
fn get_users(&self) -> Vec<String> {
self.clone()
}
}

struct ServerData {
hits: AtomicUsize,

// FIXME: The `middleware` macro typehinting doesn't support hinting with
// typeparams, i.e. the hint can't be `< ServerData<T> >` where T is a
// typeparam from the enclosing function, e.g. `start_server`.
//
// To counter this limitation, we've boxed the trait so that specifying the
// typeparam is unnecessary.
database: Box<Database>
}

impl ServerData {
fn hitcount(&self) -> usize {
self.hits.load(atomic::Ordering::Relaxed)
}

fn log_hit(&self) -> usize {
self.hits.fetch_add(1, atomic::Ordering::Relaxed)
}

fn get_users(&self) -> Vec<String> {
self.database.get_users()
}
}

fn main() {
let port = env::var("PORT").map(|s| s.parse().unwrap()).unwrap_or(3000);
let address = &format!("0.0.0.0:{}", port);
let database = vec![];

start_server(&format!("0.0.0.0:{}", port)).unwrap();
start_server(address, database).unwrap();
}

fn start_server(address: &str) -> Result<ListeningServer, Box<StdError>> {
let hits = AtomicUsize::new(0);
let mut server = Nickel::with_data(hits);
fn start_server<D>(address: &str, database: D) -> Result<ListeningServer, Box<StdError>>
where D: Database {
let server_data = ServerData {
hits: AtomicUsize::new(0),
database: Box::new(database),
};

let mut server = Nickel::with_data(server_data);

// Track all hits to the server
server.utilize(middleware! { |_req, res| <AtomicUsize>
let _hits = res.data().fetch_add(1, atomic::Ordering::Relaxed);
server.utilize(middleware! { |_req, res| <ServerData>
res.data().log_hit();
return res.next_middleware()
});

// Core server
server.get("/", middleware!( "Hello World" ));

server.get("/users", middleware! { |_, res| <ServerData>
let users = res.data().get_users();

Json::from_str(&format!(r#"{{ "users": {:?} }}"#, users)).unwrap()
});

// Json example
server.post("/", middleware! { |req, res|
#[derive(RustcEncodable, RustcDecodable)]
Expand All @@ -56,10 +107,8 @@ fn start_server(address: &str) -> Result<ListeningServer, Box<StdError>> {
});

// Get the hitcount
server.get("/hits", middleware!{ |_req, res| <AtomicUsize>
let hits = res.data().load(atomic::Ordering::Relaxed);

hits.to_string()
server.get("/hits", middleware!{ |_req, res| <ServerData>
res.data().hitcount().to_string()
});

server.listen(address)
Expand Down Expand Up @@ -135,13 +184,47 @@ mod tests {
#[test]
fn non_shared_server() {
let test_local_server = {
let server = super::start_server("127.0.0.1:0").unwrap();
let server = super::start_server("127.0.0.1:0", vec![]).unwrap();
Server::new(server)
};

assert_eq!(get_hits_after_delay(&test_local_server), 1);
}

#[test]
fn has_no_users_by_default() {
let mut response = get("/users");

let json = Json::from_str(&response.body()).unwrap();

assert_eq!(json["users"].as_array().unwrap().len(), 0);
assert_eq!(response.status, StatusCode::Ok);
assert_eq!(
response.headers.get::<header::ContentType>(),
Some(&header::ContentType::json())
);
}

#[test]
fn non_shared_server_with_different_database() {
let server = {
let bots = vec!["bors".into(), "homu".into(), "highfive".into()];
let server = super::start_server("127.0.0.1:0", bots).unwrap();
Server::new(server)
};

let mut response = server.get("/users");

let json = Json::from_str(&response.body()).unwrap();

assert_eq!(json["users"].as_array().unwrap().len(), 3);
assert_eq!(response.status, StatusCode::Ok);
assert_eq!(
response.headers.get::<header::ContentType>(),
Some(&header::ContentType::json())
);
}

mod support {
use hyper::client::{Client, Response as HyperResponse};
use nickel::ListeningServer;
Expand Down Expand Up @@ -192,7 +275,7 @@ mod tests {
lazy_static! {
/// This is a shared instance of the server between all the tests
pub static ref STATIC_SERVER: Server = {
let server = super::super::start_server("127.0.0.1:0").unwrap();
let server = super::super::start_server("127.0.0.1:0", vec![]).unwrap();
Server::new(server)
};
}
Expand Down

0 comments on commit 28eb6e2

Please sign in to comment.