tarpaulin: Missing coverage for logical lines split on multiple lines
System: Linux laptop 5.3.5-arch1-1-ARCH #1 SMP PREEMPT Mon Oct 7 19:03:08 UTC 2019 x86_64 GNU/Linux Rust version: rustc 1.38.0 (625451e37 2019-09-23) cargo-tarpaulin version: 0.9.0
It seems that Tarpaulin has the most trouble when logical lines are split across multiple lines.
I have a few examples of this behavior. I maintain rubik/orizuru, and I’m referring to the code at commit https://github.com/rubik/orizuru/tree/6a569c574137549af0d2c9148be694e2254c175c.
It’s easier to see Tarpaulin’s output on Coveralls, but I’ll attach the raw output at the bottom of this post. On Coveralls, we can see that lines 32, 122, 126, 127, 130, 132, 133, 150, 165 of src/consumer.rs
are marked as uncovered but they are obviously covered. In src/gc.rs
, the same thing is true for line 36, while on the other hand line 37 is wrongly marked as covered, when it should be line 38.
Here is the raw output from cargo tarpaulin -v --ignore-tests
:
$ cargo tarpaulin --ignore-tests -v
[INFO tarpaulin] Running Tarpaulin
[INFO tarpaulin] Building project
Compiling orizuru v0.0.1 (/home/miki/exp/orizuru)
Finished dev [unoptimized + debuginfo] target(s) in 4.62s
[DEBUG tarpaulin] Processing Target(test: producer)
[INFO tarpaulin] Launching test
[INFO tarpaulin] running /home/miki/exp/orizuru/target/debug/deps/producer-2ef6002cc111b285
running 1 test
test producer_can_enqueue ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
[DEBUG tarpaulin] Processing Target(test: consumer)
[INFO tarpaulin] Launching test
[INFO tarpaulin] running /home/miki/exp/orizuru/target/debug/deps/consumer-fe2596306e0a75d1
running 9 tests
test no_heartbeat ... ok
test register ... ok
test one_heartbeat ... ok
test acked_are_released ... ok
test decodes_job ... ok
test can_be_stopped ... ok
test unacked_to_unack_queue ... ok
test rejected_to_unack_queue ... ok
test multiple_heartbeat ... ok
test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
[DEBUG tarpaulin] Processing Target(test: gc)
[INFO tarpaulin] Launching test
[INFO tarpaulin] running /home/miki/exp/orizuru/target/debug/deps/gc-421ed796d3795885
running 5 tests
test collect_one_runs_with_no_jobs ... ok
test collect_noop_with_no_consumers ... ok
test collect_runs_with_a_consumer_and_no_jobs ... ok
test collect_one_runs_with_some_jobs ... ok
test collect_runs_with_a_consumer_and_some_jobs ... ok
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
[DEBUG tarpaulin] Processing Target(test: test_utils)
[INFO tarpaulin] Launching test
[INFO tarpaulin] running /home/miki/exp/orizuru/target/debug/deps/test_utils-7a56f348bdb14280
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
[DEBUG tarpaulin] Processing Target(lib)
[INFO tarpaulin] Launching test
[INFO tarpaulin] running /home/miki/exp/orizuru/target/debug/deps/orizuru-7134647b58b7d504
running 4 tests
test message::tests::cant_decode_if_not_string ... ok
test message::tests::cant_decode_if_not_msgpack ... ok
test message::tests::payload_field_is_accessible ... ok
test message::tests::message_field_is_accessible ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
[INFO tarpaulin] Coverage Results:
|| Uncovered Lines:
|| src/consumer.rs: 32, 119, 122, 126-127, 130, 132-133, 150, 157-159, 165, 167-168
|| src/gc.rs: 36, 38-39
|| src/message.rs: 126-127
|| Tested/Total Lines:
|| src/consumer.rs: 62/77
|| src/gc.rs: 25/28
|| src/message.rs: 28/30
|| src/producer.rs: 8/8
||
86.01% coverage, 123/143 lines covered
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 10
- Comments: 15 (5 by maintainers)
No movement of this, I’m trying to figure out an issue on selecting the right lines for breakpoints that solves this. Though currently I’ve only managed to do trial and error switching between multiple potential breakpoints and finding there is a correct solution and an incorrect solution. Need to figure out how to do this analytically and change tarpaulin to match that behaviour
@jamestwebber In static analysis there is a concept of “logical line of code”, as opposed to the physical source line of code. The latter is simply what is present in the file, whereas the logical one measures the number of executable statements.
You can see some examples on Wikipedia; they are in C but they easily translate to Rust: https://en.wikipedia.org/wiki/Source_lines_of_code#Measurement_methods
I suppose Tarpaulin could adopt a similar approach. It’s very frequently used by static analysis tools.