mirror of
https://git.proxmox.com/git/rustc
synced 2025-08-17 07:48:55 +00:00
121 lines
4.2 KiB
Rust
121 lines
4.2 KiB
Rust
use anyhow::{Context, Result};
|
|
use libtest_mimic::{Arguments, Trial};
|
|
use pretty_assertions::assert_eq;
|
|
use std::fs;
|
|
use std::path::Path;
|
|
use wit_component::WitPrinter;
|
|
use wit_parser::{PackageId, Resolve, UnresolvedPackageGroup};
|
|
|
|
/// Tests the encoding of a WIT package as a WebAssembly binary.
|
|
///
|
|
/// This test looks in the `interfaces/` directory for test cases. Each test
|
|
/// case is a `*.wit` file or a folder which contains `*.wit` files as part of a
|
|
/// multi-file package. Each tests `foo.wit` is accompanied with a `foo.wat` for
|
|
/// the WebAssembly text format encoding of the package. Additionally each test
|
|
/// has a `foo.print.wit` which is the machine-printed version of the WIT
|
|
/// document as decoded from the binary encoded interface.
|
|
///
|
|
/// Run the test with the environment variable `BLESS` set to update
|
|
/// the baseline files.
|
|
fn main() -> Result<()> {
|
|
env_logger::init();
|
|
|
|
let mut trials = Vec::new();
|
|
for entry in fs::read_dir("tests/interfaces")? {
|
|
let path = entry?.path();
|
|
let name = match path.file_name().and_then(|s| s.to_str()) {
|
|
Some(s) => s,
|
|
None => continue,
|
|
};
|
|
let is_dir = path.is_dir();
|
|
let is_test = is_dir || name.ends_with(".wit");
|
|
if is_test {
|
|
trials.push(Trial::test(name.to_string(), move || {
|
|
run_test(&path, is_dir)
|
|
.context(format!("failed test `{}`", path.display()))
|
|
.map_err(|e| format!("{e:?}").into())
|
|
}));
|
|
}
|
|
}
|
|
|
|
let mut args = Arguments::from_args();
|
|
if cfg!(target_family = "wasm") && !cfg!(target_feature = "atomics") {
|
|
args.test_threads = Some(1);
|
|
}
|
|
libtest_mimic::run(&args, trials).exit();
|
|
}
|
|
|
|
fn run_test(path: &Path, is_dir: bool) -> Result<()> {
|
|
let mut resolve = Resolve::new();
|
|
let package = if is_dir {
|
|
resolve.push_dir(path)?.0
|
|
} else {
|
|
resolve.push_file(path)?
|
|
};
|
|
|
|
assert_print(&resolve, package, path, is_dir)?;
|
|
|
|
// First convert the WIT package to a binary WebAssembly output, then
|
|
// convert that binary wasm to textual wasm, then assert it matches the
|
|
// expectation.
|
|
let wasm = wit_component::encode(&resolve, package)?;
|
|
let wat = wasmprinter::print_bytes(&wasm)?;
|
|
assert_output(&path.with_extension("wat"), &wat)?;
|
|
wasmparser::Validator::new()
|
|
.validate_all(&wasm)
|
|
.context("failed to validate wasm output")?;
|
|
|
|
// Next decode a fresh WIT package from the WebAssembly generated. Print
|
|
// this package's documents and assert they all match the expectations.
|
|
let decoded = wit_component::decode(&wasm)?;
|
|
|
|
let decoded_package = decoded.package();
|
|
let resolve = decoded.resolve();
|
|
|
|
assert_print(resolve, decoded.package(), path, is_dir)?;
|
|
|
|
// Finally convert the decoded package to wasm again and make sure it
|
|
// matches the prior wasm.
|
|
let wasm2 = wit_component::encode(resolve, decoded_package)?;
|
|
if wasm != wasm2 {
|
|
let wat2 = wasmprinter::print_bytes(&wasm)?;
|
|
assert_eq!(wat, wat2, "document did not roundtrip correctly");
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn assert_print(resolve: &Resolve, pkg_id: PackageId, path: &Path, is_dir: bool) -> Result<()> {
|
|
let output = WitPrinter::default().print(resolve, pkg_id, &[])?;
|
|
let pkg = &resolve.packages[pkg_id];
|
|
let expected = if is_dir {
|
|
path.join(format!("{}.wit.print", &pkg.name.name))
|
|
} else {
|
|
path.with_extension("wit.print")
|
|
};
|
|
assert_output(&expected, &output)?;
|
|
|
|
UnresolvedPackageGroup::parse("foo.wit", &output).context("failed to parse printed output")?;
|
|
Ok(())
|
|
}
|
|
|
|
fn assert_output(expected: &Path, actual: &str) -> Result<()> {
|
|
let actual = actual.replace(
|
|
concat!("\"", env!("CARGO_PKG_VERSION"), "\""),
|
|
"\"$CARGO_PKG_VERSION\"",
|
|
);
|
|
if std::env::var_os("BLESS").is_some() {
|
|
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(())
|
|
}
|