Skip to content

Commit aa6bce1

Browse files
authored
Merge pull request #1162 from rajatjindal/redis-trigger-test1
add e2e tests for redis trigger
2 parents 885434f + fd8404a commit aa6bce1

File tree

14 files changed

+655
-238
lines changed

14 files changed

+655
-238
lines changed

Cargo.lock

Lines changed: 36 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/e2e-testing/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ hyper = { version = "0.14", features = [ "full" ] }
1515
regex = "1.5.5"
1616
reqwest = { version = "0.11", features = ["blocking"] }
1717
nix = "0.26.1"
18-
url = "2.2.2"
18+
url = "2.2.2"
19+
derive_builder = "0.12.0"
20+
hyper-tls = "0.5.0"

crates/e2e-testing/src/asserts.rs

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
use anyhow::Result;
2+
use hyper::client::HttpConnector;
3+
use hyper::{body, Body, Client, Request, Response};
4+
use hyper_tls::HttpsConnector;
5+
use std::str;
26

3-
pub fn assert_status(url: &str, expected: u16) -> Result<()> {
4-
let resp = req(url)?;
7+
pub async fn assert_status(url: &str, expected: u16) -> Result<()> {
8+
let resp = make_request("GET", url, "").await?;
59
let status = resp.status();
6-
let body = resp.text()?;
7-
assert_eq!(status, expected, "{}", body);
10+
11+
let response = body::to_bytes(resp.into_body()).await.unwrap().to_vec();
12+
let actual_body = str::from_utf8(&response).unwrap().to_string();
13+
14+
assert_eq!(status, expected, "{}", actual_body);
15+
816
Ok(())
917
}
1018

11-
pub fn assert_http_response(
19+
pub async fn assert_http_response(
1220
url: &str,
1321
expected: u16,
1422
expected_headers: &[(&str, &str)],
1523
expected_body: Option<&str>,
1624
) -> Result<()> {
17-
let res = req(url)?;
25+
let res = make_request("GET", url, "").await?;
1826

1927
let status = res.status();
2028
assert_eq!(expected, status.as_u16());
@@ -31,14 +39,33 @@ pub fn assert_http_response(
3139
}
3240

3341
if let Some(expected_body_str) = expected_body {
34-
let body = &res.text()?;
35-
assert_eq!(expected_body_str, body);
42+
let response = body::to_bytes(res.into_body()).await.unwrap().to_vec();
43+
let actual_body = str::from_utf8(&response).unwrap().to_string();
44+
assert_eq!(expected_body_str, actual_body);
3645
}
3746

3847
Ok(())
3948
}
4049

41-
fn req(url: &str) -> reqwest::Result<reqwest::blocking::Response> {
42-
println!("{}", url);
43-
reqwest::blocking::get(url)
50+
pub async fn create_request(method: &str, url: &str, body: &str) -> Result<Request<Body>> {
51+
let req = Request::builder()
52+
.method(method)
53+
.uri(url)
54+
.body(Body::from(body.to_string()))
55+
.expect("request builder");
56+
57+
Ok(req)
58+
}
59+
60+
pub fn create_client() -> Client<HttpsConnector<HttpConnector>> {
61+
let connector = HttpsConnector::new();
62+
Client::builder().build::<_, hyper::Body>(connector)
63+
}
64+
65+
pub async fn make_request(method: &str, path: &str, body: &str) -> Result<Response<Body>> {
66+
let c = create_client();
67+
let req = create_request(method, path, body);
68+
69+
let resp = c.request(req.await?).await.unwrap();
70+
Ok(resp)
4471
}

crates/e2e-testing/src/controller.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use crate::metadata_extractor::AppMetadata;
22
use anyhow::Result;
33
use async_trait::async_trait;
44
use std::process::Output;
5+
use tokio::io::BufReader;
6+
use tokio::process::{ChildStderr, ChildStdout};
57

68
/// defines crate::controller::Controller trait
79
/// this is to enable running same set of tests
@@ -11,10 +13,15 @@ pub trait Controller {
1113
fn name(&self) -> String;
1214
fn login(&self) -> Result<()>;
1315
fn template_install(&self, args: Vec<&str>) -> Result<Output>;
14-
fn new_app(&self, template_name: &str, app_name: &str) -> Result<Output>;
16+
fn new_app(&self, template_name: &str, app_name: &str, args: Vec<&str>) -> Result<Output>;
1517
fn build_app(&self, app_name: &str) -> Result<Output>;
1618
fn install_plugins(&self, plugins: Vec<&str>) -> Result<Output>;
17-
async fn run_app(&self, app_name: &str) -> Result<AppInstance>;
19+
async fn run_app(
20+
&self,
21+
app_name: &str,
22+
trigger_type: &str,
23+
mut args: Vec<&str>,
24+
) -> Result<AppInstance>;
1825
async fn stop_app(
1926
&self,
2027
app_name: Option<&str>,
@@ -27,20 +34,43 @@ pub trait Controller {
2734
pub struct AppInstance {
2835
pub metadata: AppMetadata,
2936
pub process: Option<tokio::process::Child>,
37+
pub stdout_stream: Option<BufReader<ChildStdout>>,
38+
pub stderr_stream: Option<BufReader<ChildStderr>>,
3039
}
3140

3241
impl AppInstance {
3342
pub fn new(metadata: AppMetadata) -> AppInstance {
3443
AppInstance {
3544
metadata,
3645
process: None,
46+
stdout_stream: None,
47+
stderr_stream: None,
3748
}
3849
}
3950

4051
pub fn new_with_process(
4152
metadata: AppMetadata,
4253
process: Option<tokio::process::Child>,
4354
) -> AppInstance {
44-
AppInstance { metadata, process }
55+
AppInstance {
56+
metadata,
57+
process,
58+
stdout_stream: None,
59+
stderr_stream: None,
60+
}
61+
}
62+
63+
pub fn new_with_process_and_logs_stream(
64+
metadata: AppMetadata,
65+
process: Option<tokio::process::Child>,
66+
stdout_stream: Option<BufReader<ChildStdout>>,
67+
stderr_stream: Option<BufReader<ChildStderr>>,
68+
) -> AppInstance {
69+
AppInstance {
70+
metadata,
71+
process,
72+
stdout_stream,
73+
stderr_stream,
74+
}
4575
}
4676
}

crates/e2e-testing/src/spin.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,18 @@ pub fn template_install(mut args: Vec<&str>) -> Result<Output> {
2626
result
2727
}
2828

29-
pub fn new_app(template_name: &str, app_name: &str) -> Result<Output> {
29+
pub fn new_app<'a>(
30+
template_name: &'a str,
31+
app_name: &'a str,
32+
mut args: Vec<&'a str>,
33+
) -> Result<Output> {
3034
let basedir = utils::testcases_base_dir();
35+
let mut cmd = vec!["spin", "new", template_name, app_name, "--accept-defaults"];
36+
if !args.is_empty() {
37+
cmd.append(&mut args);
38+
}
3139

32-
return utils::run(
33-
vec!["spin", "new", template_name, app_name, "--accept-defaults"],
34-
Some(basedir.as_str()),
35-
None,
36-
);
40+
return utils::run(cmd, Some(basedir.as_str()), None);
3741
}
3842

3943
pub fn install_plugins(plugins: Vec<&str>) -> Result<Output> {
@@ -69,7 +73,7 @@ pub fn appdir(appname: &str) -> String {
6973
#[cfg(target_family = "unix")]
7074
pub async fn stop_app_process(process: &mut tokio::process::Child) -> Result<(), anyhow::Error> {
7175
let pid = process.id().unwrap();
72-
println!("stopping app with pid {}", pid);
76+
// println!("stopping app with pid {}", pid);
7377
let pid = Pid::from_raw(pid as i32);
7478
kill(pid, Signal::SIGINT).map_err(anyhow::Error::msg)
7579
}

crates/e2e-testing/src/spin_controller.rs

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::utils;
55
use anyhow::Result;
66
use async_trait::async_trait;
77
use std::process::Output;
8+
use tokio::io::BufReader;
89

910
pub struct SpinUp {}
1011

@@ -24,8 +25,8 @@ impl Controller for SpinUp {
2425
spin::template_install(args)
2526
}
2627

27-
fn new_app(&self, template_name: &str, app_name: &str) -> Result<Output> {
28-
spin::new_app(template_name, app_name)
28+
fn new_app(&self, template_name: &str, app_name: &str, args: Vec<&str>) -> Result<Output> {
29+
spin::new_app(template_name, app_name, args)
2930
}
3031

3132
fn install_plugins(&self, plugins: Vec<&str>) -> Result<Output> {
@@ -36,34 +37,55 @@ impl Controller for SpinUp {
3637
spin::build_app(app_name)
3738
}
3839

39-
async fn run_app(&self, app_name: &str) -> Result<AppInstance> {
40+
async fn run_app(
41+
&self,
42+
app_name: &str,
43+
trigger_type: &str,
44+
mut xargs: Vec<&str>,
45+
) -> Result<AppInstance> {
4046
let appdir = spin::appdir(app_name);
4147

42-
let port = utils::get_random_port()?;
43-
let address = format!("127.0.0.1:{}", port);
48+
let mut cmd = vec!["spin", "up"];
49+
if !xargs.is_empty() {
50+
cmd.append(&mut xargs);
51+
}
52+
53+
let mut address = "".to_string();
54+
if trigger_type == "http" {
55+
let port = utils::get_random_port()?;
56+
address = format!("127.0.0.1:{}", port);
57+
cmd.append(&mut vec!["--listen", address.as_str()]);
58+
}
59+
60+
let mut child = utils::run_async(cmd, Some(&appdir), None);
4461

45-
let mut child = utils::run_async(
46-
vec!["spin", "up", "--listen", &address],
47-
Some(&appdir),
48-
None,
49-
);
62+
if trigger_type == "http" {
63+
// ensure the server is accepting requests before continuing.
64+
utils::wait_tcp(&address, &mut child, "spin").await?;
65+
}
5066

51-
// ensure the server is accepting requests before continuing.
52-
utils::wait_tcp(&address, &mut child, "spin").await?;
67+
let stdout = child
68+
.stdout
69+
.take()
70+
.expect("child did not have a handle to stdout");
71+
let stdout_stream = BufReader::new(stdout);
5372

54-
match utils::get_output(&mut child).await {
55-
Ok(output) => print!("this output is {:?} until here", output),
56-
Err(error) => panic!("problem running app {:?}", error),
57-
};
73+
let stderr = child
74+
.stderr
75+
.take()
76+
.expect("child did not have a handle to stderr");
77+
let stderr_stream = BufReader::new(stderr);
5878

59-
Ok(AppInstance::new_with_process(
79+
Ok(AppInstance::new_with_process_and_logs_stream(
6080
AppMetadata {
6181
name: app_name.to_string(),
6282
base: format!("http://{}", address),
6383
app_routes: vec![],
6484
version: "".to_string(),
6585
},
6686
Some(child),
87+
Some(stdout_stream),
88+
Some(stderr_stream),
6789
))
6890
}
6991

0 commit comments

Comments
 (0)