diff --git a/compiler_tester/src/directories/ethereum/test.rs b/compiler_tester/src/directories/ethereum/test.rs index 31a43242..1f2f7742 100644 --- a/compiler_tester/src/directories/ethereum/test.rs +++ b/compiler_tester/src/directories/ethereum/test.rs @@ -14,6 +14,8 @@ use crate::environment::Environment; use crate::filters::Filters; use crate::summary::Summary; use crate::test::case::Case; +use crate::test::description::TestDescription; +use crate::test::selector::TestSelector; use crate::test::Test; use crate::vm::address_iterator::AddressIterator; use crate::vm::eravm::address_iterator::EraVMAddressIterator; @@ -24,8 +26,8 @@ use crate::vm::evm::address_iterator::EVMAddressIterator; /// #[derive(Debug)] pub struct EthereumTest { - /// The test identifier. - pub identifier: String, + /// The test selector. + pub selector: TestSelector, /// The index test entity. pub index_entity: solidity_adapter::EnabledTest, /// The test data. @@ -41,9 +43,9 @@ impl EthereumTest { summary: Arc>, filters: &Filters, ) -> Option { - let identifier = index_entity.path.to_string_lossy().to_string(); + let path = index_entity.path.to_string_lossy().to_string(); - if !filters.check_case_path(&identifier) { + if !filters.check_case_path(&path) { return None; } @@ -51,16 +53,21 @@ impl EthereumTest { return None; } + let selector = TestSelector { + path, + case: None, + input: None, + }; let test = match solidity_adapter::Test::try_from(index_entity.path.as_path()) { Ok(test) => test, Err(error) => { - Summary::invalid(summary, None, identifier, error); + Summary::invalid(summary, TestDescription::default_for(selector), error); return None; } }; Some(Self { - identifier, + selector, index_entity, test, }) @@ -177,9 +184,12 @@ impl EthereumTest { None => { Summary::invalid( summary, - Some(mode.to_owned()), - self.identifier.to_owned(), - anyhow::anyhow!("The Ethereum test `{}` sources are empty", self.identifier), + TestDescription { + group: None, + mode: Some(mode.clone()), + selector: self.selector.clone(), + }, + anyhow::anyhow!("The Ethereum test `{}` sources are empty", &self.selector), ); None } @@ -204,6 +214,12 @@ impl Buildable for EthereumTest { let last_source = self.last_source(summary.clone(), &mode)?; + let test_description = TestDescription { + group: None, + mode: Some(mode.clone()), + selector: self.selector.clone(), + }; + let (contract_address, libraries_addresses, libraries) = match self.get_addresses( EraVMAddressIterator::new(), calls.as_slice(), @@ -213,7 +229,7 @@ impl Buildable for EthereumTest { (contract_address, libraries_addresses, libraries) } Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -221,7 +237,7 @@ impl Buildable for EthereumTest { let evm_version = self.test.params.evm_version; let eravm_input = match compiler .compile_for_eravm( - self.identifier.to_owned(), + self.selector.to_string(), self.test.sources.clone(), libraries, &mode, @@ -232,7 +248,7 @@ impl Buildable for EthereumTest { { Ok(output) => output, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -244,7 +260,7 @@ impl Buildable for EthereumTest { ) { Ok(instance) => instance, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -257,12 +273,7 @@ impl Buildable for EthereumTest { ) { Ok(case) => case, Err(error) => { - Summary::invalid( - summary.clone(), - Some(mode), - self.identifier.to_owned(), - error, - ); + Summary::invalid(summary.clone(), test_description, error); return None; } }; @@ -281,7 +292,7 @@ impl Buildable for EthereumTest { .collect(); Some(Test::new( - self.identifier.to_owned(), + self.selector.to_string(), vec![case], mode, self.index_entity.group.clone(), @@ -305,6 +316,11 @@ impl Buildable for EthereumTest { let mut calls = self.test.calls.clone(); self.insert_deploy_calls(&mut calls); + let test_description = TestDescription { + group: None, + mode: Some(mode.clone()), + selector: self.selector.clone(), + }; let last_source = self.last_source(summary.clone(), &mode)?; let (contract_address, libraries_addresses, libraries) = match self.get_addresses( @@ -316,7 +332,7 @@ impl Buildable for EthereumTest { (contract_address, libraries_addresses, libraries) } Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -324,7 +340,7 @@ impl Buildable for EthereumTest { let evm_version = self.test.params.evm_version; let evm_input = match compiler .compile_for_evm( - self.identifier.to_owned(), + self.selector.to_string(), self.test.sources.clone(), libraries, &mode, @@ -336,7 +352,7 @@ impl Buildable for EthereumTest { { Ok(output) => output, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -348,7 +364,7 @@ impl Buildable for EthereumTest { ) { Ok(instance) => instance, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -361,18 +377,13 @@ impl Buildable for EthereumTest { ) { Ok(case) => case, Err(error) => { - Summary::invalid( - summary.clone(), - Some(mode), - self.identifier.to_owned(), - error, - ); + Summary::invalid(summary.clone(), test_description, error); return None; } }; Some(Test::new( - self.identifier.to_owned(), + self.selector.path.to_string(), vec![case], mode, self.index_entity.group.clone(), diff --git a/compiler_tester/src/directories/matter_labs/test/mod.rs b/compiler_tester/src/directories/matter_labs/test/mod.rs index 8a32951e..e79a194d 100644 --- a/compiler_tester/src/directories/matter_labs/test/mod.rs +++ b/compiler_tester/src/directories/matter_labs/test/mod.rs @@ -19,7 +19,9 @@ use crate::environment::Environment; use crate::filters::Filters; use crate::summary::Summary; use crate::test::case::Case; +use crate::test::description::TestDescription; use crate::test::instance::Instance; +use crate::test::selector::TestSelector; use crate::test::Test; use crate::vm::address_iterator::AddressIterator; use crate::vm::eravm::address_iterator::EraVMAddressIterator; @@ -61,8 +63,8 @@ pub fn default_caller_address() -> String { pub struct MatterLabsTest { /// The test path. path: PathBuf, - /// The test identifier. - identifier: String, + /// The test selector. + selector: TestSelector, /// The test metadata. metadata: Metadata, /// The test sources. @@ -74,16 +76,22 @@ impl MatterLabsTest { /// Try to create new test. /// pub fn new(path: PathBuf, summary: Arc>, filters: &Filters) -> Option { - let identifier = path.to_string_lossy().to_string(); + let selector = TestSelector { + path: path.to_string_lossy().to_string(), + case: None, + input: None, + }; - if !filters.check_test_path(identifier.as_str()) { + if !filters.check_test_path(selector.path.to_string().as_str()) { return None; } + let test_description = TestDescription::default_for(selector.clone()); + let main_file_string = match std::fs::read_to_string(path.as_path()) { Ok(data) => data, Err(error) => { - Summary::invalid(summary, None, identifier.clone(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -93,13 +101,13 @@ impl MatterLabsTest { { Ok(metadata) => metadata, Err(error) => { - Summary::invalid(summary, None, identifier.clone(), error); + Summary::invalid(summary, test_description, error); return None; } }; if metadata.ignore { - Summary::ignored(summary, identifier.clone()); + Summary::ignored(summary, test_description); return None; } @@ -147,7 +155,7 @@ impl MatterLabsTest { { Ok(source) => source, Err(error) => { - Summary::invalid(summary, None, identifier.clone(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -157,12 +165,19 @@ impl MatterLabsTest { }; metadata.cases.retain(|case| { - let case_name = format!("{}::{}", identifier, case.name); + let selector_with_case = TestSelector { + path: selector.path.clone(), + case: Some(case.name.clone()), + input: selector.input.clone(), + }; if case.ignore { - Summary::ignored(summary.clone(), case_name); + Summary::ignored( + summary.clone(), + TestDescription::default_for(selector_with_case), + ); return false; } - + let case_name = selector_with_case.to_string(); if !filters.check_case_path(&case_name) { return false; } @@ -171,7 +186,7 @@ impl MatterLabsTest { Some(Self { path, - identifier, + selector, metadata, sources, }) @@ -215,9 +230,9 @@ impl MatterLabsTest { ) { if contracts.is_empty() { let contract_name = if is_multi_contract { - format!("{}:{}", self.identifier, SIMPLE_TESTS_CONTRACT_NAME) + format!("{}:{}", self.selector.path, SIMPLE_TESTS_CONTRACT_NAME) } else { - self.identifier.to_owned() + self.selector.path.to_string() }; contracts.insert(SIMPLE_TESTS_INSTANCE.to_owned(), contract_name); } @@ -398,7 +413,6 @@ impl Buildable for MatterLabsTest { debug_config: Option, ) -> Option { mode.enable_eravm_extensions(self.metadata.enable_eravm_extensions); - self.check_filters(filters, &mode, era_compiler_common::Target::EraVM)?; let mut contracts = self.metadata.contracts.clone(); @@ -407,11 +421,16 @@ impl Buildable for MatterLabsTest { let mut eravm_address_iterator = EraVMAddressIterator::new(); let evm_address_iterator = EVMAddressIterator::default(); - let (libraries, library_addresses) = self.get_libraries(&mut eravm_address_iterator); + let test_description = TestDescription { + group: None, + mode: Some(mode.clone()), + selector: self.selector.clone(), + }; + let (libraries, library_addresses) = self.get_libraries(&mut eravm_address_iterator); let eravm_input = match compiler .compile_for_eravm( - self.identifier.to_owned(), + self.selector.path.to_string(), self.sources.clone(), libraries, &mode, @@ -422,7 +441,7 @@ impl Buildable for MatterLabsTest { { Ok(vm_input) => vm_input, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -434,7 +453,7 @@ impl Buildable for MatterLabsTest { ) { Ok(instances) => instances, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -442,7 +461,7 @@ impl Buildable for MatterLabsTest { let evm_instances = match self.get_evm_instances() { Ok(evm_instances) => evm_instances, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -462,7 +481,7 @@ impl Buildable for MatterLabsTest { let case = match case.normalize(&contracts, &instances, environment) { Ok(case) => case, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -475,7 +494,7 @@ impl Buildable for MatterLabsTest { ) { Ok(_) => {} Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } } @@ -492,7 +511,7 @@ impl Buildable for MatterLabsTest { { Ok(case) => case, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -514,7 +533,7 @@ impl Buildable for MatterLabsTest { .collect(); Some(Test::new( - self.identifier.to_owned(), + self.selector.to_string(), cases, mode, self.metadata.group.clone(), @@ -542,9 +561,15 @@ impl Buildable for MatterLabsTest { let (libraries, library_addresses) = self.get_libraries(&mut evm_address_iterator); + let test_description = TestDescription { + group: None, + mode: Some(mode.clone()), + selector: self.selector.clone(), + }; + let evm_input = match compiler .compile_for_evm( - self.identifier.to_owned(), + self.selector.path.to_string(), sources, libraries, &mode, @@ -556,7 +581,7 @@ impl Buildable for MatterLabsTest { { Ok(output) => output, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -564,7 +589,7 @@ impl Buildable for MatterLabsTest { let mut instances = match evm_input.get_instances(&contracts, library_addresses, None) { Ok(instances) => instances, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -583,7 +608,7 @@ impl Buildable for MatterLabsTest { { Ok(case) => case, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -596,7 +621,7 @@ impl Buildable for MatterLabsTest { ) { Ok(_) => {} Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } } @@ -613,7 +638,7 @@ impl Buildable for MatterLabsTest { { Ok(case) => case, Err(error) => { - Summary::invalid(summary, Some(mode), self.identifier.to_owned(), error); + Summary::invalid(summary, test_description, error); return None; } }; @@ -622,7 +647,7 @@ impl Buildable for MatterLabsTest { } Some(Test::new( - self.identifier.to_owned(), + self.selector.to_string(), cases, mode, self.metadata.group.clone(), diff --git a/compiler_tester/src/summary/element/mod.rs b/compiler_tester/src/summary/element/mod.rs index fd0f6e48..f1a6a01c 100644 --- a/compiler_tester/src/summary/element/mod.rs +++ b/compiler_tester/src/summary/element/mod.rs @@ -6,7 +6,7 @@ pub mod outcome; use colored::Colorize; -use crate::compilers::mode::Mode; +use crate::test::description::TestDescription; use self::outcome::passed_variant::PassedVariant; use self::outcome::Outcome; @@ -16,10 +16,8 @@ use self::outcome::Outcome; /// #[derive(Debug)] pub struct Element { - /// The mode. - pub mode: Option, - /// The test name. - pub name: String, + /// Information about test instance. + pub test_description: TestDescription, /// The test outcome. pub outcome: Outcome, } @@ -28,10 +26,9 @@ impl Element { /// /// A shortcut constructor. /// - pub fn new(mode: Option, name: String, outcome: Outcome) -> Self { + pub fn new(name: TestDescription, outcome: Outcome) -> Self { Self { - mode, - name, + test_description: name, outcome, } } @@ -103,13 +100,14 @@ impl Element { Some(format!( "{:16} {:>7} {} {}", - self.mode + self.test_description + .mode .as_ref() .map(|mode| mode.to_string()) .unwrap_or_default() .bright_white(), outcome, - self.name, + self.test_description.selector, details )) } diff --git a/compiler_tester/src/summary/mod.rs b/compiler_tester/src/summary/mod.rs index 891fa381..5f028441 100644 --- a/compiler_tester/src/summary/mod.rs +++ b/compiler_tester/src/summary/mod.rs @@ -9,8 +9,8 @@ use std::sync::Mutex; use colored::Colorize; -use crate::compilers::mode::Mode; use crate::test::case::input::output::Output; +use crate::test::description::TestDescription; use crate::toolchain::Toolchain; use self::element::outcome::passed_variant::PassedVariant; @@ -130,13 +130,15 @@ impl Summary { let key = format!( "{:24} {}", element + .test_description .mode .as_ref() .map(|mode| mode.to_string()) .unwrap_or_default(), - element.name + element.test_description.selector ); let mode = element + .test_description .mode .as_ref() .and_then(|mode| mode.llvm_optimizer_settings().cloned()); @@ -191,9 +193,7 @@ impl Summary { /// pub fn passed_deploy( summary: Arc>, - mode: Mode, - name: String, - group: Option, + test: TestDescription, size: usize, cycles: usize, ergs: u64, @@ -205,7 +205,7 @@ impl Summary { ergs, gas, }; - Self::passed(summary, mode, name, group, passed_variant); + Self::passed(summary, test, passed_variant); } /// @@ -213,28 +213,21 @@ impl Summary { /// pub fn passed_runtime( summary: Arc>, - mode: Mode, - name: String, - group: Option, + test: TestDescription, cycles: usize, ergs: u64, gas: u64, ) { let passed_variant = PassedVariant::Runtime { cycles, ergs, gas }; - Self::passed(summary, mode, name, group, passed_variant); + Self::passed(summary, test, passed_variant); } /// /// Adds a passed outcome of a special call, like `storageEmpty` or `balance`. /// - pub fn passed_special( - summary: Arc>, - mode: Mode, - name: String, - group: Option, - ) { + pub fn passed_special(summary: Arc>, test: TestDescription) { let passed_variant = PassedVariant::Special; - Self::passed(summary, mode, name, group, passed_variant); + Self::passed(summary, test, passed_variant); } /// @@ -242,46 +235,40 @@ impl Summary { /// pub fn failed( summary: Arc>, - mode: Mode, - name: String, + test: TestDescription, expected: Output, found: Output, calldata: Vec, ) { - let element = Element::new(Some(mode), name, Outcome::failed(expected, found, calldata)); + let element = Element::new(test, Outcome::failed(expected, found, calldata)); summary.lock().expect("Sync").push_element(element); } /// /// Adds an invalid outcome. /// - pub fn invalid(summary: Arc>, mode: Option, name: String, error: S) + pub fn invalid(summary: Arc>, test: TestDescription, error: S) where S: ToString, { - let element = Element::new(mode, name, Outcome::invalid(error)); + let element = Element::new(test, Outcome::invalid(error)); summary.lock().expect("Sync").push_element(element); } /// /// Adds an ignored outcome. /// - pub fn ignored(summary: Arc>, name: String) { - let element = Element::new(None, name, Outcome::ignored()); + pub fn ignored(summary: Arc>, test: TestDescription) { + let element = Element::new(test.with_erased_mode(), Outcome::ignored()); summary.lock().expect("Sync").push_element(element); } /// /// The unified function for passed outcomes. /// - fn passed( - summary: Arc>, - mode: Mode, - name: String, - group: Option, - passed_variant: PassedVariant, - ) { - let element = Element::new(Some(mode), name, Outcome::passed(group, passed_variant)); + fn passed(summary: Arc>, test: TestDescription, passed_variant: PassedVariant) { + let group = test.group.clone(); + let element = Element::new(test, Outcome::passed(group, passed_variant)); summary.lock().expect("Sync").push_element(element); } diff --git a/compiler_tester/src/test/case/input/balance.rs b/compiler_tester/src/test/case/input/balance.rs index c0f9ac97..db6ad675 100644 --- a/compiler_tester/src/test/case/input/balance.rs +++ b/compiler_tester/src/test/case/input/balance.rs @@ -5,8 +5,10 @@ use std::sync::Arc; use std::sync::Mutex; -use crate::compilers::mode::Mode; use crate::summary::Summary; +use crate::test::case::input::identifier::InputIdentifier; +use crate::test::context::input::InputContext; +use crate::test::description::TestDescription; use crate::vm::eravm::system_context::SystemContext; use crate::vm::eravm::EraVM; use crate::vm::evm::EVM; @@ -41,13 +43,11 @@ impl Balance { self, summary: Arc>, vm: &mut EraVM, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, + context: InputContext<'_>, ) { - let name = format!("{name_prefix}[#balance_check:{index}]"); - + let input_index = context.selector; + let identifier = + TestDescription::from_context(context, InputIdentifier::Balance { input_index }); let rich_addresses = SystemContext::get_rich_addresses(); if rich_addresses.contains(&self.address) { vm.mint_ether( @@ -62,12 +62,11 @@ impl Balance { let found = vm.get_balance(self.address); if found == self.balance { - Summary::passed_special(summary, mode, name, test_group); + Summary::passed_special(summary, identifier); } else { Summary::failed( summary, - mode, - name, + identifier, self.balance.into(), found.into(), self.address.to_fixed_bytes().to_vec(), @@ -82,10 +81,7 @@ impl Balance { self, _summary: Arc>, _vm: &EVM, - _mode: Mode, - _test_group: Option, - _name_prefix: String, - _index: usize, + _context: InputContext<'_>, ) { todo!() } @@ -93,16 +89,9 @@ impl Balance { /// /// Runs the balance check on REVM. /// - pub fn run_revm( - self, - summary: Arc>, - vm: &mut Revm, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, - ) { - let name = format!("{name_prefix}[#balance_check:{index}]"); + pub fn run_revm(self, summary: Arc>, vm: &mut Revm, context: InputContext<'_>) { + let input_index = context.selector; + let test = TestDescription::from_context(context, InputIdentifier::Balance { input_index }); let found = vm .state .context @@ -112,12 +101,11 @@ impl Balance { Ok(found) => { let u256_found = web3::types::U256::from(found.data.to_be_bytes()); if u256_found == self.balance { - Summary::passed_special(summary, mode, name, test_group); + Summary::passed_special(summary, test); } else { Summary::failed( summary, - mode, - name, + test, self.balance.into(), u256_found.into(), self.address.to_fixed_bytes().to_vec(), @@ -127,8 +115,7 @@ impl Balance { Err(_) => { Summary::failed( summary, - mode, - name, + test, self.balance.into(), web3::types::U256::zero().into(), self.address.to_fixed_bytes().to_vec(), @@ -144,20 +131,17 @@ impl Balance { self, summary: Arc>, vm: &EraVM, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, + context: InputContext<'_>, ) { - let name = format!("{name_prefix}[#balance_check:{index}]"); + let input_index = context.selector; + let test = TestDescription::from_context(context, InputIdentifier::Balance { input_index }); let found = vm.get_balance(self.address); if found == self.balance { - Summary::passed_special(summary, mode, name, test_group); + Summary::passed_special(summary, test); } else { Summary::failed( summary, - mode, - name, + test, self.balance.into(), found.into(), self.address.to_fixed_bytes().to_vec(), diff --git a/compiler_tester/src/test/case/input/deploy_eravm.rs b/compiler_tester/src/test/case/input/deploy_eravm.rs index b6ef0a26..790b9e1c 100644 --- a/compiler_tester/src/test/case/input/deploy_eravm.rs +++ b/compiler_tester/src/test/case/input/deploy_eravm.rs @@ -5,11 +5,13 @@ use std::sync::Arc; use std::sync::Mutex; -use crate::compilers::mode::Mode; use crate::summary::Summary; use crate::test::case::input::calldata::Calldata; +use crate::test::case::input::identifier::InputIdentifier; use crate::test::case::input::output::Output; use crate::test::case::input::storage::Storage; +use crate::test::description::TestDescription; +use crate::test::InputContext; use crate::vm::eravm::deployers::EraVMDeployer; use crate::vm::eravm::EraVM; @@ -67,18 +69,21 @@ impl DeployEraVM { self, summary: Arc>, vm: &mut EraVM, - mode: Mode, deployer: &mut D, - test_group: Option, - name_prefix: String, + context: InputContext<'_>, ) where D: EraVMDeployer, { - let name = format!("{name_prefix}[#deployer:{}]", self.path); - + let test = TestDescription::from_context( + context, + InputIdentifier::Deployer { + contract_identifier: self.path, + }, + ); + let name = test.selector.path.to_string(); vm.populate_storage(self.storage.inner); let result = match deployer.deploy_eravm::( - name.clone(), + name, self.caller, self.hash, self.calldata.inner.clone(), @@ -87,7 +92,7 @@ impl DeployEraVM { ) { Ok(result) => result, Err(error) => { - Summary::invalid(summary, Some(mode), name, error); + Summary::invalid(summary, test, error); return; } }; @@ -96,9 +101,7 @@ impl DeployEraVM { let build_size = vm.get_contract_size(self.hash); Summary::passed_deploy( summary, - mode, - name, - test_group, + test, build_size, result.cycles, result.ergs, @@ -107,8 +110,7 @@ impl DeployEraVM { } else { Summary::failed( summary, - mode, - name, + test, self.expected, result.output, self.calldata.inner, diff --git a/compiler_tester/src/test/case/input/deploy_evm.rs b/compiler_tester/src/test/case/input/deploy_evm.rs index a5b6b7bd..d667058c 100644 --- a/compiler_tester/src/test/case/input/deploy_evm.rs +++ b/compiler_tester/src/test/case/input/deploy_evm.rs @@ -9,11 +9,13 @@ use revm::primitives::EVMError; use revm::primitives::ExecutionResult; use solidity_adapter::EVMVersion; -use crate::compilers::mode::Mode; use crate::summary::Summary; use crate::test::case::input::calldata::Calldata; +use crate::test::case::input::identifier::InputIdentifier; use crate::test::case::input::output::Output; use crate::test::case::input::storage::Storage; +use crate::test::description::TestDescription; +use crate::test::InputContext; use crate::vm::eravm::deployers::EraVMDeployer; use crate::vm::eravm::EraVM; use crate::vm::evm::EVM; @@ -76,15 +78,19 @@ impl DeployEVM { self, summary: Arc>, vm: &mut EVM, - mode: Mode, - test_group: Option, - name_prefix: String, + context: InputContext<'_>, ) { - let name = format!("{}[#deployer:{}]", name_prefix, self.identifier); + let test = TestDescription::from_context( + context, + InputIdentifier::Deployer { + contract_identifier: self.identifier.clone(), + }, + ); + let name = test.selector.to_string(); vm.populate_storage(self.storage.inner); let result = match vm.execute_deploy_code( - name.clone(), + name, self.identifier.as_str(), self.caller, self.value, @@ -92,25 +98,16 @@ impl DeployEVM { ) { Ok(execution_result) => execution_result, Err(error) => { - Summary::invalid(summary, Some(mode), name, error); + Summary::invalid(summary, test, error); return; } }; if result.output == self.expected { - Summary::passed_runtime( - summary, - mode, - name, - test_group, - result.cycles, - 0, - result.gas, - ); + Summary::passed_runtime(summary, test, result.cycles, 0, result.gas); } else { Summary::failed( summary, - mode, - name, + test, self.expected, result.output, self.calldata.inner, @@ -121,17 +118,19 @@ impl DeployEVM { /// /// Runs the deploy transaction on native REVM. /// - pub fn run_revm( + pub fn run_revm<'b>( self, summary: Arc>, - vm: Revm, - mode: Mode, - test_group: Option, - name_prefix: String, + vm: Revm<'b>, evm_version: Option, - ) -> Revm { - let name = format!("{}[#deployer:{}]", name_prefix, self.identifier); - + context: InputContext<'_>, + ) -> Revm<'b> { + let test = TestDescription::from_context( + context, + InputIdentifier::Deployer { + contract_identifier: self.identifier.clone(), + }, + ); let size = self.deploy_code.len(); let vm = vm.update_deploy_balance(&self.caller); @@ -141,48 +140,15 @@ impl DeployEVM { let result = match vm.state.transact_commit() { Ok(res) => res, Err(error) => { - match error { - EVMError::Transaction(error) => { - Summary::invalid( - summary.clone(), - Some(mode.clone()), - name.clone(), - format!("Error on Transaction: {error:?}"), - ); - } - EVMError::Header(error) => { - Summary::invalid( - summary.clone(), - Some(mode.clone()), - name.clone(), - format!("Error on Header: {error:?}"), - ); - } - EVMError::Database(_error) => { - Summary::invalid( - summary.clone(), - Some(mode.clone()), - name.clone(), - "Error on Database", - ); - } - EVMError::Custom(error) => { - Summary::invalid( - summary.clone(), - Some(mode.clone()), - name.clone(), - format!("Error on Custom: {error:?}"), - ); - } - EVMError::Precompile(error) => { - Summary::invalid( - summary.clone(), - Some(mode.clone()), - name.clone(), - format!("Error on Precompile: {error:?}"), - ); - } - } + let error_msg = match error { + EVMError::Transaction(error) => format!("Error on Transaction: {error:?}"), + EVMError::Header(error) => format!("Error on Header: {error:?}"), + EVMError::Database(_error) => "Error on Database".into(), + EVMError::Custom(error) => format!("Error on Custom: {error:?}"), + EVMError::Precompile(error) => format!("Error on Precompile: {error:?}"), + }; + + Summary::invalid(summary.clone(), test, error_msg); return vm; } }; @@ -205,18 +171,11 @@ impl DeployEVM { }; if output == self.expected { - Summary::passed_deploy(summary, mode, name, test_group, size, 0, 0, gas); + Summary::passed_deploy(summary, test, size, 0, 0, gas); } else if let Some(error) = error { - Summary::invalid(summary, Some(mode), name, format!("{error:?}")); + Summary::invalid(summary, test, format!("{error:?}")); } else { - Summary::failed( - summary, - mode, - name, - self.expected, - output, - self.calldata.inner, - ); + Summary::failed(summary, test, self.expected, output, self.calldata.inner); } vm @@ -229,20 +188,24 @@ impl DeployEVM { self, summary: Arc>, vm: &mut EraVM, - mode: Mode, deployer: &mut D, - test_group: Option, - name_prefix: String, + context: InputContext<'_>, ) where D: EraVMDeployer, { - let name = format!("{}[#deployer:{}]", name_prefix, self.identifier); - + let test = TestDescription::from_context( + context, + InputIdentifier::Deployer { + contract_identifier: self.identifier.clone(), + }, + ); + + let name = test.selector.to_string(); let size = self.deploy_code.len(); vm.populate_storage(self.storage.inner); let result = match deployer.deploy_evm::( - name.clone(), + name, self.caller, self.deploy_code, self.calldata.inner.clone(), @@ -251,26 +214,16 @@ impl DeployEVM { ) { Ok(result) => result, Err(error) => { - Summary::invalid(summary, Some(mode), name, error); + Summary::invalid(summary, test, error); return; } }; if result.output == self.expected { - Summary::passed_deploy( - summary, - mode, - name, - test_group, - size, - result.cycles, - result.ergs, - result.gas, - ); + Summary::passed_deploy(summary, test, size, result.cycles, result.ergs, result.gas); } else { Summary::failed( summary, - mode, - name, + test, self.expected, result.output, self.calldata.inner, diff --git a/compiler_tester/src/test/case/input/identifier.rs b/compiler_tester/src/test/case/input/identifier.rs new file mode 100644 index 00000000..6210abf5 --- /dev/null +++ b/compiler_tester/src/test/case/input/identifier.rs @@ -0,0 +1,37 @@ +//! +//! Identifier for the test input. Describes the input type and position but not the actual contents. +//! + +/// +/// Identifier for the test input. Describes the input type and position but not the actual contents. +/// +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum InputIdentifier { + /// The contract deploy, regardless of target. + Deployer { contract_identifier: String }, + /// The contract call. + Runtime { input_index: usize, name: String }, + /// The storage empty check. + StorageEmpty { input_index: usize }, + /// Check account balance. + Balance { input_index: usize }, +} + +impl std::fmt::Display for InputIdentifier { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + InputIdentifier::Deployer { + contract_identifier, + } => f.write_fmt(format_args!("#deployer:{contract_identifier}")), + InputIdentifier::Runtime { input_index, name } => { + f.write_fmt(format_args!("{name}:{input_index}")) + } + InputIdentifier::StorageEmpty { input_index } => { + f.write_fmt(format_args!("#storage_empty_check:{input_index}")) + } + InputIdentifier::Balance { input_index } => { + f.write_fmt(format_args!("#balance_check:{input_index}")) + } + } + } +} diff --git a/compiler_tester/src/test/case/input/mod.rs b/compiler_tester/src/test/case/input/mod.rs index e0750819..663420a0 100644 --- a/compiler_tester/src/test/case/input/mod.rs +++ b/compiler_tester/src/test/case/input/mod.rs @@ -6,6 +6,7 @@ pub mod balance; pub mod calldata; pub mod deploy_eravm; pub mod deploy_evm; +pub mod identifier; pub mod output; pub mod runtime; pub mod storage; @@ -21,6 +22,7 @@ use crate::compilers::mode::Mode; use crate::directories::matter_labs::test::metadata::case::input::Input as MatterLabsTestInput; use crate::summary::Summary; use crate::test::instance::Instance; +use crate::test::InputContext; use crate::vm::eravm::deployers::EraVMDeployer; use crate::vm::eravm::EraVM; use crate::vm::evm::EVM; @@ -367,35 +369,19 @@ impl Input { self, summary: Arc>, vm: &mut EraVM, - mode: Mode, deployer: &mut D, - test_group: Option, - name_prefix: String, - index: usize, + context: InputContext<'_>, ) where D: EraVMDeployer, { match self { - Self::DeployEraVM(deploy) => { - deploy.run_eravm::<_, M>(summary, vm, mode, deployer, test_group, name_prefix) - } - Self::DeployEVM(deploy) => deploy.run_evm_interpreter::<_, M>( - summary, - vm, - mode, - deployer, - test_group, - name_prefix, - ), - Self::Runtime(runtime) => { - runtime.run_eravm::(summary, vm, mode, test_group, name_prefix, index) - } - Self::StorageEmpty(storage_empty) => { - storage_empty.run_eravm(summary, vm, mode, test_group, name_prefix, index) - } - Self::Balance(balance_check) => { - balance_check.run_eravm(summary, vm, mode, test_group, name_prefix, index) + Self::DeployEraVM(deploy) => deploy.run_eravm::<_, M>(summary, vm, deployer, context), + Self::DeployEVM(deploy) => { + deploy.run_evm_interpreter::<_, M>(summary, vm, deployer, context) } + Self::Runtime(runtime) => runtime.run_eravm::(summary, vm, context), + Self::StorageEmpty(storage_empty) => storage_empty.run_eravm(summary, vm, context), + Self::Balance(balance_check) => balance_check.run_eravm(summary, vm, context), }; } @@ -406,61 +392,39 @@ impl Input { self, summary: Arc>, vm: &mut EVM, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, + context: InputContext<'_>, ) { match self { Self::DeployEraVM { .. } => panic!("EraVM deploy transaction cannot be run on EVM"), - Self::DeployEVM(deploy) => { - deploy.run_evm_emulator(summary, vm, mode, test_group, name_prefix) - } - Self::Runtime(runtime) => { - runtime.run_evm_emulator(summary, vm, mode, test_group, name_prefix, index) - } + Self::DeployEVM(deploy) => deploy.run_evm_emulator(summary, vm, context), + Self::Runtime(runtime) => runtime.run_evm_emulator(summary, vm, context), Self::StorageEmpty(storage_empty) => { - storage_empty.run_evm_emulator(summary, vm, mode, test_group, name_prefix, index) - } - Self::Balance(balance_check) => { - balance_check.run_evm_emulator(summary, vm, mode, test_group, name_prefix, index) + storage_empty.run_evm_emulator(summary, vm, context) } + Self::Balance(balance_check) => balance_check.run_evm_emulator(summary, vm, context), }; } /// /// Runs the input on REVM. /// - pub fn run_revm( + pub fn run_revm<'b>( self, summary: Arc>, - mut vm: Revm, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, + mut vm: Revm<'b>, evm_version: Option, - ) -> Revm { + context: InputContext<'_>, + ) -> Revm<'b> { match self { Self::DeployEraVM { .. } => panic!("EraVM deploy transaction cannot be run on REVM"), - Self::DeployEVM(deploy) => { - deploy.run_revm(summary, vm, mode, test_group, name_prefix, evm_version) - } - Self::Runtime(runtime) => runtime.run_revm( - summary, - vm, - mode, - test_group, - name_prefix, - index, - evm_version, - ), + Self::DeployEVM(deploy) => deploy.run_revm(summary, vm, evm_version, context), + Self::Runtime(runtime) => runtime.run_revm(summary, vm, evm_version, context), Self::StorageEmpty(storage_empty) => { - storage_empty.run_revm(summary, &mut vm, mode, test_group, name_prefix, index); + storage_empty.run_revm(summary, &mut vm, context); vm } Self::Balance(balance_check) => { - balance_check.run_revm(summary, &mut vm, mode, test_group, name_prefix, index); + balance_check.run_revm(summary, &mut vm, context); vm } } @@ -473,11 +437,8 @@ impl Input { self, summary: Arc>, vm: &mut EraVM, - mode: Mode, deployer: &mut D, - test_group: Option, - name_prefix: String, - index: usize, + context: InputContext<'_>, ) where D: EraVMDeployer, { @@ -485,23 +446,14 @@ impl Input { Self::DeployEraVM { .. } => { panic!("EraVM deploy transaction cannot be run on EVM interpreter") } - Self::DeployEVM(deploy) => deploy.run_evm_interpreter::<_, M>( - summary, - vm, - mode, - deployer, - test_group, - name_prefix, - ), - Self::Runtime(runtime) => { - runtime.run_evm_interpreter::(summary, vm, mode, test_group, name_prefix, index) + Self::DeployEVM(deploy) => { + deploy.run_evm_interpreter::<_, M>(summary, vm, deployer, context) } + Self::Runtime(runtime) => runtime.run_evm_interpreter::(summary, vm, context), Self::StorageEmpty(storage_empty) => { - storage_empty.run_evm_interpreter(summary, vm, mode, test_group, name_prefix, index) - } - Self::Balance(balance_check) => { - balance_check.run_evm_interpreter(summary, vm, mode, test_group, name_prefix, index) + storage_empty.run_evm_interpreter(summary, vm, context) } + Self::Balance(balance_check) => balance_check.run_evm_interpreter(summary, vm, context), }; } } diff --git a/compiler_tester/src/test/case/input/runtime.rs b/compiler_tester/src/test/case/input/runtime.rs index ad4b6dbc..48be0254 100644 --- a/compiler_tester/src/test/case/input/runtime.rs +++ b/compiler_tester/src/test/case/input/runtime.rs @@ -10,11 +10,13 @@ use revm::primitives::EVMError; use revm::primitives::ExecutionResult; use solidity_adapter::EVMVersion; -use crate::compilers::mode::Mode; use crate::summary::Summary; use crate::test::case::input::calldata::Calldata; +use crate::test::case::input::identifier::InputIdentifier; use crate::test::case::input::output::Output; use crate::test::case::input::storage::Storage; +use crate::test::context::input::InputContext; +use crate::test::description::TestDescription; use crate::vm::eravm::system_context::SystemContext; use crate::vm::eravm::EraVM; use crate::vm::evm::EVM; @@ -76,15 +78,20 @@ impl Runtime { self, summary: Arc>, vm: &mut EraVM, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, + context: InputContext<'_>, ) { - let name = format!("{name_prefix}[{}:{index}]", self.name); + let group = context.case_context.group.clone(); + let input_index = context.selector; + let test = TestDescription::from_context( + context, + InputIdentifier::Runtime { + input_index, + name: self.name, + }, + ); + let name = test.selector.to_string(); vm.populate_storage(self.storage.inner); - - let vm_function = match test_group.as_deref() { + let vm_function = match group.as_deref() { Some(benchmark_analyzer::Benchmark::EVM_INTERPRETER_GROUP_NAME) => { EraVM::execute_evm_interpreter:: } @@ -92,7 +99,7 @@ impl Runtime { }; let result = match vm_function( vm, - name.clone(), + name, self.address, self.caller, self.value, @@ -101,26 +108,17 @@ impl Runtime { ) { Ok(result) => result, Err(error) => { - Summary::invalid(summary, Some(mode), name, error); + Summary::invalid(summary, test, error); return; } }; if result.output == self.expected { - Summary::passed_runtime( - summary, - mode, - name, - test_group, - result.cycles, - result.ergs, - result.gas, - ); + Summary::passed_runtime(summary, test, result.cycles, result.ergs, result.gas); } else { Summary::failed( summary, - mode, - name, + test, self.expected, result.output, self.calldata.inner, @@ -135,15 +133,20 @@ impl Runtime { self, summary: Arc>, vm: &mut EVM, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, + context: InputContext<'_>, ) { - let name = format!("{}[{}:{}]", name_prefix, self.name, index); + let input_index = context.selector; + let test = TestDescription::from_context( + context, + InputIdentifier::Runtime { + input_index, + name: self.name, + }, + ); + let name = test.selector.to_string(); vm.populate_storage(self.storage.inner); let result = match vm.execute_runtime_code( - name.clone(), + name, self.address, self.caller, self.value, @@ -151,25 +154,16 @@ impl Runtime { ) { Ok(execution_result) => execution_result, Err(error) => { - Summary::invalid(summary, Some(mode), name, error); + Summary::invalid(summary, test, error); return; } }; if result.output == self.expected { - Summary::passed_runtime( - summary, - mode, - name, - test_group, - result.cycles, - result.ergs, - result.gas, - ); + Summary::passed_runtime(summary, test, result.cycles, result.ergs, result.gas); } else { Summary::failed( summary, - mode, - name, + test, self.expected, result.output, self.calldata.inner, @@ -180,22 +174,27 @@ impl Runtime { /// /// Runs the call on REVM. /// - pub fn run_revm( + pub fn run_revm<'b>( self, summary: Arc>, - vm: Revm, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, + vm: Revm<'b>, evm_version: Option, - ) -> Revm { - let name = format!("{}[{}:{}]", name_prefix, self.name, index); + context: InputContext<'_>, + ) -> Revm<'b> { + let input_index = context.selector; + let test = TestDescription::from_context( + context, + InputIdentifier::Runtime { + input_index, + name: self.name, + }, + ); + let name = test.selector.to_string(); // On revm we can't send a tx with a tx_origin different from the tx_sender, // this specific test expects tx_origin to be that value, so we change the sender let mut caller = self.caller; - if name_prefix == "solidity/test/libsolidity/semanticTests/state/tx_origin.sol" { + if name == "solidity/test/libsolidity/semanticTests/state/tx_origin.sol" { caller = web3::types::Address::from_str("0x9292929292929292929292929292929292929292") .unwrap(); } @@ -219,48 +218,15 @@ impl Runtime { let result = match vm.state.transact_commit() { Ok(result) => result, Err(error) => { - match error { - EVMError::Transaction(error) => { - Summary::invalid( - summary.clone(), - Some(mode.clone()), - name.clone(), - format!("Error on Transaction: {error:?}"), - ); - } - EVMError::Header(error) => { - Summary::invalid( - summary.clone(), - Some(mode.clone()), - name.clone(), - format!("Error on Header: {error:?}"), - ); - } - EVMError::Database(_error) => { - Summary::invalid( - summary.clone(), - Some(mode.clone()), - name.clone(), - "Error on Database", - ); - } - EVMError::Custom(error) => { - Summary::invalid( - summary.clone(), - Some(mode.clone()), - name.clone(), - format!("Error on Custom: {error:?}"), - ); - } - EVMError::Precompile(error) => { - Summary::invalid( - summary.clone(), - Some(mode.clone()), - name.clone(), - format!("Error on Precompile: {error:?}"), - ); - } - } + let error_msg = match error { + EVMError::Transaction(error) => format!("Error on Transaction: {error:?}"), + EVMError::Header(error) => format!("Error on Header: {error:?}"), + EVMError::Database(_error) => "Error on Database".into(), + EVMError::Custom(error) => format!("Error on Custom: {error:?}"), + EVMError::Precompile(error) => format!("Error on Precompile: {error:?}"), + }; + + Summary::invalid(summary.clone(), test, error_msg); return vm; } }; @@ -289,18 +255,11 @@ impl Runtime { }; if output == self.expected { - Summary::passed_runtime(summary, mode, name, test_group, 0, 0, gas); + Summary::passed_runtime(summary, test, 0, 0, gas); } else if let Some(error) = error { - Summary::invalid(summary, Some(mode), name, format!("{error:?}")); + Summary::invalid(summary, test, format!("{error:?}")); } else { - Summary::failed( - summary, - mode, - name, - self.expected, - output, - self.calldata.inner, - ); + Summary::failed(summary, test, self.expected, output, self.calldata.inner); }; vm } @@ -312,15 +271,20 @@ impl Runtime { self, summary: Arc>, vm: &mut EraVM, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, + context: InputContext<'_>, ) { - let name = format!("{}[{}:{}]", name_prefix, self.name, index); + let input_index = context.selector; + let test = TestDescription::from_context( + context, + InputIdentifier::Runtime { + input_index, + name: self.name, + }, + ); + let name = test.selector.to_string(); vm.populate_storage(self.storage.inner); let result = match vm.execute_evm_interpreter::( - name.clone(), + name, self.address, self.caller, self.value, @@ -329,26 +293,17 @@ impl Runtime { ) { Ok(result) => result, Err(error) => { - Summary::invalid(summary, Some(mode), name, error); + Summary::invalid(summary, test, error); return; } }; if result.output == self.expected { - Summary::passed_runtime( - summary, - mode, - name, - test_group, - result.cycles, - result.ergs, - result.gas, - ); + Summary::passed_runtime(summary, test, result.cycles, result.ergs, result.gas); } else { Summary::failed( summary, - mode, - name, + test, self.expected, result.output, self.calldata.inner, diff --git a/compiler_tester/src/test/case/input/storage_empty.rs b/compiler_tester/src/test/case/input/storage_empty.rs index 7807a80d..dce8342f 100644 --- a/compiler_tester/src/test/case/input/storage_empty.rs +++ b/compiler_tester/src/test/case/input/storage_empty.rs @@ -5,8 +5,10 @@ use std::sync::Arc; use std::sync::Mutex; -use crate::compilers::mode::Mode; use crate::summary::Summary; +use crate::test::case::input::identifier::InputIdentifier; +use crate::test::description::TestDescription; +use crate::test::InputContext; use crate::vm::eravm::EraVM; use crate::vm::evm::EVM; use crate::vm::revm::Revm; @@ -33,29 +35,15 @@ impl StorageEmpty { /// /// Runs the storage empty check on EraVM. /// - pub fn run_eravm( - self, - summary: Arc>, - vm: &EraVM, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, - ) { - let name = format!("{name_prefix}[#storage_empty_check:{index}]"); - + pub fn run_eravm(self, summary: Arc>, vm: &EraVM, context: InputContext<'_>) { + let input_index = context.selector; + let test = + TestDescription::from_context(context, InputIdentifier::StorageEmpty { input_index }); let found = vm.is_storage_empty(); if found == self.is_empty { - Summary::passed_special(summary, mode, name, test_group); + Summary::passed_special(summary, test); } else { - Summary::failed( - summary, - mode, - name, - self.is_empty.into(), - found.into(), - vec![], - ); + Summary::failed(summary, test, self.is_empty.into(), found.into(), vec![]); } } @@ -66,10 +54,7 @@ impl StorageEmpty { self, _summary: Arc>, _vm: &EVM, - _mode: Mode, - _test_group: Option, - _name_prefix: String, - _index: usize, + _context: InputContext<'_>, ) { todo!() } @@ -77,17 +62,10 @@ impl StorageEmpty { /// /// Runs the storage empty check on REVM. /// - pub fn run_revm( - self, - summary: Arc>, - vm: &mut Revm, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, - ) { - let name = format!("{name_prefix}[#storage_empty_check:{index}]"); - + pub fn run_revm(self, summary: Arc>, vm: &mut Revm, context: InputContext<'_>) { + let input_index = context.selector; + let test = + TestDescription::from_context(context, InputIdentifier::StorageEmpty { input_index }); let mut is_empty = true; for cache_account in vm.state.db().cache.accounts.values() { let plain_account = cache_account.clone().account; @@ -101,16 +79,9 @@ impl StorageEmpty { } if is_empty == self.is_empty { - Summary::passed_special(summary, mode, name, test_group); + Summary::passed_special(summary, test); } else { - Summary::failed( - summary, - mode, - name, - self.is_empty.into(), - is_empty.into(), - vec![], - ); + Summary::failed(summary, test, self.is_empty.into(), is_empty.into(), vec![]); } } @@ -121,25 +92,16 @@ impl StorageEmpty { self, summary: Arc>, vm: &EraVM, - mode: Mode, - test_group: Option, - name_prefix: String, - index: usize, + context: InputContext<'_>, ) { - let name = format!("{name_prefix}[#storage_empty_check:{index}]"); - + let input_index = context.selector; + let test = + TestDescription::from_context(context, InputIdentifier::StorageEmpty { input_index }); let found = vm.is_storage_empty(); if found == self.is_empty { - Summary::passed_special(summary, mode, name, test_group); + Summary::passed_special(summary, test); } else { - Summary::failed( - summary, - mode, - name, - self.is_empty.into(), - found.into(), - vec![], - ); + Summary::failed(summary, test, self.is_empty.into(), found.into(), vec![]); } } } diff --git a/compiler_tester/src/test/case/mod.rs b/compiler_tester/src/test/case/mod.rs index 8f9d0ba4..ba7803d7 100644 --- a/compiler_tester/src/test/case/mod.rs +++ b/compiler_tester/src/test/case/mod.rs @@ -19,6 +19,9 @@ use crate::vm::revm::Revm; use self::input::Input; +use super::CaseContext; +use super::InputContext; + /// /// The test case. /// @@ -100,28 +103,17 @@ impl Case { self, summary: Arc>, mut vm: EraVM, - mode: &Mode, - test_name: String, - test_group: Option, + context: &CaseContext, ) where D: EraVMDeployer, { - let name = if let Some(case_name) = self.name { - format!("{test_name}::{case_name}") - } else { - test_name - }; - for (index, input) in self.inputs.into_iter().enumerate() { - input.run_eravm::<_, M>( - summary.clone(), - &mut vm, - mode.to_owned(), - &mut D::new(), - test_group.clone(), - name.clone(), - index, - ) + let context = InputContext { + case_context: context, + case_name: &self.name, + selector: index, + }; + input.run_eravm::<_, M>(summary.clone(), &mut vm, &mut D::new(), context) } } @@ -132,25 +124,15 @@ impl Case { self, summary: Arc>, mut vm: EVM, - mode: &Mode, - test_name: String, - test_group: Option, + context: &CaseContext, ) { - let name = if let Some(case_name) = self.name { - format!("{test_name}::{case_name}") - } else { - test_name - }; - for (index, input) in self.inputs.into_iter().enumerate() { - input.run_evm_emulator( - summary.clone(), - &mut vm, - mode.clone(), - test_group.clone(), - name.clone(), - index, - ) + let context = InputContext { + case_context: context, + case_name: &self.name, + selector: index, + }; + input.run_evm_emulator(summary.clone(), &mut vm, context) } } @@ -160,28 +142,17 @@ impl Case { pub fn run_revm( self, summary: Arc>, - mode: &Mode, - test_name: String, - test_group: Option, evm_version: Option, + context: &CaseContext, ) { - let name = if let Some(case_name) = self.name { - format!("{test_name}::{case_name}") - } else { - test_name - }; - let mut vm = Revm::new(); for (index, input) in self.inputs.into_iter().enumerate() { - vm = input.run_revm( - summary.clone(), - vm, - mode.clone(), - test_group.clone(), - name.clone(), - index, - evm_version, - ) + let context = InputContext { + case_context: context, + case_name: &self.name, + selector: index, + }; + vm = input.run_revm(summary.clone(), vm, evm_version, context) } } @@ -192,29 +163,19 @@ impl Case { self, summary: Arc>, mut vm: EraVM, - mode: &Mode, - test_name: String, - test_group: Option, + context: &CaseContext<'_>, ) where D: EraVMDeployer, { - let name = if let Some(case_name) = self.name { - format!("{test_name}::{case_name}") - } else { - test_name - }; - for (index, input) in self.inputs.into_iter().enumerate() { vm.increment_evm_block_number_and_timestamp(); - input.run_evm_interpreter::<_, M>( - summary.clone(), - &mut vm, - mode.clone(), - &mut D::new(), - test_group.clone(), - name.clone(), - index, - ) + + let context = InputContext { + case_context: context, + case_name: &self.name, + selector: index, + }; + input.run_evm_interpreter::<_, M>(summary.clone(), &mut vm, &mut D::new(), context) } } } diff --git a/compiler_tester/src/test/context/case.rs b/compiler_tester/src/test/context/case.rs new file mode 100644 index 00000000..079412c6 --- /dev/null +++ b/compiler_tester/src/test/context/case.rs @@ -0,0 +1,15 @@ +//! +//! Context used to process test cases, consisting of a number of inputs. +//! + +use crate::Mode; + +/// +/// Context used to process test cases, consisting of a number of inputs. +/// +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct CaseContext<'a> { + pub mode: &'a Mode, + pub group: &'a Option, + pub name: &'a str, +} diff --git a/compiler_tester/src/test/context/input.rs b/compiler_tester/src/test/context/input.rs new file mode 100644 index 00000000..12536210 --- /dev/null +++ b/compiler_tester/src/test/context/input.rs @@ -0,0 +1,15 @@ +//! +//! Context used to process test inputs, organized in test cases. +//! + +use super::case::CaseContext; + +/// +/// Context used to process test inputs, organized in test cases. +/// +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct InputContext<'a> { + pub case_context: &'a CaseContext<'a>, + pub case_name: &'a Option, + pub selector: usize, +} diff --git a/compiler_tester/src/test/context/mod.rs b/compiler_tester/src/test/context/mod.rs new file mode 100644 index 00000000..1f756d3b --- /dev/null +++ b/compiler_tester/src/test/context/mod.rs @@ -0,0 +1,2 @@ +pub mod case; +pub mod input; diff --git a/compiler_tester/src/test/description.rs b/compiler_tester/src/test/description.rs new file mode 100644 index 00000000..85755f8b --- /dev/null +++ b/compiler_tester/src/test/description.rs @@ -0,0 +1,68 @@ +//! +//! Test description with additional information such as the compiler mode and test group. +//! + +use crate::Mode; + +use crate::test::case::input::identifier::InputIdentifier; +use crate::test::context::input::InputContext; +use crate::test::selector::TestSelector; + +/// +/// Test description with additional information such as the compiler mode and test group. +/// +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct TestDescription { + /// Test group. + pub group: Option, + /// Compiler mode. + pub mode: Option, + /// Test selector, matching a precise input location or a case collecting several inputs. + pub selector: TestSelector, +} + +impl TestDescription { + /// + /// Creates a test description matching specified selector with no additonal + /// information. + /// + pub fn default_for(test: TestSelector) -> Self { + Self { + group: None, + mode: None, + selector: test, + } + } + + /// + /// Erase information about mode from this selector. + /// + pub fn with_erased_mode(self) -> Self { + let Self { + group, + mode: _, + selector: identifier, + } = self; + Self { + group, + mode: None, + selector: identifier, + } + } + + /// + /// Create a selector from accumulated input context and provided input + /// identifier. + /// + pub fn from_context(ctx: InputContext<'_>, input: InputIdentifier) -> Self { + Self { + group: ctx.case_context.group.clone(), + mode: Some(ctx.case_context.mode.clone()), + selector: TestSelector { + path: ctx.case_context.name.to_string(), + case: ctx.case_name.clone(), + input: Some(input), + }, + } + } +} diff --git a/compiler_tester/src/test/mod.rs b/compiler_tester/src/test/mod.rs index 3e77b457..06430046 100644 --- a/compiler_tester/src/test/mod.rs +++ b/compiler_tester/src/test/mod.rs @@ -3,7 +3,10 @@ //! pub mod case; +pub mod context; +pub mod description; pub mod instance; +pub mod selector; use solidity_adapter::EVMVersion; use std::collections::HashMap; @@ -13,6 +16,8 @@ use std::sync::Mutex; use crate::compilers::mode::Mode; use crate::summary::Summary; use crate::test::case::Case; +use crate::test::context::case::CaseContext; +use crate::test::context::input::InputContext; use crate::vm::eravm::deployers::EraVMDeployer; use crate::vm::eravm::EraVM; use crate::vm::evm::input::build::Build as EVMBuild; @@ -72,15 +77,14 @@ impl Test { where D: EraVMDeployer, { + let context = CaseContext { + name: &self.name, + mode: &self.mode, + group: &self.group, + }; for case in self.cases { let vm = EraVM::clone_with_contracts(vm.clone(), self.eravm_builds.clone(), None); - case.run_eravm::( - summary.clone(), - vm.clone(), - &self.mode, - self.name.clone(), - self.group.clone(), - ); + case.run_eravm::(summary.clone(), vm.clone(), &context); } } @@ -97,13 +101,13 @@ impl Test { let invoker = EVMInvoker::new(&config, &resolver); let vm = EVM::new(self.evm_builds.clone(), invoker); - case.run_evm_emulator( - summary.clone(), - vm, - &self.mode, - self.name.clone(), - self.group.clone(), - ); + + let context = CaseContext { + name: &self.name, + mode: &self.mode, + group: &self.group, + }; + case.run_evm_emulator(summary.clone(), vm, &context); } } @@ -112,13 +116,12 @@ impl Test { /// pub fn run_revm(self, summary: Arc>) { for case in self.cases { - case.run_revm( - summary.clone(), - &self.mode, - self.name.clone(), - self.group.clone(), - self.evm_version, - ); + let context = CaseContext { + name: &self.name, + mode: &self.mode, + group: &self.group, + }; + case.run_revm(summary.clone(), self.evm_version, &context); } } @@ -135,13 +138,12 @@ impl Test { self.eravm_builds.clone(), self.evm_version, ); - case.run_evm_interpreter::( - summary.clone(), - vm, - &self.mode, - self.name.clone(), - self.group.clone(), - ); + let context = CaseContext { + name: &self.name, + mode: &self.mode, + group: &self.group, + }; + case.run_evm_interpreter::(summary.clone(), vm, &context); } } } diff --git a/compiler_tester/src/test/selector.rs b/compiler_tester/src/test/selector.rs new file mode 100644 index 00000000..54936d0a --- /dev/null +++ b/compiler_tester/src/test/selector.rs @@ -0,0 +1,36 @@ +//! +//! Test selector, unambiously locating a test suite, or a specific input. +//! + +use crate::test::case::input::identifier::InputIdentifier; + +/// +/// Test selector, unambiously locating a test suite, case, or input. +/// +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct TestSelector { + /// Path to the file containing test. + pub path: String, + /// Name of the case, if any. `None` means nameless case. + pub case: Option, + /// Identifier of the specific input. + pub input: Option, +} + +impl std::fmt::Display for TestSelector { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + path: filename, + case: case_name, + input, + } = self; + f.write_fmt(format_args!("{filename}"))?; + if let Some(case_name) = case_name { + f.write_fmt(format_args!("::{case_name}"))?; + } + if let Some(input) = input { + f.write_fmt(format_args!("[{input}]"))?; + } + Ok(()) + } +}