Zest is a code coverage CLI tool for Solana programs. Zest is built by LimeChain, a blockchain development and consulting firm founded in 2017. The development of the tool is supported by a grant from the Solana Foundation.
cargo install --git https://github.com/LimeChain/zest zest --force
# Move into the target project
cd ./examples/setter/anchor
# This will run coverage for the example using the `instrument-coverage` strategy without `branch` info
zest coverage
# Path to the target project can also be specified using the `--path` option
zest coverage --path ./examples/setter/anchor
# Configuration options can also be read from a (TOML) config file (`zest-coverage.toml` by default)
cat <<TOML > my_zest_config.toml
path = "./examples/setter/anchor"
branch = true
# contract_style = "anchor"
# tests = ["integration"]
# output_types = ["lcov", "html"]
TOML
# Which would run with
# `coverage_strategy` being `instrument-coverage` (Default)
# `path` being `./examples/setter/anchor/` (from config file)
# `branch` being `false` (CLI override)
zest coverage --config ./my_zest_config.toml --branch false
Note
Check zest --help
and zest coverage --help
for more info
Note
More info on the different strategies can be found here
Currently, zest
only supports testing programs, written in Rust, with tests written in Rust (usually using solana-program-test, as opposed to the classic Typescript
tests), which do not depend on the cargo-{build,test}-sbf
toolchain. A.K.A if cargo test
works for you (not cargo test-sbf
), then zest
will too
Here's a small list of publicly available Solana programs that we've tested if they work with zest
or not:
Works on:
How to make sure zest
works for your program:
-
Make sure you're using a Rust framework (solana-program-test or similar, like liteSVM) for your testing purposes
-
Make sure your tests are runnable by just
cargo test
This is done by supplying your program's
processor
(theprocess_instruction
function) directly when adding it to the test validatorlet mut validator = ProgramTest::default(); validator.add_program( "counter_solana_native", counter_solana_native::ID, processor!(counter_solana_native::process_instruction), );
That requirement is incompatible with
shank
framework, since it puts a type constraint on theprocessor
function.
Note
That happens because of the context
function from ShankContext
, seen in their example (the 'a
lifetime), which breaks the compatibility (and thus makes it testable only in sbf
mode).
Note
Branch coverage can be enabled with the --branch
flag but it requires a recent enough version of the nightly compiler to work.
It is also only supported when using the instrument-coverage
coverage strategy (default).
There isn't yet a version of the compiler that both supports `branch` coverage and `solana-program` compilation
- To support the
rustc
coverage-options
setting (tellingrustc
how to gather coverage information), we need a recent version of the compiler (this (seen in1.78.0
) for simple branch coverage and this (seen in1.79.0
) for advancedmcdc
branch coverage) - Our solana programs transitively depend on
ahash
:solana-program v1.18.1
(latest) ->borsh v0.9.3
->hashbrown v0.11.2
->ahash v0.7.7
- Unfortunately, since
Rust
removed support for thestdsimd
feature here (seen in1.78.0
),ahash v0.7.7
breaks - This is fixed in
ahash v0.8.0
, but we cannot directly update the version used bysolana-program
.- We can try to use
Cargo patches
to force the version ofahash
but they do not work for transitive dependencies (only for top-level ones, i.e. the ones in ourCargo.toml
s)
- We can try to use
- The last version of the
Rust
compiler from before the removal ofstdsimd
isnightly-2024-02-04
, but it does not yet include support for-Z coverage-options
(introduced roughly a month later)
Possible long-term solutions:
- The
solana
ecosystem moves to a newer version of theRust
compiler Have no details about such intentions, haven't researched, will probably not be soon Cargo patches
start working for transitive dependencies Unlikely, since it would be a nontrivial task to select the exact dependencies you want to patch
TLDR: we either chose to support branch
coverage or the ability to compile solana programs (IMO the second is a far more important requirement)
For feedback, feature requests or general inquiries, please reach out to [email protected]