Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactor tests layout #7410

Merged
merged 11 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ jobs:
# so running `forge fmt` with `--root testdata` won't actually check anything
run: |
shopt -s extglob
cargo run --bin forge -- fmt --check testdata/**/!(Vm).sol
cargo run --bin forge -- fmt --check $(find testdata -name '*.sol' ! -name Vm.sol)

crate-checks:
runs-on: ubuntu-latest
Expand Down
8 changes: 4 additions & 4 deletions crates/forge/tests/it/cheats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

use crate::{
config::*,
test_helpers::{PROJECT, RE_PATH_SEPARATOR},
test_helpers::{RE_PATH_SEPARATOR, TEST_DATA_DEFAULT},
};
use foundry_config::{fs_permissions::PathPermission, Config, FsPermissions};
use foundry_config::{fs_permissions::PathPermission, FsPermissions};
use foundry_test_utils::Filter;

/// Executes all cheat code tests but not fork cheat codes
Expand All @@ -18,9 +18,9 @@ async fn test_cheats_local() {
filter = filter.exclude_tests("(Ffi|File|Line|Root)");
}

let mut config = Config::with_root(PROJECT.root());
let mut config = TEST_DATA_DEFAULT.config.clone();
config.fs_permissions = FsPermissions::new(vec![PathPermission::read_write("./")]);
let runner = runner_with_config(config);
let runner = TEST_DATA_DEFAULT.runner_with_config(config);

TestConfig::with_filter(runner, filter).run().await;
}
92 changes: 2 additions & 90 deletions crates/forge/tests/it/config.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
//! Test config.

use crate::test_helpers::{COMPILED, EVM_OPTS, PROJECT, TEST_OPTS};
use forge::{
result::{SuiteResult, TestStatus},
MultiContractRunner, MultiContractRunnerBuilder,
};
use foundry_config::{
fs_permissions::PathPermission, Config, FsPermissions, RpcEndpoint, RpcEndpoints,
MultiContractRunner,
};
use foundry_evm::{
decode::decode_console_logs,
inspectors::CheatsConfig,
revm::primitives::SpecId,
traces::{render_trace_arena, CallTraceDecoderBuilder},
};
use foundry_test_utils::{init_tracing, Filter};
use futures::future::join_all;
use itertools::Itertools;
use std::{collections::BTreeMap, path::Path};
use std::collections::BTreeMap;

/// How to execute a test run.
pub struct TestConfig {
Expand All @@ -31,10 +26,6 @@ impl TestConfig {
Self::with_filter(runner, Filter::matches_all())
}

pub fn filter(filter: Filter) -> Self {
Self::with_filter(runner(), filter)
}

pub fn with_filter(runner: MultiContractRunner, filter: Filter) -> Self {
init_tracing();
Self { runner, should_fail: false, filter }
Expand Down Expand Up @@ -108,85 +99,6 @@ impl TestConfig {
}
}

pub fn manifest_root() -> &'static Path {
let mut root = Path::new(env!("CARGO_MANIFEST_DIR"));
// need to check here where we're executing the test from, if in `forge` we need to also allow
// `testdata`
if root.ends_with("forge") {
root = root.parent().unwrap();
}
root
}

/// Builds a base runner
pub fn base_runner() -> MultiContractRunnerBuilder {
init_tracing();
MultiContractRunnerBuilder::default()
.sender(EVM_OPTS.sender)
.with_test_options(TEST_OPTS.clone())
}

/// Builds a non-tracing runner
pub fn runner() -> MultiContractRunner {
let mut config = Config::with_root(PROJECT.root());
config.fs_permissions = FsPermissions::new(vec![PathPermission::read_write(manifest_root())]);
runner_with_config(config)
}

/// Builds a non-tracing runner
pub fn runner_with_config(mut config: Config) -> MultiContractRunner {
config.rpc_endpoints = rpc_endpoints();
config.allow_paths.push(manifest_root().to_path_buf());

let root = &PROJECT.paths.root;
let opts = &*EVM_OPTS;
let env = opts.local_evm_env();
let output = COMPILED.clone();
base_runner()
.with_cheats_config(CheatsConfig::new(&config, opts.clone(), None))
.sender(config.sender)
.build(root, output, env, opts.clone())
.unwrap()
}

/// Builds a tracing runner
pub fn tracing_runner() -> MultiContractRunner {
let mut opts = EVM_OPTS.clone();
opts.verbosity = 5;
base_runner()
.build(&PROJECT.paths.root, (*COMPILED).clone(), EVM_OPTS.local_evm_env(), opts)
.unwrap()
}

// Builds a runner that runs against forked state
pub async fn forked_runner(rpc: &str) -> MultiContractRunner {
let mut opts = EVM_OPTS.clone();

opts.env.chain_id = None; // clear chain id so the correct one gets fetched from the RPC
opts.fork_url = Some(rpc.to_string());

let env = opts.evm_env().await.expect("Could not instantiate fork environment");
let fork = opts.get_fork(&Default::default(), env.clone());

base_runner()
.with_fork(fork)
.build(&PROJECT.paths.root, (*COMPILED).clone(), env, opts)
.unwrap()
}

/// the RPC endpoints used during tests
pub fn rpc_endpoints() -> RpcEndpoints {
RpcEndpoints::new([
(
"rpcAlias",
RpcEndpoint::Url(
"https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf".to_string(),
),
),
("rpcEnvAlias", RpcEndpoint::Env("${RPC_ENV_ALIAS}".to_string())),
])
}

/// A helper to assert the outcome of multiple tests with helpful assert messages
#[track_caller]
#[allow(clippy::type_complexity)]
Expand Down
49 changes: 26 additions & 23 deletions crates/forge/tests/it/core.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Forge tests for core functionality.

use crate::config::*;
use crate::{config::*, test_helpers::TEST_DATA_DEFAULT};
use forge::result::SuiteResult;
use foundry_evm::traces::TraceKind;
use foundry_test_utils::Filter;
Expand All @@ -9,14 +9,14 @@ use std::{collections::BTreeMap, env};
#[tokio::test(flavor = "multi_thread")]
async fn test_core() {
let filter = Filter::new(".*", ".*", ".*core");
let mut runner = runner();
let mut runner = TEST_DATA_DEFAULT.runner();
let results = runner.test_collect(&filter);

assert_multiple(
&results,
BTreeMap::from([
(
"core/FailingSetup.t.sol:FailingSetupTest",
"default/core/FailingSetup.t.sol:FailingSetupTest",
vec![(
"setUp()",
false,
Expand All @@ -26,7 +26,7 @@ async fn test_core() {
)],
),
(
"core/MultipleSetup.t.sol:MultipleSetup",
"default/core/MultipleSetup.t.sol:MultipleSetup",
vec![(
"setUp()",
false,
Expand All @@ -36,34 +36,37 @@ async fn test_core() {
)],
),
(
"core/Reverting.t.sol:RevertingTest",
"default/core/Reverting.t.sol:RevertingTest",
vec![("testFailRevert()", true, None, None, None)],
),
(
"core/SetupConsistency.t.sol:SetupConsistencyCheck",
"default/core/SetupConsistency.t.sol:SetupConsistencyCheck",
vec![
("testAdd()", true, None, None, None),
("testMultiply()", true, None, None, None),
],
),
(
"core/DSStyle.t.sol:DSStyleTest",
"default/core/DSStyle.t.sol:DSStyleTest",
vec![("testFailingAssertions()", true, None, None, None)],
),
(
"core/ContractEnvironment.t.sol:ContractEnvironmentTest",
"default/core/ContractEnvironment.t.sol:ContractEnvironmentTest",
vec![
("testAddresses()", true, None, None, None),
("testEnvironment()", true, None, None, None),
],
),
(
"core/PaymentFailure.t.sol:PaymentFailureTest",
"default/core/PaymentFailure.t.sol:PaymentFailureTest",
vec![("testCantPay()", false, Some("EvmError: Revert".to_string()), None, None)],
),
("core/Abstract.t.sol:AbstractTest", vec![("testSomething()", true, None, None, None)]),
(
"core/FailingTestAfterFailedSetup.t.sol:FailingTestAfterFailedSetupTest",
"default/core/Abstract.t.sol:AbstractTest",
vec![("testSomething()", true, None, None, None)],
),
(
"default/core/FailingTestAfterFailedSetup.t.sol:FailingTestAfterFailedSetupTest",
vec![(
"setUp()",
false,
Expand All @@ -79,25 +82,25 @@ async fn test_core() {
#[tokio::test(flavor = "multi_thread")]
async fn test_linking() {
let filter = Filter::new(".*", ".*", ".*linking");
let mut runner = runner();
let mut runner = TEST_DATA_DEFAULT.runner();
let results = runner.test_collect(&filter);

assert_multiple(
&results,
BTreeMap::from([
(
"linking/simple/Simple.t.sol:SimpleLibraryLinkingTest",
"default/linking/simple/Simple.t.sol:SimpleLibraryLinkingTest",
vec![("testCall()", true, None, None, None)],
),
(
"linking/nested/Nested.t.sol:NestedLibraryLinkingTest",
"default/linking/nested/Nested.t.sol:NestedLibraryLinkingTest",
vec![
("testDirect()", true, None, None, None),
("testNested()", true, None, None, None),
],
),
(
"linking/duplicate/Duplicate.t.sol:DuplicateLibraryLinkingTest",
"default/linking/duplicate/Duplicate.t.sol:DuplicateLibraryLinkingTest",
vec![
("testA()", true, None, None, None),
("testB()", true, None, None, None),
Expand All @@ -113,14 +116,14 @@ async fn test_linking() {
#[tokio::test(flavor = "multi_thread")]
async fn test_logs() {
let filter = Filter::new(".*", ".*", ".*logs");
let mut runner = runner();
let mut runner = TEST_DATA_DEFAULT.runner();
let results = runner.test_collect(&filter);

assert_multiple(
&results,
BTreeMap::from([
(
"logs/DebugLogs.t.sol:DebugLogsTest",
"default/logs/DebugLogs.t.sol:DebugLogsTest",
vec![
(
"test1()",
Expand Down Expand Up @@ -289,7 +292,7 @@ async fn test_logs() {
],
),
(
"logs/HardhatLogs.t.sol:HardhatLogsTest",
"default/logs/HardhatLogs.t.sol:HardhatLogsTest",
vec![
(
"testInts()",
Expand Down Expand Up @@ -678,7 +681,7 @@ async fn test_env_vars() {
env::remove_var(env_var_key);

let filter = Filter::new("testSetEnv", ".*", ".*");
let mut runner = runner();
let mut runner = TEST_DATA_DEFAULT.runner();
let _ = runner.test_collect(&filter);

assert_eq!(env::var(env_var_key).unwrap(), env_var_val);
Expand All @@ -687,16 +690,16 @@ async fn test_env_vars() {
#[tokio::test(flavor = "multi_thread")]
async fn test_doesnt_run_abstract_contract() {
let filter = Filter::new(".*", ".*", ".*Abstract.t.sol".to_string().as_str());
let mut runner = runner();
let mut runner = TEST_DATA_DEFAULT.runner();
let results = runner.test_collect(&filter);
assert!(!results.contains_key("core/Abstract.t.sol:AbstractTestBase"));
assert!(results.contains_key("core/Abstract.t.sol:AbstractTest"));
assert!(!results.contains_key("default/core/Abstract.t.sol:AbstractTestBase"));
assert!(results.contains_key("default/core/Abstract.t.sol:AbstractTest"));
}

#[tokio::test(flavor = "multi_thread")]
async fn test_trace() {
let filter = Filter::new(".*", ".*", ".*trace");
let mut runner = tracing_runner();
let mut runner = TEST_DATA_DEFAULT.tracing_runner();
let suite_result = runner.test_collect(&filter);

// TODO: This trace test is very basic - it is probably a good candidate for snapshot
Expand Down
Loading
Loading