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

Can we use external tests to generate coverage report? #93

Closed
YJDoc2 opened this issue Sep 19, 2021 · 5 comments
Closed

Can we use external tests to generate coverage report? #93

YJDoc2 opened this issue Sep 19, 2021 · 5 comments
Labels
C-enhancement Category: A new feature or an improvement for an existing one

Comments

@YJDoc2
Copy link

YJDoc2 commented Sep 19, 2021

I do not know much about how the code coverage data generation works, so sorry if this is a stupid question, but can we use external programs that run our binary to generate coverage data?

To elaborate, I am contributing to https://github.com/containers/youki/ , where we use cargo-llvm-cov in CI to generate coverage report. As of now, we generate coverage using unit tests, which are Rust tests (marked with #[tests] attribute).

Now to validate that the runtime itself is consistent with OCI spec, OCI has validation tests which run youki binary and test it on various conditions : https://github.com/opencontainers/runtime-tools

My question is : is it possible to generate coverage data from those tests, and use that as well to find total coverage?

Thanks for you time.

@taiki-e
Copy link
Owner

taiki-e commented Sep 20, 2021

Currently, there is no easy way to get coverage data from binaries run outside of the cargo process. (When running binaries inside the cargo process, there are a few ways: #68, #1 (comment))

Having said that, I don't think it would be difficult to implement that.

Probably, adding an option to output the environment variables set by set_env function, and combining a command that does that with --no-run should work well. Something like:

cargo llvm-cov show-env > ./env # get the environment variables needed for get coverage data 
source ./env # apply environment variables

cargo build # build rust binaries

# commands using binaries in target/debug/*, including `cargo test`

cargo llvm-cov --no-run --lcov # collect coverage data and generate report

@taiki-e taiki-e added the C-enhancement Category: A new feature or an improvement for an existing one label Sep 20, 2021
@YJDoc2
Copy link
Author

YJDoc2 commented Sep 21, 2021

Hey, Thanks for the reply. I will surely try it out by setting the env variables as per the set_env function. If you won't mind, can you keep this issue open for some more time? Thanks again. :)

@davidhewitt
Copy link
Sponsor Contributor

👍 this looks potentially useful for PyO3 too - we build dynamic libraries for a number of example Python extensions and run pytest against those. I think the same pattern suggested here could apply for measuring coverage of those.

bors bot added a commit that referenced this issue Jan 1, 2022
115: cli: add show-env subcommand r=taiki-e a=davidhewitt

Implements the `show-env` suggestion from #93 (comment)

An example output:

```
$ cargo llvm-cov show-env
RUSTFLAGS=" -Z instrument-coverage --remap-path-prefix /home/david/dev/pyo3/= --cfg coverage --cfg trybuild_no_target"
LLVM_PROFILE_FILE="/home/david/dev/pyo3/target/llvm-cov-target/pyo3-%m.profraw"
CARGO_INCREMENTAL="0"
CARGO_TARGET_DIR="/home/david/dev/pyo3/target/llvm-cov-target"
```

After exporting these vars, I had a go at building pyo3's `cdylib` examples and then running them with `pytest`.

Pleased to see that I do get profile output in the expected location:

```
$ ls target/llvm-cov-target/
CACHEDIR.TAG                         pyo3-6622988374613674511_0.profraw
debug                                pyo3-8390305564713967804_0.profraw
pyo3-10144924340354712083_0.profraw  pyo3-8655209440434687052_0.profraw
pyo3-12448306348928428713_0.profraw  pyo3-9115749969700858718_0.profraw
pyo3-13212718739740305352_0.profraw  pyo3-9296542518232051450_0.profraw
pyo3-17208771140764127027_0.profraw  pyo3.profdata
pyo3-40338836728015828_0.profraw     release
pyo3-5761173678925874245_0.profraw   wheels
pyo3-6135639819960792837_0.profraw
```

There's still some pain points:
  1. I need to unset `CARGO_TARGET_DIR` before attempting to run `cargo llvm-cov` command, or I get crashes because it tries to append `llvm-cov-target` for a second time:
  
  ```
  $ cargo llvm-cov --no-run --summary-only
  error: no input files specified. See llvm-profdata merge -help
  error: failed to merge profile data: process didn't exit successfully: `/home/david/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -sparse -o /home/david/dev/pyo3/target/llvm-cov-target/llvm-cov-target/pyo3.profdata` (exit status: 1)
  ```
  
  2. After unsetting `CARGO_TARGET_DIR`, I still get a failure to generate the report. I suspect this is because `cargo-llvm-cov` is not finding and passing the `cdylib` outputs to `llvm-cov report`?
  
  ```
  $ cargo llvm-cov --no-run --summary-only --verbose
     Running `/home/david/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -sparse /home/david/dev/pyo3/target/llvm-cov-target/pyo3-10144924340354712083_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-12448306348928428713_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-13212718739740305352_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-17208771140764127027_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-40338836728015828_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-5761173678925874245_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-6135639819960792837_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-6622988374613674511_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-8390305564713967804_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-8655209440434687052_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-9115749969700858718_0.profraw /home/david/dev/pyo3/target/llvm-cov-target/pyo3-9296542518232051450_0.profraw -o /home/david/dev/pyo3/target/llvm-cov-target/pyo3.profdata`
     Running `/home/david/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-cov report -instr-profile=/home/david/dev/pyo3/target/llvm-cov-target/pyo3.profdata -ignore-filename-regex '(^|/)(rustc/[0-9a-f]+|(\.)?cargo/(registry|git)|(\.)?rustup/toolchains|tests|examples|benches|target/llvm-cov-target)/|^/home/david/|^pyo3-macros/|^pyo3-macros-backend/|^pyo3-build-config/|^examples/|^xtask/'`
  No filenames specified!
  error: failed to generate report: process didn't exit successfully: `/home/david/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-cov report -instr-profile=/home/david/dev/pyo3/target/llvm-cov-target/pyo3.profdata -ignore-filename-regex '(^|/)(rustc/[0-9a-f]+|(\.)?cargo/(registry|git)|(\.)?rustup/toolchains|tests|examples|benches|target/llvm-cov-target)/|^/home/david/|^pyo3-macros/|^pyo3-macros-backend/|^pyo3-build-config/|^examples/|^xtask/'` (exit status: 1)
   ```
   
If you're interested, you can see the companion PyO3 at PyO3/pyo3#2067



Co-authored-by: David Hewitt <1939362+davidhewitt@users.noreply.github.com>
Co-authored-by: Taiki Endo <te316e89@gmail.com>
@taiki-e
Copy link
Owner

taiki-e commented Jan 6, 2022

show-env subcommand has been added in 0.1.14 (#115, thanks @davidhewitt)

I think the next step here is to actually run external tests and see if the results are reflected in the coverage report. (There is already one case that does not work, reported by #115.)

The current cargo-llvm-cov uses heuristics that are tuned to cargo run/cargo test to collect build artifacts, so it might be missed other build artifacts used in external tests.

EDIT: It is probably difficult to actually use show-env without #121.

bors bot added a commit that referenced this issue Jan 6, 2022
121: Fix show-env subcommand bug r=taiki-e a=taiki-e

This fixes the problem that the readme example does not work.
This probably fixes the remaining problem reported in #115.

cc #93
cc `@davidhewitt` 


Co-authored-by: Taiki Endo <te316e89@gmail.com>
@taiki-e
Copy link
Owner

taiki-e commented Jan 6, 2022

Closing -- I believe known problems have been fixed in 0.1.15 (#121).

@taiki-e taiki-e closed this as completed Jan 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: A new feature or an improvement for an existing one
Projects
None yet
Development

No branches or pull requests

3 participants