Skip to content

Commit

Permalink
Merge pull request #84 from Chia-Network/20240422-more-fuzz-facilities
Browse files Browse the repository at this point in the history
20240422 more fuzz facilities
  • Loading branch information
prozacchiwawa authored Apr 23, 2024
2 parents 7eb0289 + ec734d1 commit db47eab
Show file tree
Hide file tree
Showing 3 changed files with 663 additions and 3 deletions.
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

0 comments on commit db47eab

Please sign in to comment.