Skip to content

Commit

Permalink
feat: add e2e tests to check different examples are working properly (#…
Browse files Browse the repository at this point in the history
…134)

* feat: add e2e tests to check different examples are working properly

* feat: make e2e timeouts configurable on the CI

* feat: use wws release binary when available on e2e tests

* feat: add ruby and python e2e tests. Reuse wws release from cache

* format: improve E2E_WAITING_TIME load

Co-authored-by: Rafael Fernández López <[email protected]>

---------

Co-authored-by: Rafael Fernández López <[email protected]>
  • Loading branch information
Angelmmiguel and ereslibre authored May 25, 2023
1 parent 40c6405 commit feedff9
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 10 deletions.
20 changes: 11 additions & 9 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ jobs:
run: cargo fmt --check
- name: Clippy
run: cargo clippy -- -D warnings
test:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
Expand All @@ -42,11 +42,13 @@ jobs:
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install Wasm32-wasi target
run: rustup target add wasm32-wasi
- name: Build Rust examples
working-directory: ./examples
run: make all
- name: Build wws on release mode
if: steps.check_file_release.outputs.files_exists != 'true'
run: cargo build --verbose --release
- name: Test
run: cargo test --workspace --exclude wasm-workers-quick-js-engine
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: cargo build --verbose
run: cargo test --workspace --exclude wasm-workers-quick-js-engine -- --show-output
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ wws-router = { workspace = true }
wws-server = { workspace = true }
wws-runtimes-manager = { workspace = true }

[dev-dependencies]
reqwest = { version = "0.11", features = ["blocking"] }

[target.x86_64-unknown-linux-musl.dependencies]
openssl = { version = "=0.10.48", features = ["vendored"] }

Expand Down
2 changes: 1 addition & 1 deletion examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ pdf-create:
cargo build --target wasm32-wasi --release && \
mv target/wasm32-wasi/release/pdf-create.wasm ./index.wasm

all: rust-basic rust-kv rust-params pdf-create
all: rust-basic rust-kv rust-params
44 changes: 44 additions & 0 deletions examples/ruby-basic/.wws.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
version = 1

[[repositories]]
name = "wasmlabs"
url = "https://workers.wasmlabs.dev/repository/v1/index.toml"

[[repositories.runtimes]]
name = "ruby"
version = "3.2.0+20230215-1"
tags = [
"latest",
"3.2",
"3.2.0",
]
status = "active"
extensions = ["rb"]
args = [
"--",
"/src/index.rb",
]

[repositories.runtimes.binary]
url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/ruby%2F3.2.0%2B20230215-1349da9/ruby-3.2.0.wasm"
filename = "ruby.wasm"

[repositories.runtimes.binary.checksum]
type = "sha256"
value = "abe348fba157a756f86194be445c77c99e8ed64ca76495ea07ed984f09eb66ae"

[repositories.runtimes.polyfill]
url = "https://workers.wasmlabs.dev/repository/v1/files/ruby/3-1/poly.rb"
filename = "poly.rb"

[repositories.runtimes.polyfill.checksum]
type = "sha256"
value = "449855a5d315879ab0ad830aa6a3f689e68fed4490617ea03efc77c9da64f630"

[repositories.runtimes.wrapper]
url = "https://workers.wasmlabs.dev/repository/v1/files/ruby/3-1/wrapper.txt"
filename = "wrapper.txt"

[repositories.runtimes.wrapper.checksum]
type = "sha256"
value = "6d808b4747cf30f82665a38a47e1176513bbdd6ad558c09db03d719e33ad2da0"
163 changes: 163 additions & 0 deletions tests/e2e.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#[cfg(test)]
mod test {
use std::path::PathBuf;
use std::process::{Child, Command, Stdio};
use std::{env, io, thread, time};

#[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")
} else {
path.join("target/debug/wws")
};

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")
} else {
path.join("target/debug/wws.exe")
};

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

wws_path
}

fn run(example_path: &str) -> io::Result<Child> {
let path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let example_path = path.join("examples").join(example_path);
let wws_path = get_wws_path();

// Install missing runtimes
println!("[E2E] Installing missing runtimes");
Command::new(&wws_path)
.current_dir(&example_path)
.args(["runtimes", "install"])
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.status()?;

// Run the example
println!("[E2E] Running the service");
Command::new(&wws_path).arg(&example_path).spawn()
}

fn sleep_for(seconds: u64) {
thread::sleep(time::Duration::from_secs(seconds));
}

fn request_body(url: &str) -> Result<String, reqwest::Error> {
reqwest::blocking::get(url)?.text()
}

// Check the examples/js-json works
fn run_end_to_end_test(example: &str, waiting_seconds: u64, url: &str, expected_text: &str) {
println!("[E2E] Running example: {example}");

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

sleep_for(waiting_seconds);

let body = match request_body(url) {
Ok(body) => body,
Err(err) => {
eprintln!("[E2E] Error getting the body from the request to {url}");
eprintln!("[E2E] Error: {}", err);
String::new()
}
};

println!("[E2E] Body content: {body}");

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

// Test
assert!(body.contains(expected_text));
}

#[test]
// Use this approach to run tests sequentially
fn test_end_to_end() {
// Allow configuring waiting times. It avoids having long waiting times
// in development, while making it configurable in the CI
let global_timeout =
env::var("E2E_WAITING_TIME").map_or(None, |str| str.parse::<u64>().ok());

// env (Result(String)) -> map ()

let tests = [
(
"rust-basic",
global_timeout.unwrap_or(5),
"http://localhost:8080/basic",
"This page was generated by a Wasm module built from Rust",
),
(
"rust-kv",
global_timeout.unwrap_or(5),
"http://localhost:8080/kv",
"Counter: 0",
),
(
"rust-params",
global_timeout.unwrap_or(5),
"http://localhost:8080/thisisatest",
"thisisatest",
),
(
"js-basic",
global_timeout.unwrap_or(5),
"http://localhost:8080",
"This page was generated by a JavaScript file",
),
(
"js-json",
global_timeout.unwrap_or(5),
"http://localhost:8080/handler",
"This message comes from an environment variable",
),
(
"js-params",
global_timeout.unwrap_or(10),
"http://localhost:8080/thisisatest",
"thisisatest",
),
(
"python-basic",
global_timeout.unwrap_or(20),
"http://localhost:8080/",
"This page was generated by a Python script",
),
(
"python-mount",
global_timeout.unwrap_or(20),
"http://localhost:8080/",
"This page was loaded from a mounted file",
),
(
"ruby-basic",
global_timeout.unwrap_or(20),
"http://localhost:8080/",
"This page was generated by a Ruby script",
),
];

for (example, waiting_seconds, url, expected_text) in tests {
run_end_to_end_test(example, waiting_seconds, url, expected_text);
}
}
}

0 comments on commit feedff9

Please sign in to comment.