aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorGravatar Irina Iancu <elenairina@google.com>2018-08-01 09:29:01 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-08-01 09:30:29 -0700
commitf8afad6f22786ba646cbd10a73e5738884cc84b8 (patch)
tree5c651454fa4c9fd49949bcbdaad3f6f39fb04216 /tools
parentf330439fb970cfa17c70fc59c1458bb1c31c9522 (diff)
Add a parser for gcov intermediate file format.
This change comes as a preparation for using gcov for Bazel C++ coverage instead of lcov. See documentation of gcov intermediate format at https://gcc.gnu.org/onlinedocs/gcc/Invoking-Gcov.html#Invoking-Gcov under --intermediate-format. Change-Id: I6cd2df8b3a6611b187a2b0c161b14388413bc670 PiperOrigin-RevId: 206940660
Diffstat (limited to 'tools')
-rw-r--r--tools/test/LcovMerger/java/com/google/devtools/lcovmerger/BUILD30
-rw-r--r--tools/test/LcovMerger/java/com/google/devtools/lcovmerger/BranchCoverage.java23
-rw-r--r--tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Constants.java (renamed from tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovConstants.java)20
-rw-r--r--tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Coverage.java15
-rw-r--r--tools/test/LcovMerger/java/com/google/devtools/lcovmerger/GcovParser.java196
-rw-r--r--tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovParser.java66
-rw-r--r--tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovPrinter.java44
-rw-r--r--tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Main.java112
-rw-r--r--tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Parser.java23
-rw-r--r--tools/test/LcovMerger/java/com/google/devtools/lcovmerger/SourceFileCoverage.java8
-rw-r--r--tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/BUILD25
-rw-r--r--tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/BranchCoverageTest.java68
-rw-r--r--tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/GcovParserTest.java129
-rw-r--r--tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/MainTest.java6
14 files changed, 588 insertions, 177 deletions
diff --git a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/BUILD b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/BUILD
index 38e0816a95..7af7779a78 100644
--- a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/BUILD
+++ b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/BUILD
@@ -56,8 +56,8 @@ java_library(
srcs = ["LcovPrinter.java"],
deps = [
":BranchCoverage",
+ ":Constants",
":Coverage",
- ":LcovConstants",
":LineCoverage",
":SourceFileCoverage",
"//third_party:guava",
@@ -65,16 +65,33 @@ java_library(
)
java_library(
- name = "LcovConstants",
- srcs = ["LcovConstants.java"],
+ name = "Constants",
+ srcs = ["Constants.java"],
+)
+
+java_library(
+ name = "GcovParser",
+ srcs = [
+ "GcovParser.java",
+ "Parser.java",
+ ],
+ deps = [
+ ":BranchCoverage",
+ ":Constants",
+ ":LineCoverage",
+ ":SourceFileCoverage",
+ ],
)
java_library(
name = "LcovParser",
- srcs = ["LcovParser.java"],
+ srcs = [
+ "LcovParser.java",
+ "Parser.java",
+ ],
deps = [
":BranchCoverage",
- ":LcovConstants",
+ ":Constants",
":LineCoverage",
":SourceFileCoverage",
],
@@ -90,8 +107,9 @@ java_library(
name = "MainLibrary",
srcs = ["Main.java"],
deps = [
+ ":Constants",
":Coverage",
- ":LcovConstants",
+ ":GcovParser",
":LcovParser",
":LcovPrinter",
":SourceFileCoverage",
diff --git a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/BranchCoverage.java b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/BranchCoverage.java
index 0fbe78311a..bc12dc6098 100644
--- a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/BranchCoverage.java
+++ b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/BranchCoverage.java
@@ -22,15 +22,14 @@ import com.google.auto.value.AutoValue;
@AutoValue
abstract class BranchCoverage {
- static BranchCoverage create(
- int lineNumber,
- String blockNumber,
- String branchNumber,
- boolean wasExecuted,
- int nrOfExecutions) {
- assert (wasExecuted && nrOfExecutions > 0) || (!wasExecuted && nrOfExecutions == 0);
+ static BranchCoverage create(int lineNumber, int nrOfExecutions) {
return new AutoValue_BranchCoverage(
- lineNumber, blockNumber, branchNumber, wasExecuted, nrOfExecutions);
+ lineNumber, /*blockNumber=*/ "", /*branchNumber=*/ "", nrOfExecutions);
+ }
+
+ static BranchCoverage createWithBlockAndBranch(
+ int lineNumber, String blockNumber, String branchNumber, int nrOfExecutions) {
+ return new AutoValue_BranchCoverage(lineNumber, blockNumber, branchNumber, nrOfExecutions);
}
/**
@@ -44,11 +43,10 @@ abstract class BranchCoverage {
assert first.blockNumber().equals(second.blockNumber());
assert first.branchNumber().equals(second.branchNumber());
- return create(
+ return createWithBlockAndBranch(
first.lineNumber(),
first.blockNumber(),
first.branchNumber(),
- first.wasExecuted() || second.wasExecuted(),
first.nrOfExecutions() + second.nrOfExecutions());
}
@@ -56,6 +54,9 @@ abstract class BranchCoverage {
// The two numbers below should be -1 for non-gcc emitted coverage (e.g. Java).
abstract String blockNumber(); // internal gcc internal ID for the branch
abstract String branchNumber(); // internal gcc internal ID for the branch
- abstract boolean wasExecuted();
abstract int nrOfExecutions();
+
+ boolean wasExecuted() {
+ return nrOfExecutions() > 0;
+ }
}
diff --git a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovConstants.java b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Constants.java
index 83c6ce5f85..9a8fe88850 100644
--- a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovConstants.java
+++ b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Constants.java
@@ -15,10 +15,12 @@
package com.google.devtools.lcovmerger;
/**
- * Stores markers used by the lcov tracefile. See
- * <a href="http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php"> lcov documentation</a>
+ * Stores markers used by the lcov tracefile and gcov intermediate format file. See <a
+ * href="http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php">lcov documentation</a> and the flag
+ * {@code --intermediate-format} in <a href="https://gcc.gnu.org/onlinedocs/gcc/Invoking-Gcov.html">
+ * gcov documentation</a>.
*/
-class LcovConstants {
+class Constants {
static final String SF_MARKER = "SF:";
static final String FN_MARKER = "FN:";
static final String FNDA_MARKER = "FNDA:";
@@ -32,7 +34,17 @@ class LcovConstants {
static final String LH_MARKER = "LH:";
static final String LF_MARKER = "LF:";
static final String END_OF_RECORD_MARKER = "end_of_record";
- static final String LCOV_DELIMITER = ",";
static final String TAKEN = "-";
static final String TRACEFILE_EXTENSION = ".dat";
+ static final String DELIMITER = ",";
+ static final String GCOV_EXTENSION = ".gcov";
+ static final String GCOV_VERSION_MARKER = "version:";
+ static final String GCOV_CWD_MARKER = "cwd:";
+ static final String GCOV_FILE_MARKER = "file:";
+ static final String GCOV_FUNCTION_MARKER = "function:";
+ static final String GCOV_LINE_MARKER = "lcount:";
+ static final String GCOV_BRANCH_MARKER = "branch:";
+ static final String GCOV_BRANCH_NOTEXEC = "notexec";
+ static final String GCOV_BRANCH_NOTTAKEN = "taken";
+ static final String GCOV_BRANCH_TAKEN = "nottaken";
}
diff --git a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Coverage.java b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Coverage.java
index 82733aa84a..75eaa420cc 100644
--- a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Coverage.java
+++ b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Coverage.java
@@ -34,6 +34,21 @@ class Coverage {
}
}
+ static Coverage merge(Coverage c1, Coverage c2) {
+ Coverage merged = new Coverage();
+ for (SourceFileCoverage sourceFile : c1.getAllSourceFiles()) {
+ merged.add(sourceFile);
+ }
+ for (SourceFileCoverage sourceFile : c2.getAllSourceFiles()) {
+ merged.add(sourceFile);
+ }
+ return merged;
+ }
+
+ boolean isEmpty() {
+ return sourceFiles.isEmpty();
+ }
+
Collection<SourceFileCoverage> getAllSourceFiles() {
return sourceFiles.values();
}
diff --git a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/GcovParser.java b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/GcovParser.java
new file mode 100644
index 0000000000..25592192b2
--- /dev/null
+++ b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/GcovParser.java
@@ -0,0 +1,196 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.lcovmerger;
+
+import static com.google.devtools.lcovmerger.Constants.DELIMITER;
+import static com.google.devtools.lcovmerger.Constants.GCOV_BRANCH_MARKER;
+import static com.google.devtools.lcovmerger.Constants.GCOV_BRANCH_NOTEXEC;
+import static com.google.devtools.lcovmerger.Constants.GCOV_BRANCH_NOTTAKEN;
+import static com.google.devtools.lcovmerger.Constants.GCOV_BRANCH_TAKEN;
+import static com.google.devtools.lcovmerger.Constants.GCOV_CWD_MARKER;
+import static com.google.devtools.lcovmerger.Constants.GCOV_FILE_MARKER;
+import static com.google.devtools.lcovmerger.Constants.GCOV_FUNCTION_MARKER;
+import static com.google.devtools.lcovmerger.Constants.GCOV_LINE_MARKER;
+import static com.google.devtools.lcovmerger.Constants.GCOV_VERSION_MARKER;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A {@link Parser} for gcov intermediate format. See the flag {@code --intermediate-format} in <a
+ * href="https://gcc.gnu.org/onlinedocs/gcc/Invoking-gcov.html">gcov documentation</a>.
+ */
+public class GcovParser {
+
+ private static final Logger logger = Logger.getLogger(GcovParser.class.getName());
+ private List<SourceFileCoverage> allSourceFiles;
+ private final InputStream inputStream;
+ private SourceFileCoverage currentSourceFileCoverage;
+
+ private GcovParser(InputStream inputStream) {
+ this.inputStream = inputStream;
+ }
+
+ public static List<SourceFileCoverage> parse(InputStream inputStream) throws IOException {
+ return new GcovParser(inputStream).parse();
+ }
+
+ private List<SourceFileCoverage> parse() throws IOException {
+ allSourceFiles = new ArrayList<>();
+ boolean malformedInput = false;
+ try (BufferedReader bufferedReader =
+ new BufferedReader(new InputStreamReader(inputStream, UTF_8))) {
+ String line;
+ // TODO(bazel-team): This is susceptible to OOM if the input file is too large and doesn't
+ // contain any newlines.
+ while ((line = bufferedReader.readLine()) != null) {
+ if (!parseLine(line)) {
+ malformedInput = true;
+ }
+ }
+ bufferedReader.close();
+ }
+ endSourceFile();
+ if (malformedInput) {
+ throw new IOException("gcov intermediate input is malformed.");
+ }
+ return allSourceFiles;
+ }
+
+ /**
+ * Merges {@code currentSourceFileCoverage} into {@code allSourceFilesCoverageData} and resets
+ * {@code currentSourceFileCoverage} to null.
+ */
+ private void endSourceFile() {
+ if (currentSourceFileCoverage == null) {
+ return;
+ }
+ allSourceFiles.add(currentSourceFileCoverage);
+ currentSourceFileCoverage = null;
+ }
+
+ private boolean parseLine(String line) {
+ if (line.startsWith(GCOV_FILE_MARKER)) {
+ endSourceFile();
+ return parseSource(line);
+ }
+ if (line.startsWith(GCOV_FUNCTION_MARKER)) {
+ return parseFunction(line);
+ }
+ if (line.startsWith(GCOV_LINE_MARKER)) {
+ return parseLCount(line);
+ }
+ if (line.startsWith(GCOV_BRANCH_MARKER)) {
+ return parseBranch(line);
+ }
+ if (line.startsWith(GCOV_VERSION_MARKER) || line.startsWith(GCOV_CWD_MARKER)) {
+ // Ignore these fields for now as they are not necessary.
+ return true;
+ }
+ return false;
+ }
+
+ private boolean parseSource(String line) {
+ String sourcefile = line.substring(GCOV_FILE_MARKER.length());
+ if (sourcefile.isEmpty()) {
+ logger.log(Level.WARNING, "gcov info doesn't contain source file name on line: " + line);
+ return false;
+ }
+ currentSourceFileCoverage = new SourceFileCoverage(sourcefile);
+ return true;
+ }
+
+ // function:start_line_number,end_line_number,execution_count,function_name
+ private boolean parseFunction(String line) {
+ String lineContent = line.substring(GCOV_FUNCTION_MARKER.length());
+ String[] items = lineContent.split(DELIMITER, -1);
+ if (items.length != 4) {
+ logger.log(Level.WARNING, "gcov info contains invalid line " + line);
+ return false;
+ }
+ try {
+ // Ignore end_line_number since it's redundant information.
+ int startLine = Integer.parseInt(items[0]);
+ int execCount = Integer.parseInt(items[2]);
+ String functionName = items[3];
+ currentSourceFileCoverage.addLineNumber(functionName, startLine);
+ currentSourceFileCoverage.addFunctionExecution(functionName, execCount);
+ } catch (NumberFormatException e) {
+ logger.log(Level.WARNING, "gcov info contains invalid line " + line);
+ return false;
+ }
+ return true;
+ }
+
+ // lcount:line number,execution_count,has_unexecuted_block
+ private boolean parseLCount(String line) {
+ String lineContent = line.substring(GCOV_LINE_MARKER.length());
+ String[] items = lineContent.split(DELIMITER, -1);
+ if (items.length != 3) {
+ logger.log(Level.WARNING, "gcov info contains invalid line " + line);
+ return false;
+ }
+ try {
+ // Ignore has_unexecuted_block since it's not used.
+ int lineNr = Integer.parseInt(items[0]);
+ int execCount = Integer.parseInt(items[1]);
+ currentSourceFileCoverage.addLine(lineNr, LineCoverage.create(lineNr, execCount, null));
+ } catch (NumberFormatException e) {
+ logger.log(Level.WARNING, "gcov info contains invalid line " + line);
+ return false;
+ }
+ return true;
+ }
+
+ // branch:line_number,branch_coverage_type
+ private boolean parseBranch(String line) {
+ String lineContent = line.substring(GCOV_BRANCH_MARKER.length());
+ String[] items = lineContent.split(DELIMITER, -1);
+ if (items.length != 2) {
+ logger.log(Level.WARNING, "gcov info contains invalid line " + line);
+ return false;
+ }
+ try {
+ // Ignore has_unexecuted_block since it's not used.
+ int lineNr = Integer.parseInt(items[0]);
+ String type = items[1];
+ int execCount;
+ switch (type) {
+ case GCOV_BRANCH_NOTEXEC:
+ execCount = 0;
+ break;
+ case GCOV_BRANCH_NOTTAKEN:
+ case GCOV_BRANCH_TAKEN:
+ execCount = 1;
+ break;
+ default:
+ logger.log(Level.WARNING, "gcov info contains invalid line " + line);
+ return false;
+ }
+ currentSourceFileCoverage.addBranch(lineNr, BranchCoverage.create(lineNr, execCount));
+ } catch (NumberFormatException e) {
+ logger.log(Level.WARNING, "gcov info contains invalid line " + line);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovParser.java b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovParser.java
index b441b8761e..64062db60b 100644
--- a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovParser.java
+++ b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovParser.java
@@ -14,21 +14,21 @@
package com.google.devtools.lcovmerger;
-import static com.google.devtools.lcovmerger.LcovConstants.BA_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.BRDA_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.BRF_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.BRH_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.DA_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.END_OF_RECORD_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.FNDA_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.FNF_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.FNH_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.FN_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.LCOV_DELIMITER;
-import static com.google.devtools.lcovmerger.LcovConstants.LF_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.LH_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.SF_MARKER;
-import static com.google.devtools.lcovmerger.LcovConstants.TAKEN;
+import static com.google.devtools.lcovmerger.Constants.BA_MARKER;
+import static com.google.devtools.lcovmerger.Constants.BRDA_MARKER;
+import static com.google.devtools.lcovmerger.Constants.BRF_MARKER;
+import static com.google.devtools.lcovmerger.Constants.BRH_MARKER;
+import static com.google.devtools.lcovmerger.Constants.DA_MARKER;
+import static com.google.devtools.lcovmerger.Constants.DELIMITER;
+import static com.google.devtools.lcovmerger.Constants.END_OF_RECORD_MARKER;
+import static com.google.devtools.lcovmerger.Constants.FNDA_MARKER;
+import static com.google.devtools.lcovmerger.Constants.FNF_MARKER;
+import static com.google.devtools.lcovmerger.Constants.FNH_MARKER;
+import static com.google.devtools.lcovmerger.Constants.FN_MARKER;
+import static com.google.devtools.lcovmerger.Constants.LF_MARKER;
+import static com.google.devtools.lcovmerger.Constants.LH_MARKER;
+import static com.google.devtools.lcovmerger.Constants.SF_MARKER;
+import static com.google.devtools.lcovmerger.Constants.TAKEN;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.BufferedReader;
@@ -47,19 +47,15 @@ import java.util.logging.Logger;
class LcovParser {
private static final Logger logger = Logger.getLogger(LcovParser.class.getName());
+ private final InputStream inputStream;
private SourceFileCoverage currentSourceFileCoverage;
- private final InputStream tracefileStream;
- private LcovParser(InputStream tracefileStream) {
- this.tracefileStream = tracefileStream;
+ private LcovParser(InputStream inputStream) {
+ this.inputStream = inputStream;
}
- /**
- * Returns a list of the source files found in the given tracefile.
- */
- public static List<SourceFileCoverage> parse(InputStream tracefileStream) throws IOException {
- LcovParser lcovParser = new LcovParser(tracefileStream);
- return lcovParser.parse();
+ public static List<SourceFileCoverage> parse(InputStream inputStream) throws IOException {
+ return new LcovParser(inputStream).parse();
}
/**
@@ -72,7 +68,7 @@ class LcovParser {
private List<SourceFileCoverage> parse() throws IOException {
List<SourceFileCoverage> allSourceFiles = new ArrayList<>();
try (BufferedReader bufferedReader =
- new BufferedReader(new InputStreamReader(tracefileStream, UTF_8))) {
+ new BufferedReader(new InputStreamReader(inputStream, UTF_8))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
parseLine(line, allSourceFiles);
@@ -164,7 +160,7 @@ class LcovParser {
// FN:<line number of function start>,<function name>
private boolean parseFNLine(String line) {
String lineContent = line.substring(FN_MARKER.length());
- String[] funcData = lineContent.split(LCOV_DELIMITER, -1);
+ String[] funcData = lineContent.split(DELIMITER, -1);
if (funcData.length != 2 || funcData[0].isEmpty() || funcData[1].isEmpty()) {
logger.log(Level.WARNING, "Tracefile contains invalid FN line " + line);
return false;
@@ -183,7 +179,7 @@ class LcovParser {
// FNDA:<execution count>,<function name>
private boolean parseFNDALine(String line) {
String lineContent = line.substring(FNDA_MARKER.length());
- String[] funcData = lineContent.split(LCOV_DELIMITER, -1);
+ String[] funcData = lineContent.split(DELIMITER, -1);
if (funcData.length != 2 || funcData[0].isEmpty() || funcData[1].isEmpty()) {
logger.log(Level.WARNING, "Tracefile contains invalid FNDA line " + line);
return false;
@@ -238,7 +234,7 @@ class LcovParser {
// BA:<line number>,<taken>
private boolean parseBALine(String line) {
String lineContent = line.substring(BA_MARKER.length());
- String[] lineData = lineContent.split(LCOV_DELIMITER, -1);
+ String[] lineData = lineContent.split(DELIMITER, -1);
if (lineData.length != 2) {
logger.log(Level.WARNING, "Tracefile contains invalid BRDA line " + line);
return false;
@@ -253,12 +249,7 @@ class LcovParser {
int lineNumber = Integer.parseInt(lineData[0]);
int taken = Integer.parseInt(lineData[1]);
- boolean wasExecuted = false;
- if (taken == 1 || taken == 2) {
- wasExecuted = true;
- }
- BranchCoverage branchCoverage =
- BranchCoverage.create(lineNumber, "", "", wasExecuted, taken);
+ BranchCoverage branchCoverage = BranchCoverage.create(lineNumber, taken);
currentSourceFileCoverage.addBranch(lineNumber, branchCoverage);
} catch (NumberFormatException e) {
@@ -271,7 +262,7 @@ class LcovParser {
// BRDA:<line number>,<block number>,<branch number>,<taken>
private boolean parseBRDALine(String line) {
String lineContent = line.substring(BRDA_MARKER.length());
- String[] lineData = lineContent.split(LCOV_DELIMITER, -1);
+ String[] lineData = lineContent.split(DELIMITER, -1);
if (lineData.length != 4) {
logger.log(Level.WARNING, "Tracefile contains invalid BRDA line " + line);
return false;
@@ -295,7 +286,8 @@ class LcovParser {
wasExecuted = true;
}
BranchCoverage branchCoverage =
- BranchCoverage.create(lineNumber, blockNumber, branchNumber, wasExecuted, executionCount);
+ BranchCoverage.createWithBlockAndBranch(
+ lineNumber, blockNumber, branchNumber, executionCount);
currentSourceFileCoverage.addBranch(lineNumber, branchCoverage);
} catch (NumberFormatException e) {
@@ -344,7 +336,7 @@ class LcovParser {
// DA:<line number>,<execution count>,[,<checksum>]
private boolean parseDALine(String line) {
String lineContent = line.substring(DA_MARKER.length());
- String[] lineData = lineContent.split(LCOV_DELIMITER, -1);
+ String[] lineData = lineContent.split(DELIMITER, -1);
if (lineData.length != 2 && lineData.length != 3) {
logger.log(Level.WARNING, "Tracefile contains invalid DA line " + line);
return false;
diff --git a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovPrinter.java b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovPrinter.java
index ef5f9e16ad..7fa6ccc38b 100644
--- a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovPrinter.java
+++ b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/LcovPrinter.java
@@ -88,7 +88,7 @@ class LcovPrinter {
// SF:<absolute path to the source file>
private void printSFLine(SourceFileCoverage sourceFile) throws IOException {
- bufferedWriter.write(LcovConstants.SF_MARKER);
+ bufferedWriter.write(Constants.SF_MARKER);
bufferedWriter.write(sourceFile.sourceFileName());
bufferedWriter.newLine();
}
@@ -97,9 +97,9 @@ class LcovPrinter {
private void printFNLines(SourceFileCoverage sourceFile) throws IOException {
for (Entry<String, Integer> entry :
sourceFile.getAllLineNumbers()) {
- bufferedWriter.write(LcovConstants.FN_MARKER);
+ bufferedWriter.write(Constants.FN_MARKER);
bufferedWriter.write(Integer.toString(entry.getValue())); // line number of function start
- bufferedWriter.write(LcovConstants.LCOV_DELIMITER);
+ bufferedWriter.write(Constants.DELIMITER);
bufferedWriter.write(entry.getKey()); // function name
bufferedWriter.newLine();
}
@@ -109,9 +109,9 @@ class LcovPrinter {
private void printFNDALines(SourceFileCoverage sourceFile) throws IOException {
for (Entry<String, Integer> entry :
sourceFile.getAllExecutionCount()) {
- bufferedWriter.write(LcovConstants.FNDA_MARKER);
+ bufferedWriter.write(Constants.FNDA_MARKER);
bufferedWriter.write(Integer.toString(entry.getValue())); // execution count
- bufferedWriter.write(LcovConstants.LCOV_DELIMITER);
+ bufferedWriter.write(Constants.DELIMITER);
bufferedWriter.write(entry.getKey()); // function name
bufferedWriter.newLine();
}
@@ -119,14 +119,14 @@ class LcovPrinter {
// FNF:<number of functions found>
private void printFNFLine(SourceFileCoverage sourceFile) throws IOException {
- bufferedWriter.write(LcovConstants.FNF_MARKER);
+ bufferedWriter.write(Constants.FNF_MARKER);
bufferedWriter.write(Integer.toString(sourceFile.nrFunctionsFound()));
bufferedWriter.newLine();
}
// FNH:<number of functions hit>
private void printFNHLine(SourceFileCoverage sourceFile) throws IOException {
- bufferedWriter.write(LcovConstants.FNH_MARKER);
+ bufferedWriter.write(Constants.FNH_MARKER);
bufferedWriter.write(Integer.toString(sourceFile.nrFunctionsHit()));
bufferedWriter.newLine();
}
@@ -138,17 +138,17 @@ class LcovPrinter {
// We skip printing this as a BRDA line and print it later as a BA line.
continue;
}
- bufferedWriter.write(LcovConstants.BRDA_MARKER);
+ bufferedWriter.write(Constants.BRDA_MARKER);
bufferedWriter.write(Integer.toString(branch.lineNumber()));
- bufferedWriter.write(LcovConstants.LCOV_DELIMITER);
+ bufferedWriter.write(Constants.DELIMITER);
bufferedWriter.write(branch.blockNumber());
- bufferedWriter.write(LcovConstants.LCOV_DELIMITER);
+ bufferedWriter.write(Constants.DELIMITER);
bufferedWriter.write(branch.branchNumber());
- bufferedWriter.write(LcovConstants.LCOV_DELIMITER);
+ bufferedWriter.write(Constants.DELIMITER);
if (branch.wasExecuted()) {
bufferedWriter.write(Integer.toString(branch.nrOfExecutions()));
} else {
- bufferedWriter.write(LcovConstants.TAKEN);
+ bufferedWriter.write(Constants.TAKEN);
}
bufferedWriter.newLine();
}
@@ -161,9 +161,9 @@ class LcovPrinter {
// This branch was already printed with more information as a BRDA line.
continue;
}
- bufferedWriter.write(LcovConstants.BA_MARKER);
+ bufferedWriter.write(Constants.BA_MARKER);
bufferedWriter.write(Integer.toString(branch.lineNumber()));
- bufferedWriter.write(LcovConstants.LCOV_DELIMITER);
+ bufferedWriter.write(Constants.DELIMITER);
// 0 = branch was not executed
// 1 = branch was executed but not taken
// 2 = branch was executed and taken
@@ -175,7 +175,7 @@ class LcovPrinter {
// BRF:<number of branches found>
private void printBRFLine(SourceFileCoverage sourceFile) throws IOException {
if (sourceFile.nrBranchesFound() > 0) {
- bufferedWriter.write(LcovConstants.BRF_MARKER);
+ bufferedWriter.write(Constants.BRF_MARKER);
bufferedWriter.write(Integer.toString(sourceFile.nrBranchesFound()));
bufferedWriter.newLine();
}
@@ -185,7 +185,7 @@ class LcovPrinter {
private void printBRHLine(SourceFileCoverage sourceFile) throws IOException {
// Only print if there were any branches found.
if (sourceFile.nrBranchesFound() > 0) {
- bufferedWriter.write(LcovConstants.BRH_MARKER);
+ bufferedWriter.write(Constants.BRH_MARKER);
bufferedWriter.write(Integer.toString(sourceFile.nrBranchesHit()));
bufferedWriter.newLine();
}
@@ -195,12 +195,12 @@ class LcovPrinter {
private void printDALines(SourceFileCoverage sourceFile) throws IOException {
for (LineCoverage lineExecution :
sourceFile.getAllLineExecution()) {
- bufferedWriter.write(LcovConstants.DA_MARKER);
+ bufferedWriter.write(Constants.DA_MARKER);
bufferedWriter.write(Integer.toString(lineExecution.lineNumber()));
- bufferedWriter.write(LcovConstants.LCOV_DELIMITER);
+ bufferedWriter.write(Constants.DELIMITER);
bufferedWriter.write(Integer.toString(lineExecution.executionCount()));
if (lineExecution.checksum() != null) {
- bufferedWriter.write(LcovConstants.LCOV_DELIMITER);
+ bufferedWriter.write(Constants.DELIMITER);
bufferedWriter.write(lineExecution.checksum());
}
bufferedWriter.newLine();
@@ -209,21 +209,21 @@ class LcovPrinter {
// LH:<number of lines with a non-zero execution count>
private void printLHLine(SourceFileCoverage sourceFile) throws IOException {
- bufferedWriter.write(LcovConstants.LH_MARKER);
+ bufferedWriter.write(Constants.LH_MARKER);
bufferedWriter.write(Integer.toString(sourceFile.nrOfLinesWithNonZeroExecution()));
bufferedWriter.newLine();
}
// LF:<number of instrumented lines>
private void printLFLine(SourceFileCoverage sourceFile) throws IOException {
- bufferedWriter.write(LcovConstants.LF_MARKER);
+ bufferedWriter.write(Constants.LF_MARKER);
bufferedWriter.write(Integer.toString(sourceFile.nrOfInstrumentedLines()));
bufferedWriter.newLine();
}
// end_of_record
private void printEndOfRecordLine() throws IOException {
- bufferedWriter.write(LcovConstants.END_OF_RECORD_MARKER);
+ bufferedWriter.write(Constants.END_OF_RECORD_MARKER);
bufferedWriter.newLine();
}
}
diff --git a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Main.java b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Main.java
index 2984d7b274..b490765383 100644
--- a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Main.java
+++ b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Main.java
@@ -14,7 +14,8 @@
package com.google.devtools.lcovmerger;
-import static com.google.devtools.lcovmerger.LcovConstants.TRACEFILE_EXTENSION;
+import static com.google.devtools.lcovmerger.Constants.GCOV_EXTENSION;
+import static com.google.devtools.lcovmerger.Constants.TRACEFILE_EXTENSION;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.annotations.VisibleForTesting;
@@ -28,6 +29,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -51,65 +53,107 @@ public class Main {
System.exit(1);
}
+ List<File> filesInCoverageDir =
+ flags.containsKey("coverage_dir")
+ ? getCoverageFilesInDir(flags.get("coverage_dir"))
+ : Collections.emptyList();
+ Coverage coverage =
+ Coverage.merge(
+ parseFiles(getTracefiles(flags, filesInCoverageDir), LcovParser::parse),
+ parseFiles(getGcovInfoFiles(filesInCoverageDir), GcovParser::parse));
+
+ if (coverage.isEmpty()) {
+ logger.log(Level.SEVERE, "There was no coverage found.");
+ System.exit(1);
+ }
+
+ int exitStatus = 0;
+ String outputFile = flags.get("output_file");
+ try {
+ LcovPrinter.print(new FileOutputStream(new File(outputFile)), coverage);
+ } catch (IOException e) {
+ logger.log(
+ Level.SEVERE,
+ "Could not write to output file " + outputFile + " due to " + e.getMessage());
+ exitStatus = 1;
+ }
+ System.exit(exitStatus);
+ }
+
+ private static List<File> getGcovInfoFiles(List<File> filesInCoverageDir) {
+ List<File> gcovFiles = getFilesWithExtension(filesInCoverageDir, GCOV_EXTENSION);
+ if (gcovFiles.isEmpty()) {
+ logger.log(Level.SEVERE, "No gcov info file found.");
+ } else {
+ logger.log(Level.INFO, "Found " + gcovFiles.size() + " gcov info files.");
+ }
+ return gcovFiles;
+ }
+
+ private static List<File> getTracefiles(
+ Map<String, String> flags, List<File> filesInCoverageDir) {
List<File> lcovTracefiles = new ArrayList<>();
if (flags.containsKey("coverage_dir")) {
- logger.log(Level.SEVERE, "Retrieving tracefiles from coverage_dir.");
- lcovTracefiles = getLcovTracefilesFromDir(flags.get("coverage_dir"));
+ lcovTracefiles = getFilesWithExtension(filesInCoverageDir, TRACEFILE_EXTENSION);
} else if (flags.containsKey("reports_file")) {
- logger.log(Level.SEVERE, "Retrieving tracefiles from reports_file.");
- lcovTracefiles = getLcovTracefilesFromFile(flags.get("reports_file"));
+ lcovTracefiles = getTracefilesFromFile(flags.get("reports_file"));
}
if (lcovTracefiles.isEmpty()) {
logger.log(Level.SEVERE, "No lcov file found.");
- System.exit(1);
+ } else {
+ logger.log(Level.INFO, "Found " + lcovTracefiles.size() + " tracefiles.");
}
- logger.log(Level.SEVERE, "Found " + lcovTracefiles.size() + " tracefiles.");
+ return lcovTracefiles;
+ }
+
+ private static Coverage parseFiles(List<File> files, Parser parser) {
Coverage coverage = new Coverage();
- for (File tracefile : lcovTracefiles) {
+ for (File file : files) {
try {
- logger.log(Level.SEVERE, "Parsing tracefile " + tracefile.toString());
- List<SourceFileCoverage> sourceFilesCoverage =
- LcovParser.parse(new FileInputStream(tracefile));
+ logger.log(Level.SEVERE, "Parsing file " + file.toString());
+ List<SourceFileCoverage> sourceFilesCoverage = parser.parse(new FileInputStream(file));
for (SourceFileCoverage sourceFileCoverage : sourceFilesCoverage) {
coverage.add(sourceFileCoverage);
}
} catch (IOException e) {
- logger.log(Level.SEVERE, "Tracefile " + tracefile.getAbsolutePath() + " was deleted");
+ logger.log(
+ Level.SEVERE,
+ "File " + file.getAbsolutePath() + " could not be parsed due to: " + e.getMessage());
System.exit(1);
}
}
- int exitStatus = 0;
- String outputFile = flags.get("output_file");
- try {
- File coverageFile = new File(outputFile);
- LcovPrinter.print(new FileOutputStream(coverageFile), coverage);
- } catch (IOException e) {
- logger.log(Level.SEVERE,
- "Could not write to output file " + outputFile + " due to " + e.getMessage());
- exitStatus = 1;
- }
- System.exit(exitStatus);
+ return coverage;
}
/**
- * Returns a list of all the files with a “.dat” extension found recursively under the given
- * directory.
+ * Returns a list of all the files with the given extension found recursively under the given dir.
*/
@VisibleForTesting
- static List<File> getLcovTracefilesFromDir(String coverageDir) {
- List<File> datFiles = new ArrayList<>();
- try (Stream<Path> stream = Files.walk(Paths.get(coverageDir))) {
- datFiles = stream.filter(p -> p.toString().endsWith(TRACEFILE_EXTENSION))
- .map(path -> path.toFile())
- .collect(Collectors.toList());
+ static List<File> getCoverageFilesInDir(String dir) {
+ List<File> files = new ArrayList<>();
+ try (Stream<Path> stream = Files.walk(Paths.get(dir))) {
+ files =
+ stream
+ .filter(
+ p ->
+ p.toString().endsWith(TRACEFILE_EXTENSION)
+ || p.toString().endsWith(GCOV_EXTENSION))
+ .map(path -> path.toFile())
+ .collect(Collectors.toList());
} catch (IOException ex) {
- logger.log(Level.SEVERE, "Error reading folder " + coverageDir + ": " + ex.getMessage());
+ logger.log(Level.SEVERE, "Error reading folder " + dir + ": " + ex.getMessage());
}
+ return files;
+ }
- return datFiles;
+ static List<File> getFilesWithExtension(List<File> files, String extension) {
+ return files
+ .stream()
+ .filter(file -> file.toString().endsWith(extension))
+ .collect(Collectors.toList());
}
- static List<File> getLcovTracefilesFromFile(String reportsFile) {
+ static List<File> getTracefilesFromFile(String reportsFile) {
List<File> datFiles = new ArrayList<>();
try (FileInputStream inputStream = new FileInputStream(reportsFile)) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, UTF_8);
diff --git a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Parser.java b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Parser.java
new file mode 100644
index 0000000000..4cfafdce07
--- /dev/null
+++ b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/Parser.java
@@ -0,0 +1,23 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.lcovmerger;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+interface Parser {
+ List<SourceFileCoverage> parse(InputStream inputStream) throws IOException;
+}
diff --git a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/SourceFileCoverage.java b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/SourceFileCoverage.java
index 0cdb1a6f85..b98a873a8c 100644
--- a/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/SourceFileCoverage.java
+++ b/tools/test/LcovMerger/java/com/google/devtools/lcovmerger/SourceFileCoverage.java
@@ -237,6 +237,10 @@ class SourceFileCoverage {
}
void addBranch(Integer lineNumber, BranchCoverage branch) {
+ if (this.branches.get(lineNumber) != null) {
+ this.branches.put(lineNumber, BranchCoverage.merge(this.branches.get(lineNumber), branch));
+ return;
+ }
this.branches.put(lineNumber, branch);
}
@@ -245,6 +249,10 @@ class SourceFileCoverage {
}
void addLine(Integer lineNumber, LineCoverage line) {
+ if (this.lines.get(lineNumber) != null) {
+ this.lines.put(lineNumber, LineCoverage.merge(line, this.lines.get(lineNumber)));
+ return;
+ }
this.lines.put(lineNumber, line);
}
diff --git a/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/BUILD b/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/BUILD
index daf81b51d3..51a6e0bcf8 100644
--- a/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/BUILD
+++ b/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/BUILD
@@ -6,6 +6,7 @@ java_test(
name = "BranchCoverageTest",
srcs = ["BranchCoverageTest.java"],
deps = [
+ "//third_party:guava",
"//third_party:junit4",
"//third_party:truth",
"//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:BranchCoverage",
@@ -16,6 +17,7 @@ java_test(
name = "LineCoverageTest",
srcs = ["LineCoverageTest.java"],
deps = [
+ "//third_party:guava",
"//third_party:junit4",
"//third_party:truth",
"//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:LineCoverage",
@@ -28,6 +30,7 @@ java_test(
deps = [
":LcovMergerTestUtils",
":LineCoverageTest",
+ "//third_party:guava",
"//third_party:junit4",
"//third_party:truth",
"//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:LineCoverage",
@@ -43,8 +46,8 @@ java_test(
"//third_party:guava",
"//third_party:junit4",
"//third_party:truth",
+ "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:Constants",
"//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:Coverage",
- "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:LcovConstants",
"//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:LcovPrinter",
"//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:SourceFileCoverage",
],
@@ -58,14 +61,31 @@ java_test(
"//third_party:guava",
"//third_party:junit4",
"//third_party:truth",
+ "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:Constants",
"//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:Coverage",
- "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:LcovConstants",
"//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:LcovParser",
"//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:SourceFileCoverage",
],
)
java_test(
+ name = "GcovParserTest",
+ srcs = ["GcovParserTest.java"],
+ deps = [
+ ":LcovMergerTestUtils",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:BranchCoverage",
+ "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:Constants",
+ "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:Coverage",
+ "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:GcovParser",
+ "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:LineCoverage",
+ "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:SourceFileCoverage",
+ ],
+)
+
+java_test(
name = "CoverageTest",
srcs = ["CoverageTest.java"],
deps = [
@@ -85,6 +105,7 @@ java_test(
":LcovMergerTestUtils",
"//third_party:junit4",
"//third_party:truth",
+ "//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:Constants",
"//tools/test/LcovMerger/java/com/google/devtools/lcovmerger:MainLibrary",
],
)
diff --git a/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/BranchCoverageTest.java b/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/BranchCoverageTest.java
index 2e0056e700..85003ef1d7 100644
--- a/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/BranchCoverageTest.java
+++ b/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/BranchCoverageTest.java
@@ -30,59 +30,41 @@ public class BranchCoverageTest {
private static final int BRANCH1_LINE_NR = 10;
private static final String BRANCH1_BLOCK_NR = "3";
private static final String BRANCH1_BRANCH_NR = "2";
- private static final boolean BRANCH1_WAS_EXECUTED = false;
private static final int BRANCH1_NR_EXECUTIONS = 0;
- private static final boolean BRANCH1_OTHER_TRACEFILE_WAS_EXECUTED = true;
private static final int BRANCH1_OTHER_TRACEFILE_NR_EXECUTIONS = 5;
private static final int BRANCH2_LINE_NR = 20;
private static final String BRANCH2_BLOCK_NR = "7";
private static final String BRANCH2_BRANCH_NR = "2";
- private static final boolean BRANCH2_WAS_EXECUTED = false;
private static final int BRANCH2_NR_EXECUTIONS = 0;
- private static final boolean BRANCH2_OTHER_TRACEFILE_WAS_EXECUTED = false;
private static final int BRANCH2_OTHER_TRACEFILE_NR_EXECUTIONS = 0;
static final BranchCoverage getBranch1CoverageData() {
- return BranchCoverage.create(
- BRANCH1_LINE_NR,
- BRANCH1_BLOCK_NR,
- BRANCH1_BRANCH_NR,
- BRANCH1_WAS_EXECUTED,
- BRANCH1_NR_EXECUTIONS
- );
+ return BranchCoverage.createWithBlockAndBranch(
+ BRANCH1_LINE_NR, BRANCH1_BLOCK_NR, BRANCH1_BRANCH_NR, BRANCH1_NR_EXECUTIONS);
}
static final BranchCoverage getBranch2CoverageData() {
- return BranchCoverage.create(
- BRANCH2_LINE_NR,
- BRANCH2_BLOCK_NR,
- BRANCH2_BRANCH_NR,
- BRANCH2_WAS_EXECUTED,
- BRANCH2_NR_EXECUTIONS
- );
+ return BranchCoverage.createWithBlockAndBranch(
+ BRANCH2_LINE_NR, BRANCH2_BLOCK_NR, BRANCH2_BRANCH_NR, BRANCH2_NR_EXECUTIONS);
}
static final BranchCoverage getBranch1OtherTracefileCoverageData() {
- return BranchCoverage.create(
+ return BranchCoverage.createWithBlockAndBranch(
BRANCH1_LINE_NR,
BRANCH1_BLOCK_NR,
BRANCH1_BRANCH_NR,
- BRANCH1_OTHER_TRACEFILE_WAS_EXECUTED,
- BRANCH1_OTHER_TRACEFILE_NR_EXECUTIONS
- );
+ BRANCH1_OTHER_TRACEFILE_NR_EXECUTIONS);
}
static final BranchCoverage getBranch2OtherTracefileCoverageData() {
- return BranchCoverage.create(
+ return BranchCoverage.createWithBlockAndBranch(
BRANCH2_LINE_NR,
BRANCH2_BLOCK_NR,
BRANCH2_BRANCH_NR,
- BRANCH2_OTHER_TRACEFILE_WAS_EXECUTED,
- BRANCH2_OTHER_TRACEFILE_NR_EXECUTIONS
- );
+ BRANCH2_OTHER_TRACEFILE_NR_EXECUTIONS);
}
@Test
@@ -109,7 +91,7 @@ public class BranchCoverageTest {
assertThat(merged.wasExecuted()).isFalse();
assertThat(merged.nrOfExecutions()).isEqualTo(0);
}
-
+
@Test
public void testMergeBranch1Branch2AssertationError() {
BranchCoverage branch1 = getBranch1CoverageData();
@@ -121,36 +103,4 @@ public class BranchCoverageTest {
}
fail();
}
-
- @Test
- public void testcreateBranchCoverageDataInvalidWasExecutedTrue() {
- try {
- BranchCoverage.create(
- BRANCH1_LINE_NR,
- BRANCH1_BLOCK_NR,
- BRANCH1_BRANCH_NR,
- true,
- 0
- );
- } catch (AssertionError er) {
- return;
- }
- fail();
- }
-
- @Test
- public void testcreateBranchCoverageDataInvalidWasExecutedFalse() {
- try {
- BranchCoverage.create(
- BRANCH1_LINE_NR,
- BRANCH1_BLOCK_NR,
- BRANCH1_BRANCH_NR,
- false,
- 10
- );
- } catch (AssertionError er) {
- return;
- }
- fail();
- }
}
diff --git a/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/GcovParserTest.java b/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/GcovParserTest.java
new file mode 100644
index 0000000000..85b069ef0e
--- /dev/null
+++ b/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/GcovParserTest.java
@@ -0,0 +1,129 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.lcovmerger;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@GcovParser}. */
+@RunWith(JUnit4.class)
+public class GcovParserTest {
+
+ private static final ImmutableList<String> GCOV_INFO_FILE =
+ ImmutableList.of(
+ "version: 8.1.0 20180103",
+ "cwd:/home/gcc/testcase",
+ "file:tmp.cpp",
+ "function:7,7,0,_ZN3FooIcEC2Ev",
+ "function:7,7,1,_ZN3FooIiEC2Ev",
+ "function:8,8,0,_ZN3FooIcE3incEv",
+ "function:8,8,2,_ZN3FooIiE3incEv",
+ "function:18,37,1,main",
+ "lcount:7,0,1",
+ "lcount:7,1,0",
+ "lcount:8,0,1",
+ "lcount:8,2,0",
+ "lcount:18,1,0",
+ "lcount:21,1,0",
+ "branch:21,taken",
+ "branch:21,nottaken",
+ "lcount:23,1,0",
+ "branch:23,taken",
+ "branch:23,nottaken",
+ "lcount:24,1,0",
+ "branch:24,taken",
+ "branch:24,nottaken",
+ "lcount:25,1,0",
+ "lcount:27,11,0",
+ "branch:27,taken",
+ "branch:27,taken",
+ "lcount:28,10,0",
+ "lcount:30,1,1",
+ "branch:30,nottaken",
+ "branch:30,taken",
+ "lcount:32,1,0",
+ "branch:32,nottaken",
+ "branch:32,taken",
+ "lcount:33,0,1",
+ "branch:33,notexec",
+ "branch:33,notexec",
+ "lcount:35,1,0",
+ "branch:35,taken",
+ "branch:35,nottaken",
+ "lcount:36,1,0");
+
+ @Test(expected = IOException.class)
+ public void testParseInvalidFile() throws IOException {
+ GcovParser.parse(new ByteArrayInputStream("Invalid gcov file".getBytes(UTF_8)));
+ }
+
+ @Test
+ public void testParseTracefileWithOneSourcefile() throws IOException {
+
+ List<SourceFileCoverage> sourceFiles =
+ GcovParser.parse(
+ new ByteArrayInputStream(Joiner.on("\n").join(GCOV_INFO_FILE).getBytes(UTF_8)));
+ assertThat(sourceFiles).hasSize(1);
+ assertGcovInfoFile(sourceFiles.get(0));
+ }
+
+ private void assertGcovInfoFile(SourceFileCoverage sourceFileCoverage) {
+ assertThat(sourceFileCoverage.sourceFileName()).isEqualTo("tmp.cpp");
+
+ assertThat(sourceFileCoverage.nrFunctionsFound()).isEqualTo(5);
+ assertThat(sourceFileCoverage.nrFunctionsHit()).isEqualTo(3);
+ assertThat(sourceFileCoverage.nrOfInstrumentedLines()).isEqualTo(14);
+ assertThat(sourceFileCoverage.nrOfLinesWithNonZeroExecution()).isEqualTo(13);
+ assertThat(sourceFileCoverage.nrBranchesFound()).isEqualTo(8);
+ assertThat(sourceFileCoverage.nrBranchesHit()).isEqualTo(7);
+
+ assertThat(sourceFileCoverage.getAllLineExecution())
+ .containsExactly(
+ LineCoverage.create(7, 1, null),
+ LineCoverage.create(8, 2, null),
+ LineCoverage.create(18, 1, null),
+ LineCoverage.create(21, 1, null),
+ LineCoverage.create(23, 1, null),
+ LineCoverage.create(24, 1, null),
+ LineCoverage.create(25, 1, null),
+ LineCoverage.create(27, 11, null),
+ LineCoverage.create(28, 10, null),
+ LineCoverage.create(30, 1, null),
+ LineCoverage.create(32, 1, null),
+ LineCoverage.create(33, 0, null),
+ LineCoverage.create(35, 1, null),
+ LineCoverage.create(36, 1, null));
+
+ assertThat(sourceFileCoverage.getAllBranches())
+ .containsExactly(
+ BranchCoverage.create(21, 2),
+ BranchCoverage.create(23, 2),
+ BranchCoverage.create(24, 2),
+ BranchCoverage.create(27, 2),
+ BranchCoverage.create(30, 2),
+ BranchCoverage.create(32, 2),
+ BranchCoverage.create(33, 0),
+ BranchCoverage.create(35, 2));
+ }
+}
diff --git a/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/MainTest.java b/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/MainTest.java
index a6b99fb12e..e8a6c754bf 100644
--- a/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/MainTest.java
+++ b/tools/test/LcovMerger/javatests/com/google/devtools/lcovmerger/MainTest.java
@@ -15,6 +15,7 @@
package com.google.devtools.lcovmerger;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.lcovmerger.Constants.TRACEFILE_EXTENSION;
import java.io.File;
import java.io.IOException;
@@ -41,7 +42,7 @@ public class MainTest {
@Test
public void testMainEmptyCoverageDir() {
- assertThat(Main.getLcovTracefilesFromDir(coverageDir.toAbsolutePath().toString())).isEmpty();
+ assertThat(Main.getCoverageFilesInDir(coverageDir.toAbsolutePath().toString())).isEmpty();
}
@Test
@@ -52,7 +53,8 @@ public class MainTest {
Files.createTempFile(ccCoverageDir, "tracefile1", ".dat");
Files.createTempFile(javaCoverageDir, "tracefile2", ".dat");
- List<File> tracefiles = Main.getLcovTracefilesFromDir(coverageDir.toAbsolutePath().toString());
+ List<File> coverageFiles = Main.getCoverageFilesInDir(coverageDir.toAbsolutePath().toString());
+ List<File> tracefiles = Main.getFilesWithExtension(coverageFiles, TRACEFILE_EXTENSION);
assertThat(tracefiles).hasSize(2);
}
}