Skip to content

LimeChain/zest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

64 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Zest

Logo

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.

Demo screenshot

image

Install

cargo install --git https://github.com/LimeChain/zest zest --force

Usage

# 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

Program compatibility

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:

Compatibility requirements

How to make sure zest works for your program:

  1. Make sure you're using a Rust framework (solana-program-test or similar, like liteSVM) for your testing purposes

  2. Make sure your tests are runnable by just cargo test

    This is done by supplying your program's processor (the process_instruction function) directly when adding it to the test validator

    let 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 the processor 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).

Branch coverage

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 (telling rustc how to gather coverage information), we need a recent version of the compiler (this (seen in 1.78.0) for simple branch coverage and this (seen in 1.79.0) for advanced mcdc 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
    • solana-program also sets its rust-version to be 1.75.0 for the whole platform-tools suite, solana-program-library does too
  • Unfortunately, since Rust removed support for the stdsimd feature here (seen in 1.78.0), ahash v0.7.7 breaks
  • This is fixed in ahash v0.8.0, but we cannot directly update the version used by solana-program.
    • We can try to use Cargo patches to force the version of ahash but they do not work for transitive dependencies (only for top-level ones, i.e. the ones in our Cargo.tomls)
  • The last version of the Rust compiler from before the removal of stdsimd is nightly-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 the Rust 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)

Contact

For feedback, feature requests or general inquiries, please reach out to [email protected]

About

Limechain Solana Code Coverage CLI

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages