Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

20240422 more fuzz facilities #84

Merged
merged 6 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 163 additions & 3 deletions src/tests/compiler/fuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ use rand::prelude::Distribution;
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::{BTreeSet, HashMap};
use std::fmt::Debug;
use std::rc::Rc;

use clvmr::Allocator;

use crate::classic::clvm_tools::stages::stage_0::{DefaultProgramRunner, TRunProgram};
use crate::compiler::clvm::run;
use crate::compiler::compiler::DefaultCompilerOpts;
use crate::compiler::comptypes::{BodyForm, CompileErr, CompilerOpts};
use crate::compiler::clvm::{convert_to_clvm_rs, run};
use crate::compiler::compiler::{compile_file, DefaultCompilerOpts};
use crate::compiler::comptypes::{BodyForm, CompileErr, CompilerOpts, PrimaryCodegen};
use crate::compiler::dialect::{detect_modern, AcceptedDialect};
use crate::compiler::fuzz::{ExprModifier, FuzzChoice, FuzzGenerator, FuzzTypeParams, Rule};
use crate::compiler::prims::primquote;
use crate::compiler::sexp::{enlist, extract_atom_replacement, parse_sexp, SExp};
Expand All @@ -36,6 +38,164 @@ pub fn compose_sexp(loc: Srcloc, s: &str) -> Rc<SExp> {
parse_sexp(loc, s.bytes()).expect("should parse")[0].clone()
}

#[derive(Clone)]
pub struct TestModuleCompilerOpts {
opts: Rc<dyn CompilerOpts>,
written_files: Rc<RefCell<HashMap<String, Vec<u8>>>>,
}

impl TestModuleCompilerOpts {
pub fn new(opts: Rc<dyn CompilerOpts>) -> Self {
TestModuleCompilerOpts {
opts: opts,
written_files: Rc::new(RefCell::new(HashMap::new())),
}
}

fn new_opts(&self, opts: Rc<dyn CompilerOpts>) -> Rc<dyn CompilerOpts> {
Rc::new(TestModuleCompilerOpts {
opts,
written_files: self.written_files.clone(),
})
}
}

impl CompilerOpts for TestModuleCompilerOpts {
fn filename(&self) -> String {
self.opts.filename()
}

fn code_generator(&self) -> Option<PrimaryCodegen> {
self.opts.code_generator()
}
fn dialect(&self) -> AcceptedDialect {
self.opts.dialect()
}
fn in_defun(&self) -> bool {
self.opts.in_defun()
}
fn stdenv(&self) -> bool {
self.opts.stdenv()
}
fn optimize(&self) -> bool {
self.opts.optimize()
}
fn frontend_opt(&self) -> bool {
self.opts.frontend_opt()
}
fn frontend_check_live(&self) -> bool {
self.opts.frontend_check_live()
}
fn start_env(&self) -> Option<Rc<SExp>> {
self.opts.start_env()
}
fn disassembly_ver(&self) -> Option<usize> {
self.opts.disassembly_ver()
}
fn prim_map(&self) -> Rc<HashMap<Vec<u8>, Rc<SExp>>> {
self.opts.prim_map()
}
fn get_search_paths(&self) -> Vec<String> {
self.opts.get_search_paths()
}
fn set_dialect(&self, dialect: AcceptedDialect) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_dialect(dialect))
}
fn set_search_paths(&self, dirs: &[String]) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_search_paths(dirs))
}
fn set_in_defun(&self, new_in_defun: bool) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_in_defun(new_in_defun))
}
fn set_stdenv(&self, new_stdenv: bool) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_stdenv(new_stdenv))
}
fn set_optimize(&self, opt: bool) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_optimize(opt))
}
fn set_frontend_opt(&self, opt: bool) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_frontend_opt(opt))
}
fn set_frontend_check_live(&self, check: bool) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_frontend_check_live(check))
}
fn set_code_generator(&self, new_compiler: PrimaryCodegen) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_code_generator(new_compiler))
}
fn set_start_env(&self, start_env: Option<Rc<SExp>>) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_start_env(start_env))
}
fn set_prim_map(&self, prims: Rc<HashMap<Vec<u8>, Rc<SExp>>>) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_prim_map(prims))
}
fn set_disassembly_ver(&self, ver: Option<usize>) -> Rc<dyn CompilerOpts> {
self.new_opts(self.opts.set_disassembly_ver(ver))
}
fn read_new_file(
&self,
inc_from: String,
filename: String,
) -> Result<(String, Vec<u8>), CompileErr> {
self.opts.read_new_file(inc_from, filename)
}
fn compile_program(
&self,
allocator: &mut Allocator,
runner: Rc<dyn TRunProgram>,
sexp: Rc<SExp>,
symbol_table: &mut HashMap<String, String>,
) -> Result<SExp, CompileErr> {
self.opts
.compile_program(allocator, runner, sexp, symbol_table)
}
}

pub struct PerformCompileResult {
pub compiled: Rc<SExp>,
pub source_opts: TestModuleCompilerOpts,
}

pub fn perform_compile_of_file(
allocator: &mut Allocator,
runner: Rc<dyn TRunProgram>,
filename: &str,
content: &str,
) -> Result<PerformCompileResult, CompileErr> {
let loc = Srcloc::start(filename);
let parsed: Vec<Rc<SExp>> = parse_sexp(loc.clone(), content.bytes()).expect("should parse");
let listed = Rc::new(enlist(loc.clone(), &parsed));
let nodeptr = convert_to_clvm_rs(allocator, listed.clone()).expect("should convert");
let dialect = detect_modern(allocator, nodeptr);
let orig_opts: Rc<dyn CompilerOpts> = Rc::new(DefaultCompilerOpts::new(filename))
.set_optimize(true)
.set_frontend_opt(false)
.set_dialect(dialect)
.set_search_paths(&["resources/tests/module".to_string()]);
let source_opts = TestModuleCompilerOpts::new(orig_opts);
let opts: Rc<dyn CompilerOpts> = Rc::new(source_opts.clone());
let mut symbol_table = HashMap::new();
let compiled = compile_file(allocator, runner.clone(), opts, &content, &mut symbol_table)?;
Ok(PerformCompileResult {
compiled: Rc::new(compiled),
source_opts,
})
}

#[test]
fn test_perform_compile_of_file() {
let mut allocator = Allocator::new();
let runner = Rc::new(DefaultProgramRunner::new());
let result = perform_compile_of_file(
&mut allocator,
runner,
"test.clsp",
"(mod (A) (include *standard-cl-23*) (+ A 1))",
)
.expect("should compile");
assert_eq!(result.source_opts.dialect().stepping, Some(23));
assert_eq!(result.compiled.to_string(), "(16 2 (1 . 1))");
}

pub fn simple_run(
opts: Rc<dyn CompilerOpts>,
expr: Rc<SExp>,
Expand Down
Loading
Loading