Skip to content

Commit

Permalink
test(script): make ScriptTester configurable (#2365)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse authored Jul 18, 2022
1 parent 7821c5a commit 0c289ef
Show file tree
Hide file tree
Showing 6 changed files with 1,652 additions and 1,588 deletions.
111 changes: 66 additions & 45 deletions cli/test-utils/src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,6 @@ use crate::TestCommand;

pub const BROADCAST_TEST_PATH: &str = "src/Broadcast.t.sol";

pub enum ScriptOutcome {
OkSimulation,
OkBroadcast,
WarnSpecifyDeployer,
MissingSender,
MissingWallet,
FailedScript,
}

impl ScriptOutcome {
pub fn as_str(&self) -> &'static str {
match self {
ScriptOutcome::OkSimulation => "SIMULATION COMPLETE. To broadcast these",
ScriptOutcome::OkBroadcast => "ONCHAIN EXECUTION COMPLETE & SUCCESSFUL",
ScriptOutcome::WarnSpecifyDeployer => "You have more than one deployer who could predeploy libraries. Using `--sender` instead.",
ScriptOutcome::MissingSender => "You seem to be using Foundry's default sender. Be sure to set your own --sender",
ScriptOutcome::MissingWallet => "No associated wallet",
ScriptOutcome::FailedScript => "Script failed.",
}
}

pub fn is_err(&self) -> bool {
match self {
ScriptOutcome::OkSimulation => false,
ScriptOutcome::OkBroadcast => false,
ScriptOutcome::WarnSpecifyDeployer => false,
ScriptOutcome::MissingSender => true,
ScriptOutcome::MissingWallet => true,
ScriptOutcome::FailedScript => true,
}
}
}

/// A helper struct to test forge script scenarios
pub struct ScriptTester {
pub accounts_pub: Vec<Address>,
Expand All @@ -53,19 +20,23 @@ pub struct ScriptTester {
}

impl ScriptTester {
pub fn new(mut cmd: TestCommand, endpoint: &str, current_dir: &Path) -> Self {
ScriptTester::copy_testdata(current_dir).unwrap();
cmd.set_current_dir(current_dir);

let target_contract = current_dir.join(BROADCAST_TEST_PATH).to_string_lossy().to_string();
/// Creates a new instance of a Tester for the given contract
pub fn new(
mut cmd: TestCommand,
endpoint: &str,
project_root: &Path,
target_contract: &str,
) -> Self {
ScriptTester::copy_testdata(project_root).unwrap();
cmd.set_current_dir(project_root);

cmd.args([
"script",
"-r",
"ds-test/=lib/",
target_contract.as_str(),
target_contract,
"--root",
current_dir.to_str().unwrap(),
project_root.to_str().unwrap(),
"--fork-url",
endpoint,
"-vvvvv",
Expand All @@ -88,13 +59,28 @@ impl ScriptTester {
}
}

/// Creates a new instance of a Tester for the `broadcast` test at the given `project_root` by
/// configuring the `TestCommand` with script
pub fn new_broadcast(cmd: TestCommand, endpoint: &str, project_root: &Path) -> Self {
let target_contract = project_root.join(BROADCAST_TEST_PATH).to_string_lossy().to_string();

// copy the broadcast test
let testdata = Self::testdata_path();
std::fs::copy(testdata + "/cheats/Broadcast.t.sol", project_root.join(BROADCAST_TEST_PATH))
.expect("Failed to initialize broadcast contract");

Self::new(cmd, endpoint, project_root, &target_contract)
}

/// Returns the path to the dir that contains testdata
fn testdata_path() -> String {
format!("{}/../../testdata", env!("CARGO_MANIFEST_DIR"))
}

/// Initialises the test contracts by copying them into the workspace
fn copy_testdata(current_dir: &Path) -> eyre::Result<()> {
let testdata = format!("{}/../../testdata", env!("CARGO_MANIFEST_DIR"));
let testdata = Self::testdata_path();
std::fs::copy(testdata.clone() + "/cheats/Cheats.sol", current_dir.join("src/Cheats.sol"))?;
std::fs::copy(
testdata.clone() + "/cheats/Broadcast.t.sol",
current_dir.join(BROADCAST_TEST_PATH),
)?;
std::fs::copy(testdata + "/lib/ds-test/src/test.sol", current_dir.join("lib/test.sol"))?;

Ok(())
Expand Down Expand Up @@ -176,3 +162,38 @@ impl ScriptTester {
self
}
}

/// Various `forge` script results
#[derive(Debug)]
pub enum ScriptOutcome {
OkSimulation,
OkBroadcast,
WarnSpecifyDeployer,
MissingSender,
MissingWallet,
FailedScript,
}

impl ScriptOutcome {
pub fn as_str(&self) -> &'static str {
match self {
ScriptOutcome::OkSimulation => "SIMULATION COMPLETE. To broadcast these",
ScriptOutcome::OkBroadcast => "ONCHAIN EXECUTION COMPLETE & SUCCESSFUL",
ScriptOutcome::WarnSpecifyDeployer => "You have more than one deployer who could predeploy libraries. Using `--sender` instead.",
ScriptOutcome::MissingSender => "You seem to be using Foundry's default sender. Be sure to set your own --sender",
ScriptOutcome::MissingWallet => "No associated wallet",
ScriptOutcome::FailedScript => "Script failed.",
}
}

pub fn is_err(&self) -> bool {
match self {
ScriptOutcome::OkSimulation |
ScriptOutcome::OkBroadcast |
ScriptOutcome::WarnSpecifyDeployer => false,
ScriptOutcome::MissingSender |
ScriptOutcome::MissingWallet |
ScriptOutcome::FailedScript => true,
}
}
}
6 changes: 6 additions & 0 deletions cli/test-utils/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,12 @@ impl TestProject {
self.inner().add_source("test.sol", s).unwrap()
}

/// Adds `console.sol` as a source under "console.sol"
pub fn insert_console(&self) -> PathBuf {
let s = include_str!("../../../testdata/logs/console.sol");
self.inner().add_source("console.sol", s).unwrap()
}

/// Asserts all project paths exist
///
/// - sources
Expand Down
2 changes: 1 addition & 1 deletion cli/tests/it/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ethers::solc::{
use foundry_cli_test_utils::{
ethers_solc::PathStyle,
forgetest, forgetest_init,
util::{pretty_err, read_string, OutputExt, TestCommand, TestProject},
util::{read_string, OutputExt, TestCommand, TestProject},
};
use foundry_config::{parse_with_profile, BasicConfig, Chain, Config, SolidityErrorCode};
use std::{env, fs, path::PathBuf};
Expand Down
59 changes: 46 additions & 13 deletions cli/tests/it/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,47 @@
use anvil::{spawn, NodeConfig};
use ethers::abi::Address;
use foundry_cli_test_utils::{
forgetest, forgetest_async,
forgetest, forgetest_async, forgetest_init,
util::{TestCommand, TestProject},
ScriptOutcome, ScriptTester,
};

use regex::Regex;
use std::{env, path::PathBuf, str::FromStr};

// Tests that fork cheat codes can be used in script
forgetest_init!(
#[ignore]
can_use_fork_cheat_codes_in_script,
|prj: TestProject, mut cmd: TestCommand| {
let script = prj
.inner()
.add_source(
"Foo",
r#"
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.10;
import "forge-std/Script.sol";
contract ContractScript is Script {
function setUp() public {}
function run() public {
uint256 fork = vm.activeFork();
vm.rollFork(11469702);
}
}
"#,
)
.unwrap();

let rpc = foundry_utils::rpc::next_http_rpc_endpoint();

cmd.arg("script").arg(script).args(["--fork-url", rpc.as_str(), "-vvvv"]);
}
);

// Tests that the `run` command works correctly
forgetest!(can_execute_script_command, |prj: TestProject, mut cmd: TestCommand| {
let script = prj
Expand Down Expand Up @@ -180,7 +213,7 @@ result: uint256 255

forgetest_async!(can_deploy_script_without_lib, |prj: TestProject, cmd: TestCommand| async move {
let (_api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.load_private_keys(vec![0, 1])
Expand All @@ -194,7 +227,7 @@ forgetest_async!(can_deploy_script_without_lib, |prj: TestProject, cmd: TestComm

forgetest_async!(can_deploy_script_with_lib, |prj: TestProject, cmd: TestCommand| async move {
let (_api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.load_private_keys(vec![0, 1])
Expand All @@ -208,7 +241,7 @@ forgetest_async!(can_deploy_script_with_lib, |prj: TestProject, cmd: TestCommand

forgetest_async!(can_resume_script, |prj: TestProject, cmd: TestCommand| async move {
let (_api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.load_private_keys(vec![0])
Expand All @@ -226,7 +259,7 @@ forgetest_async!(can_resume_script, |prj: TestProject, cmd: TestCommand| async m

forgetest_async!(can_deploy_broadcast_wrap, |prj: TestProject, cmd: TestCommand| async move {
let (_api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.add_deployer(2)
Expand All @@ -241,7 +274,7 @@ forgetest_async!(can_deploy_broadcast_wrap, |prj: TestProject, cmd: TestCommand|

forgetest_async!(panic_no_deployer_set, |prj: TestProject, cmd: TestCommand| async move {
let (_api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.load_private_keys(vec![0, 1])
Expand All @@ -253,7 +286,7 @@ forgetest_async!(panic_no_deployer_set, |prj: TestProject, cmd: TestCommand| asy

forgetest_async!(can_deploy_no_arg_broadcast, |prj: TestProject, cmd: TestCommand| async move {
let (_api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.add_deployer(0)
Expand All @@ -268,7 +301,7 @@ forgetest_async!(can_deploy_no_arg_broadcast, |prj: TestProject, cmd: TestComman

forgetest_async!(can_deploy_with_create2, |prj: TestProject, cmd: TestCommand| async move {
let (api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

// Prepare CREATE2 Deployer
let addr = Address::from_str("0x4e59b44847b379578588920ca78fbf26c0b4956c").unwrap();
Expand All @@ -292,7 +325,7 @@ forgetest_async!(
can_deploy_100_txes_concurrently,
|prj: TestProject, cmd: TestCommand| async move {
let (_api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.load_private_keys(vec![0])
Expand All @@ -309,7 +342,7 @@ forgetest_async!(
can_deploy_mixed_broadcast_modes,
|prj: TestProject, cmd: TestCommand| async move {
let (_api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.load_private_keys(vec![0])
Expand All @@ -324,7 +357,7 @@ forgetest_async!(

forgetest_async!(deploy_with_setup, |prj: TestProject, cmd: TestCommand| async move {
let (_api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.load_private_keys(vec![0])
Expand All @@ -338,7 +371,7 @@ forgetest_async!(deploy_with_setup, |prj: TestProject, cmd: TestCommand| async m

forgetest_async!(fail_broadcast_staticcall, |prj: TestProject, cmd: TestCommand| async move {
let (_api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.load_private_keys(vec![0])
Expand All @@ -352,7 +385,7 @@ forgetest_async!(
check_broadcast_log,
|prj: TestProject, cmd: TestCommand| async move {
let (api, handle) = spawn(NodeConfig::test()).await;
let mut tester = ScriptTester::new(cmd, &handle.http_endpoint(), prj.root());
let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

// Prepare CREATE2 Deployer
let addr = Address::from_str("0x4e59b44847b379578588920ca78fbf26c0b4956c").unwrap();
Expand Down
Loading

0 comments on commit 0c289ef

Please sign in to comment.