diff --git a/.gitignore b/.gitignore index 5c0d0763..61a6613f 100644 --- a/.gitignore +++ b/.gitignore @@ -14,9 +14,7 @@ /.vscode/ # Test artifacts -**/cli-tests/node_modules -**/cli-tests/artifacts -*.xml +/**/tests/data/temp/ # Accidentally created backup files *.bak diff --git a/era-compiler-solidity/src/build_evm/contract.rs b/era-compiler-solidity/src/build_evm/contract.rs index 24440aa5..6bb77f3e 100644 --- a/era-compiler-solidity/src/build_evm/contract.rs +++ b/era-compiler-solidity/src/build_evm/contract.rs @@ -78,12 +78,10 @@ impl Contract { /// /// Writes the contract text assembly and bytecode to files. /// - /// TODO: output assembly - /// pub fn write_to_directory( self, output_path: &Path, - _output_assembly: bool, + output_assembly: bool, output_binary: bool, overwrite: bool, ) -> anyhow::Result<()> { @@ -98,33 +96,43 @@ impl Contract { output_path.push(file_name); std::fs::create_dir_all(output_path.as_path())?; + if output_assembly { + let output_name = format!( + "{}.{}", + self.name.name.as_deref().unwrap_or(file_name), + "asm" + ); + let mut output_path = output_path.clone(); + output_path.push(output_name.as_str()); + + if output_path.exists() && !overwrite { + anyhow::bail!( + "Refusing to overwrite an existing file {output_path:?} (use --overwrite to force)." + ); + } else { + std::fs::write(output_path.as_path(), []) + .map_err(|error| anyhow::anyhow!("File {output_path:?} writing: {error}"))?; + } + } + if output_binary { - for (code_segment, bytecode) in [ - era_compiler_common::CodeSegment::Deploy, - era_compiler_common::CodeSegment::Runtime, - ] - .into_iter() - .zip([self.deploy_build, self.runtime_build].into_iter()) - { - let output_name = format!( - "{}.{code_segment}.{}", - self.name.name.as_deref().unwrap_or(file_name), - era_compiler_common::EXTENSION_EVM_BINARY + let output_name = format!( + "{}.{}", + self.name.name.as_deref().unwrap_or(file_name), + era_compiler_common::EXTENSION_EVM_BINARY + ); + let mut output_path = output_path.clone(); + output_path.push(output_name.as_str()); + + if output_path.exists() && !overwrite { + anyhow::bail!( + "Refusing to overwrite an existing file {output_path:?} (use --overwrite to force)." ); - let mut output_path = output_path.clone(); - output_path.push(output_name.as_str()); - - if output_path.exists() && !overwrite { - anyhow::bail!( - "Refusing to overwrite an existing file {output_path:?} (use --overwrite to force)." - ); - } else { - std::fs::write( - output_path.as_path(), - hex::encode(bytecode.as_slice()).as_bytes(), - ) + } else { + let mut bytecode_hexadecimal = hex::encode(self.deploy_build.as_slice()); + bytecode_hexadecimal.push_str(hex::encode(self.runtime_build.as_slice()).as_str()); + std::fs::write(output_path.as_path(), bytecode_hexadecimal.as_bytes()) .map_err(|error| anyhow::anyhow!("File {output_path:?} writing: {error}"))?; - } } } diff --git a/era-compiler-solidity/tests/cli/allow_paths.rs b/era-compiler-solidity/tests/cli/allow_paths.rs index 1f3471da..2dd984a8 100644 --- a/era-compiler-solidity/tests/cli/allow_paths.rs +++ b/era-compiler-solidity/tests/cli/allow_paths.rs @@ -1,8 +1,11 @@ use crate::{cli, common}; +use era_compiler_common::Target; use predicates::prelude::*; +use test_case::test_case; -#[test] -fn with_allow_paths() -> anyhow::Result<()> { +#[test_case(Target::EraVM)] +#[test_case(Target::EVM)] +fn with_allow_paths(target: Target) -> anyhow::Result<()> { common::setup()?; let args = &[ @@ -12,7 +15,7 @@ fn with_allow_paths() -> anyhow::Result<()> { cli::TEST_SOLIDITY_CONTRACT_PATH, ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result .success() .stdout(predicate::str::contains("Binary:\n")); @@ -20,8 +23,9 @@ fn with_allow_paths() -> anyhow::Result<()> { Ok(()) } -#[test] -fn with_allow_paths_yul_mode() -> anyhow::Result<()> { +#[test_case(Target::EraVM)] +#[test_case(Target::EVM)] +fn with_allow_paths_yul_mode(target: Target) -> anyhow::Result<()> { common::setup()?; let args = &[ @@ -32,7 +36,7 @@ fn with_allow_paths_yul_mode() -> anyhow::Result<()> { cli::TEST_YUL_CONTRACT_PATH, ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result.failure().stderr(predicate::str::contains( "`allow-paths` is only allowed in Solidity mode", )); @@ -40,8 +44,9 @@ fn with_allow_paths_yul_mode() -> anyhow::Result<()> { Ok(()) } -#[test] -fn with_allow_paths_llvm_ir_mode() -> anyhow::Result<()> { +#[test_case(Target::EraVM)] +#[test_case(Target::EVM)] +fn with_allow_paths_llvm_ir_mode(target: Target) -> anyhow::Result<()> { common::setup()?; let args = &[ @@ -52,7 +57,7 @@ fn with_allow_paths_llvm_ir_mode() -> anyhow::Result<()> { cli::TEST_LLVM_IR_CONTRACT_PATH, ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result.failure().stderr(predicate::str::contains( "`allow-paths` is only allowed in Solidity mode", )); @@ -60,8 +65,9 @@ fn with_allow_paths_llvm_ir_mode() -> anyhow::Result<()> { Ok(()) } -#[test] -fn with_allow_paths_eravm_assembly_mode() -> anyhow::Result<()> { +#[test_case(Target::EraVM)] +#[test_case(Target::EVM)] +fn with_allow_paths_eravm_assembly_mode(target: Target) -> anyhow::Result<()> { common::setup()?; let args = &[ @@ -72,7 +78,7 @@ fn with_allow_paths_eravm_assembly_mode() -> anyhow::Result<()> { cli::TEST_ERAVM_ASSEMBLY_CONTRACT_PATH, ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result.failure().stderr(predicate::str::contains( "`allow-paths` is only allowed in Solidity mode", )); diff --git a/era-compiler-solidity/tests/cli/base_path.rs b/era-compiler-solidity/tests/cli/base_path.rs index ae64fb91..690d6850 100644 --- a/era-compiler-solidity/tests/cli/base_path.rs +++ b/era-compiler-solidity/tests/cli/base_path.rs @@ -1,8 +1,11 @@ use crate::{cli, common}; +use era_compiler_common::Target; use predicates::prelude::*; +use test_case::test_case; -#[test] -fn with_base_path() -> anyhow::Result<()> { +#[test_case(Target::EraVM)] +#[test_case(Target::EVM)] +fn with_base_path(target: Target) -> anyhow::Result<()> { common::setup()?; let args = &[ @@ -12,7 +15,7 @@ fn with_base_path() -> anyhow::Result<()> { cli::TEST_SOLIDITY_CONTRACT_PATH, ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result .success() .stdout(predicate::str::contains("Binary:\n")); @@ -20,8 +23,9 @@ fn with_base_path() -> anyhow::Result<()> { Ok(()) } -#[test] -fn with_base_path_yul_mode() -> anyhow::Result<()> { +#[test_case(Target::EraVM)] +#[test_case(Target::EVM)] +fn with_base_path_yul_mode(target: Target) -> anyhow::Result<()> { common::setup()?; let args = &[ @@ -32,7 +36,7 @@ fn with_base_path_yul_mode() -> anyhow::Result<()> { cli::TEST_YUL_CONTRACT_PATH, ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result.failure().stderr(predicate::str::contains( "`base-path` is only allowed in Solidity mode", )); @@ -40,8 +44,9 @@ fn with_base_path_yul_mode() -> anyhow::Result<()> { Ok(()) } -#[test] -fn with_base_path_llvm_ir_mode() -> anyhow::Result<()> { +#[test_case(Target::EraVM)] +#[test_case(Target::EVM)] +fn with_base_path_llvm_ir_mode(target: Target) -> anyhow::Result<()> { common::setup()?; let args = &[ @@ -52,7 +57,7 @@ fn with_base_path_llvm_ir_mode() -> anyhow::Result<()> { cli::TEST_LLVM_IR_CONTRACT_PATH, ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result.failure().stderr(predicate::str::contains( "`base-path` is only allowed in Solidity mode", )); @@ -60,8 +65,9 @@ fn with_base_path_llvm_ir_mode() -> anyhow::Result<()> { Ok(()) } -#[test] -fn with_base_path_eravm_assembly_mode() -> anyhow::Result<()> { +#[test_case(Target::EraVM)] +#[test_case(Target::EVM)] +fn with_base_path_eravm_assembly_mode(target: Target) -> anyhow::Result<()> { common::setup()?; let args = &[ @@ -72,7 +78,7 @@ fn with_base_path_eravm_assembly_mode() -> anyhow::Result<()> { cli::TEST_ERAVM_ASSEMBLY_CONTRACT_PATH, ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result.failure().stderr(predicate::str::contains( "`base-path` is only allowed in Solidity mode", )); diff --git a/era-compiler-solidity/tests/cli/basic.rs b/era-compiler-solidity/tests/cli/basic.rs index c91d481a..4fb154b0 100644 --- a/era-compiler-solidity/tests/cli/basic.rs +++ b/era-compiler-solidity/tests/cli/basic.rs @@ -1,10 +1,13 @@ use crate::{cli, common}; +use era_compiler_common::Target; use predicates::prelude::*; use tempfile::TempDir; +use test_case::test_case; #[test] fn without_any_args() -> anyhow::Result<()> { common::setup()?; + let args: &[&str] = &[]; let result = cli::execute_zksolc(args)?; @@ -24,9 +27,11 @@ fn without_any_args() -> anyhow::Result<()> { Ok(()) } -#[test] -fn with_args_from_help_example() -> anyhow::Result<()> { +#[test_case(Target::EraVM, cli::SOLIDITY_BIN_OUTPUT_NAME_ERAVM)] +#[test_case(Target::EVM, cli::SOLIDITY_BIN_OUTPUT_NAME_EVM)] +fn with_args_from_help_example(target: Target, bin_output_file_name: &str) -> anyhow::Result<()> { common::setup()?; + let tmp_dir = TempDir::new()?; let args = &[ cli::TEST_SOLIDITY_CONTRACT_PATH, @@ -36,7 +41,7 @@ fn with_args_from_help_example() -> anyhow::Result<()> { tmp_dir.path().to_str().unwrap(), ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result .success() .stderr(predicate::str::contains("Compiler run successful.")); @@ -46,7 +51,7 @@ fn with_args_from_help_example() -> anyhow::Result<()> { let bin_output_file = tmp_dir .path() .join(cli::TEST_SOLIDITY_CONTRACT_NAME) - .join(cli::SOLIDITY_BIN_OUTPUT_NAME); + .join(bin_output_file_name); assert!(bin_output_file.exists()); assert!(!cli::is_file_empty(bin_output_file.to_str().unwrap())?); @@ -54,8 +59,21 @@ fn with_args_from_help_example() -> anyhow::Result<()> { Ok(()) } -#[test] -fn with_multiple_output_options() -> anyhow::Result<()> { +#[test_case( + Target::EraVM, + cli::SOLIDITY_BIN_OUTPUT_NAME_ERAVM, + cli::SOLIDITY_ASM_OUTPUT_NAME_ERAVM +)] +// #[test_case( +// Target::EVM, +// cli::SOLIDITY_BIN_OUTPUT_NAME_EVM, +// cli::SOLIDITY_ASM_OUTPUT_NAME_EVM +// )] TODO: assembly +fn with_multiple_output_options( + target: Target, + bin_output_file_name: &str, + asm_output_file_name: &str, +) -> anyhow::Result<()> { common::setup()?; let tmp_dir = TempDir::new()?; let args = &[ @@ -67,7 +85,7 @@ fn with_multiple_output_options() -> anyhow::Result<()> { tmp_dir.path().to_str().unwrap(), ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result .success() .stderr(predicate::str::contains("Compiler run successful.")); @@ -77,11 +95,11 @@ fn with_multiple_output_options() -> anyhow::Result<()> { let bin_output_file = tmp_dir .path() .join(cli::TEST_SOLIDITY_CONTRACT_NAME) - .join(cli::SOLIDITY_BIN_OUTPUT_NAME); + .join(bin_output_file_name); let asm_output_file = tmp_dir .path() .join(cli::TEST_SOLIDITY_CONTRACT_NAME) - .join(cli::SOLIDITY_ASM_OUTPUT_NAME); + .join(asm_output_file_name); assert!(bin_output_file.exists()); assert!(asm_output_file.exists()); @@ -91,8 +109,12 @@ fn with_multiple_output_options() -> anyhow::Result<()> { Ok(()) } -#[test] -fn with_bin_output_same_file_and_cli() -> anyhow::Result<()> { +#[test_case(Target::EraVM, cli::SOLIDITY_BIN_OUTPUT_NAME_ERAVM)] +#[test_case(Target::EVM, cli::SOLIDITY_BIN_OUTPUT_NAME_EVM)] +fn with_bin_output_same_file_and_cli( + target: Target, + bin_output_file_name: &str, +) -> anyhow::Result<()> { common::setup()?; let tmp_dir = TempDir::new()?; @@ -104,7 +126,7 @@ fn with_bin_output_same_file_and_cli() -> anyhow::Result<()> { tmp_dir.path().to_str().unwrap(), ]; - let result = cli::execute_zksolc(args)?; + let result = cli::execute_zksolc_with_target(args, target)?; result .success() .stderr(predicate::str::contains("Compiler run successful.")); @@ -112,11 +134,11 @@ fn with_bin_output_same_file_and_cli() -> anyhow::Result<()> { let bin_output_file = tmp_dir .path() .join(cli::TEST_SOLIDITY_CONTRACT_NAME) - .join(cli::SOLIDITY_BIN_OUTPUT_NAME); + .join(bin_output_file_name); assert!(bin_output_file.exists()); let cli_args = &[cli::TEST_SOLIDITY_CONTRACT_PATH, "-O3", "--bin"]; - let cli_result = cli::execute_zksolc(cli_args)?; + let cli_result = cli::execute_zksolc_with_target(cli_args, target)?; let stdout = String::from_utf8_lossy(cli_result.get_output().stdout.as_slice()); diff --git a/era-compiler-solidity/tests/cli/bin.rs b/era-compiler-solidity/tests/cli/bin.rs index c9eb7f10..69eb626a 100644 --- a/era-compiler-solidity/tests/cli/bin.rs +++ b/era-compiler-solidity/tests/cli/bin.rs @@ -4,7 +4,7 @@ use predicates::prelude::*; use test_case::test_case; #[test_case(Target::EraVM)] -/// TODO: EVM +#[test_case(Target::EVM)] fn with_bin(target: Target) -> anyhow::Result<()> { common::setup()?; diff --git a/era-compiler-solidity/tests/cli/mod.rs b/era-compiler-solidity/tests/cli/mod.rs index 2fba1b6e..a5246afa 100644 --- a/era-compiler-solidity/tests/cli/mod.rs +++ b/era-compiler-solidity/tests/cli/mod.rs @@ -69,10 +69,16 @@ pub const TEST_SOLIDITY_CONTRACT_PATH: &str = "tests/data/contracts/solidity/Tes pub const TEST_SOLIDITY_CONTRACT_GREETER_PATH: &str = "tests/data/contracts/solidity/Greeter.sol"; /// A test input file. -pub const SOLIDITY_BIN_OUTPUT_NAME: &str = "C.zbin"; +pub const SOLIDITY_BIN_OUTPUT_NAME_ERAVM: &str = "C.zbin"; /// A test input file. -pub const SOLIDITY_ASM_OUTPUT_NAME: &str = "C.zasm"; +pub const SOLIDITY_BIN_OUTPUT_NAME_EVM: &str = "C.bin"; + +/// A test input file. +pub const SOLIDITY_ASM_OUTPUT_NAME_ERAVM: &str = "C.zasm"; + +/// A test input file. +pub const SOLIDITY_ASM_OUTPUT_NAME_EVM: &str = "C.asm"; /// A test input file. pub const TEST_YUL_CONTRACT_PATH: &str = "tests/data/contracts/yul/Default.yul"; @@ -194,7 +200,7 @@ pub const TEST_LINKER_BYTECODE_PATH: &str = "tests/data/bytecodes/linker.hex"; /// A test input file. /// The linker hexadecimal string bytecode sample path. /// This file must be copied from `TEST_LINKER_BYTECODE_PATH` before linking and removed afterwards. -pub const TEST_LINKER_BYTECODE_COPY_PATH: &str = "tests/data/bytecodes/linker_copy.hex"; +pub const TEST_LINKER_BYTECODE_COPY_PATH: &str = "tests/data/temp/linker_copy.hex"; /// The broken input file path. pub const TEST_BROKEN_INPUT_PATH: &str = "tests/data/broken.bad"; @@ -311,5 +317,6 @@ pub fn is_file_empty(file_path: &str) -> anyhow::Result { /// pub fn is_output_same_as_file(file_path: &str, output: &str) -> anyhow::Result { let file_content = std::fs::read_to_string(file_path)?; + dbg!(&file_content, &output); Ok(file_content.trim().contains(output.trim()) || output.trim().contains(file_content.trim())) }