General overview

To get an idea about what hevm is, see CAV'24 paper. You can also check out a few presentations by @msooseth.

Debugging

Printf-style debugging

Haskell offers a way to print messages anywhere in the code with Debug.Trace. The simplest is trace which takes a string and a value and returns the same value while printing the string. For example

add x y = trace "Hello from add!" (x + y)

Testing

hevm uses Tasty framework for running tests, including QuickCheck for property-based testing.

Running tests

The basic command to run the tests is:

cabal run test

For development, it might be beneficial to pass devel flag:

cabal run -f devel test

This should enable parallel compilation and test runs (see the config file hevm.cabal).

Additional parameters can be passed to the test runner after --. For example cabal run test -- --help will list all the additional parameters.

Some of the interesting options are -p <PATTERN> to filter only some of the tests and --quickcheck-tests <NUMBER> to control how many tests quickcheck will generate for each property test.

On property-based testing

There are a few ways to control how many tests Quickcheck will generate per property. By default, it generates 100 tests (satisfying the precondition). This can be controlled by maxSuccess argument passed to Quickcheck, or, in Tasty framework, using localOption (QuickCheckTests <N>). Passing --quickcheck-tests <N> to the binary will change this value to <N>. This value can be dynamically adjusted for a test group or a specific test. For example, instead of localOption it is possible to use adjustOption for a test group. The following ensures that for the following test group, the maximal value of the QuickCheckTests option is 50 (but if the current value is lower, it will be left unchanged).

adjustOption (\(Test.Tasty.QuickCheck.QuickCheckTests n) -> Test.Tasty.QuickCheck.QuickCheckTests (min n 50))

Similarly, the maxSuccess value can be modified for a single test. The following sets the number of tests generated to 20 for the particular test:

testProperty <property_name> $ withMaxSuccess 20 $ ...

Profiling

Profiling Haskell code

NOTE: Most of the time will likely be spent in the solver, and that will not show up when profiling Haskell application.

In order to build the application with profiling information, we need to pass --enable-profiling to cabal. If we want to profile the test suite, we could run

cabal run test --enable-profiling -- +RTS -p

Note that +RTS means the next arguments will be passed to GHC and -p instructs the program to create a time profile report. This report is written into the .prof file. If we want to pass arguments to our executable, we have to indicate this with -RTS, for example, to profile run of only some tests, we would use

cabal run test --enable-profiling -- +RTS -p -RTS -p <test_to_profile>