test: add tests for scraper API test endpoint

main
_ 2020-12-13 04:44:37 +00:00
parent 0737edd8f8
commit 9c7b2b7a86
2 changed files with 150 additions and 27 deletions

View File

@ -102,7 +102,7 @@ pub async fn handle_scraper_api (
#[cfg (test)]
mod tests {
use std::{
convert::TryFrom,
convert::{TryFrom, TryInto},
};
use tokio::runtime::Runtime;
@ -112,35 +112,140 @@ mod tests {
};
use super::*;
#[derive (Clone)]
struct TestCase {
// Inputs
path_rest: &'static str,
valid_key: Option <&'static str>,
input_key: Option <&'static str>,
// Expected
expected_status: StatusCode,
expected_headers: Vec <(&'static str, &'static str)>,
expected_body: &'static str,
}
impl TestCase {
fn path_rest (&self, v: &'static str) -> Self {
let mut x = self.clone ();
x.path_rest = v;
x
}
fn valid_key (&self, v: Option <&'static str>) -> Self {
let mut x = self.clone ();
x.valid_key = v;
x
}
fn input_key (&self, v: Option <&'static str>) -> Self {
let mut x = self.clone ();
x.input_key = v;
x
}
fn expected_status (&self, v: StatusCode) -> Self {
let mut x = self.clone ();
x.expected_status = v;
x
}
fn expected_headers (&self, v: Vec <(&'static str, &'static str)>) -> Self {
let mut x = self.clone ();
x.expected_headers = v;
x
}
fn expected_body (&self, v: &'static str) -> Self {
let mut x = self.clone ();
x.expected_body = v;
x
}
fn expected (&self, sc: StatusCode, body: &'static str) -> Self {
self
.expected_status (sc)
.expected_body (body)
}
async fn test (&self) {
let mut input = Request::builder ()
.method ("GET")
.uri (format! ("http://127.0.0.1:4000/scraper/{}", self.path_rest));
if let Some (input_key) = self.input_key {
input = input.header ("X-ApiKey", input_key);
}
let input = input.body (Body::empty ()).unwrap ();
let config_file = config::file::Config {
port: Some (4000),
servers: vec! [],
iso: config::file::Isomorphic {
enable_scraper_auth: true,
dev_mode: self.valid_key.map (|key| config::file::DevMode {
scraper_key: Some (key_validity::ScraperKey::new (key.as_bytes ())),
}),
},
};
let config = config::Config::try_from (config_file).expect ("Can't load config");
let relay_state = Arc::new (RelayState::try_from (config).expect ("Can't create relay state"));
let actual = handle_scraper_api (input, relay_state, self.path_rest).await;
let actual = actual.expect ("Relay didn't respond");
let (actual_head, actual_body) = actual.into_parts ();
let mut expected_headers = hyper::header::HeaderMap::new ();
for (key, value) in &self.expected_headers {
expected_headers.insert (*key, (*value).try_into ().expect ("Couldn't convert header value"));
}
assert_eq! (actual_head.status, self.expected_status);
assert_eq! (actual_head.headers, expected_headers);
let actual_body = hyper::body::to_bytes (actual_body).await;
let actual_body = actual_body.expect ("Body should be convertible to bytes");
let actual_body = actual_body.to_vec ();
let actual_body = String::from_utf8 (actual_body).expect ("Body should be UTF-8");
assert_eq! (&actual_body, self.expected_body);
}
}
#[test]
fn auth () {
let input = Request::builder ()
.method ("GET")
.uri ("http://127.0.0.1:4000/scraper/v1/test")
.header ("X-ApiKey", "bogus")
.body (Body::empty ())
.unwrap ();
let config_file = config::file::Config {
port: Some (4000),
servers: vec! [],
iso: config::file::Isomorphic {
enable_scraper_auth: true,
dev_mode: Some (config::file::DevMode {
scraper_key: Some (key_validity::ScraperKey::new (b"bogus")),
}),
},
};
let config = config::Config::try_from (config_file).expect ("Can't load config");
let relay_state = Arc::new (RelayState::try_from (config).expect ("Can't create relay state"));
let mut rt = Runtime::new ().expect ("Can't create runtime for testing");
rt.block_on (async move {
let actual = handle_scraper_api (input, relay_state, "").await;
let actual = actual.expect ("Relay didn't respond");
let base_case = TestCase {
path_rest: "v1/test",
valid_key: Some ("bogus"),
input_key: Some ("bogus"),
expected_status: StatusCode::OK,
expected_headers: vec! [
("content-type", "text/plain"),
],
expected_body: "You're valid!\n",
};
for case in &[
base_case.clone (),
base_case.path_rest ("v9999/test")
.expected (StatusCode::NOT_FOUND, "Unknown scraper API version\n"),
base_case.valid_key (None)
.expected (StatusCode::FORBIDDEN, "403 Forbidden\n"),
base_case.input_key (Some ("borgus"))
.expected (StatusCode::FORBIDDEN, "403 Forbidden\n"),
base_case.path_rest ("v1/toast")
.expected (StatusCode::NOT_FOUND, "Unknown API endpoint\n"),
base_case.input_key (None)
.expected (StatusCode::FORBIDDEN, "Can't run scraper without an API key\n"),
] {
case.test ().await;
}
});
}
}

View File

@ -179,8 +179,26 @@ fn scraper_endpoints () {
.timeout (Duration::from_secs (2))
.build ().expect ("Couldn't build HTTP client");
let resp = client.get (&format! ("{}/scraper/api/test", relay_url))
.send ().await.expect ("Couldn't check if relay is up").bytes ().await.expect ("Couldn't check if relay is up");
let mut resp = None;
for _ in 0usize..5 {
let x = client.get (&format! ("{}/scraper/api/test", relay_url))
.send ().await;
match x {
Err (_) => {
// Probably a reqwest error cause the port is in
// use or something. Try again.
()
},
Ok (x) => {
resp = Some (x);
break;
},
};
delay_for (Duration::from_millis (200)).await;
}
let resp = resp.expect ("Reqwest repeatedly failed to connect to the relay");
let resp = resp.bytes ().await.expect ("Couldn't check if relay is up");
assert_eq! (resp, "You're valid!\n");