-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
feat(fuzz): ability to declare fuzz test fixtures #7428
Merged
Merged
Changes from 11 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
ef15bab
fix(fuzz): deduplicate fuzz inputs
grandizzy 3c48666
Fix tests, collect fixtures in test setup, arc fixtures
grandizzy e1f8a95
Merge remote-tracking branch 'origin' into issue-3521-fixtures
grandizzy 254017c
Cleanup
grandizzy 8586bf4
Merge remote-tracking branch 'origin' into issue-3521-fixtures
grandizzy 14c869a
Use fixture_ prefix
grandizzy d0442de
Update tests to reflect that random values are used if no fixtures
grandizzy 7e4b14c
Review changes
grandizzy 972d993
Group fuzz_calldata and fuzz_calldata_from_state in calldata mod
grandizzy 708e4db
Review changes: remove unnecessary clones, nicer code to collect fixt…
grandizzy f93254a
Merge remote-tracking branch 'origin' into issue-3521-fixtures
grandizzy 9276893
Add support for bytes and string fixtures, fixture strategy macro. So…
grandizzy a5e8da0
Remove unnecessary clone
grandizzy 14273fa
Merge remote-tracking branch 'origin' into issue-3521-fixtures
grandizzy 09ee66e
Use inline config
grandizzy 342eaf7
Merge remote-tracking branch 'origin' into issue-3521-fixtures
grandizzy 4785f93
More robust invariant assume test
grandizzy 0b7a230
Merge remote-tracking branch 'origin' into issue-3521-fixtures
grandizzy f9adb66
Merge remote-tracking branch 'origin' into issue-3521-fixtures
grandizzy fb86084
Fixtures as storage arrays, remove inline config
grandizzy 6874ead
Simplify code
grandizzy ca4d44b
Support fixed size arrays fixtures
grandizzy acdf92d
Update comment
grandizzy 12115fa
Use DynSolValue::type_strategy for address and fixed bytes fuzzed params
grandizzy e76fe8e
Add prefix to mark a storage array or a function as fixture
grandizzy 3ac9e33
Fix test
grandizzy 7e95208
Simplify code / fixture strategy macro, panic if configured fixture n…
grandizzy 4cf19cb
Consistent panic with fixture strategy if uint / int fixture of diffe…
grandizzy 53c64d3
Merge remote-tracking branch 'origin' into issue-3521-fixtures
grandizzy 997c5d4
Review changes: don't panic when invalid fixture, use prop_filter_map…
grandizzy a127780
Merge remote-tracking branch 'origin' into issue-3521-fixtures
grandizzy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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 |
---|---|---|
|
@@ -14,7 +14,7 @@ use foundry_evm_coverage::HitMaps; | |
use foundry_evm_traces::CallTraceArena; | ||
use itertools::Itertools; | ||
use serde::{Deserialize, Serialize}; | ||
use std::{collections::HashMap, fmt}; | ||
use std::{collections::HashMap, fmt, sync::Arc}; | ||
|
||
pub use proptest::test_runner::{Config as FuzzConfig, Reason}; | ||
|
||
|
@@ -272,3 +272,28 @@ impl FuzzedCases { | |
self.lowest().map(|c| c.gas).unwrap_or_default() | ||
} | ||
} | ||
|
||
/// Fixtures to be used for fuzz tests. | ||
/// The key represents name of the fuzzed parameter, value holds possible fuzzed values. | ||
/// For example, for a fixture function declared as | ||
/// `function fixture_sender() external returns (address[] memory senders)` | ||
/// the fuzz fixtures will contain `sender` key with `senders` array as value | ||
#[derive(Clone, Default, Debug)] | ||
pub struct FuzzFixtures { | ||
inner: Arc<HashMap<String, DynSolValue>>, | ||
} | ||
|
||
impl FuzzFixtures { | ||
pub fn new(fixtures: HashMap<String, DynSolValue>) -> FuzzFixtures { | ||
Self { inner: Arc::new(fixtures) } | ||
} | ||
|
||
/// Returns configured fixtures for `param_name` fuzzed parameter. | ||
pub fn param_fixtures(&self, param_name: &String) -> Option<&[DynSolValue]> { | ||
if let Some(param_fixtures) = self.inner.get(param_name) { | ||
param_fixtures.as_array() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will now only parse dynamic arrays, let's support fixed-sized arrays as well There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added with ca4d44b |
||
} else { | ||
None | ||
} | ||
} | ||
} |
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,53 @@ | ||
use alloy_dyn_abi::DynSolValue; | ||
use alloy_primitives::Address; | ||
use proptest::{ | ||
arbitrary::any, | ||
prelude::{prop, BoxedStrategy}, | ||
strategy::Strategy, | ||
}; | ||
|
||
/// The address strategy combines 2 different strategies: | ||
/// 1. A random addresses strategy if no fixture defined for current parameter. | ||
/// 2. A fixture based strategy if configured values for current parameters. | ||
/// If fixture is not a valid type then an error is raised and test suite will continue to execute | ||
/// with random address. | ||
/// | ||
/// | ||
/// For example: | ||
/// To define fixture for `owner` fuzzed parameter, return an array of possible values from | ||
/// `function fixture_owner() public returns (address[] memory)`. | ||
/// Use `owner` named parameter in fuzzed test in order to create a custom strategy | ||
/// `function testFuzz_ownerAddress(address owner, uint amount)`. | ||
#[derive(Debug, Default)] | ||
pub struct AddressStrategy {} | ||
|
||
impl AddressStrategy { | ||
/// Create a new address strategy. | ||
pub fn init(fixtures: Option<&[DynSolValue]>) -> BoxedStrategy<DynSolValue> { | ||
if let Some(fixtures) = fixtures { | ||
let address_fixtures: Vec<DynSolValue> = | ||
fixtures.iter().enumerate().map(|(_, value)| value.to_owned()).collect(); | ||
let address_fixtures_len = address_fixtures.len(); | ||
any::<prop::sample::Index>() | ||
.prop_map(move |index| { | ||
// Generate value tree from fixture. | ||
// If fixture is not a valid address, raise error and generate random value. | ||
let index = index.index(address_fixtures_len); | ||
if let Some(addr_fixture) = address_fixtures.get(index) { | ||
if let Some(addr_fixture) = addr_fixture.as_address() { | ||
return DynSolValue::Address(addr_fixture); | ||
} | ||
} | ||
error!( | ||
"{:?} is not a valid address fixture, generate random value", | ||
address_fixtures.get(index) | ||
); | ||
DynSolValue::Address(Address::random()) | ||
}) | ||
.boxed() | ||
} else { | ||
// If no config for addresses dictionary then create unbounded addresses strategy. | ||
any::<Address>().prop_map(DynSolValue::Address).boxed() | ||
} | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs oneline doc