Skip to content

Commit

Permalink
feat: add more e2e tests to validate static assets
Browse files Browse the repository at this point in the history
  • Loading branch information
Angelmmiguel committed Oct 5, 2023
1 parent d786339 commit b13b09b
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 18 deletions.
2 changes: 2 additions & 0 deletions examples/js-json/public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
User-agent: *
Disallow: /
3 changes: 2 additions & 1 deletion examples/js-params/public/main.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* This is just a comment for testing purposes */
body {
max-width: 1000px;
}
Expand Down Expand Up @@ -25,4 +26,4 @@ pre>code {

p {
margin-top: 2rem;
}
}
115 changes: 98 additions & 17 deletions tests/e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,25 @@ mod test {
use std::time::Instant;
use std::{env, io};

use reqwest::StatusCode;

// Default timeout when waiting for wws to be ready
static DEFAULT_MAX_TIMEOUT: u64 = 30;

#[cfg(not(target_os = "windows"))]
fn get_wws_path() -> PathBuf {
let path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());

// Use release when it's available
let wws_path = if path.join("target/release/wws").exists() {
path.join("target/release/wws")
let binary = if cfg!(target_os = "windows") {
"wws"
} else {
path.join("target/debug/wws")
"wws.exe"
};

println!("[E2E] Running wws from {}", wws_path.display());

wws_path
}

#[cfg(target_os = "windows")]
fn get_wws_path() -> PathBuf {
let path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());

// Use release when it's available
let wws_path = if path.join("target/release/wws.exe").exists() {
path.join("target/release/wws.exe")
let wws_path = if path.join("target/release").join(binary).exists() {
path.join("target/release").join(binary)
} else {
path.join("target/debug/wws.exe")
path.join("target/debug").join(binary)
};

println!("[E2E] Running wws from {}", wws_path.display());
Expand Down Expand Up @@ -87,6 +78,10 @@ mod test {
reqwest::blocking::get(url)?.text()
}

fn request_status(url: &str) -> Result<StatusCode, reqwest::Error> {
Ok(reqwest::blocking::get(url)?.status())
}

// Check the examples/js-json works
fn run_end_to_end_test(example: &str, max_timeout: u64, url: &str, expected_text: &str) {
println!("[E2E] Running example: {example}");
Expand Down Expand Up @@ -116,6 +111,40 @@ mod test {
);
}

/// Runs the given example and ensures it returns a 404 error.
fn run_not_found_test(example: &str, max_timeout: u64, urls: &[&str]) {
println!("[E2E] Running example (not found): {example}");
let mut codes = Vec::new();

let mut child = run(example, max_timeout).expect("Failed to execute command");

for url in urls {
let code = match request_status(url) {
Ok(code) => code,
Err(err) => {
eprintln!("[E2E] Error getting the StatusCode from the request to {url}");
eprintln!("[E2E] Error: {}", err);

// Make it fail
StatusCode::FOUND
}
};

codes.push((url, code));

println!("[E2E] URL: {url} / Status code: {code}");
}

println!("[E2E] Stopping wws process [{}]", &child.id());
child.kill().expect("Error stopping wws");

// Assert all of them at the same time to avoid leaving an instance running
for (_url, code) in codes {
// Test
assert!(matches!(code, StatusCode::NOT_FOUND));
}
}

#[test]
// Use this approach to run tests sequentially
fn test_end_to_end() {
Expand Down Expand Up @@ -172,6 +201,11 @@ mod test {
"http://localhost:8080/thisisatest",
"thisisatest",
),
(
"js-params",
"http://localhost:8080/main.css",
"This is just a comment for testing purposes",
),
(
"python-basic",
"http://localhost:8080/",
Expand All @@ -193,4 +227,51 @@ mod test {
run_end_to_end_test(example, max_timeout, url, expected_text);
}
}

#[test]
fn test_not_found_examples() {
// Allow configuring waiting times. It avoids having long waiting times
// in development, while making it configurable in the CI
let max_timeout = env::var("E2E_MAX_WAITING_TIME").map_or(DEFAULT_MAX_TIMEOUT, |str| {
str.parse::<u64>().ok().unwrap_or(DEFAULT_MAX_TIMEOUT)
});
let path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let cargo_toml = path.join("Cargo.toml");
let cargo_toml_str = cargo_toml.to_string_lossy().to_string();

// Test we're not exposing wrong files
let tests = [
(
"js-basic",
Vec::from([
"http://localhost:8080/index.js",
"http://localhost:8080/examples/js-basic/index.js",
"http://localhost:8080/Cargo.toml",
// Check path traversal issues
"http://localhost:8080/../README.md",
"http://localhost:8080/%C0AE%C0AE%C0AFREADME.md",
"http://localhost:8080/%2e%2e/README.md",
cargo_toml_str.as_str(),
]),
),
(
"js-json",
Vec::from([
"http://localhost:8080/handler.js",
"http://localhost:8080/examples/js-json/handler.js",
"http://localhost:8080/Cargo.toml",
"http://localhost:8080/handler.toml",
// Check path traversal issues
"http://localhost:8080/../README.md",
"http://localhost:8080/%C0AE%C0AE%C0AFREADME.md",
"http://localhost:8080/%2e%2e/README.md",
cargo_toml_str.as_str(),
]),
),
];

for (example, urls) in tests {
run_not_found_test(example, max_timeout, &urls);
}
}
}

0 comments on commit b13b09b

Please sign in to comment.