1
2
3
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.lang.instrument.ClassFileTransformer;
11 import java.security.ProtectionDomain;
12
13 import mockit.coverage.data.CoverageData;
14 import mockit.coverage.modification.ClassModification;
15 import mockit.coverage.modification.ClassesNotLoaded;
16 import mockit.internal.startup.Startup;
17
18 public final class CodeCoverage implements ClassFileTransformer {
19 @NonNull
20 private final ClassModification classModification;
21
22 public static void main(@NonNull String[] args) {
23 OutputFileGenerator generator = createOutputFileGenerator();
24 generator.generateAggregateReportFromInputFiles(args);
25 }
26
27 @NonNull
28 private static OutputFileGenerator createOutputFileGenerator() {
29 OutputFileGenerator generator = new OutputFileGenerator();
30 CoverageData.instance().setWithCallPoints(generator.isWithCallPoints());
31 return generator;
32 }
33
34 public static boolean active() {
35 String coverageOutput = Configuration.getProperty("output");
36 String coverageClasses = Configuration.getProperty("classes");
37 return (coverageOutput != null || coverageClasses != null) && !"none".equals(coverageOutput)
38 && !"none".equals(coverageClasses);
39 }
40
41 public CodeCoverage() {
42 classModification = new ClassModification();
43 final OutputFileGenerator outputGenerator = createOutputFileGenerator();
44 final CoverageCheck coverageCheck = CoverageCheck.createIfApplicable();
45
46 Runtime.getRuntime().addShutdownHook(new Thread() {
47 @Override
48 public void run() {
49 TestRun.terminate();
50
51 if (outputGenerator.isOutputToBeGenerated()) {
52 if (classModification.shouldConsiderClassesNotLoaded()) {
53 new ClassesNotLoaded(classModification).gatherCoverageData();
54 }
55
56 Startup.instrumentation().removeTransformer(CodeCoverage.this);
57 outputGenerator.generate();
58 } else {
59 Startup.instrumentation().removeTransformer(CodeCoverage.this);
60 }
61
62 if (coverageCheck != null) {
63 coverageCheck.verifyThresholds();
64 }
65 }
66 });
67 }
68
69 @Nullable
70 @Override
71 public byte[] transform(@Nullable ClassLoader loader, @NonNull String internalClassName,
72 @Nullable Class<?> classBeingRedefined, @Nullable ProtectionDomain protectionDomain,
73 @NonNull byte[] originalClassfile) {
74 if (loader == null || classBeingRedefined != null || protectionDomain == null) {
75 return null;
76 }
77
78 String className = internalClassName.replace('/', '.');
79 return classModification.modifyClass(className, protectionDomain, originalClassfile);
80 }
81 }