use hyper::client::{Client, Response};
use hyper::method::Method;
use std::collections::HashSet;
use std::process::{Child, Command, Stdio};
use std::thread;
use std::io::{BufReader, BufRead, Read};
use std::sync::Mutex;
use std::env;
struct Bomb(Child);
impl Drop for Bomb {
fn drop(&mut self) {
match self.0.kill() {
Ok(()) => {},
Err(e) => panic!("Leaking child process: {:?}", e)
}
if thread::panicking() {
let mut s = String::new();
let stdout = self.0.stdout.as_mut().unwrap();
stdout.read_to_string(&mut s).unwrap();
println!("Unparsed Stdout:\n{}", s);
}
}
}
pub fn response_for_post(url: &str, body: &str) -> Response {
Client::new()
.post(url)
.body(body)
.send()
.unwrap()
}
pub fn response_for_method(method: Method, url: &str) -> Response {
Client::new()
.request(method, url)
.send()
.unwrap()
}
pub fn response_for(url: &str) -> Response {
response_for_method(Method::Get, url)
}
pub fn read_body_to_string(res: &mut Response) -> String {
let mut s = String::new();
res.read_to_string(&mut s).unwrap();
s
}
pub fn read_url(url: &str) -> String {
let mut res = response_for(url);
read_body_to_string(&mut res)
}
pub fn run_example<F>(name: &str, f: F)
where F: FnOnce(u16) {
cargo_build(name);
let command = format!("target/debug/examples/{}", name);
let child = Command::new(&command)
.env("NICKEL_TEST_HARNESS", "1")
.stdout(Stdio::piped())
.spawn()
.unwrap();
let mut bomb = Bomb(child);
let port = parse_port(&mut bomb);
f(port);
}
fn cargo_build(name: &str) {
let mut built_set = BUILD_LOCK.lock().expect("Failed to get build lock");
if !built_set.insert(name.to_owned()) {
return
}
let mut command = Command::new("cargo");
command.env("NICKEL_TEST_HARNESS", "1")
.stdout(Stdio::piped())
.arg("build")
.arg("--example")
.arg(name);
if let Some(arg) = env::var("FEATURES").ok() {
for feature_arg in arg.split_whitespace() {
command.arg(feature_arg);
}
}
let mut child = command.spawn().unwrap();
child.wait().unwrap();
}
lazy_static! {
static ref BUILD_LOCK : Mutex<HashSet<String>> = Mutex::new(HashSet::new());
}
fn parse_port(&mut Bomb(ref mut process): &mut Bomb) -> u16 {
let stdout = BufReader::new(process.stdout.as_mut().unwrap());
let line = stdout.lines()
.map(Result::unwrap)
.inspect(|line| println!("Processing Stdout: {:?}", line))
.filter(|line| line.starts_with("Listening"))
.next()
.expect("Didn't find a line from stdout");
let port = line.rsplitn(2, ':')
.next()
.and_then(|s| s.parse().ok())
.expect(&format!("Failed to parse port from {:?}", line));
println!("Parsed: port={} from {:?}", port, line);
port
}