• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / jmockit1 / 496

15 Nov 2025 05:33PM UTC coverage: 72.192% (-0.008%) from 72.2%
496

push

github

web-flow
Merge pull request #412 from hazendaz/renovate/major-spring-core

Update spring core to v7 (major)

5677 of 8360 branches covered (67.91%)

Branch coverage included in aggregate %.

11922 of 16018 relevant lines covered (74.43%)

0.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/main/src/main/java/mockit/coverage/reporting/packages/IndexPage.java
1
/*
2
 * MIT License
3
 * Copyright (c) 2006-2025 JMockit developers
4
 * See LICENSE file for full license text.
5
 */
6
package mockit.coverage.reporting.packages;
7

8
import edu.umd.cs.findbugs.annotations.NonNull;
9
import edu.umd.cs.findbugs.annotations.Nullable;
10

11
import java.io.File;
12
import java.io.IOException;
13
import java.lang.reflect.Method;
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.Collections;
17
import java.util.Date;
18
import java.util.HashMap;
19
import java.util.List;
20
import java.util.Map;
21

22
import mockit.coverage.CoveragePercentage;
23
import mockit.coverage.data.FileCoverageData;
24
import mockit.coverage.reporting.OutputFile;
25
import mockit.coverage.testRedundancy.TestCoverage;
26

27
import org.checkerframework.checker.index.qual.NonNegative;
28

29
public final class IndexPage extends ListWithFilesAndPercentages {
×
30
    @Nullable
31
    private final List<File> sourceDirs;
32
    @NonNull
33
    private final Map<String, List<String>> packageToFiles;
34
    @NonNull
35
    private final Map<String, Integer> packageToPackagePercentages;
36
    @NonNull
37
    private final PackageCoverageReport packageReport;
38
    @NonNegative
39
    private final int totalFileCount;
40

41
    public IndexPage(@NonNull File outputFile, @Nullable List<File> sourceDirs,
42
            @Nullable Collection<String> sourceFilesNotFound, @NonNull Map<String, List<String>> packageToFiles,
43
            @NonNull Map<String, FileCoverageData> fileToFileData) throws IOException {
44
        super(new OutputFile(outputFile), "    ");
×
45
        this.sourceDirs = sourceDirs;
×
46
        this.packageToFiles = packageToFiles;
×
47
        packageToPackagePercentages = new HashMap<>();
×
48
        packageReport = new PackageCoverageReport(output, sourceFilesNotFound, fileToFileData, packageToFiles.values());
×
49
        totalFileCount = totalNumberOfSourceFilesWithCoverageData(fileToFileData.values());
×
50
    }
×
51

52
    @NonNegative
53
    private static int totalNumberOfSourceFilesWithCoverageData(@NonNull Collection<FileCoverageData> fileData) {
54
        return fileData.size() - Collections.frequency(fileData, null);
×
55
    }
56

57
    public void generate() {
58
        try {
59
            writeHeader();
×
60

61
            List<String> packages = new ArrayList<>(packageToFiles.keySet());
×
62
            writeMetricsForEachFile(null, packages);
×
63
            writeLineWithCoverageTotal();
×
64
            output.println("  </table>");
×
65

66
            writeListOfRedundantTestsIfAny();
×
67
            writeFooter();
×
68
        } finally {
69
            output.close();
×
70
        }
71
    }
×
72

73
    private void writeHeader() {
74
        ((OutputFile) output).writeCommonHeader("Code Coverage Report");
×
75

76
        output.println("  <table id='packages'>");
×
77

78
        writeTableCaption();
×
79
        writeTableFirstRowWithColumnTitles();
×
80
    }
×
81

82
    private void writeTableCaption() {
83
        if (sourceDirs == null) {
×
84
            output.println("    <caption>All Packages and Files</caption>");
×
85
        } else {
86
            output.write("    <caption>All Packages and Files<div style='font-size: smaller'>");
×
87
            output.write(getCommaSeparatedListOfSourceDirs());
×
88
            output.println("</div></caption>");
×
89
        }
90
    }
×
91

92
    @NonNull
93
    private String getCommaSeparatedListOfSourceDirs() {
94
        List<File> dirs = sourceDirs;
×
95
        assert dirs != null;
×
96
        removeRedundantSourceDirectories(dirs);
×
97

98
        String concatenatedSourceDirs = dirs.toString();
×
99
        String prefixToRemove = ".." + File.separatorChar;
×
100
        String commaSepDirs = concatenatedSourceDirs.replace(prefixToRemove, "");
×
101
        return commaSepDirs.substring(1, commaSepDirs.length() - 1);
×
102
    }
103

104
    private static void removeRedundantSourceDirectories(@NonNull List<File> dirs) {
105
        int i = 0;
×
106
        while (i < dirs.size()) {
×
107
            int newIndex = removeRedundantSourceDirectory(dirs, i);
×
108
            if (newIndex == i) {
×
109
                i++;
×
110
            } else {
111
                i = newIndex;
×
112
            }
113
        }
×
114
    }
×
115

116
    private static int removeRedundantSourceDirectory(@NonNull List<File> dirs, @NonNegative int dirIndex) {
117
        String dir1 = dirs.get(dirIndex).getPath();
×
118
        int j = dirIndex + 1;
×
119

120
        while (j < dirs.size()) {
×
121
            String dir2 = dirs.get(j).getPath();
×
122

123
            if (dir1.startsWith(dir2)) {
×
124
                dirs.remove(j);
×
125
            } else if (dir2.startsWith(dir1)) {
×
126
                dirs.remove(dirIndex);
×
127
                dirIndex--;
×
128
                break;
×
129
            } else {
130
                j++;
×
131
            }
132
        }
×
133

134
        return dirIndex;
×
135
    }
136

137
    private void writeTableFirstRowWithColumnTitles() {
138
        output.println("    <tr>");
×
139
        output.write("      <th style='cursor: col-resize' onclick='showHideAllFiles()'>Packages: ");
×
140
        output.print(packageToFiles.size());
×
141
        output.println("</th>");
×
142
        output.write("      <th onclick='location.reload()' style='cursor: n-resize' title='"
×
143
                + "Click on the column title to the right to sort by size (total number of items).'>Files: ");
144
        output.print(totalFileCount);
×
145
        output.println("</th>");
×
146
        writeHeaderCellWithMetricNameAndDescription();
×
147
        output.println("    </tr>");
×
148
    }
×
149

150
    private void writeHeaderCellWithMetricNameAndDescription() {
151
        output.println("      <th onclick='sortTables()' style='cursor: n-resize' title='"
×
152
                + "Measures how much of the executable production code (executable lines and fields) was exercised by tests.\n\n"
153
                + "An executable line of code contains one or more executable segments, separated by branching points\n"
154
                + "(if..else instructions, logical operators, etc.).\n\n"
155
                + "A non-final field must have the last value assigned to it read by at least one test, to be considered as covered.\n\n"
156
                + "Percentages are calculated as          100 × (CS + CF)\n"
157
                + "                                                         ────────\n"
158
                + "                                                                   S + F\n\n"
159
                + "where S+F is the total number of segments and fields, and CS+CF the covered segments and fields."
160
                + "'>Cvrg</th>");
161
    }
×
162

163
    private void writeLineWithCoverageTotal() {
164
        output.println("    <tr class='total'>");
×
165
        output.println("      <td>Total</td><td>&nbsp;</td>");
×
166

167
        int covered = coveredItems;
×
168
        int total = totalItems;
×
169
        int percentage = CoveragePercentage.calculate(covered, total);
×
170
        printCoveragePercentage(covered, total, percentage);
×
171

172
        output.println("    </tr>");
×
173
    }
×
174

175
    @Override
176
    @SuppressWarnings("ParameterNameDiffersFromOverriddenParameter")
177
    protected void writeMetricsForFile(String unused, @NonNull String packageName) {
178
        writeRowStart();
×
179
        writeTableCellWithPackageName(packageName);
×
180
        writeInternalTableForSourceFiles(packageName);
×
181
        writeCoveragePercentageForPackage(packageName);
×
182
        writeRowClose();
×
183
    }
×
184

185
    private void writeTableCellWithPackageName(@NonNull String packageName) {
186
        printIndent();
×
187
        output.write("  <td");
×
188

189
        List<String> filesInPackage = packageToFiles.get(packageName);
×
190

191
        if (filesInPackage.size() > 1) {
×
192
            output.write(" class='click' onclick='shFls(this)'");
×
193
        }
194

195
        output.write('>');
×
196
        output.write(packageName.replace('/', '.'));
×
197
        output.println("</td>");
×
198
    }
×
199

200
    private void writeInternalTableForSourceFiles(@NonNull String packageName) {
201
        printIndent();
×
202
        output.println("  <td>");
×
203

204
        printIndent();
×
205
        output.println("    <table>");
×
206

207
        List<String> fileNames = packageToFiles.get(packageName);
×
208
        packageReport.writeMetricsForEachFile(packageName, fileNames);
×
209

210
        recordCoverageInformationForPackage(packageName);
×
211

212
        printIndent();
×
213
        output.println("    </table>");
×
214
        printIndent();
×
215

216
        writeInitiallyHiddenSourceFileCount(fileNames.size());
×
217
        printIndent();
×
218
        output.println("  </td>");
×
219
    }
×
220

221
    private void recordCoverageInformationForPackage(@NonNull String packageName) {
222
        int coveredInPackage = packageReport.coveredItems;
×
223
        int totalInPackage = packageReport.totalItems;
×
224
        int packagePercentage = CoveragePercentage.calculate(coveredInPackage, totalInPackage);
×
225

226
        totalItems += totalInPackage;
×
227
        coveredItems += coveredInPackage;
×
228
        packageToPackagePercentages.put(packageName, packagePercentage);
×
229
    }
×
230

231
    private void writeInitiallyHiddenSourceFileCount(@NonNegative int fileCount) {
232
        output.write("    <span>(");
×
233
        output.print(fileCount);
×
234
        output.println(" source files)</span>");
×
235
    }
×
236

237
    private void writeCoveragePercentageForPackage(@NonNull String packageName) {
238
        int filePercentage = packageToPackagePercentages.get(packageName);
×
239
        printCoveragePercentage(packageReport.coveredItems, packageReport.totalItems, filePercentage);
×
240
    }
×
241

242
    private void writeListOfRedundantTestsIfAny() {
243
        TestCoverage testCoverage = TestCoverage.INSTANCE;
×
244

245
        if (testCoverage == null) {
×
246
            return;
×
247
        }
248

249
        List<Method> redundantTests = testCoverage.getRedundantTests();
×
250

251
        if (!redundantTests.isEmpty()) {
×
252
            output.println("  <br>Redundant tests:");
×
253
            output.println("  <ol title=\"Tests are regarded as redundant when they don't cover any additional line "
×
254
                    + "segments or fields that haven't already been covered by a previous test.\n"
255
                    + "Note this means the list of redundant tests depends on the order of test execution.\n"
256
                    + "Such a test can be removed without weakening the test suite, as long as another test "
257
                    + "for the same scenario performs its assertions.\">");
258

259
            for (Method testMethod : redundantTests) {
×
260
                String testDescription = testMethod.getDeclaringClass().getSimpleName() + '.' + testMethod.getName();
×
261

262
                output.append("");
×
263
                output.write("    <li>");
×
264
                output.write(testDescription);
×
265
                output.println("</li>");
×
266
            }
×
267

268
            output.println("  </ol>");
×
269
        }
270
    }
×
271

272
    private void writeFooter() {
273
        output.println("  <p>");
×
274
        output.println("    <a href='http://jmockit.github.io'><img src='logo.png'></a>");
×
275
        output.write("    Generated on ");
×
276
        output.println(new Date());
×
277
        output.println("  </p>");
×
278
        ((OutputFile) output).writeCommonFooter();
×
279
    }
×
280
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc