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

Rustdoc doctests should have their file/lines remapped when using -Zinstrument-coverage #79417

Open
Swatinem opened this issue Nov 25, 2020 · 5 comments
Labels
A-code-coverage Area: Source-based code coverage (-Cinstrument-coverage) C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.

Comments

@Swatinem
Copy link
Contributor

I have a workspace with crate_a (and crate_b, but its not used for this example), and use the following env vars set to have my rustdoc tests run through code coverage:

RUSTDOCFLAGS="-Z instrument-coverage -Z unstable-options --persist-doctests=C:\Users\swatinem\AppData\Local\Temp\_rustdoc

Running the result later through llvm-cov gives me errors for my rustdocs, and unexpected results:

> llvm-cov show -format=html -instr-profile=coverage/coverage.profdata -object=C:\Users\swatinem\AppData\Local\Temp\_rustdoc\crate_a_src_somemod_someothermod_mod_rs_1_0\rust_out

error: src\somemod\someothermod\mod.rs: no such file or directory
warning: The file 'src\somemod\someothermod\mod.rs' isn't covered.

When using export -format=lcov, I get the following:

SF:src\somemod\someothermod\mod.rs
FN:3,_RNvCs4fqI2P2rA04_8rust_out4main
FNDA:1,_RNvCs4fqI2P2rA04_8rust_out4main
FNF:1
FNH:1
DA:3,1
DA:4,1
LF:2
LH:2
end_of_record

This is not really a problem per-se, but note that the filename is not relative to my workspace, but to the crate inside the workspace, which creates problems down the road, because uploading that report to codecov actually finds the correct file for some reason, but then highlights lines 3 and 4.

So ideally, the coverage support should similarly re-map line numbers such as compile errors in doctests do, and the filename should be relative to the workspace (but that seems to be a separate issue with rustdoc I guess).

@richkadel I guess you know the code the best: Is such a re-mapping that I propose possible at all? If so, I would be happy to work on this if you point me in the right direction and would be willing to mentor me ;-)

@jonas-schievink jonas-schievink added A-code-coverage Area: Source-based code coverage (-Cinstrument-coverage) C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Nov 25, 2020
@Swatinem
Copy link
Contributor Author

Here is some example code:
https://github.com/Swatinem/fucov
And here are some examples how I try to invoke the tools:
https://github.com/Swatinem/fucov/runs/1454817756

@richkadel
Copy link
Contributor

richkadel commented Dec 3, 2020

Hi @Swatinem !

Thanks for your patience.

It would be great if you could work on this! (I will probably not be able to work on it any time soon.)

I was able to reproduce this issue as well. Your instructions above are great. Another way to see these results, using cargo commands similar to what's in the updated "Rust Unstable Book" documentation (just for comparison and context) is:

$ rm -rf target/debug/doctestbins/*
$ RUSTFLAGS="-Zinstrument-coverage" RUSTDOCFLAGS="-Zinstrument-coverage -Z unstable-options \
    --persist-doctests target/debug/doctestbins" LLVM_PROFILE_FILE="json5format-%m.profraw" \
    cargo test --doc

# or full coverage status after running both doc and non-doc tests:
# $ RUSTFLAGS="-Zinstrument-coverage" RUSTDOCFLAGS="-Zinstrument-coverage -Z unstable-options \
#     --persist-doctests target/debug/doctestbins" LLVM_PROFILE_FILE="json5format-%m.profraw" \
#     cargo test   # (default: both --tests and --doc)
$ cargo profdata -- merge -sparse json5format-*.profraw -o json5format.profdata
$ cargo cov -- show --color -Xdemangler=rustfilt --instr-profile=json5format.profdata \
    $(for file in target/debug/build/* target/debug/doctestbins/*/*; \
      do [[ ! -d $file &&  -x $file ]] && echo $file; done) \
    --show-line-counts-or-regions --show-instantiations | less -R

When I ran this, I saw (for example) the large test block in json5format/src/lib.rs was apparently executed (3 times, for some reason), but the line numbers were clearly off. Since that test is near the top of the source, the line counters started just a few lines too high, for the reasons you described (I assume).

If you do work on this, I'm happy to try to help and answer questions if you have them, either via this issue (for more strategic issues in particular) or via a Zulip topic.

I don't know how rustdoc does its remapping specifically, but that sounds like a good place to start looking.

The InstrumentCoverage MIR pass uses the Rust compiler's default session SourceMap, via:

tcx.sess.source_map();

to get the file name, line, and column.

One nice thing about that is, I know there are ways to remap the source directly in the SourceMap, so the coverage code doesn't even need to be aware.

I know this works for file names, at least.

If I add the following to RUSTFLAGS and RUSTDOCFLAGS, for example:

--remap-path-prefix=$HOME/.cargo/registry/src/github.com-1ecc6299db9ec823=/tmp/s"

the coverage map embedded in the binary will use the /tmp/s/ file prefix instead of the very long absolute path prefix I get by default for the cargo build dependency crates' sources.

Maybe there's already support for remapping line numbers. If not, that may still be the place to implement a line mapping feature.

Obviously a command line flag is not the right approach for line number mapping. You would need to derive the line number offset from the line position of each test, and you would only apply that offset to the test code, without changing the line numbers of other "real" functions in the source file. So, a bit different, but it should be possible.

@Swatinem
Copy link
Contributor Author

Swatinem commented Dec 6, 2020

Thanks for pointing me to SourceMap.
Indeed it has a method that re-maps lines specifically for doctests:

// If there is a doctest offset, applies it to the line.
pub fn doctest_offset_line(&self, file: &FileName, orig: usize) -> usize {
match file {
FileName::DocTest(_, offset) => {
if *offset < 0 {
orig - (-(*offset)) as usize
} else {
orig + *offset as usize
}
}
_ => orig,
}
}

Just for reference, this was added here: #47274 and later passed via unstable env vars here: #63827

I’m playing around with this a bit and it seems like I have found a way to re-map the lines, however there is still other problems related to rustdoc that I would have to fix separately.

I will test a bit more locally and then open a PR :-)

@Swatinem
Copy link
Contributor Author

Swatinem commented Dec 6, 2020

rust-lang/cargo#8954 is a change to cargo that should make rustdoc use the correct filenames for workspace crates. I think that will solve the filename problem, although I haven’t tested that directly yet.

Swatinem added a commit to Swatinem/rust that referenced this issue Dec 19, 2020
This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done.

Part of issue rust-lang#79417.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 21, 2020
…Swatinem

Remap instrument-coverage line numbers in doctests

This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done, and rustdoc
still does not output the correct filename when running doctests in a
workspace.

Part of rust-lang#79417 although I dont consider that fixed until both filenames
and columns are mapped correctly.

r? `@richkadel`

I might jump on zulip the comming days. Still need to figure out how to properly write tests for this, and deal with other doctest issues in the meantime.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 22, 2020
…Swatinem

Remap instrument-coverage line numbers in doctests

This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done, and rustdoc
still does not output the correct filename when running doctests in a
workspace.

Part of rust-lang#79417 although I dont consider that fixed until both filenames
and columns are mapped correctly.

r? ``@richkadel``

I might jump on zulip the comming days. Still need to figure out how to properly write tests for this, and deal with other doctest issues in the meantime.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 22, 2020
…Swatinem

Remap instrument-coverage line numbers in doctests

This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done, and rustdoc
still does not output the correct filename when running doctests in a
workspace.

Part of rust-lang#79417 although I dont consider that fixed until both filenames
and columns are mapped correctly.

r? ```@richkadel```

I might jump on zulip the comming days. Still need to figure out how to properly write tests for this, and deal with other doctest issues in the meantime.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 22, 2020
…Swatinem

Remap instrument-coverage line numbers in doctests

This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done, and rustdoc
still does not output the correct filename when running doctests in a
workspace.

Part of rust-lang#79417 although I dont consider that fixed until both filenames
and columns are mapped correctly.

r? `@richkadel`

I might jump on zulip the comming days. Still need to figure out how to properly write tests for this, and deal with other doctest issues in the meantime.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 23, 2020
…Swatinem

Remap instrument-coverage line numbers in doctests

This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done, and rustdoc
still does not output the correct filename when running doctests in a
workspace.

Part of rust-lang#79417 although I dont consider that fixed until both filenames
and columns are mapped correctly.

r? `@richkadel`

I might jump on zulip the comming days. Still need to figure out how to properly write tests for this, and deal with other doctest issues in the meantime.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 24, 2020
…Swatinem

Remap instrument-coverage line numbers in doctests

This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done, and rustdoc
still does not output the correct filename when running doctests in a
workspace.

Part of rust-lang#79417 although I dont consider that fixed until both filenames
and columns are mapped correctly.

r? ``@richkadel``

I might jump on zulip the comming days. Still need to figure out how to properly write tests for this, and deal with other doctest issues in the meantime.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 24, 2020
…Swatinem

Remap instrument-coverage line numbers in doctests

This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done, and rustdoc
still does not output the correct filename when running doctests in a
workspace.

Part of rust-lang#79417 although I dont consider that fixed until both filenames
and columns are mapped correctly.

r? ```@richkadel```

I might jump on zulip the comming days. Still need to figure out how to properly write tests for this, and deal with other doctest issues in the meantime.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Dec 24, 2020
…Swatinem

Remap instrument-coverage line numbers in doctests

This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done, and rustdoc
still does not output the correct filename when running doctests in a
workspace.

Part of rust-lang#79417 although I dont consider that fixed until both filenames
and columns are mapped correctly.

r? ````@richkadel````

I might jump on zulip the comming days. Still need to figure out how to properly write tests for this, and deal with other doctest issues in the meantime.
bors added a commit to rust-lang-ci/rust that referenced this issue Dec 25, 2020
…atinem

Remap instrument-coverage line numbers in doctests

This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done, and rustdoc
still does not output the correct filename when running doctests in a
workspace.

Part of rust-lang#79417 although I dont consider that fixed until both filenames
and columns are mapped correctly.

r? `@richkadel`

I might jump on zulip the comming days. Still need to figure out how to properly write tests for this, and deal with other doctest issues in the meantime.
@richkadel
Copy link
Contributor

richkadel commented Jan 7, 2021

This Issue is partially resolved by #79762. (Thanks @Swatinem!)

There are some known issues still to resolve:

lpenz added a commit to lpenz/ghaction-rust-coverage that referenced this issue Jan 24, 2022
lpenz added a commit to lpenz/ghaction-rust-coverage that referenced this issue Jan 26, 2022
lpenz added a commit to lpenz/ghaction-rust-coverage that referenced this issue Jan 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-code-coverage Area: Source-based code coverage (-Cinstrument-coverage) C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants