cranelift: Build a runtest case from fuzzer TestCase's (#4590)

* cranelift: Build a runtest case from fuzzer TestCase's

* cranelift: Add a default expected output for a fuzzgen case
This commit is contained in:
Afonso Bordado
2022-08-10 22:17:11 +01:00
committed by GitHub
parent 597eb6f4ce
commit 11f0b003eb

View File

@@ -8,13 +8,13 @@ use cranelift::codegen::ir::Function;
use cranelift::codegen::Context; use cranelift::codegen::Context;
use cranelift::prelude::*; use cranelift::prelude::*;
use cranelift_native::builder_with_options; use cranelift_native::builder_with_options;
use std::fmt;
mod config; mod config;
mod function_generator; mod function_generator;
pub type TestCaseInput = Vec<DataValue>; pub type TestCaseInput = Vec<DataValue>;
#[derive(Debug)]
pub struct TestCase { pub struct TestCase {
pub func: Function, pub func: Function,
/// Generate multiple test inputs for each test case. /// Generate multiple test inputs for each test case.
@@ -22,6 +22,59 @@ pub struct TestCase {
pub inputs: Vec<TestCaseInput>, pub inputs: Vec<TestCaseInput>,
} }
impl fmt::Debug for TestCase {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
r#";; Fuzzgen test case
test interpret
test run
set enable_llvm_abi_extensions
target aarch64
target s390x
target x86_64
"#
)?;
writeln!(f, "{}", self.func)?;
writeln!(f, "; Note: the results in the below test cases are simply a placeholder and probably will be wrong\n")?;
for input in self.inputs.iter() {
// TODO: We don't know the expected outputs, maybe we can run the interpreter
// here to figure them out? Should work, however we need to be careful to catch
// panics in case its the interpreter that is failing.
// For now create a placeholder output consisting of the zero value for the type
let returns = &self.func.signature.returns;
let placeholder_output = returns
.iter()
.map(|param| DataValue::read_from_slice(&[0; 16][..], param.value_type))
.map(|val| format!("{}", val))
.collect::<Vec<_>>()
.join(", ");
// If we have no output, we don't need the == condition
let test_condition = match returns.len() {
0 => String::new(),
1 => format!(" == {}", placeholder_output),
_ => format!(" == [{}]", placeholder_output),
};
let args = input
.iter()
.map(|val| format!("{}", val))
.collect::<Vec<_>>()
.join(", ");
writeln!(f, "; run: {}({}){}", self.func.name, args, test_condition)?;
}
Ok(())
}
}
impl<'a> Arbitrary<'a> for TestCase { impl<'a> Arbitrary<'a> for TestCase {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
FuzzGen::new(u) FuzzGen::new(u)