wake
wake copied to clipboard
Adding fuzz flow result uncount functionality
It is able to specify the return value of the fuzz branch.
If there is a sort of Invalid flow, we do not want to count those flows.
FlowResult.UNCOUNT
Continue the new flow without counting the current flow.
FlowResult.REPEAT
Repeat the same flow without counting the current flow. if the flow argument is specified, those random values are regenerated.
invariants are executed in every case.
Example fuzz test code
from wake.testing import *
from wake.testing.fuzzing import *
from pytypes.contracts.Counter import Counter
from wake.core.logging import get_logger, logging
logger = get_logger(__name__)
logger.setLevel(logging.INFO)
class CounterTest(FuzzTest):
_counter: Counter
_count: int
_owner: Account
# executed before each sequence
def pre_sequence(self) -> None:
self._owner = random_account()
self._counter = Counter.deploy(from_=self._owner)
self._count = 0
assert self._counter.owner() == self._owner.address
assert self._counter.count() == 0
@flow()
def flow_increment(self):
self._counter.increment(from_=random_account())
self._count += 1
logger.info(f"incremented count to {self._count}")
@flow()
def flow_decrement(self):
with may_revert(Panic(PanicCodeEnum.UNDERFLOW_OVERFLOW)) as e:
self._counter.decrement(from_=random_account())
if e.value is not None:
assert self._count == 0
else:
self._count -= 1
logger.warning(f"uncount: uncount flow for revert execution")
##### Choose to uncount the flow #####
return FlowResult.UNCOUNT
@flow()
def random_skip(self, skip: bool):
if skip:
logger.warning(f"skip: repeat safe flow, but random value changes")
##### Choose to repeat the flow #####
return FlowResult.REPEAT
logger.warning(f"skip: skip done follows next flow")
@invariant()
def invariant_count(self):
assert self._counter.count() == self._count
@default_chain.connect()
def test_counter_fuzz():
CounterTest().run(sequences_count=1, flows_count=10)