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
[Testing] Introduce proptest
property testing library and add type alises for hashbrown
types
#4477
Open
cylewitruk
wants to merge
28
commits into
next
Choose a base branch
from
testing/introduce-fake
base: next
Could not load branches
Branch not found: {{ refName }}
Could not load tags
Nothing to show
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
423855f
testing: introduce the crate to help with faking complex types
cylewitruk c89c917
fix: update faking methods to always use the received instance.
cylewitruk 2d15f35
fix: update faking methods to always use the received 'Rng' instance.
cylewitruk 9b63f36
added new 'StacksHashMap' and 'StacksHashSet' types to 'stacks-common'
cylewitruk a706834
wip: new clarity-db tests, fix remaining impls for 'fake'
cylewitruk cd7d30d
wip: moved fake to workspace dep
cylewitruk ff26172
wip: add fuzz-loop for tests using fake
cylewitruk 7a468e8
chore: cargo fmt-stacks
cylewitruk b12c2c8
chore: update lockfile
cylewitruk ec807ed
chore: remove unnecessary include
cylewitruk fc62d41
wip: playing with propmap instead of fake
cylewitruk 47b022f
feat(clarity-proptest): add a contract strategy stub
Acaccia bde7e77
fix: resolve DNS/hostnames for signer node_host value #4466
zone117x 99a543a
wip: wrap hashbrown in fasade types
cylewitruk 5a304c8
wip: wrap hashbrown in fasade types
cylewitruk 80defd4
wip: fixes for StacksHashMap and StacksHashSet
cylewitruk 23c26f0
wip: cargo fmt-stacks
cylewitruk aa37f32
wip: proptest vs fake
cylewitruk 0bfd47d
wip: migrating from fake to proptest for generation
cylewitruk 6f2ec6d
wip: fix for random usize within a range
cylewitruk 290684a
replace fake with proptest
cylewitruk fce54d6
chore: cargo fmt-stacks
cylewitruk ec8ced6
chore: cleanup, fmt
cylewitruk f0b32a0
chore: rebase on next, cleanup & fmt
cylewitruk 2f22c6c
added proptest strategy examples in stackslib + dependency issue + fm…
cylewitruk 265ca00
wip: attempting to locate dkg timeout issue
cylewitruk ae14e59
revert wrapper hashmap/set types, caused problems in stackerlib
cylewitruk a53aeed
fmt-stacks
cylewitruk File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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 |
---|---|---|
@@ -0,0 +1,110 @@ | ||
use proptest::prelude::*; | ||
use rand::distributions::uniform::SampleRange; | ||
use serde::de::value; | ||
|
||
use super::*; | ||
use crate::vm::callables::{DefineType, DefinedFunction, FunctionIdentifier}; | ||
use crate::vm::database::{ | ||
DataMapMetadata, DataVariableMetadata, FungibleTokenMetadata, NonFungibleTokenMetadata, | ||
}; | ||
use crate::vm::representations::TraitDefinition; | ||
use crate::vm::types::FunctionSignature; | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`FunctionIdentifier`] instance | ||
/// representing a user-defined function. | ||
pub fn function_identifier_user() -> impl Strategy<Value = FunctionIdentifier> { | ||
(clarity_name(), clarity_name()).prop_map(|(name, context)| { | ||
FunctionIdentifier::new_user_function(&context.to_string(), &name.to_string()) | ||
}) | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`FunctionIdentifier`] instance | ||
/// representing a native function. | ||
pub fn function_identifier_native() -> impl Strategy<Value = FunctionIdentifier> { | ||
(clarity_name()).prop_map(|name| FunctionIdentifier::new_native_function(&name.to_string())) | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`FunctionIdentifier`] | ||
/// instance representing a function of any kind, user-defined or native. | ||
pub fn function_identifier() -> impl Strategy<Value = FunctionIdentifier> { | ||
prop_oneof![function_identifier_user(), function_identifier_native()] | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`DefineType`] variant. | ||
pub fn define_type() -> impl Strategy<Value = DefineType> { | ||
prop_oneof![ | ||
Just(DefineType::Public), | ||
Just(DefineType::Private), | ||
Just(DefineType::ReadOnly) | ||
] | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`DataVariableMetadata`] | ||
/// instance. | ||
pub fn data_variable_metadata() -> impl Strategy<Value = DataVariableMetadata> { | ||
type_signature().prop_map(|value_type| DataVariableMetadata { value_type }) | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`DataMapMetadata`] instance. | ||
pub fn data_map_metadata() -> impl Strategy<Value = DataMapMetadata> { | ||
(type_signature(), type_signature()).prop_map(|(key_type, value_type)| DataMapMetadata { | ||
key_type, | ||
value_type, | ||
}) | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`NonFungibleTokenMetadata`] | ||
/// instance. | ||
pub fn nft_metadata() -> impl Strategy<Value = NonFungibleTokenMetadata> { | ||
type_signature().prop_map(|key_type| NonFungibleTokenMetadata { key_type }) | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`FungibleTokenMetadata`] | ||
/// instance. | ||
pub fn ft_metadata() -> impl Strategy<Value = FungibleTokenMetadata> { | ||
any::<Option<u128>>().prop_map(|total_supply| FungibleTokenMetadata { total_supply }) | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`FunctionSignature`] | ||
/// instance. | ||
pub fn function_signature() -> impl Strategy<Value = FunctionSignature> { | ||
( | ||
// arg_types | ||
prop::collection::vec(type_signature(), 0..3), | ||
// return_type | ||
type_signature(), | ||
) | ||
.prop_map(|(args, returns)| FunctionSignature { args, returns }) | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`DefinedFunction`] | ||
/// instance. | ||
pub fn defined_function() -> impl Strategy<Value = DefinedFunction> { | ||
( | ||
// identifier | ||
function_identifier(), | ||
// name | ||
clarity_name(), | ||
// arg_types + arguments, which must have the same length | ||
(0usize..3usize).prop_flat_map(|x| { | ||
( | ||
prop::collection::vec(type_signature(), x..=x), | ||
prop::collection::vec(clarity_name(), x..=x), | ||
) | ||
}), | ||
// define_type | ||
define_type(), | ||
// body | ||
symbolic_expression(), | ||
) | ||
.prop_map( | ||
|(identifier, name, args, define_type, body)| DefinedFunction { | ||
identifier, | ||
name, | ||
arg_types: args.0, | ||
define_type, | ||
arguments: args.1, | ||
body, | ||
}, | ||
) | ||
} |
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,83 @@ | ||
use proptest::collection::btree_map; | ||
use proptest::prelude::*; | ||
use stacks_common::proptesting::*; | ||
|
||
use super::*; | ||
use crate::types::{StacksHashMap as HashMap, StacksHashSet as HashSet}; | ||
use crate::vm::contracts::Contract; | ||
use crate::vm::types::PrincipalData; | ||
use crate::vm::{ClarityVersion, ContractContext, Value}; | ||
|
||
pub fn contract_context(clarity_version: ClarityVersion) -> impl Strategy<Value = ContractContext> { | ||
( | ||
// contract_identifier | ||
principal_contract().prop_map(|p| match p { | ||
Value::Principal(PrincipalData::Contract(qual)) => qual, | ||
_ => unreachable!(), | ||
}), | ||
// variables | ||
prop::collection::vec((clarity_name(), PropValue::any().prop_map_into()), 0..8).prop_map( | ||
|v| { | ||
v.into_iter() | ||
.map(|(k, v)| (k, v)) | ||
.collect::<HashMap<_, _>>() | ||
}, | ||
), | ||
// functions | ||
stacks_hash_map(clarity_name(), defined_function(), 1..5), | ||
// defined_traits | ||
stacks_hash_map( | ||
clarity_name(), | ||
btree_map(clarity_name(), function_signature(), 1..5), | ||
1..5, | ||
), | ||
// implemented_traits | ||
stacks_hash_set(trait_identifier(), 0..3), | ||
// persisted_names | ||
stacks_hash_set(clarity_name(), 0..5), | ||
// meta_data_map | ||
stacks_hash_map(clarity_name(), data_map_metadata(), 1..5), | ||
// meta_data_var | ||
stacks_hash_map(clarity_name(), data_variable_metadata(), 1..5), | ||
// meta_nft | ||
stacks_hash_map(clarity_name(), nft_metadata(), 1..5), | ||
// meta_ft | ||
stacks_hash_map(clarity_name(), ft_metadata(), 1..5), | ||
// data_size | ||
0u64..64, | ||
) | ||
.prop_map( | ||
move |( | ||
contract_identifier, | ||
variables, | ||
functions, | ||
defined_traits, | ||
implemented_traits, | ||
persisted_names, | ||
meta_data_map, | ||
meta_data_var, | ||
meta_nft, | ||
meta_ft, | ||
data_size, | ||
)| { | ||
let mut cc = ContractContext::new(contract_identifier, clarity_version); | ||
cc.variables = variables; | ||
cc.functions = functions; | ||
cc.defined_traits = defined_traits; | ||
cc.implemented_traits = implemented_traits; | ||
cc.persisted_names = persisted_names; | ||
cc.meta_data_map = meta_data_map; | ||
cc.meta_data_var = meta_data_var; | ||
cc.meta_nft = meta_nft; | ||
cc.meta_ft = meta_ft; | ||
cc.data_size = data_size; | ||
cc | ||
}, | ||
) | ||
} | ||
|
||
pub fn contract() -> impl Strategy<Value = Contract> { | ||
clarity_version() | ||
.prop_flat_map(contract_context) | ||
.prop_map(|contract_context| Contract { contract_context }) | ||
} |
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,27 @@ | ||
use proptest::prop_oneof; | ||
use proptest::strategy::{Just, Strategy, ValueTree}; | ||
use proptest::test_runner::{Config, RngAlgorithm, TestRng, TestRunner}; | ||
use rand::Rng; | ||
use stacks_common::types::StacksHashMap as HashMap; | ||
|
||
pub mod callables; | ||
pub mod contracts; | ||
pub mod representations; | ||
pub mod types; | ||
pub mod values; | ||
|
||
pub use callables::*; | ||
pub use contracts::*; | ||
pub use representations::*; | ||
pub use types::*; | ||
pub use values::*; | ||
|
||
use crate::vm::ClarityVersion; | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`ClarityVersion`] instance. | ||
pub fn clarity_version() -> impl Strategy<Value = ClarityVersion> { | ||
prop_oneof![ | ||
Just(crate::vm::ClarityVersion::Clarity1), | ||
Just(crate::vm::ClarityVersion::Clarity2), | ||
] | ||
} |
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,40 @@ | ||
use proptest::prelude::*; | ||
|
||
use super::*; | ||
use crate::vm::representations::{Span, TraitDefinition}; | ||
use crate::vm::{ClarityName, ContractName, SymbolicExpression, SymbolicExpressionType}; | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`ClarityName`]. | ||
pub fn clarity_name() -> impl Strategy<Value = ClarityName> { | ||
"[a-z]{40}".prop_map(|s| s.try_into().unwrap()) | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`ContractName`]. | ||
pub fn contract_name() -> impl Strategy<Value = ContractName> { | ||
"[a-zA-Z]{1,40}".prop_map(|s| s.try_into().unwrap()) | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`TraitDefinition`]. | ||
pub fn trait_definition() -> impl Strategy<Value = TraitDefinition> { | ||
prop_oneof![ | ||
trait_identifier().prop_map(TraitDefinition::Defined), | ||
trait_identifier().prop_map(TraitDefinition::Imported) | ||
] | ||
} | ||
|
||
/// Returns a [`Strategy`] for randomly generating a [`SymbolicExpression`]. | ||
pub fn symbolic_expression() -> impl Strategy<Value = SymbolicExpression> { | ||
let leaf = prop_oneof![ | ||
clarity_name().prop_map(|name| SymbolicExpression::atom(name)), | ||
PropValue::any().prop_map(|val| SymbolicExpression::atom_value(val.into())), | ||
PropValue::any().prop_map(|val| SymbolicExpression::literal_value(val.into())), | ||
trait_identifier().prop_map(|name| SymbolicExpression::field(name)), | ||
(clarity_name(), trait_definition()) | ||
.prop_map(|(n, t)| SymbolicExpression::trait_reference(n, t)), | ||
]; | ||
|
||
leaf.prop_recursive(3, 64, 5, |inner| { | ||
prop::collection::vec(inner, 1..3) | ||
.prop_map(|list| SymbolicExpression::list(list.into_boxed_slice())) | ||
}) | ||
} |
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.
Missing copyright and licensing comment block