// This file is a copy of compile-claw's runtime tests with component opt performed before execution use compile_claw::compile; use component_opt::optimize_bytes; use std::fs; use wasmtime::component::{bindgen, Component, Linker}; use wasmtime::{Config, Engine, Store}; #[allow(dead_code)] struct Runtime { engine: Engine, component: Component, linker: Linker<()>, store: Store<()>, } impl Runtime { pub fn new(name: &str) -> Self { let path = format!("./tests/programs/{}.claw", name); let input = fs::read_to_string(path).unwrap(); let component_bytes = compile(name.to_owned(), &input).unwrap(); println!("{}", wasmprinter::print_bytes(&component_bytes).unwrap()); let component_bytes = optimize_bytes(component_bytes).unwrap(); println!("{}", wasmprinter::print_bytes(&component_bytes).unwrap()); let mut config = Config::new(); config.wasm_component_model(true); let engine = Engine::new(&config).unwrap(); let component = Component::new(&engine, &component_bytes).unwrap(); let linker = Linker::new(&engine); let store = Store::new(&engine, ()); Runtime { engine, component, linker, store, } } } #[test] fn test_arithmetic() { bindgen!("arithmetic" in "tests/programs"); let mut runtime = Runtime::new("arithmetic"); let (arithmetic, _) = Arithmetic::instantiate(&mut runtime.store, &runtime.component, &runtime.linker).unwrap(); assert!(arithmetic.call_test_u8_masking(&mut runtime.store).unwrap()); } #[test] fn test_counter() { bindgen!("counter" in "tests/programs"); let mut runtime = Runtime::new("counter"); let (counter_s64, _) = Counter::instantiate(&mut runtime.store, &runtime.component, &runtime.linker).unwrap(); for i in 1..200 { // Increase by one assert_eq!( counter_s64.call_increment_s32(&mut runtime.store).unwrap(), i ); assert_eq!( counter_s64.call_increment_s64(&mut runtime.store).unwrap(), i as i64 ); // Increase then decrease by one assert_eq!( counter_s64.call_increment_s32(&mut runtime.store).unwrap(), i + 1 ); assert_eq!( counter_s64.call_increment_s64(&mut runtime.store).unwrap(), i as i64 + 1 ); assert_eq!( counter_s64.call_decrement_s32(&mut runtime.store).unwrap(), i ); assert_eq!( counter_s64.call_decrement_s64(&mut runtime.store).unwrap(), i as i64 ); } for i in (1..200).rev() { assert_eq!( counter_s64.call_decrement_s32(&mut runtime.store).unwrap(), i - 1 ); assert_eq!( counter_s64.call_decrement_s64(&mut runtime.store).unwrap(), i as i64 - 1 ); } } #[test] fn test_factorial() { bindgen!("factorial" in "tests/programs"); let mut runtime = Runtime::new("factorial"); let (factorial, _) = Factorial::instantiate(&mut runtime.store, &runtime.component, &runtime.linker).unwrap(); for (i, val) in [1, 1, 2, 6, 24, 120].iter().enumerate() { let fact = factorial .call_factorial(&mut runtime.store, i as u64) .unwrap(); assert_eq!( fact, *val, "factorial({}) was {} instead of {}", i, fact, *val ); } } #[test] fn test_identity() { bindgen!("identity" in "tests/programs"); let mut runtime = Runtime::new("identity"); let (identity, _) = Identity::instantiate(&mut runtime.store, &runtime.component, &runtime.linker).unwrap(); for i in [0, 1, 2, 12, 5634, 34] { assert_eq!(identity.call_identity(&mut runtime.store, i).unwrap(), i); } } #[test] fn test_compare() { bindgen!("compare" in "tests/programs"); let mut runtime = Runtime::new("compare"); let (compare, _) = Compare::instantiate(&mut runtime.store, &runtime.component, &runtime.linker).unwrap(); for i in 1..200 { for j in 1..200 { let expected_min = std::cmp::min(i, j); let expected_max = std::cmp::max(i, j); let actual_min = compare.call_min_u32(&mut runtime.store, i, j).unwrap(); let actual_max = compare.call_max_u32(&mut runtime.store, i, j).unwrap(); assert_eq!( expected_min, actual_min, "expected min({}, {}) to be {} not {}", i, j, expected_min, actual_min ); assert_eq!( expected_max, actual_max, "expected max({}, {}) to be {} not {}", i, j, expected_max, actual_max ); let i = i as u64; let j = j as u64; let expected_min = expected_min as u64; let expected_max = expected_max as u64; let actual_min = compare.call_min_u64(&mut runtime.store, i, j).unwrap(); let actual_max = compare.call_max_u64(&mut runtime.store, i, j).unwrap(); assert_eq!( expected_min, actual_min, "expected min({}, {}) to be {} not {}", i, j, expected_min, actual_min ); assert_eq!( expected_max, actual_max, "expected max({}, {}) to be {} not {}", i, j, expected_max, actual_max ); } } } #[test] fn test_proxy_call() { bindgen!("proxy-call" in "tests/programs"); let mut runtime = Runtime::new("proxy_call"); impl ProxyCallImports for () { fn imported(&mut self, a: u32) -> Result { Ok(a) } } ProxyCall::add_to_linker(&mut runtime.linker, |s| s).unwrap(); let (proxy_call, _) = ProxyCall::instantiate(&mut runtime.store, &runtime.component, &runtime.linker).unwrap(); for x in 0..10 { let actual = proxy_call.call_exported(&mut runtime.store, x).unwrap(); assert_eq!(x, actual); } } #[test] fn test_quadratic() { bindgen!("quadratic" in "tests/programs"); let mut runtime = Runtime::new("quadratic"); let (quadratic, _) = Quadratic::instantiate(&mut runtime.store, &runtime.component, &runtime.linker).unwrap(); for x in 0..10 { let expected = 2 * x * x + 3 * x + 4; let actual_f32 = quadratic .call_quad_f32(&mut runtime.store, 2.0, 3.0, 4.0, x as f32) .unwrap(); let actual_f32_let = quadratic .call_quad_f32_let(&mut runtime.store, 2.0, 3.0, 4.0, x as f32) .unwrap(); let actual_f64 = quadratic .call_quad_f64(&mut runtime.store, 2.0, 3.0, 4.0, x as f64) .unwrap(); let actual_f64_let = quadratic .call_quad_f64_let(&mut runtime.store, 2.0, 3.0, 4.0, x as f64) .unwrap(); assert_eq!(expected as f32, actual_f32); assert_eq!(expected as f32, actual_f32_let); assert_eq!(expected as f64, actual_f64); assert_eq!(expected as f64, actual_f64_let); } } #[test] fn test_strings() { bindgen!("strings" in "tests/programs"); let mut runtime = Runtime::new("strings"); let (strings, _) = Strings::instantiate(&mut runtime.store, &runtime.component, &runtime.linker).unwrap(); let long_string = "Z".repeat(1000); let cases = [ "", "asdf", "673hlksdfkjh5r;4hj6s", "a", long_string.as_str(), ]; for case in cases { assert_eq!( case, strings.call_identity(&mut runtime.store, case).unwrap() ); } assert_eq!( strings.call_hello_world(&mut runtime.store).unwrap(), "hello, world!" ); for case in cases { assert_eq!( format!("{}Lorem Ipsum", case).as_str(), strings .call_concat(&mut runtime.store, case, "Lorem Ipsum") .unwrap() ); } } #[test] fn test_unary() { bindgen!("unary" in "tests/programs"); let mut runtime = Runtime::new("unary"); let (unary, _) = Unary::instantiate(&mut runtime.store, &runtime.component, &runtime.linker).unwrap(); for x in 0..10_i32 { unary.call_set(&mut runtime.store, x).unwrap(); let inverse = unary.call_get_inverse(&mut runtime.store).unwrap(); assert_eq!(-x, inverse); } }