diff --git a/crates/core/src/driver/compiler.rs b/crates/core/src/driver/compiler.rs deleted file mode 100644 index 3e6d05a..0000000 --- a/crates/core/src/driver/compiler.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! The compiler driver builds the test case contracts for selected compilers. - -use std::collections::HashMap; - -use revive_dt_compiler::{Compiler, CompilerInput, SolidityCompiler}; -use revive_dt_format::{ - metadata::Metadata, - mode::{Mode, SolcMode}, -}; -use revive_solc_json_interface::SolcStandardJsonOutput; -use semver::Version; - -pub fn build( - metadata: &Metadata, -) -> anyhow::Result, SolcStandardJsonOutput>> { - let sources = metadata.contract_sources()?; - let base_path = metadata.directory()?.display().to_string(); - let modes = metadata - .modes - .to_owned() - .unwrap_or_else(|| vec![Mode::Solidity(Default::default())]); - - let mut result = HashMap::new(); - for mode in modes { - let mut compiler = Compiler::::new().base_path(base_path.clone()); - for (file, _contract) in sources.values() { - compiler = compiler.with_source(file)?; - } - - match mode { - Mode::Solidity(SolcMode { - solc_version: _, - solc_optimize, - llvm_optimizer_settings: _, - }) => { - let optimizer = solc_optimize.unwrap_or(true); - let version = Version::new(0, 8, 29); - let output = compiler.solc_optimizer(optimizer).try_build(&version)?; - result.insert(output.input, output.output); - } - Mode::Unknown(mode) => log::debug!("compiler: ignoring unknown mode '{mode}'"), - } - } - - Ok(result) -} diff --git a/crates/core/src/driver/input.rs b/crates/core/src/driver/input.rs deleted file mode 100644 index 77ada92..0000000 --- a/crates/core/src/driver/input.rs +++ /dev/null @@ -1 +0,0 @@ -//! The input driver executes the test cases differentially against selected nodes. diff --git a/crates/core/src/driver/mod.rs b/crates/core/src/driver/mod.rs index 9403334..1a1686b 100644 --- a/crates/core/src/driver/mod.rs +++ b/crates/core/src/driver/mod.rs @@ -1,55 +1,99 @@ //! The test driver handles the compilation and execution of the test cases. -use alloy::primitives::map::HashMap; -use compiler::build; -use revive_dt_compiler::{CompilerInput, SolidityCompiler}; +use alloy::primitives::{Address, map::HashMap}; +use revive_dt_compiler::{Compiler, CompilerInput, SolidityCompiler}; use revive_dt_config::Arguments; -use revive_dt_format::metadata::Metadata; +use revive_dt_format::{ + metadata::Metadata, + mode::{Mode, SolcMode}, +}; use revive_dt_node::Node; use revive_solc_json_interface::SolcStandardJsonOutput; +use semver::Version; use crate::Platform; -pub mod compiler; -pub mod input; - type Contracts = HashMap< CompilerInput<<::Compiler as SolidityCompiler>::Options>, SolcStandardJsonOutput, >; +pub struct State { + contracts: Contracts, + deployed_contracts: HashMap, + node: T::Blockchain, +} + +impl State +where + T: Platform, +{ + fn new(config: &Arguments) -> Self { + Self { + contracts: Default::default(), + deployed_contracts: Default::default(), + node: ::new(config), + } + } + + pub fn build_contracts(&mut self, metadata: &Metadata) -> anyhow::Result<()> { + let sources = metadata.contract_sources()?; + let base_path = metadata.directory()?.display().to_string(); + let modes = metadata + .modes + .to_owned() + .unwrap_or_else(|| vec![Mode::Solidity(Default::default())]); + + let mut result = HashMap::new(); + for mode in modes { + let mut compiler = Compiler::::new().base_path(base_path.clone()); + for (file, _contract) in sources.values() { + compiler = compiler.with_source(file)?; + } + + match mode { + Mode::Solidity(SolcMode { + solc_version: _, + solc_optimize, + llvm_optimizer_settings: _, + }) => { + let optimizer = solc_optimize.unwrap_or(true); + let version = Version::new(0, 8, 29); + let output = compiler.solc_optimizer(optimizer).try_build(&version)?; + result.insert(output.input, output.output); + } + Mode::Unknown(mode) => log::debug!("compiler: ignoring unknown mode '{mode}'"), + } + } + + Ok(()) + } +} + pub struct Driver<'a, Leader: Platform, Follower: Platform> { metadata: &'a Metadata, config: &'a Arguments, - - leader_contracts: Contracts, - leader_node: ::Blockchain, - - follower_contracts: Contracts, - follower_node: ::Blockchain, + leader: State, + follower: State, } impl<'a, L, F> Driver<'a, L, F> where - L: Platform + Default, - F: Platform + Default, + L: Platform, + F: Platform, { pub fn new(metadata: &'a Metadata, config: &'a Arguments) -> Driver<'a, L, F> { Self { metadata, config, - - leader_node: <::Blockchain as Node>::new(config), - leader_contracts: Default::default(), - - follower_node: <::Blockchain as Node>::new(config), - follower_contracts: Default::default(), + leader: State::new(config), + follower: State::new(config), } } pub fn execute(&mut self) -> anyhow::Result<()> { - self.leader_contracts = build::(self.metadata)?; - self.follower_contracts = build::(self.metadata)?; + self.leader.build_contracts(self.metadata)?; + self.follower.build_contracts(self.metadata)?; if self.config.compile_only { return Ok(()); diff --git a/crates/format/src/input.rs b/crates/format/src/input.rs index ca39303..c027eb0 100644 --- a/crates/format/src/input.rs +++ b/crates/format/src/input.rs @@ -1,15 +1,38 @@ use alloy::json_abi::Function; -use alloy::primitives::U256; +use semver::VersionReq; use serde::{Deserialize, de::Deserializer}; +use serde_json::Value; #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq)] pub struct Input { - pub instance: String, + pub instance: Option, #[serde(deserialize_with = "deserialize_method")] pub method: Method, - #[serde(deserialize_with = "deserialize_calldata")] - pub calldata: Vec, - pub expected: Option>, + pub calldata: Option, + pub expected: Option, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq)] +#[serde(untagged)] +pub enum Expected { + Calldata(Calldata), + Expected(ExpectedOutput), + ExpectedMany(Vec), +} + +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq)] +pub struct ExpectedOutput { + compiler_version: Option, + return_data: Option, + events: Option, + exception: Option, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq)] +#[serde(untagged)] +pub enum Calldata { + Single(String), + Compound(Vec), } /// Specify how the contract is called. @@ -30,27 +53,6 @@ pub enum Method { Function([u8; 4]), } -fn deserialize_calldata<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let calldata_strings: Vec = Vec::deserialize(deserializer)?; - let mut result = Vec::with_capacity(calldata_strings.len() * 32); - - for calldata_string in &calldata_strings { - match calldata_string.parse::() { - Ok(parsed) => result.extend_from_slice(&parsed.to_be_bytes::<32>()), - Err(error) => { - return Err(serde::de::Error::custom(format!( - "parsing U256 {calldata_string} error: {error}" - ))); - } - }; - } - - Ok(result) -} - fn deserialize_method<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>,