diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cbd518b27d..dbb91e0da3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -179,7 +179,7 @@ jobs: if: matrix.rust == 'nightly' # Build and test all features except for lightbeam - - run: cargo test --features test_programs --all --exclude lightbeam -- --nocapture + - run: cargo test --features test_programs --all --exclude lightbeam --exclude wasmtime-c-api -- --nocapture env: RUST_BACKTRACE: 1 RUSTFLAGS: "-D warnings" @@ -194,6 +194,16 @@ jobs: env: RUST_BACKTRACE: 1 + # Build and test c-api examples. Skipping testing on Windows due to + # GNU make dependency when executing the wasm-c-api examples. + - run: cargo build --package wasmtime-c-api + if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' + - run: cargo test --package wasmtime-c-api -- --nocapture --test-threads 1 + if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' + continue-on-error: true + env: + RUST_BACKTRACE: 1 + # Builds a Python wheel (package) for Windows/Mac/Linux. Note that we're # careful to create binary-compatible releases here to old releases of # Windows/Mac/Linux. This will also build wheels for Python 3.6, 3.7 and 3.8. @@ -317,7 +327,7 @@ jobs: - run: $CENTOS cargo build --release --manifest-path crates/c-api/Cargo.toml shell: bash # Test what we just built - - run: $CENTOS cargo test --features test_programs --release --all --exclude lightbeam --exclude wasmtime --exclude wasmtime-fuzzing + - run: $CENTOS cargo test --features test_programs --release --all --exclude lightbeam --exclude wasmtime --exclude wasmtime-c-api --exclude wasmtime-fuzzing shell: bash env: RUST_BACKTRACE: 1 diff --git a/crates/c-api/tests/wasm-c-examples.rs b/crates/c-api/tests/wasm-c-examples.rs new file mode 100644 index 0000000000..66efa08c5d --- /dev/null +++ b/crates/c-api/tests/wasm-c-examples.rs @@ -0,0 +1,198 @@ +use std::env; +use std::path::PathBuf; +use std::process::Command; + +fn run_c_example(name: &'static str, expected_out: &[u8]) { + let cargo = env::var("MAKE").unwrap_or("make".to_string()); + let pkg_dir = env!("CARGO_MANIFEST_DIR"); + let examples_dir = PathBuf::from(pkg_dir).join("examples"); + let make_arg = format!("run-{}-c", name); + let output = Command::new(cargo) + .current_dir(examples_dir) + .args(&["-s", &make_arg]) + .output() + .expect("success"); + assert!( + output.status.success(), + "failed to execute the C example '{}': {}", + name, + String::from_utf8_lossy(&output.stderr), + ); + assert_eq!( + output.stdout.as_slice(), + expected_out, + "unexpected stdout from example: {}", + String::from_utf8_lossy(&output.stdout), + ); +} + +#[test] +fn test_run_hello_example() { + run_c_example( + "hello", + br#"==== C hello ==== +Initializing... +Loading binary... +Compiling module... +Creating callback... +Instantiating module... +Extracting export... +Calling export... +Calling back... +> Hello World! +Shutting down... +Done. +==== Done ==== +"#, + ); +} + +#[test] +fn test_run_memory_example() { + run_c_example( + "memory", + br#"==== C memory ==== +Initializing... +Loading binary... +Compiling module... +Instantiating module... +Extracting exports... +Checking memory... +Mutating memory... +Growing memory... +Creating stand-alone memory... +Shutting down... +Done. +==== Done ==== +"#, + ); +} + +#[test] +fn test_run_global_example() { + run_c_example( + "global", + br#"==== C global ==== +Initializing... +Loading binary... +Compiling module... +Creating globals... +Instantiating module... +Extracting exports... +Accessing globals... +Shutting down... +Done. +==== Done ==== +"#, + ); +} + +#[test] +fn test_run_callback_example() { + run_c_example( + "callback", + br#"==== C callback ==== +Initializing... +Loading binary... +Compiling module... +Creating callback... +Instantiating module... +Extracting export... +Calling export... +Calling back... +> 7 +Calling back closure... +> 42 +Printing result... +> 49 +Shutting down... +Done. +==== Done ==== +"#, + ); +} + +#[test] +fn test_run_reflect_example() { + run_c_example( + "reflect", + br#"==== C reflect ==== +Initializing... +Loading binary... +Compiling module... +Instantiating module... +Extracting export... +> export 0 "func" +>> initial: func i32 f64 f32 -> i32 +>> current: func i32 f64 f32 -> i32 +>> in-arity: 3, out-arity: 1 +> export 1 "global" +>> initial: global const f64 +>> current: global const f64 +> export 2 "table" +>> initial: table 0d 50d funcref +>> current: table 0d 50d funcref +> export 3 "memory" +>> initial: memory 1d +>> current: memory 1d +Shutting down... +Done. +==== Done ==== +"#, + ); +} + +#[test] +fn test_run_start_example() { + run_c_example( + "start", + br#"==== C start ==== +Initializing... +Loading binary... +Compiling module... +Instantiating module... +Printing message... +> wasm trap: unreachable, source location: @002e +Printing origin... +> Empty origin. +Printing trace... +> Empty trace. +Shutting down... +Done. +==== Done ==== +"#, + ); +} + +#[test] +fn test_run_trap_example() { + run_c_example( + "trap", + br#"==== C trap ==== +Initializing... +Loading binary... +Compiling module... +Creating callback... +Instantiating module... +Extracting exports... +Calling export 0... +Calling back... +Printing message... +> callback abort +Printing origin... +> Empty origin. +Printing trace... +> Empty trace. +Calling export 1... +Printing message... +> wasm trap: unreachable, source location: @0065 +Printing origin... +> Empty origin. +Printing trace... +> Empty trace. +Shutting down... +Done. +==== Done ==== +"#, + ); +}