1
2
3
4
5 package mockit.coverage;
6
7 import edu.umd.cs.findbugs.annotations.NonNull;
8
9 import java.io.File;
10 import java.io.IOException;
11 import java.io.Writer;
12 import java.nio.charset.StandardCharsets;
13 import java.nio.file.Files;
14 import java.nio.file.Path;
15 import java.util.Map.Entry;
16
17 import mockit.coverage.data.CoverageData;
18 import mockit.coverage.data.FileCoverageData;
19 import mockit.coverage.lines.LineCoverageData;
20 import mockit.coverage.lines.PerFileLineCoverage;
21
22 import org.checkerframework.checker.index.qual.NonNegative;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 final class XmlFile {
40
41
42 private static final Logger logger = LoggerFactory.getLogger(XmlFile.class);
43
44 @NonNull
45 private final String srcDir;
46 @NonNull
47 private final File outputFile;
48 @NonNull
49 private final CoverageData coverageData;
50
51 XmlFile(@NonNull String outputDir, @NonNull CoverageData coverageData) {
52
53 String firstSrcDir = Configuration.getProperty("srcDirs", "").split("\\s*,\\s*")[0];
54 srcDir = firstSrcDir.isEmpty() ? "" : firstSrcDir + '/';
55
56 String parentDir = Configuration.getOrChooseOutputDirectory(outputDir);
57 outputFile = Path.of(parentDir, "coverage.xml").toFile();
58 this.coverageData = coverageData;
59 }
60
61 void generate() throws IOException {
62 try (Writer out = Files.newBufferedWriter(outputFile.toPath(), StandardCharsets.UTF_8)) {
63 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
64 out.write("<coverage version=\"1\">\n");
65
66 for (Entry<String, FileCoverageData> fileAndData : coverageData.getFileToFileData().entrySet()) {
67 String sourceFileName = fileAndData.getKey();
68 writeOpeningXmlElementForSourceFile(out, sourceFileName);
69
70 PerFileLineCoverage lineInfo = fileAndData.getValue().lineCoverageInfo;
71 writeXmlElementsForExecutableLines(out, lineInfo);
72
73 out.write("\t</file>\n");
74 }
75
76 out.write("</coverage>\n");
77 }
78
79 logger.info("JMockit: Coverage data written to {}", outputFile.getCanonicalPath());
80 }
81
82 private void writeOpeningXmlElementForSourceFile(@NonNull Writer out, @NonNull String sourceFileName)
83 throws IOException {
84 out.write("\t<file path=\"");
85 out.write(srcDir);
86 out.write(sourceFileName);
87 out.write("\">\n");
88 }
89
90 private static void writeXmlElementsForExecutableLines(@NonNull Writer out, @NonNull PerFileLineCoverage lineInfo)
91 throws IOException {
92 int lineCount = lineInfo.getLineCount();
93
94 for (int lineNum = 1; lineNum <= lineCount; lineNum++) {
95 if (lineInfo.hasLineData(lineNum)) {
96 LineCoverageData lineData = lineInfo.getLineData(lineNum);
97
98 out.write("\t\t<lineToCover lineNumber=\"");
99 writeNumber(out, lineNum);
100 out.write("\" covered=\"");
101 out.write(Boolean.toString(lineData.isCovered()));
102
103 if (lineData.containsBranches()) {
104 out.write("\" branchesToCover=\"");
105 writeNumber(out, lineData.getNumberOfBranchingSourcesAndTargets());
106 out.write("\" coveredBranches=\"");
107 writeNumber(out, lineData.getNumberOfCoveredBranchingSourcesAndTargets());
108 }
109
110 out.write("\"/>\n");
111 }
112 }
113 }
114
115 private static void writeNumber(@NonNull Writer out, @NonNegative int value) throws IOException {
116 out.write(Integer.toString(value));
117 }
118 }