Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code coverage support for tests (scrypto coverage command) #1640

Merged
merged 3 commits into from Nov 10, 2023

Conversation

bbarwikowski-hacken
Copy link

@bbarwikowski-hacken bbarwikowski-hacken commented Oct 31, 2023

Summary

This PR adds new command scrypto coverage which allows to create code coverage report from tests. It was implemented based on https://github.com/hknio/code-coverage-for-webassembly findings.

Please let me know what you think, in same cases I had to use ugly approach like:

/// The maximum invoke payload size.
#[cfg(not(feature = "coverage"))]
pub const MAX_INVOKE_PAYLOAD_SIZE: usize = 1 * 1024 * 1024;
#[cfg(feature = "coverage")]
pub const MAX_INVOKE_PAYLOAD_SIZE: usize = 32 * 1024 * 1024;

If you have better idea how it could be implemented, please let me know.

In the next commit I'll add test_coverage.sh script, the only problem is I'll need to install nightly version of rust and the same version of llvm as nightly rustc is using. Should I add it in Dockerfile or somewhere else?

@bbarwikowski-hacken bbarwikowski-hacken changed the title Initial code coverage support for tests (scrypto coverage command) Code coverage support for tests (scrypto coverage command) Oct 31, 2023
@bbarwikowski-hacken bbarwikowski-hacken marked this pull request as ready for review October 31, 2023 19:12
@bbarwikowski-hacken bbarwikowski-hacken marked this pull request as draft October 31, 2023 19:13
Copy link
Member

@iamyulong iamyulong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice work!

I managed to run scrypto new-package hello and scrypto coverage, after following all the hints for dependencies.

A coverage report was successfully generated, and the total coverage percentage seems to be right on index.html. However, the coverage report for the hello/src/lib.rs file is completely missed. It shows zero coverage.

reason: err.to_string(),
}
})?;
#[cfg(not(feature = "coverage"))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, did you run into any issue with gas metering ingestion for the coverage-enabled wasm code?

Copy link
Contributor

@bbarwik bbarwik Nov 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. When transaction fails for example due to out of gas then dump_coverage cannot be called because it will fail due to out of gas. When this is commented, the function dump_coverage is not using any build-in native functions so it's going to work even in case of transaction failure.
The other option is to disable gas/native functions only when dump_coverage is called.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I was hoping it wasn't an error with the instrumentation itself, otherwise we have a problem. All is good.

usd_price: USD_PRICE_IN_XRD.try_into().unwrap(),
state_storage_price: Decimal::zero(),
archive_storage_price: Decimal::zero(),
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to the difference in configuration, some tests may fail in coverage mode but not in regular test mode. I guess it's not a big deal for most cases. We will need to make sure the --no-fail-fast flag is provided when running coverage.

});
let definition = manifest_decode(&definition).unwrap_or_else(|err| {
panic!(
"Failed to parse manifest definition from path {:?} - {:?}",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: manifest definition -> package definition

if !is_nightly {
println!("Coverage tool requries nightly version of rust toolchain");
println!("You can install it by using the following commands:");
println!("rustup default nightly");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wonder if it's possible to use nightly for coverage only?

Copy link
Contributor

@bbarwik bbarwik Nov 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it could use "cargo +nightly" when building package, but there may be some issues when someone is using multiple nightly versions. Anyway, I added this in the next commit.

@bbarwikowski-hacken
Copy link
Author

I managed to run scrypto new-package hello and scrypto coverage, after following all the hints for dependencies.

A coverage report was successfully generated, and the total coverage percentage seems to be right on index.html. However, the coverage report for the hello/src/lib.rs file is completely missed. It shows zero coverage.

@iamyulong This should not happened, in my case helo/src/lib.rs has correct coverage report. Did you update dependencies in cargo.toml to use version with coverage? If you did and it didn't work then please contact me to find out why it happened.

image

@bbarwikowski-hacken bbarwikowski-hacken marked this pull request as ready for review November 10, 2023 13:01

// Build package
let path = self.path.clone().unwrap_or(current_dir().unwrap());
let (wasm_path, _) = build_package(&path, false, false, true, Level::Trace, true)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iamyulong This approach, with building package before running tests and then reusing it makes tests way faster. Here's my recommendation regarding scrypto test:

  1. Build all packages in advance, including dependencies (this may be hard when it comes to dependencies)
  2. Store information what has been build in ENV, you can also store checksum and build options
  3. In test_runner.rs try to use cached version, if it doesn't exist then build it and eventually cache it somehow (this may be hard because requires synchronization)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is generally a good idea. 👍

I believe the cargo build automatically caches previous builds and avoids re-compiling if not updates have been made, right? However, we can potentially speed up tests by caching package publishing processing and genesis bootstrap.

This is definitely something that we need to measure and improve.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it does, but it's slow and requires other tests to wait when using multiple workers/threads

@iamyulong
Copy link
Member

Hi @bbarwikowski-hacken, thanks for sharing the screenshot!

I actually got the same HTML report as yours. I think I was confused by it only showing the hit counts, rather than highlighting covered lines green and uncovered lines red. Any chance we can improve this a bit? Not a blocker and I think the PR is ready for merging. :)

@bbarwikowski-hacken
Copy link
Author

bbarwikowski-hacken commented Nov 10, 2023

Hi @bbarwikowski-hacken, thanks for sharing the screenshot!

I actually got the same HTML report as yours. I think I was confused by it only showing the hit counts, rather than highlighting covered lines green and uncovered lines red. Any chance we can improve this a bit? Not a blocker and I think the PR is ready for merging. :)

The problem is that hello package has 100% code coverage so there's nothing to highlight 😆 This is how it looks in case of not covered code.
image

@iamyulong iamyulong merged commit 7c7389d into radixdlt:develop Nov 10, 2023
24 of 25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants