* Adding in the foundations for Winch `filetests` This commit adds two new crates into the Winch workspace: `filetests` and `test-macros`. The intent is to mimic the structure of Cranelift `filetests`, but in a simpler way. * Updates to documentation This commits adds a high level document to outline how to test Winch through the `winch-tools` utility. It also updates some inline documentation which gets propagated to the CLI. * Updating test-macro to use a glob instead of only a flat directory
83 lines
2.3 KiB
Rust
83 lines
2.3 KiB
Rust
extern crate proc_macro;
|
|
|
|
use std::path::Path;
|
|
|
|
use glob::glob;
|
|
use proc_macro::TokenStream;
|
|
use quote::quote;
|
|
use syn::ItemFn;
|
|
|
|
fn get_test_name_for_root(root: &Path, path: &Path) -> String {
|
|
let test_name = path
|
|
.strip_prefix(root)
|
|
.unwrap()
|
|
.to_str()
|
|
.unwrap()
|
|
.replace("/", "_")
|
|
.replace("\\", "_")
|
|
.replace(".wat", "");
|
|
|
|
format!("winch_filetests_{}", test_name)
|
|
}
|
|
|
|
/// Generate a test case for every .wat file in the filetests directory.
|
|
/// This should only be used from the filetests crate.
|
|
#[proc_macro_attribute]
|
|
pub fn generate_file_tests(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
|
// Parse the input as a function.
|
|
let input = proc_macro2::TokenStream::from(input);
|
|
|
|
let fn_ast: ItemFn =
|
|
syn::parse(input.clone().into()).expect("Failed to parse tokens as function");
|
|
|
|
// Get the function's name and body.
|
|
let name = &fn_ast.sig.ident;
|
|
|
|
let filetests_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("../filetests/filetests");
|
|
|
|
let test_file_entries = glob(format!("{}/**/*.wat", filetests_dir.to_str().unwrap()).as_str())
|
|
.expect("Failed to read glob pattern");
|
|
|
|
// Create a list of test cases by opening every .wat file in the directory.
|
|
let test_cases = test_file_entries.map(|entry| {
|
|
let path = entry.expect("Failed to read glob entry");
|
|
|
|
let full = path.to_str().expect("Path for file was empty");
|
|
|
|
let test_name = proc_macro2::Ident::new(
|
|
&get_test_name_for_root(&filetests_dir, &path),
|
|
proc_macro2::Span::call_site(),
|
|
);
|
|
quote! {
|
|
#[test]
|
|
fn #test_name() {
|
|
#name(#full);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Assemble the output by combining the function and test cases.
|
|
let output = quote! {
|
|
#input
|
|
|
|
#(#test_cases)*
|
|
};
|
|
|
|
output.into()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_get_test_name_for_root_unix() {
|
|
let root = Path::new("/home/user/Documents/winch/filetests/filetests");
|
|
let path = Path::new("/home/user/Documents/winch/filetests/filetests/simd/simple.wat");
|
|
|
|
let test_name = get_test_name_for_root(root, path);
|
|
|
|
assert_eq!(test_name, "winch_filetests_simd_simple");
|
|
}
|
|
}
|