Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/ci-rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,10 @@ jobs:
run: ./pleasew --plain_output test //...
env:
VERITAS_NO_HOOK: "1"

- name: Coverage smoke test (lib_test)
run: |
./pleasew --plain_output cover //test/rust/lib:lib_test 2>&1 | tee cover.log
grep -Eq '^\s+lib\.rs [1-9][0-9]*/' cover.log
env:
VERITAS_NO_HOOK: "1"
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed

- `rust_test` ignored `LlvmProfdataTool`, `LlvmCovTool` and `Coverage` (plugin
config was read with `CONFIG.get`, which does not see it), so `llvm-profdata`
was taken from the host. With an older host LLVM the merge failed
(`unsupported instrumentation profile format version`) and `plz cover`
reported 0%. The configured tools are now passed to the test.
- The coverage error now names the `llvm-profdata` that failed.

### Documentation

- Documented the Rust coverage report location, format and contents, and the
silent `No data` result when `[cover] fileextension = .rs` is missing.
- Added a CI coverage smoke test.

## [0.5.0] - 2026-09-19

### Added
Expand Down
6 changes: 3 additions & 3 deletions build_defs/rust/rust.build_defs
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ def _is_coverage_enabled(rule_coverage=None):
"""Determines whether coverage instrumentation is enabled for a target."""
if rule_coverage is not None:
return rule_coverage
return CONFIG.get("RUST.COVERAGE", "true").lower() in ("true", "1", "yes", "on")
return (CONFIG.RUST.COVERAGE or "true").lower() in ("true", "1", "yes", "on")

def _test_tools(profdata_override=None, cov_override=None):
"""Returns test_tools dictionary for rust_test."""
tools = {"TOOL": [_rust_tool()]}
profdata = profdata_override or CONFIG.get("RUST.LLVM_PROFDATA_TOOL", "")
cov = cov_override or CONFIG.get("RUST.LLVM_COV_TOOL", "")
profdata = profdata_override or CONFIG.RUST.LLVM_PROFDATA_TOOL
cov = cov_override or CONFIG.RUST.LLVM_COV_TOOL
if profdata and (profdata.startswith("//") or profdata.startswith("///") or profdata.startswith(":")):
tools["LLVM_PROFDATA"] = [profdata]
if cov and (cov.startswith("//") or cov.startswith("///") or cov.startswith(":")):
Expand Down
13 changes: 12 additions & 1 deletion docs/rust/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,18 @@ Display detailed, line-by-line covered source listings:
./pleasew cover -l //test/lib:lib_test
```

### 4. Per-Rule Coverage Control
### 4. Report Output

- **Location**: Please merges the per-test results into
`plz-out/log/coverage.xml` (Cobertura XML) and `plz-out/log/coverage.json`
(per-file line markers plus per-file and per-directory percentages).
- **Contents**: line coverage only. Branch coverage and per-function data are
not emitted, so consumers cannot join coverage with per-function complexity
from this report.
- **Missing `[cover]` setting**: without `fileextension = .rs` the report is
silently `Total coverage: No data`.

### 5. Per-Rule Coverage Control

You can enable or disable coverage instrumentation on individual rules:

Expand Down
3 changes: 2 additions & 1 deletion tools/please_rust/testrunner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ func mergeProfdata(profdataPath, tmpDir string, profrawFiles []string) (string,
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return "", fmt.Errorf("llvm-profdata merge failed: %w", err)
version, _ := exec.Command(resolved, "--version").CombinedOutput()
return "", fmt.Errorf("llvm-profdata merge failed using %s (%s): %w", resolved, strings.Join(strings.Fields(string(version)), " "), err)
}
return mergedPath, nil
}
Expand Down
Loading