Skip to content

Commit

Permalink
Group bindings tests and generate runner invocations at build time
Browse files Browse the repository at this point in the history
  • Loading branch information
ggiraldez committed Jun 19, 2024
1 parent 6c40818 commit 57425e7
Show file tree
Hide file tree
Showing 16 changed files with 714 additions and 248 deletions.
116 changes: 116 additions & 0 deletions crates/codegen/testing/src/bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Write;
use std::path::Path;

use anyhow::{bail, Result};
use codegen_language_definition::model::Language;
use inflector::Inflector;
use infra_utils::codegen::CodegenFileSystem;
use infra_utils::paths::FileWalker;

pub fn generate_bindings_tests(
_language: &Language,
data_dir: &Path,
output_dir: &Path,
) -> Result<()> {
let bindings_tests = collect_bindings_tests(data_dir)?;

let mut fs = CodegenFileSystem::new(data_dir)?;

generate_mod_file(&mut fs, &output_dir.join("mod.rs"), &bindings_tests)?;

for (group_name, test_files) in &bindings_tests {
generate_unit_test_file(
&mut fs,
group_name,
test_files,
&output_dir.join(format!("{0}.rs", group_name.to_snake_case())),
)?;
}

Ok(())
}

fn collect_bindings_tests(data_dir: &Path) -> Result<BTreeMap<String, BTreeSet<String>>> {
let mut bindings_tests = BTreeMap::<String, BTreeSet<String>>::new();

for file in FileWalker::from_directory(data_dir).find(["**/*.sol"])? {
let parts: Vec<_> = file
.strip_prefix(data_dir)?
.iter()
.map(|p| p.to_str().unwrap())
.collect();

match parts[..] {
[group_name, test_file] => {
bindings_tests
.entry(group_name.to_owned())
.or_default()
.insert(test_file.to_owned());
}
_ => {
bail!("Invalid test input. Should be in the form of '<tests-dir>/GROUP_NAME/TEST_FILE.sol', but found: {file:?}");
}
};
}

Ok(bindings_tests)
}

fn generate_mod_file(
fs: &mut CodegenFileSystem,
mod_file_path: &Path,
bindings_tests: &BTreeMap<String, BTreeSet<String>>,
) -> Result<()> {
let module_declarations_str =
bindings_tests
.keys()
.fold(String::new(), |mut buffer, group_name| {
writeln!(buffer, "mod {0};", group_name.to_snake_case()).unwrap();
buffer
});

let contents = format!(
"
{module_declarations_str}
",
);

fs.write_file(mod_file_path, contents)
}

fn generate_unit_test_file(
fs: &mut CodegenFileSystem,
group_name: &str,
test_files: &BTreeSet<String>,
unit_test_file_path: &Path,
) -> Result<()> {
let unit_tests_str = test_files
.iter()
.fold(String::new(), |mut buffer, test_file| {
let test_name = test_file.strip_suffix(".sol").unwrap();
writeln!(
buffer,
r#"
#[test]
fn {test_name}() -> Result<()> {{
run("{group_name}", "{test_file}")
}}
"#
)
.unwrap();
buffer
});

let contents = format!(
"
use anyhow::Result;
use crate::bindings::runner::run;
{unit_tests_str}
"
);

fs.write_file(unit_test_file_path, contents)
}
6 changes: 6 additions & 0 deletions crates/codegen/testing/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
mod bindings;
mod cst_output;

use std::path::Path;

use anyhow::Result;
use codegen_language_definition::model::Language;

use crate::bindings::generate_bindings_tests;
use crate::cst_output::generate_cst_output_tests;

pub trait TestingGeneratorExtensions {
fn generate_cst_output_tests(&self, snapshots_dir: &Path, output_dir: &Path) -> Result<()>;
fn generate_bindings_tests(&self, snapshots_dir: &Path, output_dir: &Path) -> Result<()>;
}

impl TestingGeneratorExtensions for Language {
fn generate_cst_output_tests(&self, data_dir: &Path, output_dir: &Path) -> Result<()> {
generate_cst_output_tests(self, data_dir, output_dir)
}
fn generate_bindings_tests(&self, data_dir: &Path, output_dir: &Path) -> Result<()> {
generate_bindings_tests(self, data_dir, output_dir)
}
}
6 changes: 6 additions & 0 deletions crates/solidity/outputs/cargo/tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ fn main() -> Result<()> {
&CargoWorkspace::locate_source_crate("solidity_testing_snapshots")?.join("cst_output"),
&CargoWorkspace::locate_source_crate("solidity_cargo_tests")?
.join("src/cst_output/generated"),
)?;

lang_def.generate_bindings_tests(
&CargoWorkspace::locate_source_crate("solidity_testing_snapshots")?.join("bindings"),
&CargoWorkspace::locate_source_crate("solidity_cargo_tests")?
.join("src/bindings/generated"),
)
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/solidity/outputs/cargo/tests/src/bindings/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
mod generated;
mod rules;
mod runner;
7 changes: 7 additions & 0 deletions crates/solidity/outputs/cargo/tests/src/bindings/rules.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use slang_solidity::bindings::Bindings;

#[test]
fn test_bindings_rules_parsing() {
let result = Bindings::get_graph_builder();
assert!(result.is_ok());
}
20 changes: 4 additions & 16 deletions crates/solidity/outputs/cargo/tests/src/bindings/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::path::PathBuf;

use anyhow::Result;
use infra_utils::cargo::CargoWorkspace;
use infra_utils::paths::FileWalker;
use slang_solidity::assertions::{check_assertions, collect_assertions};
use slang_solidity::bindings::graph_builder::{
ExecutionConfig, Functions, Graph, NoCancellation, Variables,
Expand All @@ -13,21 +12,10 @@ use slang_solidity::bindings::Bindings;
use slang_solidity::language::Language;
use slang_solidity::parse_output::ParseOutput;

#[test]
pub fn run_all() -> Result<()> {
let data_dir =
CargoWorkspace::locate_source_crate("solidity_testing_snapshots")?.join("bindings");

for file in FileWalker::from_directory(data_dir).find(["*.sol"])? {
run(file.file_name().unwrap().to_str().unwrap())?;
}

Ok(())
}

fn run(file_name: &str) -> Result<()> {
let data_dir =
CargoWorkspace::locate_source_crate("solidity_testing_snapshots")?.join("bindings");
pub fn run(group_name: &str, file_name: &str) -> Result<()> {
let data_dir = CargoWorkspace::locate_source_crate("solidity_testing_snapshots")?
.join("bindings")
.join(group_name);
let input_path = data_dir.join(file_name);
let input = fs::read_to_string(&input_path)?;

Expand Down
Loading

0 comments on commit 57425e7

Please sign in to comment.