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