-
Notifications
You must be signed in to change notification settings - Fork 40
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
Add parser for GoCov #99
base: main
Are you sure you want to change the base?
Conversation
…geParser.parseReport() method declaration
log.logError(USAGE_ERROR_MSG); | ||
throw new InvalidGoCoverageFormatException("Expected the coverage mode specification, but got: [" + line + "]"); | ||
} | ||
switch(line) { |
Check warning
Code scanning / CodeQL
Dereferenced variable may be null Warning
line
this
String domain = split[0]; | ||
String org = split[1]; | ||
String repo = split[2]; | ||
String module = String.join("/", domain, org, repo); |
Check notice
Code scanning / CodeQL
Unread local variable Note
|
||
String[] start = split2[1].split("\\."); | ||
String startLine = start[0]; | ||
String startCol = start[1]; |
Check notice
Code scanning / CodeQL
Unread local variable Note
String startCol = start[1]; | ||
String[] end = split2[2].split("\\."); | ||
String endLine = end[0]; | ||
String endCol = end[1]; |
Check notice
Code scanning / CodeQL
Unread local variable Note
String[] end = split2[2].split("\\."); | ||
String endLine = end[0]; | ||
String endCol = end[1]; | ||
Integer statementCount = Integer.parseInt(split[split.length-2]); |
Check notice
Code scanning / CodeQL
Missing catch of NumberFormatException Note
String endCol = end[1]; | ||
Integer statementCount = Integer.parseInt(split[split.length-2]); | ||
Integer executionCount = Integer.parseInt(split[split.length-1]); | ||
for (Integer i = Integer.parseInt(startLine), j = Integer.parseInt(endLine); i <= j; i++) { |
Check notice
Code scanning / CodeQL
Missing catch of NumberFormatException Note
String[] end = split2[2].split("\\."); | ||
String endLine = end[0]; | ||
String endCol = end[1]; | ||
Integer statementCount = Integer.parseInt(split[split.length-2]); |
Check warning
Code scanning / CodeQL
Boxed variable is never null Warning
String endLine = end[0]; | ||
String endCol = end[1]; | ||
Integer statementCount = Integer.parseInt(split[split.length-2]); | ||
Integer executionCount = Integer.parseInt(split[split.length-1]); |
Check warning
Code scanning / CodeQL
Boxed variable is never null Warning
String endCol = end[1]; | ||
Integer statementCount = Integer.parseInt(split[split.length-2]); | ||
Integer executionCount = Integer.parseInt(split[split.length-1]); | ||
for (Integer i = Integer.parseInt(startLine), j = Integer.parseInt(endLine); i <= j; i++) { |
Check warning
Code scanning / CodeQL
Boxed variable is never null Warning
String endCol = end[1]; | ||
Integer statementCount = Integer.parseInt(split[split.length-2]); | ||
Integer executionCount = Integer.parseInt(split[split.length-1]); | ||
for (Integer i = Integer.parseInt(startLine), j = Integer.parseInt(endLine); i <= j; i++) { |
Check warning
Code scanning / CodeQL
Boxed variable is never null Warning
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your pull request for this new format!
@@ -0,0 +1,12 @@ | |||
mode: atomic | |||
github.com/example/project/pkg/utils/file1.go:5.12,8.22 3 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain the counters? Is there no function information?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The format is:
<FILE>
:<start row>
.<start column>
,<end row>
.<end column>
<# of statements>
<# of statements covered>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, then this format actually provides only line and instruction (or in your case statement) coverage. That means the counters for the line and branch coverage are either 1/1 or 0/1 (covered/total), see next comment.
The exact numbers of statements can be used to set the instruction coverage. Since we have only files as elements this coverage needs to be put per file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My mistake, the format is actually:
<FILE>
:<start row>
.<start column>
,<end row>
.<end column>
<# of statements covered>
<# of statements missed>
And so that's we have a running tallies of the number of covered & missed statements, then resolve everything at the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not make sense when I look at the test case file? All of your lines actually show a coverage > 0. Or am I missing something?
mode: atomic
github.com/example/project/pkg/utils/file1.go:5.12,8.22 3 1
github.com/example/project/pkg/utils/file1.go:10.9,15.23 5 3
github.com/example/project/pkg/utils/file1.go:19.16,20.23 2 0
github.com/example/project/pkg/utils/file1.go:24.3,25.25 1 1
github.com/example/project/pkg/utils/file1.go:30.16,32.25 1 1
github.com/example/project/pkg/db/file2.go:12.7,15.7 1 0
github.com/example/project/pkg/db/file2.go:17.7,22.14 3 2
github.com/example/project/cmd/file3.go:10.12,10.21 1 0
github.com/example/project/cmd/file3.go:15.17,17.27 3 0
github.com/example/project/pkg/test/file4.go:10.12,11.21 1 0
github.com/example/project/pkg/test/file4.go:10.12,11.21 1 1
I rewrote the test so it matches my coding style:
3ae1498
I will try to refactor the parser as well. What is important and missing: your parser produces INSTRUCTION coverage. Which implies line coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's take the example line:
github.com/example/project/pkg/utils/file1.go:5.12,8.22 3 1
It'd be read as:
For file1.go
, lines 5
-8
, there were 3
statements that were covered and 1
statement that was missed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then I do not understand the actual test case:
Report:
github.com/example/project/pkg/db/file2.go:12.7,15.7 1 0
github.com/example/project/pkg/db/file2.go:17.7,22.14 3 2
Actual test:
two -> assertThat(two).hasName("file2.go")
.hasMissedLines(12, 13, 14, 15)
.hasCoveredLines(17, 18, 19, 20, 21, 22)
From the counters I would expect: Lines 12-15 have one statement covered and 0 missed. So we should have:
two -> assertThat(two).hasName("file2.go")
.hasCoveredLines(12, 13, 14, 15, 17, 18, 19, 20, 21, 22)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need some help to get this parser finished? I think we are currently struggling at the missed/covered computation, see comment above.
@@ -521,6 +521,17 @@ public FileNode addCounters(final int lineNumber, final int covered, final int m | |||
return this; | |||
} | |||
|
|||
@CanIgnoreReturnValue | |||
public FileNode addCounterIncremental(final int lineNumber, final int covered, final int missed) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that an extra method is required. From the format of your test case it looks like you do not use branch coverage at all. So the counter should be c=1 m0 or c=0 m1. If c +n > 1 then the UI assumes that you are using branch coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As addressed in previous statement, my mistake on the previous incorrect information. But because each line read in the coverage file gives N number of covered statements, and M number of missed statements, we keep running tallies of each one and then resolve everything at the end.
import static edu.hm.hafner.coverage.parser.JacocoParser.createValue; | ||
|
||
public class GoParser extends CoverageParser { | ||
private static final java.util.logging.Logger LOGGER = java.util.logging.Logger.getLogger(GoParser.class.getName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use the provided logger that will report the information in the UI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm already are doing so (example), I was using these to also log the information to Jenkins logs, but they can be removed to better align with the rest of the module, if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This parser seems to be way to complex for the simple format of the test case? Are you planning to parser different reports? So I am skipping the review on this class right now. It would also make sense to keep the static analysis happy before starting a review...
@uhafner Addressed your comments and corrected an incorrect statement I made before. Hopefully the correct explanation of the Go coverage files justifies our methodology for counting coverage. |
Wouldn't it make sense to use https://github.com/AlekSi/gocov-xml? Then we simply can reuse the Cobertura parser? Wouldn't there be also method names when used in that way? |
@uhafner we tried avoiding using any non-organization type of libraries due to possible lack of future support reasons, but this author seems to be highly involved in the Go community and if you're okay with us using this library, I can re-implement it to do so. |
I'm not sure if I can follow. What I am suggesting is: rather than creating the file At least it would make sense to use So I am not against your parser in this PR but if it is not required because a better tool already exists it would make sense to follow the other approach... And if this does not work we need to improve your parser so that the created model is correct. |
Unfortunately, we're trying to automate and minimize the number of steps needed for our users to migrate over to this new plugin. And users are currently using that |
See #99 (comment) |
Adding a parser for GoCov coverage files.
Testing done
Testing was done in both with unit tests and a test coverage file (based on real coverage files). As well as on a local Jenkins, where a local version of the Jenkins coverage-plugin was installed to use this coverage model. Ran a simple Go pipeline and validated the coverage output was available in the UI.
Once approved and merged, the corresponding coverage-plugin change can be found here: N/A
Submitter checklist