wake icon indicating copy to clipboard operation
wake copied to clipboard

Adding fuzz flow result uncount functionality

Open MeditationDuck opened this issue 7 months ago • 0 comments

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)

MeditationDuck avatar Jul 17 '24 15:07 MeditationDuck