All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mockit.coverage.CodeCoverage Maven / Gradle / Ivy

Go to download

JMockit is a Java toolkit for automated developer testing. It contains APIs for the creation of the objects to be tested, for mocking dependencies, and for faking external APIs; JUnit (4 & 5) and TestNG test runners are supported. It also contains an advanced code coverage tool.

There is a newer version: 1.49
Show newest version
/*
 * Copyright (c) 2006 Rogério Liesenfeld
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
 */
package mockit.coverage;

import java.lang.instrument.*;
import java.security.*;
import javax.annotation.*;

import mockit.coverage.data.*;
import mockit.coverage.modification.*;
import mockit.internal.startup.*;

public final class CodeCoverage implements ClassFileTransformer
{
   private static CodeCoverage instance;
   private static boolean inATestRun = true;

   @Nonnull private final ClassModification classModification;
   @Nonnull private final OutputFileGenerator outputGenerator;
   private boolean outputPendingForShutdown;
   private boolean inactive;

   public static void main(@Nonnull String[] args)
   {
      if (args.length == 1) {
         String pid = args[0];

         try {
            Integer.parseInt(pid);
            new AgentLoader(pid).loadAgent("coverage");
            return;
         }
         catch (NumberFormatException ignore) {}
      }

      OutputFileGenerator generator = createOutputFileGenerator(null);
      generator.generateAggregateReportFromInputFiles(args);
   }

   @Nonnull
   private static OutputFileGenerator createOutputFileGenerator(@Nullable ClassModification classModification)
   {
      OutputFileGenerator generator = new OutputFileGenerator(classModification);
      CoverageData.instance().setWithCallPoints(generator.isWithCallPoints());
      return generator;
   }

   public static boolean isTestRun() { return inATestRun; }

   public CodeCoverage()
   {
      classModification = new ClassModification();
      outputGenerator = createOutputFileGenerator(classModification);
      outputPendingForShutdown = true;
      instance = this;

      Runtime.getRuntime().addShutdownHook(new Thread() {
         @Override
         public void run()
         {
            TestRun.terminate();

            if (outputPendingForShutdown) {
               if (outputGenerator.isOutputToBeGenerated()) {
                  outputGenerator.generate(CodeCoverage.this);
               }

               new CoverageCheck().verifyThresholds();
            }

            Startup.instrumentation().removeTransformer(CodeCoverage.this);
         }
      });
   }

   public static boolean active()
   {
      String coverageOutput = Configuration.getProperty("output");
      String coverageClasses = Configuration.getProperty("classes");
      String coverageMetrics = Configuration.getProperty("metrics");

      if ("none".equals(coverageOutput) || "none".equals(coverageClasses) || "none".equals(coverageMetrics)) {
         return false;
      }

      return coverageOutput != null || coverageClasses != null || coverageMetrics != null;
   }

   @Nonnull
   public static CodeCoverage create(boolean generateOutputOnShutdown)
   {
      inATestRun = false;
      instance = new CodeCoverage();
      instance.outputPendingForShutdown = generateOutputOnShutdown;
      return instance;
   }

   public static void resetConfiguration()
   {
      Startup.instrumentation().removeTransformer(instance);
      CoverageData.instance().clear();

      CodeCoverage coverage = create(false);
      Startup.instrumentation().addTransformer(coverage);
      instance.outputPendingForShutdown = false;
   }

   public static void generateOutput(boolean resetState)
   {
      instance.outputGenerator.generate(null);
      instance.outputPendingForShutdown = false;

      if (resetState) {
         CoverageData.instance().reset();
      }
   }

   @Nullable @Override
   public byte[] transform(
      @Nullable ClassLoader loader, @Nonnull String internalClassName, @Nullable Class classBeingRedefined,
      @Nullable ProtectionDomain protectionDomain, @Nonnull byte[] originalClassfile)
   {
      if (loader == null || classBeingRedefined != null || protectionDomain == null || inactive) {
         return null;
      }

      String className = internalClassName.replace('/', '.');

      return classModification.modifyClass(className, protectionDomain, originalClassfile);
   }

   void deactivate() { inactive = true; }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy