From 2e3fbfa9661ce171df66d0850ceda258580dbd07 Mon Sep 17 00:00:00 2001 From: mlokr Date: Fri, 13 Sep 2024 14:30:23 +0200 Subject: [PATCH] extracting testing logic --- hblang/src/codegen.rs | 113 ++---------------------------------------- hblang/src/lib.rs | 104 ++++++++++++++++++++++++++++++++++++++ hblang/src/son.rs | 112 ++--------------------------------------- 3 files changed, 112 insertions(+), 217 deletions(-) diff --git a/hblang/src/codegen.rs b/hblang/src/codegen.rs index 9708ec6..faec209 100644 --- a/hblang/src/codegen.rs +++ b/hblang/src/codegen.rs @@ -1,5 +1,5 @@ +pub use self::reg::{RET_ADDR, STACK_PTR, ZERO}; use { - self::reg::{RET_ADDR, STACK_PTR, ZERO}, crate::{ ident::{self, Ident}, instrs::{self, *}, @@ -3540,68 +3540,12 @@ impl Codegen { #[cfg(test)] mod tests { - use { - super::parser, - crate::{codegen::LoggedMem, log, parser::FileId}, - std::io, - }; - const README: &str = include_str!("../README.md"); fn generate(ident: &'static str, input: &'static str, output: &mut String) { - fn find_block(mut input: &'static str, test_name: &'static str) -> &'static str { - const CASE_PREFIX: &str = "#### "; - const CASE_SUFFIX: &str = "\n```hb"; - loop { - let Some(pos) = input.find(CASE_PREFIX) else { - unreachable!("test {test_name} not found"); - }; + let mut codegen = + super::Codegen { files: crate::test_parse_files(ident, input), ..Default::default() }; - input = unsafe { input.get_unchecked(pos + CASE_PREFIX.len()..) }; - if !input.starts_with(test_name) { - continue; - } - input = unsafe { input.get_unchecked(test_name.len()..) }; - if !input.starts_with(CASE_SUFFIX) { - continue; - } - input = unsafe { input.get_unchecked(CASE_SUFFIX.len()..) }; - - let end = input.find("```").unwrap_or(input.len()); - break unsafe { input.get_unchecked(..end) }; - } - } - - let input = find_block(input, ident); - - let mut module_map = Vec::new(); - let mut last_start = 0; - let mut last_module_name = "test"; - for (i, m) in input.match_indices("// in module: ") { - parser::test::format(ident, input[last_start..i].trim()); - module_map.push((last_module_name, &input[last_start..i])); - let (module_name, _) = input[i + m.len()..].split_once('\n').unwrap(); - last_module_name = module_name; - last_start = i + m.len() + module_name.len() + 1; - } - parser::test::format(ident, input[last_start..].trim()); - module_map.push((last_module_name, input[last_start..].trim())); - - let loader = |path: &str, _: &str| { - module_map - .iter() - .position(|&(name, _)| name == path) - .map(|i| i as FileId) - .ok_or(io::Error::from(io::ErrorKind::NotFound)) - }; - - let mut codegen = super::Codegen { - files: module_map - .iter() - .map(|&(path, content)| parser::Ast::new(path, content.to_owned(), &loader)) - .collect(), - ..Default::default() - }; codegen.generate(); let mut out = Vec::new(); codegen.dump(&mut out).unwrap(); @@ -3613,56 +3557,7 @@ mod tests { return; } - use std::fmt::Write; - - let mut stack = [0_u64; 1024 * 20]; - - let mut vm = unsafe { - hbvm::Vm::<_, 0>::new( - LoggedMem::default(), - hbvm::mem::Address::new(out.as_ptr() as u64), - ) - }; - - vm.write_reg(super::STACK_PTR, unsafe { stack.as_mut_ptr().add(stack.len()) } as u64); - - let stat = loop { - match vm.run() { - Ok(hbvm::VmRunOk::End) => break Ok(()), - Ok(hbvm::VmRunOk::Ecall) => match vm.read_reg(2).0 { - 1 => writeln!(output, "ev: Ecall").unwrap(), // compatibility with a test - 69 => { - let [size, align] = [vm.read_reg(3).0 as usize, vm.read_reg(4).0 as usize]; - let layout = std::alloc::Layout::from_size_align(size, align).unwrap(); - let ptr = unsafe { std::alloc::alloc(layout) }; - vm.write_reg(1, ptr as u64); - } - 96 => { - let [ptr, size, align] = [ - vm.read_reg(3).0 as usize, - vm.read_reg(4).0 as usize, - vm.read_reg(5).0 as usize, - ]; - - let layout = std::alloc::Layout::from_size_align(size, align).unwrap(); - unsafe { std::alloc::dealloc(ptr as *mut u8, layout) }; - } - 3 => vm.write_reg(1, 42), - unknown => unreachable!("unknown ecall: {unknown:?}"), - }, - Ok(hbvm::VmRunOk::Timer) => { - writeln!(output, "timed out").unwrap(); - break Ok(()); - } - Ok(ev) => writeln!(output, "ev: {:?}", ev).unwrap(), - Err(e) => break Err(e), - } - }; - - writeln!(output, "code size: {}", out.len()).unwrap(); - writeln!(output, "ret: {:?}", vm.read_reg(1).0).unwrap(); - writeln!(output, "status: {:?}", stat).unwrap(); - log::inf!("input lenght: {}", input.len()); + crate::test_run_vm(&out, output); } crate::run_tests! { generate: diff --git a/hblang/src/lib.rs b/hblang/src/lib.rs index 840d3d1..2430420 100644 --- a/hblang/src/lib.rs +++ b/hblang/src/lib.rs @@ -717,6 +717,110 @@ pub fn run_test( panic!("test failed"); } +#[cfg(test)] +fn test_parse_files(ident: &'static str, input: &'static str) -> Vec { + fn find_block(mut input: &'static str, test_name: &'static str) -> &'static str { + const CASE_PREFIX: &str = "#### "; + const CASE_SUFFIX: &str = "\n```hb"; + loop { + let Some(pos) = input.find(CASE_PREFIX) else { + unreachable!("test {test_name} not found"); + }; + + input = unsafe { input.get_unchecked(pos + CASE_PREFIX.len()..) }; + if !input.starts_with(test_name) { + continue; + } + input = unsafe { input.get_unchecked(test_name.len()..) }; + if !input.starts_with(CASE_SUFFIX) { + continue; + } + input = unsafe { input.get_unchecked(CASE_SUFFIX.len()..) }; + + let end = input.find("```").unwrap_or(input.len()); + break unsafe { input.get_unchecked(..end) }; + } + } + + let input = find_block(input, ident); + + let mut module_map = Vec::new(); + let mut last_start = 0; + let mut last_module_name = "test"; + for (i, m) in input.match_indices("// in module: ") { + parser::test::format(ident, input[last_start..i].trim()); + module_map.push((last_module_name, &input[last_start..i])); + let (module_name, _) = input[i + m.len()..].split_once('\n').unwrap(); + last_module_name = module_name; + last_start = i + m.len() + module_name.len() + 1; + } + parser::test::format(ident, input[last_start..].trim()); + module_map.push((last_module_name, input[last_start..].trim())); + + let loader = |path: &str, _: &str| { + module_map + .iter() + .position(|&(name, _)| name == path) + .map(|i| i as parser::FileId) + .ok_or(io::Error::from(io::ErrorKind::NotFound)) + }; + + module_map + .iter() + .map(|&(path, content)| parser::Ast::new(path, content.to_owned(), &loader)) + .collect() +} + +#[cfg(test)] +fn test_run_vm(out: &[u8], output: &mut String) { + use std::fmt::Write; + + let mut stack = [0_u64; 1024 * 20]; + + let mut vm = unsafe { + hbvm::Vm::<_, 0>::new(LoggedMem::default(), hbvm::mem::Address::new(out.as_ptr() as u64)) + }; + + vm.write_reg(codegen::STACK_PTR, unsafe { stack.as_mut_ptr().add(stack.len()) } as u64); + + let stat = loop { + match vm.run() { + Ok(hbvm::VmRunOk::End) => break Ok(()), + Ok(hbvm::VmRunOk::Ecall) => match vm.read_reg(2).0 { + 1 => writeln!(output, "ev: Ecall").unwrap(), // compatibility with a test + 69 => { + let [size, align] = [vm.read_reg(3).0 as usize, vm.read_reg(4).0 as usize]; + let layout = std::alloc::Layout::from_size_align(size, align).unwrap(); + let ptr = unsafe { std::alloc::alloc(layout) }; + vm.write_reg(1, ptr as u64); + } + 96 => { + let [ptr, size, align] = [ + vm.read_reg(3).0 as usize, + vm.read_reg(4).0 as usize, + vm.read_reg(5).0 as usize, + ]; + + let layout = std::alloc::Layout::from_size_align(size, align).unwrap(); + unsafe { std::alloc::dealloc(ptr as *mut u8, layout) }; + } + 3 => vm.write_reg(1, 42), + unknown => unreachable!("unknown ecall: {unknown:?}"), + }, + Ok(hbvm::VmRunOk::Timer) => { + writeln!(output, "timed out").unwrap(); + break Ok(()); + } + Ok(ev) => writeln!(output, "ev: {:?}", ev).unwrap(), + Err(e) => break Err(e), + } + }; + + writeln!(output, "code size: {}", out.len()).unwrap(); + writeln!(output, "ret: {:?}", vm.read_reg(1).0).unwrap(); + writeln!(output, "status: {:?}", stat).unwrap(); +} + #[derive(Default)] pub struct Options { pub fmt: bool, diff --git a/hblang/src/son.rs b/hblang/src/son.rs index 9bb614d..2a073a1 100644 --- a/hblang/src/son.rs +++ b/hblang/src/son.rs @@ -3699,70 +3699,13 @@ impl Codegen { #[cfg(test)] mod tests { - use { - crate::{ - parser::{self, FileId}, - LoggedMem, - }, - std::io, - }; + use std::fmt::Write; const README: &str = include_str!("../README.md"); fn generate(ident: &'static str, input: &'static str, output: &mut String) { - fn find_block(mut input: &'static str, test_name: &'static str) -> &'static str { - const CASE_PREFIX: &str = "#### "; - const CASE_SUFFIX: &str = "\n```hb"; - loop { - let Some(pos) = input.find(CASE_PREFIX) else { - unreachable!("test {test_name} not found"); - }; - - input = unsafe { input.get_unchecked(pos + CASE_PREFIX.len()..) }; - if !input.starts_with(test_name) { - continue; - } - input = unsafe { input.get_unchecked(test_name.len()..) }; - if !input.starts_with(CASE_SUFFIX) { - continue; - } - input = unsafe { input.get_unchecked(CASE_SUFFIX.len()..) }; - - let end = input.find("```").unwrap_or(input.len()); - break unsafe { input.get_unchecked(..end) }; - } - } - - let input = find_block(input, ident); - - let mut module_map = Vec::new(); - let mut last_start = 0; - let mut last_module_name = "test"; - for (i, m) in input.match_indices("// in module: ") { - //parser::test::format(ident, input[last_start..i].trim()); - module_map.push((last_module_name, &input[last_start..i])); - let (module_name, _) = input[i + m.len()..].split_once('\n').unwrap(); - last_module_name = module_name; - last_start = i + m.len() + module_name.len() + 1; - } - //parser::test::format(ident, input[last_start..].trim()); - module_map.push((last_module_name, input[last_start..].trim())); - - let loader = |path: &str, _: &str| { - module_map - .iter() - .position(|&(name, _)| name == path) - .map(|i| i as FileId) - .ok_or(io::Error::from(io::ErrorKind::NotFound)) - }; - - let mut codegen = super::Codegen { - files: module_map - .iter() - .map(|&(path, content)| parser::Ast::new(path, content.to_owned(), &loader)) - .collect(), - ..Default::default() - }; + let mut codegen = + super::Codegen { files: crate::test_parse_files(ident, input), ..Default::default() }; codegen.generate(); @@ -3785,54 +3728,7 @@ mod tests { return; } - let mut stack = [0_u64; 128]; - - let mut vm = unsafe { - hbvm::Vm::<_, { 1024 * 10 }>::new( - LoggedMem::default(), - hbvm::mem::Address::new(out.as_ptr() as u64), - ) - }; - - vm.write_reg(super::reg::STACK_PTR, unsafe { stack.as_mut_ptr().add(stack.len()) } as u64); - - use std::fmt::Write; - let stat = loop { - match vm.run() { - Ok(hbvm::VmRunOk::End) => break Ok(()), - Ok(hbvm::VmRunOk::Ecall) => match vm.read_reg(2).0 { - 1 => writeln!(output, "ev: Ecall").unwrap(), // compatibility with a test - 69 => { - let [size, align] = [vm.read_reg(3).0 as usize, vm.read_reg(4).0 as usize]; - let layout = std::alloc::Layout::from_size_align(size, align).unwrap(); - let ptr = unsafe { std::alloc::alloc(layout) }; - vm.write_reg(1, ptr as u64); - } - 96 => { - let [ptr, size, align] = [ - vm.read_reg(3).0 as usize, - vm.read_reg(4).0 as usize, - vm.read_reg(5).0 as usize, - ]; - - let layout = std::alloc::Layout::from_size_align(size, align).unwrap(); - unsafe { std::alloc::dealloc(ptr as *mut u8, layout) }; - } - 3 => vm.write_reg(1, 42), - unknown => unreachable!("unknown ecall: {unknown:?}"), - }, - Ok(hbvm::VmRunOk::Timer) => { - writeln!(output, "timed out").unwrap(); - break Ok(()); - } - Ok(ev) => writeln!(output, "ev: {:?}", ev).unwrap(), - Err(e) => break Err(e), - } - }; - - writeln!(output, "code size: {}", out.len()).unwrap(); - writeln!(output, "ret: {:?}", vm.read_reg(1).0).unwrap(); - writeln!(output, "status: {:?}", stat).unwrap(); + crate::test_run_vm(&out, output); } crate::run_tests! { generate: