✅ test: add tests for scraper API test endpoint
parent
0737edd8f8
commit
9c7b2b7a86
|
@ -102,7 +102,7 @@ pub async fn handle_scraper_api (
|
||||||
#[cfg (test)]
|
#[cfg (test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryFrom,
|
convert::{TryFrom, TryInto},
|
||||||
};
|
};
|
||||||
|
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
@ -112,22 +112,79 @@ mod tests {
|
||||||
};
|
};
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[derive (Clone)]
|
||||||
fn auth () {
|
struct TestCase {
|
||||||
let input = Request::builder ()
|
// 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")
|
.method ("GET")
|
||||||
.uri ("http://127.0.0.1:4000/scraper/v1/test")
|
.uri (format! ("http://127.0.0.1:4000/scraper/{}", self.path_rest));
|
||||||
.header ("X-ApiKey", "bogus")
|
|
||||||
.body (Body::empty ())
|
if let Some (input_key) = self.input_key {
|
||||||
.unwrap ();
|
input = input.header ("X-ApiKey", input_key);
|
||||||
|
}
|
||||||
|
let input = input.body (Body::empty ()).unwrap ();
|
||||||
|
|
||||||
let config_file = config::file::Config {
|
let config_file = config::file::Config {
|
||||||
port: Some (4000),
|
port: Some (4000),
|
||||||
servers: vec! [],
|
servers: vec! [],
|
||||||
iso: config::file::Isomorphic {
|
iso: config::file::Isomorphic {
|
||||||
enable_scraper_auth: true,
|
enable_scraper_auth: true,
|
||||||
dev_mode: Some (config::file::DevMode {
|
dev_mode: self.valid_key.map (|key| config::file::DevMode {
|
||||||
scraper_key: Some (key_validity::ScraperKey::new (b"bogus")),
|
scraper_key: Some (key_validity::ScraperKey::new (key.as_bytes ())),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -136,11 +193,59 @@ mod tests {
|
||||||
|
|
||||||
let relay_state = Arc::new (RelayState::try_from (config).expect ("Can't create relay state"));
|
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 mut rt = Runtime::new ().expect ("Can't create runtime for testing");
|
let mut rt = Runtime::new ().expect ("Can't create runtime for testing");
|
||||||
|
|
||||||
rt.block_on (async move {
|
rt.block_on (async move {
|
||||||
let actual = handle_scraper_api (input, relay_state, "").await;
|
let base_case = TestCase {
|
||||||
let actual = actual.expect ("Relay didn't respond");
|
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;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
src/tests.rs
22
src/tests.rs
|
@ -179,8 +179,26 @@ fn scraper_endpoints () {
|
||||||
.timeout (Duration::from_secs (2))
|
.timeout (Duration::from_secs (2))
|
||||||
.build ().expect ("Couldn't build HTTP client");
|
.build ().expect ("Couldn't build HTTP client");
|
||||||
|
|
||||||
let resp = client.get (&format! ("{}/scraper/api/test", relay_url))
|
let mut resp = None;
|
||||||
.send ().await.expect ("Couldn't check if relay is up").bytes ().await.expect ("Couldn't check if relay is up");
|
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");
|
assert_eq! (resp, "You're valid!\n");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue