diff --git a/crates/config/src/inline/conf_parser.rs b/crates/config/src/inline/conf_parser.rs index e6944965499d8..d76c75ed67024 100644 --- a/crates/config/src/inline/conf_parser.rs +++ b/crates/config/src/inline/conf_parser.rs @@ -2,6 +2,13 @@ use super::{remove_whitespaces, InlineConfigParserError}; use crate::{inline::INLINE_CONFIG_PREFIX, InlineConfigError, NatSpec}; use regex::Regex; +/// Used to detect invalid configuration keys in the inline config. +/// +/// # Example +/// +/// forge-config: default.fuzz.runs = 100 - `fuzz` is a valid key +/// forge-config: default.wrong.runs = 100 - `wrong` is an invalid key +const VALID_CONFIG_KEYS: [&str; 2] = ["fuzz", "invariant"]; /// This trait is intended to parse configurations from /// structured text. Foundry users can annotate Solidity test functions, /// providing special configs just for the execution of a specific test. @@ -41,10 +48,27 @@ where fn merge(&self, natspec: &NatSpec) -> Result, InlineConfigError> { let config_key = Self::config_key(); - let configs = natspec - .current_profile_configs() - .filter(|l| l.contains(&config_key)) - .collect::>(); + let mut configs = Vec::new(); + for line in natspec.current_profile_configs() { + if !VALID_CONFIG_KEYS.iter().any(|&key| line.contains(key)) { + let wrong_key = line + .split('.') + .nth(1) // Get the part after the first dot (profile.KEY.value) + .unwrap_or("unknown-config-key") + .to_string(); + return Err(InlineConfigError { + line, + source: InlineConfigParserError::InvalidConfigKey( + wrong_key, + format!("{VALID_CONFIG_KEYS:?}"), + ), + }); + } + + if line.contains(&config_key) { + configs.push(line); + } + } self.try_merge(&configs).map_err(|e| { let line = natspec.debug_context(); diff --git a/crates/config/src/inline/error.rs b/crates/config/src/inline/error.rs index ddcb6a61bdb89..fd895c6deb741 100644 --- a/crates/config/src/inline/error.rs +++ b/crates/config/src/inline/error.rs @@ -5,6 +5,9 @@ pub enum InlineConfigParserError { /// The property cannot be mapped to the configuration object #[error("'{0}' is an invalid config property")] InvalidConfigProperty(String), + /// An invalid config key has been provided + #[error("'{0}' is an invalid config key. Available config keys are: {1}")] + InvalidConfigKey(String, String), /// An invalid profile has been provided #[error("'{0}' specifies an invalid profile. Available profiles are: {1}")] InvalidProfile(String, String), diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 6444802e3bc9b..5a946a1bf15da 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -108,7 +108,10 @@ mod invariant; pub use invariant::InvariantConfig; mod inline; -pub use inline::{validate_profiles, InlineConfig, InlineConfigError, InlineConfigParser, NatSpec}; +pub use inline::{ + validate_profiles, InlineConfig, InlineConfigError, InlineConfigParser, + InlineConfigParserError, NatSpec, +}; pub mod soldeer; use soldeer::{SoldeerConfig, SoldeerDependencyConfig}; diff --git a/crates/forge/tests/it/inline.rs b/crates/forge/tests/it/inline.rs index 4448f982dcd3c..af7762e474ae4 100644 --- a/crates/forge/tests/it/inline.rs +++ b/crates/forge/tests/it/inline.rs @@ -3,7 +3,7 @@ use crate::test_helpers::{ForgeTestData, ForgeTestProfile, TEST_DATA_DEFAULT}; use forge::{result::TestKind, TestOptionsBuilder}; use foundry_config::{FuzzConfig, InvariantConfig}; -use foundry_test_utils::Filter; +use foundry_test_utils::{forgetest_init, Filter}; #[tokio::test(flavor = "multi_thread")] async fn inline_config_run_fuzz() { @@ -98,3 +98,30 @@ fn build_test_options_just_one_valid_profile() { // per-test configs for "default" and "ci" profiles assert!(build_result.is_err()); } + +forgetest_init!(tests_invalid_config_key, |prj, cmd| { + prj.wipe_contracts(); + + prj.insert_ds_test(); + + prj.add_test( + "InvalidInlineConf.t.sol", + r#" + import {Test} from "forge-std/Test.sol"; + + contract InvalidInlineConf is Test { + /// forge-config: default.fuzz.runs = 1024 + /// forge-config: default.invalid.runs = 1024 + function testInvalidInlineConf() public {} + } + "#, + ) + .unwrap(); + + cmd.args(["test", "--mt", "testInvalidInlineConf"]).assert_failure().stderr_eq( + r#"Error: Inline config error detected at forge-config:default.invalid.runs=1024 + +Context: +- 'invalid' is an invalid config key. Available config keys are: [..]"#, + ); +});