use anyhow::{Context, Result}; use std::{fs, path::Path}; use wit_parser::{Resolve, WorldId}; /// Tests whether a component targets a world. /// /// This test looks in the `targets/` directory for test cases. /// /// The expected input files for a test case are: /// /// * [required] `test.wat` -- contains the component to test /// encoded as a component produced via the `embed` and `new` /// subcommands of `wasm-tools component`. /// * [required] `test.wit` -- WIT package describing the target /// world to use when checking conformance. /// /// And the output file is: /// * `error.txt` - the expected error message if the synthetic /// component constructed for testing is a invalid component encoding. /// NOTE: an invalid encoding here indicates that the targets check has failed. /// /// Run the test with the environment variable `BLESS` set to update `error.txt`. /// /// Each test is effectively executing as: /// `wasm-tools component targets -w foobar test.wit test.wat` #[test] fn targets() -> Result<()> { drop(env_logger::try_init()); for entry in fs::read_dir("tests/targets")? { let path = entry?.path(); if !path.is_dir() { continue; } let test_case = path.file_stem().unwrap().to_str().unwrap(); println!("testing {test_case}"); let (resolve, world) = load_test_wit(&path)?; let component = wat::parse_file(path.join("test.wat")) .with_context(|| "failed to parse component WAT".to_string())?; match wit_component::targets(&resolve, world, &component) { Ok(_) => { assert!( !test_case.starts_with("error-"), "should have failed targets check" ); } Err(e) => { assert!(test_case.starts_with("error-"), "{e:?}"); assert_output(&path.join("error.txt"), &format!("{e:#}"))?; } } } Ok(()) } fn assert_output(expected: &Path, actual: &str) -> Result<()> { if std::env::var_os("BLESS").is_some() { fs::create_dir_all(expected.parent().unwrap())?; fs::write(expected, actual).with_context(|| format!("failed to write {expected:?}"))?; } else { assert_eq!( fs::read_to_string(expected) .with_context(|| format!("failed to read {expected:?}"))? .replace("\r\n", "\n"), actual, "expectation `{}` did not match actual", expected.display(), ); } Ok(()) } fn load_test_wit(path: &Path) -> Result<(Resolve, WorldId)> { const TEST_TARGET_WORLD_ID: &str = "foobar"; let test_wit_path = path.join("test.wit"); let mut resolve = Resolve::default(); let pkg = resolve.push_file(&test_wit_path)?; let world_id = resolve .select_world(pkg, Some(TEST_TARGET_WORLD_ID)) .with_context(|| "failed to select world from package".to_string())?; Ok((resolve, world_id)) }