• 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/data/CoverageData.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.data;
7

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

11
import java.io.BufferedInputStream;
12
import java.io.BufferedOutputStream;
13
import java.io.File;
14
import java.io.IOException;
15
import java.io.ObjectInputStream;
16
import java.io.ObjectOutputStream;
17
import java.io.OutputStream;
18
import java.io.Serializable;
19
import java.nio.file.Files;
20
import java.nio.file.Path;
21
import java.util.ArrayList;
22
import java.util.Iterator;
23
import java.util.LinkedHashMap;
24
import java.util.List;
25
import java.util.Map;
26
import java.util.Map.Entry;
27
import java.util.jar.JarEntry;
28
import java.util.jar.JarFile;
29

30
import mockit.coverage.CoveragePercentage;
31
import mockit.internal.util.Utilities;
32

33
import org.checkerframework.checker.index.qual.NonNegative;
34

35
/**
36
 * Coverage data captured for all source files exercised during a test run.
37
 */
38
public final class CoverageData implements Serializable {
×
39
    private static final long serialVersionUID = -4860004226098360259L;
40
    @NonNull
41
    private static final CoverageData instance = new CoverageData();
×
42

43
    @NonNull
44
    public static CoverageData instance() {
45
        return instance;
×
46
    }
47

48
    private boolean withCallPoints;
49

50
    @NonNull
×
51
    private final Map<String, FileCoverageData> fileToFileData = new LinkedHashMap<>();
52
    @NonNull
×
53
    private final List<FileCoverageData> indexedFileData = new ArrayList<>(100);
54

55
    public boolean isWithCallPoints() {
56
        return withCallPoints;
×
57
    }
58

59
    public void setWithCallPoints(boolean withCallPoints) {
60
        this.withCallPoints = withCallPoints;
×
61
    }
×
62

63
    @NonNull
64
    public Map<String, FileCoverageData> getFileToFileData() {
65
        return fileToFileData;
×
66
    }
67

68
    @NonNull
69
    public FileCoverageData getOrAddFile(@NonNull String file, @Nullable String kindOfTopLevelType) {
70
        FileCoverageData fileData = fileToFileData.get(file);
×
71

72
        // For a class with nested/inner classes, a previous class in the same source file may already have been added.
73
        if (fileData == null) {
×
74
            int fileIndex = indexedFileData.size();
×
75
            fileData = new FileCoverageData(fileIndex, kindOfTopLevelType);
×
76
            indexedFileData.add(fileData);
×
77
            fileToFileData.put(file, fileData);
×
78
        } else if (kindOfTopLevelType != null) {
×
79
            fileData.kindOfTopLevelType = kindOfTopLevelType;
×
80
        }
81

82
        return fileData;
×
83
    }
84

85
    @NonNull
86
    public FileCoverageData getFileData(@NonNull String file) {
87
        return fileToFileData.get(file);
×
88
    }
89

90
    @NonNull
91
    public FileCoverageData getFileData(@NonNegative int fileIndex) {
92
        return indexedFileData.get(fileIndex);
×
93
    }
94

95
    public boolean isEmpty() {
96
        return fileToFileData.isEmpty();
×
97
    }
98

99
    public void clear() {
100
        fileToFileData.clear();
×
101
    }
×
102

103
    /**
104
     * Computes the coverage percentage over a subset of the available source files.
105
     *
106
     * @param fileNamePrefix
107
     *            a regular expression for matching the names of the source files to be considered, or <code>null</code>
108
     *            to consider <em>all</em> files
109
     *
110
     * @return the computed percentage from <code>0</code> to <code>100</code> (inclusive), or <code>-1</code> if no
111
     *         meaningful value could be computed
112
     */
113
    public int getPercentage(@Nullable String fileNamePrefix) {
114
        int coveredItems = 0;
×
115
        int totalItems = 0;
×
116

117
        for (Entry<String, FileCoverageData> fileAndFileData : fileToFileData.entrySet()) {
×
118
            String sourceFile = fileAndFileData.getKey();
×
119

120
            if (fileNamePrefix == null || sourceFile.startsWith(fileNamePrefix)) {
×
121
                FileCoverageData fileData = fileAndFileData.getValue();
×
122
                coveredItems += fileData.getCoveredItems();
×
123
                totalItems += fileData.getTotalItems();
×
124
            }
125
        }
×
126

127
        return CoveragePercentage.calculate(coveredItems, totalItems);
×
128
    }
129

130
    /**
131
     * Finds the source file with the smallest coverage percentage.
132
     *
133
     * @return the percentage value for the file found, or <code>Integer.MAX_VALUE</code> if no file is found with a
134
     *         meaningful percentage
135
     */
136
    @NonNegative
137
    public int getSmallestPerFilePercentage() {
138
        int minPercentage = Integer.MAX_VALUE;
×
139

140
        for (FileCoverageData fileData : fileToFileData.values()) {
×
141
            if (!fileData.wasLoadedAfterTestCompletion()) {
×
142
                int percentage = fileData.getCoveragePercentage();
×
143

144
                if (percentage >= 0 && percentage < minPercentage) {
×
145
                    minPercentage = percentage;
×
146
                }
147
            }
148
        }
×
149

150
        return minPercentage;
×
151
    }
152

153
    public void fillLastModifiedTimesForAllClassFiles() {
154
        for (Iterator<Entry<String, FileCoverageData>> itr = fileToFileData.entrySet().iterator(); itr.hasNext();) {
×
155
            Entry<String, FileCoverageData> fileAndFileData = itr.next();
×
156
            long lastModified = getLastModifiedTimeForClassFile(fileAndFileData.getKey());
×
157

158
            if (lastModified > 0L) {
×
159
                FileCoverageData fileCoverageData = fileAndFileData.getValue();
×
160
                fileCoverageData.lastModified = lastModified;
×
161
                continue;
×
162
            }
163

164
            itr.remove();
×
165
        }
×
166
    }
×
167

168
    private long getLastModifiedTimeForClassFile(@NonNull String sourceFilePath) {
169
        String sourceFilePathNoExt = sourceFilePath.substring(0, sourceFilePath.lastIndexOf('.'));
×
170
        String className = sourceFilePathNoExt.replace('/', '.');
×
171

172
        Class<?> coveredClass = findCoveredClass(className);
×
173

174
        if (coveredClass == null) {
×
175
            return 0L;
×
176
        }
177

178
        String locationPath = Utilities.getClassFileLocationPath(coveredClass);
×
179

180
        if (locationPath.endsWith(".jar")) {
×
181
            try {
182
                return getLastModifiedTimeFromJarEntry(sourceFilePathNoExt, locationPath);
×
183
            } catch (IOException ignore) {
×
184
                return 0L;
×
185
            }
186
        }
187

188
        String pathToClassFile = locationPath + sourceFilePathNoExt + ".class";
×
189

190
        return Path.of(pathToClassFile).toFile().lastModified();
×
191
    }
192

193
    private static long getLastModifiedTimeFromJarEntry(@NonNull String sourceFilePathNoExt,
194
            @NonNull String locationPath) throws IOException {
195

196
        try (JarFile jarFile = new JarFile(locationPath)) {
×
197
            JarEntry classEntry = jarFile.getJarEntry(sourceFilePathNoExt + ".class");
×
198
            return classEntry.getTime();
×
199
        }
200
    }
201

202
    @Nullable
203
    private Class<?> findCoveredClass(@NonNull String className) {
204
        ClassLoader currentCL = getClass().getClassLoader();
×
205
        Class<?> coveredClass = loadClass(className, currentCL);
×
206

207
        if (coveredClass == null) {
×
208
            ClassLoader systemCL = ClassLoader.getSystemClassLoader();
×
209

210
            if (systemCL != currentCL) {
×
211
                coveredClass = loadClass(className, systemCL);
×
212
            }
213

214
            if (coveredClass == null) {
×
215
                ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
×
216

217
                if (contextCL != null && contextCL != systemCL) {
×
218
                    coveredClass = loadClass(className, contextCL);
×
219
                }
220
            }
221
        }
222

223
        return coveredClass;
×
224
    }
225

226
    @Nullable
227
    private static Class<?> loadClass(@NonNull String className, @Nullable ClassLoader loader) {
228
        try {
229
            return Class.forName(className, false, loader);
×
230
        } catch (ClassNotFoundException | NoClassDefFoundError ignore) {
×
231
            return null;
×
232
        }
233
    }
234

235
    /**
236
     * Reads a serialized <code>CoverageData</code> object from the given file (normally, a "<code>coverage.ser</code>"
237
     * file generated at the end of a previous test run).
238
     *
239
     * @param dataFile
240
     *            the ".ser" file containing a serialized <code>CoverageData</code> instance
241
     *
242
     * @return a new object containing all coverage data resulting from a previous test run
243
     */
244
    @NonNull
245
    public static CoverageData readDataFromFile(@NonNull File dataFile) throws IOException {
246
        try (ObjectInputStream input = new ObjectInputStream(
×
247
                new BufferedInputStream(Files.newInputStream(dataFile.toPath())))) {
×
248
            return (CoverageData) input.readObject();
×
249
        } catch (ClassNotFoundException e) {
×
250
            throw new RuntimeException(
×
251
                    "Serialized class in coverage data file \"" + dataFile + "\" not found in classpath", e);
252
        }
253
    }
254

255
    public void writeDataToFile(@NonNull File dataFile) throws IOException {
256
        try (OutputStream outputStream = Files.newOutputStream(dataFile.toPath());
×
257
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
×
258
                ObjectOutputStream output = new ObjectOutputStream(bufferedOutputStream)) {
×
259
            output.writeObject(this);
×
260
        }
261
    }
×
262

263
    public void merge(@NonNull CoverageData previousData) {
264
        withCallPoints |= previousData.withCallPoints;
×
265

266
        for (Entry<String, FileCoverageData> previousFileAndFileData : previousData.fileToFileData.entrySet()) {
×
267
            String previousFile = previousFileAndFileData.getKey();
×
268
            FileCoverageData previousFileData = previousFileAndFileData.getValue();
×
269
            FileCoverageData fileData = fileToFileData.get(previousFile);
×
270

271
            if (fileData == null) {
×
272
                fileToFileData.put(previousFile, previousFileData);
×
273
            } else if (fileData.lastModified > 0 && previousFileData.lastModified == fileData.lastModified) {
×
274
                fileData.mergeWithDataFromPreviousTestRun(previousFileData);
×
275
            }
276
        }
×
277
    }
×
278
}
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