-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Rationale for this change #166 disabled solidity tests due to instability in the forge repo. # What changes are included in this PR? * Added a new `ForgeScript` type to enable testing. This type only depends on the published version of `alloy-sol-types`, which should be stable enough for our purposes. * Refactored the existing tests to use this instead. * Updated the CI to run these tests. # Are these changes tested? Yes
- Loading branch information
Showing
6 changed files
with
83 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
// mod sol_test; | ||
mod sol_test; | ||
mod sol_test_util; | ||
pub(crate) use sol_test_util::{ForgeScript, ForgeScriptError}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,39 @@ | ||
use alloy_primitives::{Bytes, U256}; | ||
use alloy_sol_types::{sol, SolValue}; | ||
use forge_script::ScriptArgs; | ||
use crate::tests::{ForgeScript, ForgeScriptError}; | ||
use alloy_sol_types::{private::primitives::U256, sol}; | ||
|
||
#[tokio::test(flavor = "multi_thread")] | ||
async fn we_can_run_solidity_script_from_rust() { | ||
ScriptArgs { | ||
path: "./sol_src/tests/TestScript.t.sol".to_string(), | ||
sig: "rustTestWeCanThrowErrorDependingOnParameter".to_string(), | ||
args: vec![U256::from(1234).to_string()], | ||
..Default::default() | ||
} | ||
.run_script() | ||
.await | ||
#[test] | ||
#[ignore = "Because forge needs to be installed, we are ignoring this test by default. They will still be run from within the ci."] | ||
fn we_can_run_solidity_script_from_rust() { | ||
ForgeScript::new( | ||
"./sol_src/tests/TestScript.t.sol", | ||
"rustTestWeCanThrowErrorDependingOnParameter", | ||
) | ||
.arg(U256::from(1234)) | ||
.execute() | ||
.unwrap(); | ||
|
||
assert!(ScriptArgs { | ||
path: "./sol_src/tests/TestScript.t.sol".to_string(), | ||
sig: "rustTestWeCanThrowErrorDependingOnParameter".to_string(), | ||
args: vec![U256::from(0).to_string()], | ||
..Default::default() | ||
} | ||
.run_script() | ||
.await | ||
.is_err()); | ||
assert!(matches!( | ||
ForgeScript::new( | ||
"./sol_src/tests/TestScript.t.sol", | ||
"rustTestWeCanThrowErrorDependingOnParameter", | ||
) | ||
.arg(U256::from(0)) | ||
.execute(), | ||
Err(ForgeScriptError::SolidityError { .. }) | ||
)); | ||
} | ||
#[tokio::test(flavor = "multi_thread")] | ||
async fn we_can_pass_custom_struct_into_solidity_from_rust() { | ||
#[test] | ||
#[ignore = "Because forge needs to be installed, we are ignoring this test by default. They will still be run from within the ci."] | ||
fn we_can_pass_custom_struct_into_solidity_from_rust() { | ||
sol!("./sol_src/tests/TestScript.t.sol"); | ||
let arg = TestScript::CustomStruct { | ||
value: U256::from(1234), | ||
}; | ||
ScriptArgs { | ||
path: "./sol_src/tests/TestScript.t.sol".to_string(), | ||
sig: "rustTestWeCanAcceptCustomStructAsEncodedBytes".to_string(), | ||
args: vec![Bytes::from(arg.abi_encode()).to_string()], | ||
..Default::default() | ||
} | ||
.run_script() | ||
.await | ||
ForgeScript::new( | ||
"./sol_src/tests/TestScript.t.sol", | ||
"rustTestWeCanAcceptCustomStructAsEncodedBytes", | ||
) | ||
.arg(arg) | ||
.execute() | ||
.unwrap(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use alloy_sol_types::{private::primitives::Bytes, SolValue}; | ||
use snafu::Snafu; | ||
use std::{ffi::OsStr, io, process::Command}; | ||
|
||
/// Error type returned by [ForgeScript] functions. | ||
#[derive(Debug, Snafu)] | ||
pub enum ForgeScriptError<'a> { | ||
/// The script failed to run. This is usually because `forge` is not installed. | ||
#[snafu(transparent)] | ||
ExecutionFailed { source: io::Error }, | ||
#[snafu(display("Script threw and error. Underlying command: {underlying_command:?}."))] | ||
/// The script threw an error. This could be expected behavior. | ||
SolidityError { underlying_command: &'a Command }, | ||
} | ||
|
||
/// [ForgeScript] enables running solidity from within rust. Ultimately this type calls `forge script`. | ||
/// As a result, `forge` must be installed. | ||
/// See <https://book.getfoundry.sh/getting-started/installation> for instructions. | ||
pub struct ForgeScript { | ||
command: Command, | ||
} | ||
|
||
impl ForgeScript { | ||
/// Constructs a new `ForgeScript` for running a solidity function in `path` file, where the function is named `signature`. | ||
pub fn new(path: impl AsRef<OsStr>, signature: impl AsRef<OsStr>) -> Self { | ||
let mut command = Command::new("forge"); | ||
command.arg("script").arg(path).arg("--sig").arg(signature); | ||
Self { command } | ||
} | ||
/// Adds an argument to pass to the script. Only one argument can be passed per use. | ||
pub fn arg(&mut self, arg: impl SolValue) -> &mut Self { | ||
self.command.arg(Bytes::from(arg.abi_encode()).to_string()); | ||
self | ||
} | ||
/// Executes the script as a child process, waiting for it to finish and collecting its status. | ||
pub fn execute(&mut self) -> Result<(), ForgeScriptError> { | ||
self.command | ||
.status()? | ||
.success() | ||
.then_some(()) | ||
.ok_or(ForgeScriptError::SolidityError { | ||
underlying_command: &self.command, | ||
}) | ||
} | ||
} |