Skip to content

Commit

Permalink
ci: reenable solidity tests (#200)
Browse files Browse the repository at this point in the history
# 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
iajoiner authored Oct 1, 2024
2 parents 173ec57 + a5c5a67 commit 1ef6c48
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 41 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ jobs:
sudo apt-get install -y clang lld
- name: Run cargo test
run: cargo test --all-features
- name: Install Foundry/forge for solidity tests
uses: foundry-rs/foundry-toolchain@v1
- name: Run solidity tests (ignored by default)
run: cargo test --all-features --package proof-of-sql --lib -- tests::sol_test --show-output --ignored
- name: Run cargo test without rayon
run: cargo test --no-default-features --features="arrow blitzar"
- name: Dry run cargo test (proof-of-sql) (test feature only)
Expand Down
5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ license-file = "LICENSE"

[workspace.dependencies]
ahash = { version = "0.8.11", default-features = false }
# alloy-primitives = { version = "0.8.1" }
# alloy-sol-types = { version = "0.8.1" }
alloy-sol-types = { version = "0.8.5" }
ark-bls12-381 = { version = "0.4.0" }
ark-curve25519 = { version = "0.4.0" }
ark-ec = { version = "0.4.0" }
Expand All @@ -36,7 +35,6 @@ chrono = { version = "0.4.38", default-features = false }
curve25519-dalek = { version = "4", features = ["rand_core"] }
derive_more = { version = "0.99" }
flexbuffers = { version = "2.0.0" }
# forge-script = { git = "https://github.com/foundry-rs/foundry", tag = "nightly-bf1a39980532f76cd76fd87ee32661180f606435" }
indexmap = { version = "2.1", default-features = false }
itertools = { version = "0.13.0", default-features = false, features = ["use_alloc"] }
lalrpop = { version = "0.21.0" }
Expand All @@ -56,7 +54,6 @@ serde = { version = "1", default-features = false }
serde_json = { version = "1", default-features = false, features = ["alloc"] }
snafu = { version = "0.8.4", default-features = false }
tiny-keccak = { version = "2.0.2", features = [ "keccak" ] }
# tokio = { version = "1.39.3" }
tracing = { version = "0.1.36", default-features = false }
tracing-opentelemetry = { version = "0.22.0" }
tracing-subscriber = { version = "0.3.0" }
Expand Down
5 changes: 1 addition & 4 deletions crates/proof-of-sql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,17 @@ tracing = { workspace = true, features = ["attributes"] }
zerocopy = { workspace = true }

[dev-dependencies]
# alloy-primitives = { workspace = true }
# alloy-sol-types = { workspace = true }
alloy-sol-types = { workspace = true }
arrow-csv = { workspace = true }
blitzar = { workspace = true }
clap = { workspace = true, features = ["derive"] }
criterion = { workspace = true, features = ["html_reports"] }
# forge-script = { workspace = true }
merlin = { workspace = true }
opentelemetry = { workspace = true }
opentelemetry-jaeger = { workspace = true }
rand = { workspace = true, default-features = false }
rand_core = { workspace = true, default-features = false }
serde_json = { workspace = true }
# tokio = { workspace = true }
tracing = { workspace = true }
tracing-opentelemetry = { workspace = true }
tracing-subscriber = { workspace = true }
Expand Down
4 changes: 3 additions & 1 deletion crates/proof-of-sql/src/tests/mod.rs
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};
61 changes: 29 additions & 32 deletions crates/proof-of-sql/src/tests/sol_test.rs
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();
}
45 changes: 45 additions & 0 deletions crates/proof-of-sql/src/tests/sol_test_util.rs
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,
})
}
}

0 comments on commit 1ef6c48

Please sign in to comment.