View Javadoc
1   /*
2    * Copyright (c) 2006 JMockit developers
3    * This file is subject to the terms of the MIT license (see LICENSE.txt).
4    */
5   package mockit.coverage;
6   
7   import edu.umd.cs.findbugs.annotations.NonNull;
8   import edu.umd.cs.findbugs.annotations.Nullable;
9   
10  import java.io.File;
11  import java.io.IOException;
12  import java.nio.file.Path;
13  
14  import mockit.coverage.data.CoverageData;
15  import mockit.coverage.reporting.CoverageReport;
16  
17  import org.slf4j.Logger;
18  import org.slf4j.LoggerFactory;
19  
20  @SuppressWarnings("DynamicRegexReplaceableByCompiledPattern")
21  final class OutputFileGenerator {
22  
23      /** The logger. */
24      private static final Logger logger = LoggerFactory.getLogger(CoverageReport.class);
25  
26      private static final String[] ALL_SOURCE_DIRS = {};
27  
28      @NonNull
29      private final String[] outputFormats;
30      @NonNull
31      private final String outputDir;
32      @Nullable
33      private final String[] sourceDirs;
34  
35      OutputFileGenerator() {
36          outputFormats = getOutputFormat();
37          outputDir = Configuration.getProperty("outputDir", "");
38  
39          String commaSeparatedDirs = Configuration.getProperty("srcDirs");
40  
41          if (commaSeparatedDirs == null) {
42              sourceDirs = ALL_SOURCE_DIRS;
43          } else if (commaSeparatedDirs.isEmpty()) {
44              sourceDirs = null;
45          } else {
46              sourceDirs = commaSeparatedDirs.split("\\s*,\\s*");
47          }
48      }
49  
50      @NonNull
51      private static String[] getOutputFormat() {
52          String format = Configuration.getProperty("output", "");
53          return format.isEmpty() ? new String[] { "html" } : format.trim().split("\\s*,\\s*|\\s+");
54      }
55  
56      boolean isOutputToBeGenerated() {
57          return isHTMLWithNoCallPoints() || isWithCallPoints() || hasOutputFormat("serial")
58                  || hasOutputFormat("serial-append") || hasOutputFormat("xml");
59      }
60  
61      private boolean isHTMLWithNoCallPoints() {
62          return hasOutputFormat("html") || hasOutputFormat("html-nocp");
63      }
64  
65      boolean isWithCallPoints() {
66          return hasOutputFormat("html-cp");
67      }
68  
69      private boolean hasOutputFormat(@NonNull String format) {
70          for (String outputFormat : outputFormats) {
71              if (format.equals(outputFormat)) {
72                  return true;
73              }
74          }
75  
76          return false;
77      }
78  
79      void generate() {
80          CoverageData coverageData = CoverageData.instance();
81  
82          if (coverageData.isEmpty()) {
83              logger.info("JMockit: No classes were instrumented for coverage; please make sure that ");
84  
85              String classesRegexp = Configuration.getProperty("classes");
86  
87              if (classesRegexp == null) {
88                  logger.info("classes exercised by tests are in a directory included in the runtime classpath");
89              } else {
90                  logger.info(
91                          "classes selected for coverage through the regular expression '{}' are available from the runtime classpath",
92                          classesRegexp);
93              }
94  
95              logger.info(", and that they have been compiled with debug information.");
96              return;
97          }
98  
99          boolean outputDirCreated = createOutputDirIfSpecifiedButNotExists();
100 
101         try {
102             generateAccretionDataFileIfRequested(coverageData);
103             generateXmlDataFileIfRequested(coverageData);
104             generateHTMLReportIfRequested(coverageData, outputDirCreated);
105         } catch (IOException e) {
106             throw new RuntimeException(e);
107         }
108     }
109 
110     void generateAggregateReportFromInputFiles(@NonNull String[] inputPaths) {
111         boolean outputDirCreated = createOutputDirIfSpecifiedButNotExists();
112 
113         try {
114             CoverageData coverageData = new DataFileMerging(inputPaths).merge();
115             generateHTMLReportIfRequested(coverageData, outputDirCreated);
116         } catch (IOException e) {
117             throw new RuntimeException(e);
118         }
119     }
120 
121     private boolean createOutputDirIfSpecifiedButNotExists() {
122         if (outputDir.isEmpty()) {
123             return false;
124         }
125 
126         File outDir = Path.of(outputDir).toFile();
127         return outDir.mkdirs();
128     }
129 
130     private void generateAccretionDataFileIfRequested(@NonNull CoverageData newData) throws IOException {
131         if (hasOutputFormat("serial")) {
132             new AccretionFile(outputDir, newData).generate();
133         } else if (hasOutputFormat("serial-append")) {
134             AccretionFile accretionFile = new AccretionFile(outputDir, newData);
135             accretionFile.mergeDataFromExistingFileIfAny();
136             accretionFile.generate();
137         }
138     }
139 
140     private void generateXmlDataFileIfRequested(@NonNull CoverageData newData) throws IOException {
141         if (hasOutputFormat("xml")) {
142             new XmlFile(outputDir, newData).generate();
143         }
144     }
145 
146     private void generateHTMLReportIfRequested(@NonNull CoverageData coverageData, boolean outputDirCreated)
147             throws IOException {
148         if (isHTMLWithNoCallPoints()) {
149             new CoverageReport(outputDir, outputDirCreated, sourceDirs, coverageData, false).generate();
150         } else if (isWithCallPoints()) {
151             new CoverageReport(outputDir, outputDirCreated, sourceDirs, coverageData, true).generate();
152         }
153     }
154 }