Bug 17613 – Inconsistent behaviour in code coverage

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2017-07-06T18:02:19Z
Last change time
2024-12-13T18:53:12Z
Assigned to
No Owner
Creator
hsteoh
Moved to GitHub: dmd#19277 →

Comments

Comment #0 by hsteoh — 2017-07-06T18:02:19Z
Reduced code: ------------ import std.stdio; struct MyFile { this(string filename) { } auto byLine() { return 0; } } struct Wrapper { this(Args...)(Args args) {} } auto func(F = std.stdio.File)(bool[] args) { import std.algorithm.iteration : map; foreach (x; args.map!(arg => arg ? Wrapper( F("A").byLine) : Wrapper( 0))) { } } void main() { import std.algorithm : each; func!MyFile([ true, false ]); func([ false ]); } ------------ Compile with dmd -unittest -cov, and run the program. Here is the obtained .lst file: ------------ |import std.stdio; |struct MyFile |{ 1| this(string filename) { } 1| auto byLine() { return 0; } |} |struct Wrapper |{ 3| this(Args...)(Args args) {} |} |auto func(F = std.stdio.File)(bool[] args) |{ | import std.algorithm.iteration : map; 17| foreach (x; args.map!(arg => arg ? Wrapper( 0000000| F("A").byLine) : 2| Wrapper( | 0))) | { } |} |void main() |{ | import std.algorithm : each; 1| func!MyFile([ true, false ]); 1| func([ false ]); |} util.d is 87% covered ------------ Note the line with 0000000. This is clearly wrong, because the first call to func!MyFile ought to have traversed both branches of the ?: operator, so F("A").byLine must have been invoked at least once. Now comment out the second call to func (func([ false ])), recompile, and run again. Here is the obtained .lst file: ------------ |import std.stdio; |struct MyFile |{ 1| this(string filename) { } 1| auto byLine() { return 0; } |} |struct Wrapper |{ 2| this(Args...)(Args args) {} |} |auto func(F = std.stdio.File)(bool[] args) |{ | import std.algorithm.iteration : map; 11| foreach (x; args.map!(arg => arg ? Wrapper( | F("A").byLine) : 1| Wrapper( | 0))) | { } |} |void main() |{ | import std.algorithm : each; 1| func!MyFile([ true, false ]); | //func([ false ]); |} util.d is 100% covered ------------ Note that the call to F("A").byLine is now *no longer part of the coverage count*. So here we have a paradoxical situation where decreasing code coverage (by not instantiating func with the default parameter for F) increases the reported code coverage to 100%. Note that defaulting F to std.stdio.File seems to be an essential part of this bug; I could not get rid of the reference to std.stdio.File without making the bug also vanish. (I tried declaring my own version of File in a different module and importing that, but that made the bug disappear.) Also, the odd formatting of the Wrapper lines are necessary to expose this bug; in the original, unreduced code, the lines were wrapped this way because the original code had longer lines that needed to be wrapped. However, wrapping lines should not affect the code coverage percentage(!).
Comment #1 by dlang-bugzilla — 2017-07-07T07:02:37Z
(In reply to hsteoh from comment #0) > 0000000| F("A").byLine) : FWIW, this line had no coverage counters at all before https://github.com/dlang/dmd/pull/5003 (so the bug as presented wasn't observable before that PR), but it seems unrelated and not the cause of a regression.
Comment #2 by robert.schadek — 2024-12-13T18:53:12Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19277 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB