Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(wasm): Wasm Integration Tests working in CI #197

Merged
merged 28 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c09d4f9
fix(wasm): Fix running wasm integration tests
stevenj Apr 4, 2024
0292329
fix(wasm): Make logging work inside the wasm integration tests
stevenj Apr 4, 2024
a137743
feat(wasm): working hashing integration test
stevenj Apr 4, 2024
99060a4
ci(wasm): align rust builds with cat-ci latest version
stevenj Apr 4, 2024
33ef281
feat(wasm): Add crypto wasm integration tests
stevenj Apr 4, 2024
1a60add
fix(hermes): Re-enable hermes full build after getting wasm integrati…
stevenj Apr 4, 2024
4511f44
fix(wasm): silence the initial print inside wasm integration tests to…
stevenj Apr 4, 2024
c476900
fix(wasm): remove unused import after silencing the wasm integration …
stevenj Apr 4, 2024
708ee9d
Merge branch 'main' into feat/verbose-rust-unit-tests
stevenj Apr 4, 2024
4943b76
style(hermes): Fix code format
stevenj Apr 4, 2024
922acd8
Merge branch 'feat/verbose-rust-unit-tests' of github.com:input-outpu…
stevenj Apr 4, 2024
ea6a2ef
fix(spelling): spelling issue
stevenj Apr 4, 2024
f4619f2
fix(cbork): Align deny,toml with CI
stevenj Apr 4, 2024
89d43f1
fix(wasm): Align deny.toml with CI
stevenj Apr 4, 2024
e3f4e50
Update hermes/bin/src/runtime_extensions/hermes/crypto/host.rs
stevenj Apr 5, 2024
451ae21
Update hermes/bin/src/runtime_extensions/hermes/crypto/host.rs
stevenj Apr 5, 2024
977f09b
feat: hermes-cron integration test cases (#199)
saibatizoku Apr 5, 2024
d04e4ee
feat(warm): Add Cardano Runtime Extension integration test skeleton (…
FelipeRosa Apr 5, 2024
80cb887
fix(wasm): remove commented obsolete code
stevenj Apr 5, 2024
b82d20e
Merge branch 'feat/verbose-rust-unit-tests' of github.com:input-outpu…
stevenj Apr 5, 2024
de1c36f
Update wasm/integration-test/crypto/crypto.c
stevenj Apr 5, 2024
3894281
test: time module (#200)
apskhem Apr 8, 2024
42bf378
fix(spelling): add to project words
stevenj Apr 8, 2024
0302377
Merge branch 'main' into feat/verbose-rust-unit-tests
stevenj Apr 8, 2024
9719e75
fix(wasm): remove generated bindings, try and use autogenerated ones
stevenj Apr 8, 2024
09bcff3
Merge branch 'feat/verbose-rust-unit-tests' of github.com:input-outpu…
stevenj Apr 8, 2024
608c2c7
chore(wasm): Fix Cardano RTE wasm integration test module (#204)
FelipeRosa Apr 9, 2024
8b585ec
fix(hermes): Update rust builders to the latest
stevenj Apr 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 25 additions & 6 deletions hermes/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ VERSION 0.7

# Set up our target toolchains, and copy our files.
builder:
DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.10.3+SETUP
DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.11.0+SETUP
COPY --dir .cargo .config crates bin .
COPY Cargo.toml .
COPY clippy.toml deny.toml rustfmt.toml .

RUN mkdir /wasm
COPY --dir ../wasm+wasi-src/wasi /wasm/wasi
# Compiled WASM component for benchmarks
COPY ../wasm/c+build/component.wasm /wasm/c/bench_component.wasm
COPY ../wasm/stub-module+build/stub.wasm /wasm/stub-module/stub.wasm

# Expands `wasmtime::bindgen!` macro into the `bindings.rs` file
bindings-expand:
Expand Down Expand Up @@ -44,16 +44,35 @@ all-hosts-check:
build:
FROM +builder

# build wasm artifacts for testing
COPY (../wasm/c+build/component.wasm --c_files="integration-test.c") ../wasm/test-components/
# Directory where WASM test components go when we run wasm module integration tests.
RUN mkdir ../wasm/test-components

RUN /scripts/std_build.py --bench_flags="--features bench" \
--libs="cardano-chain-follower" \
--bins="hermes/hermes"
--bins="hermes/hermes" \
--verbose

SAVE ARTIFACT target/$TARGETARCH/doc doc
SAVE ARTIFACT target/$TARGETARCH/release/hermes hermes
SAVE ARTIFACT target/criterion
SAVE ARTIFACT target/criterion

test-wasm-integration:
FROM +build

# Copy all wasm module artifacts for testing
COPY ../wasm/integration-test/cron+build/cron.wasm ../wasm/test-components/
COPY ../wasm/integration-test/crypto+build/crypto.wasm ../wasm/test-components/
COPY ../wasm/integration-test/cardano+build/cardano.wasm ../wasm/test-components/
COPY ../wasm/integration-test/hashing+build/hashing.wasm ../wasm/test-components/
COPY ../wasm/integration-test/logger+build/logger.wasm ../wasm/test-components/
COPY ../wasm/integration-test/smoke-test+build/smoke-test.wasm ../wasm/test-components/

# List all WASM integration tests/benches and also run them.
#RUN cargo test --release --test wasm-component-integration-tests -- --help
RUN cargo test --release --test wasm-component-integration-tests -- --list
RUN cargo test --release --test wasm-component-integration-tests -- --test
RUN cargo test --release --test wasm-component-integration-tests -- --bench


# Test which runs check with all supported host tooling. Needs qemu or rosetta to run.
# Only used to validate tooling is working across host toolsets.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ mod tests_bip32_ed25519 {
#[test]
fn test_get_public_key() {
let xprv = XPrv::from_extended_and_chaincode(&XPRV1, &CHAINCODE1);
// 3986768884739312704, 9782938079688165927, 7977656244723921923, 12587033252467133758
let pubk_tuple = get_public_key(&xprv);
let pubk_hex = format!(
"{:x}{:x}{:x}{:x}",
Expand Down
11 changes: 6 additions & 5 deletions hermes/bin/src/runtime_extensions/hermes/crypto/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ impl HostBip32Ed25519 for HermesRuntimeContext {
match xprv {
Ok(xprv) => {
if let Some(id) = add_resource(self.app_name(), xprv) {
return Ok(Resource::new_own(id));
Ok(Resource::new_own(id))
} else {
// TODO(bkioshn): https://github.com/input-output-hk/hermes/issues/183
Err(wasmtime::Error::msg("Error creating new resource"))
stevenj marked this conversation as resolved.
Show resolved Hide resolved
}
},
Err(e) => return Err(wasmtime::Error::msg(e.to_string())),
};
// TODO(bkioshn): https://github.com/input-output-hk/hermes/issues/183
Err(wasmtime::Error::msg("Error creating new resource"))
Err(e) => Err(wasmtime::Error::msg(e.to_string())),
}
}

/// Get the public key for this private key.
Expand Down
2 changes: 1 addition & 1 deletion hermes/bin/src/runtime_extensions/hermes/crypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod state;
pub(crate) fn new_context(ctx: &crate::runtime_context::HermesRuntimeContext) {
// check whether it exist
let state = get_state();
if state.contains_key(ctx.app_name()) {
if !state.contains_key(ctx.app_name()) {
set_state(ctx.app_name().clone());
}
}
3 changes: 1 addition & 2 deletions hermes/bin/src/wasm/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@ pub mod bench {
}
}

let module =
Module::new(include_bytes!("../../../../wasm/c/bench_component.wasm")).unwrap();
let module = Module::new(include_bytes!("../../../../wasm/stub-module/stub.wasm")).unwrap();

b.iter(|| {
module
Expand Down
198 changes: 116 additions & 82 deletions hermes/bin/tests/wasm-integration/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,101 +23,132 @@ use hermes::{
wasm::module::Module,
};
use libtest_mimic::{Arguments, Failed, Measurement, Trial};
use tracing::{level_filters::LevelFilter, subscriber::SetGlobalDefaultError};
use tracing_subscriber::{fmt::time, FmtSubscriber};

/// Init the logger
fn init_logger() -> Result<(), SetGlobalDefaultError> {
let subscriber = FmtSubscriber::builder()
.json()
.with_level(true)
.with_thread_names(true)
.with_thread_ids(true)
.with_file(true)
.with_line_number(true)
.with_timer(time::UtcTime::rfc_3339())
//.with_span_events(FmtSpan::CLOSE)
stevenj marked this conversation as resolved.
Show resolved Hide resolved
.with_max_level(LevelFilter::INFO)
.finish();

tracing::subscriber::set_global_default(subscriber)
}

fn main() -> Result<(), Box<dyn Error>> {
// This is necessary otherwise the logging functions inside hermes are silent during the
// test run.
init_logger()?;
// This causes issues with normal test runs, so comment out for now.
// info!("Starting Hermes WASM integration tests");

let args = Arguments::from_args();
let tests = collect_tests()?;
libtest_mimic::run(&args, tests).exit();
}

/// Creates as many tests as required for each `.wasm` file in the current directory or
/// sub-directories of the current directory.
fn collect_tests() -> Result<Vec<Trial>, Box<dyn Error>> {
#[allow(clippy::missing_docs_in_private_items)]
fn visit_dir(path: &Path, tests: &mut Vec<Trial>) -> Result<(), Box<dyn Error>> {
let args = Arguments::from_args();

let n_test: u32 = env::var(ENV_N_TEST)
.unwrap_or_else(|_| DEFAULT_ENV_N_TEST.to_owned())
.parse()?;
let n_bench: u32 = env::var(ENV_N_BENCH)
.unwrap_or_else(|_| DEFAULT_ENV_N_BENCH.to_owned())
.parse()?;

let entries: Vec<_> = fs::read_dir(path)?
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.map(|entry| entry.file_type().map(|file_type| (file_type, entry.path())))
.collect::<Result<_, _>>()?;
let wasm_file_paths: Vec<_> = entries
.iter()
.filter_map(|(file_type, path)| {
(file_type.is_file() && path.extension() == Some(OsStr::new("wasm")))
.then_some(path)
})
.collect();
let dir_paths: Vec<_> = entries
.iter()
.filter_map(|(file_type, path)| file_type.is_dir().then_some(path))
.collect();

// process `.wasm` files
for file_path in wasm_file_paths {
let name = file_path.strip_prefix(path)?.display().to_string();

// Execute the wasm tests to get their name
// Load WASM module in the executor.
let wasm_buf = fs::read(file_path)?;
let mut module = Module::new(&wasm_buf)?;

let mut collect = |event_type: EventType, n: u32| -> Result<(), Box<dyn Error>> {
// Collect the cases in a loop until no more cases.
for i in 0..n {
match execute_event(&mut module, i, false, event_type)? {
Some(result) => {
let path_string = file_path.to_string_lossy().to_string();

let test = match event_type {
EventType::Test => {
Trial::test(result.name, move || {
execute_test(i, path_string, event_type)
})
},
EventType::Bench => {
Trial::bench(result.name, move |test_mode| {
execute_bench(test_mode, i, path_string, event_type)
})
},
}
.with_kind(name.clone());

tests.push(test);
},
_ => {
break;
},
}
/// Collect all the tests to run from a specified directory
fn visit_dir(path: &Path, tests: &mut Vec<Trial>) -> Result<(), Box<dyn Error>> {
let args = Arguments::from_args();

let n_test: u32 = env::var(ENV_N_TEST)
.unwrap_or_else(|_| DEFAULT_ENV_N_TEST.to_owned())
.parse()?;
let n_bench: u32 = env::var(ENV_N_BENCH)
.unwrap_or_else(|_| DEFAULT_ENV_N_BENCH.to_owned())
.parse()?;

let raw_entries = match fs::read_dir(path) {
Ok(entries) => entries,
Err(_e) => return Ok(()), // If the directory of modules can not be found, just skip it.
};

let entries: Vec<_> = raw_entries
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.map(|entry| entry.file_type().map(|file_type| (file_type, entry.path())))
.collect::<Result<_, _>>()?;

let wasm_file_paths: Vec<_> = entries
.iter()
.filter_map(|(file_type, path)| {
(file_type.is_file() && path.extension() == Some(OsStr::new("wasm"))).then_some(path)
})
.collect();

let dir_paths: Vec<_> = entries
.iter()
.filter_map(|(file_type, path)| file_type.is_dir().then_some(path))
.collect();

// process `.wasm` files
for file_path in wasm_file_paths {
let name = file_path.strip_prefix(path)?.display().to_string();

// Execute the wasm tests to get their name
// Load WASM module in the executor.
let wasm_buf = fs::read(file_path)?;
let mut module = Module::new(&wasm_buf)?;

let mut collect = |event_type: EventType, n: u32| -> Result<(), Box<dyn Error>> {
// Collect the cases in a loop until no more cases.
for i in 0..n {
match execute_event(&mut module, i, false, event_type)? {
Some(result) => {
let path_string = file_path.to_string_lossy().to_string();

let test = match event_type {
EventType::Test => {
Trial::test(result.name, move || {
execute_test(i, path_string, event_type)
})
},
EventType::Bench => {
Trial::bench(result.name, move |test_mode| {
execute_bench(test_mode, i, path_string, event_type)
})
},
}
.with_kind(name.clone());

tests.push(test);
},
_ => {
break;
},
}
}

Ok(())
};
Ok(())
};

if args.bench {
collect(EventType::Bench, n_bench)?;
}
if args.test {
collect(EventType::Test, n_test)?;
}
if args.test || args.list {
collect(EventType::Test, n_test)?;
}

// process items inside directories
for path in dir_paths {
visit_dir(path, tests)?;
if args.bench || args.list {
collect(EventType::Bench, n_bench)?;
}
}

Ok(())
// process items inside directories
for path in dir_paths {
visit_dir(path, tests)?;
}

Ok(())
}

/// Creates as many tests as required for each `.wasm` file in the current directory or
/// sub-directories of the current directory.
fn collect_tests() -> Result<Vec<Trial>, Box<dyn Error>> {
// Read wasm components to be test in a directory.
let mut tests = Vec::new();
let test_module_dir =
Expand All @@ -137,8 +168,11 @@ fn execute(test_case: u32, path: String, event_type: EventType) -> Result<(), Fa

match execute_event(&mut module, test_case, true, event_type)? {
Some(result) => {
assert!(result.status);
Ok(())
if result.status {
Ok(())
} else {
Err(Failed::from("Failed"))
}
},
_ => Err(Failed::from("result unexpected")),
}
Expand Down
2 changes: 1 addition & 1 deletion hermes/crates/cbork/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ VERSION 0.7

# Set up our target toolchains, and copy our files.
builder:
DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.10.0+SETUP
DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.11.0+SETUP

COPY --dir .cargo .config cddl-parser abnf-parser .
COPY Cargo.toml clippy.toml deny.toml rustfmt.toml .
Expand Down
7 changes: 3 additions & 4 deletions hermes/crates/cbork/deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,8 @@ unknown-git = "deny"
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
# List of URLs for allowed Git repositories
allow-git = [
# Remove this once upstream changes are merged.
# issue: https://github.com/input-output-hk/hermes/issues/63
"https://github.com/input-output-hk/hermes.git"
"https://github.com/input-output-hk/hermes.git",
"https://github.com/input-output-hk/catalyst-pallas.git"
]

[sources.allow-org]
Expand All @@ -281,4 +280,4 @@ allow-git = [
# 1 or more gitlab.com organizations to allow git sources for
#gitlab = [""]
# 1 or more bitbucket.org organizations to allow git sources for
#bitbucket = [""]
#bitbucket = [""]