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

mockit.coverage.lines.PerFileLineCoverage 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.lines;

import java.io.*;
import java.util.*;
import javax.annotation.*;

import mockit.coverage.*;
import mockit.coverage.data.*;

public final class PerFileLineCoverage implements PerFileCoverage
{
   private static final long serialVersionUID = 6318915843739466316L;
   private static final int[] NO_EXECUTIONS_YET = new int[0];

   @Nonnull private final Map lineToLineData = new HashMap(128);

   @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
   @Nonnull private int[] executionCounts = NO_EXECUTIONS_YET;

   @Nonnull private transient LineCoverageData sharedLineData;

   // Computed on demand:
   private int lastLine;
   private transient int totalSegments;
   private transient int coveredSegments;

   public PerFileLineCoverage()
   {
      sharedLineData = new LineCoverageData();
      initializeCache();
   }

   private void initializeCache() { totalSegments = coveredSegments = -1; }

   private void readObject(@Nonnull ObjectInputStream in) throws IOException, ClassNotFoundException
   {
      sharedLineData = new LineCoverageData();
      initializeCache();
      in.defaultReadObject();

      if (executionCounts.length == 0) {
         executionCounts = NO_EXECUTIONS_YET;
      }
   }

   public void addLine(int line, boolean reprocessing)
   {
      if (lineToLineData.containsKey(line)) {
         if (reprocessing) {
            LineCoverageData lineData = lineToLineData.get(line);

            if (lineData != null) {
               lineData.clearBranches();
            }
         }
      }
      else {
         lineToLineData.put(line, null);
      }

      if (line > lastLine) {
         // Happens for source files with multiple types, where one is only loaded
         // after another has already executed some code.
         int[] initialExecutionCounts = executionCounts;

         if (initialExecutionCounts != NO_EXECUTIONS_YET && line >= initialExecutionCounts.length) {
            int[] newCounts = new int[line + 30];
            System.arraycopy(initialExecutionCounts, 0, newCounts, 0, initialExecutionCounts.length);
            executionCounts = newCounts;
         }

         lastLine = line;
      }
   }

   @Nonnull
   public LineCoverageData getOrCreateLineData(int line)
   {
      LineCoverageData lineData = lineToLineData.get(line);

      if (lineData == null) {
         lineData = new LineCoverageData();
         lineToLineData.put(line, lineData);
      }

      return lineData;
   }

   @Nonnull
   public BranchCoverageData getBranchData(int line, int index)
   {
      LineCoverageData lineData = lineToLineData.get(line);
      return lineData.getBranchData(index);
   }

   public void markLastLineSegmentAsEmpty(int line)
   {
      LineCoverageData lineData = lineToLineData.get(line);
      lineData.markLastSegmentAsEmpty();
   }

   public boolean acceptsAdditionalCallPoints(int line)
   {
      LineCoverageData lineData = getOrCreateLineData(line);
      return lineData.acceptsAdditionalCallPoints();
   }

   public int registerExecution(int line, @Nullable CallPoint callPoint)
   {
      if (executionCounts == NO_EXECUTIONS_YET) {
         executionCounts = new int[lastLine + 1];
      }

      int previousExecutionCount = executionCounts[line]++;

      if (callPoint != null) {
         LineCoverageData lineData = lineToLineData.get(line);
         lineData.registerExecution(callPoint);
      }

      return previousExecutionCount;
   }

   public boolean hasValidBranch(int line, int branchIndex)
   {
      LineCoverageData lineData = lineToLineData.get(line);
      return lineData.isValidBranch(branchIndex);
   }

   public boolean acceptsAdditionalCallPoints(int line, int branchIndex)
   {
      LineCoverageData lineData = lineToLineData.get(line);
      return lineData.acceptsAdditionalCallPoints(branchIndex);
   }

   public int registerExecution(int line, int branchIndex, @Nullable CallPoint callPoint)
   {
      LineCoverageData lineData = lineToLineData.get(line);
      return lineData.registerExecution(branchIndex, callPoint);
   }

   public int getLineCount() { return lastLine; }
   public int getExecutableLineCount() { return lineToLineData.size(); }

   public boolean hasLineData(int line)
   {
      return executionCounts != NO_EXECUTIONS_YET && lineToLineData.containsKey(line);
   }

   @Nonnull
   public LineCoverageData getLineData(int line)
   {
      LineCoverageData data = lineToLineData.get(line);

      if (data == null) {
         data = sharedLineData;
      }

      data.setExecutionCount(executionCounts[line]);
      return data;
   }

   public int getExecutionCount(int line)
   {
      return line < executionCounts.length ? executionCounts[line] : -1;
   }

   @Override
   public int getTotalItems()
   {
      computeValuesIfNeeded();
      return totalSegments;
   }

   @Override
   public int getCoveredItems()
   {
      computeValuesIfNeeded();
      return coveredSegments;
   }

   @Override
   public int getCoveragePercentage()
   {
      computeValuesIfNeeded();
      return CoveragePercentage.calculate(coveredSegments, totalSegments);
   }

   private void computeValuesIfNeeded()
   {
      if (totalSegments >= 0) return;

      totalSegments = coveredSegments = 0;

      for (int line = 1, n = lastLine; line <= n; line++) {
         if (lineToLineData.containsKey(line)) {
            LineCoverageData lineData = lineToLineData.get(line);
            int executionCount = executionCounts == NO_EXECUTIONS_YET ? 0 : executionCounts[line];

            if (lineData == null) {
               totalSegments++;

               if (executionCount > 0) {
                  coveredSegments++;
               }
            }
            else {
               lineData.setExecutionCount(executionCount);
               totalSegments += lineData.getNumberOfSegments();
               coveredSegments += lineData.getNumberOfCoveredSegments();
            }
         }
      }
   }

   public int getNumberOfSegments(int line)
   {
      if (!lineToLineData.containsKey(line)) {
         return 0;
      }

      LineCoverageData lineData = lineToLineData.get(line);
      return lineData == null ? 1 : lineData.getNumberOfSegments();
   }

   public int getNumberOfBranchingSourcesAndTargets(int line)
   {
      LineCoverageData lineData = lineToLineData.get(line);

      if (lineData == null) {
         return 0;
      }

      return lineData.getNumberOfBranchingSourcesAndTargets();
   }

   public void mergeInformation(@Nonnull PerFileLineCoverage previousCoverage)
   {
      Map previousInfo = previousCoverage.lineToLineData;
      boolean previousRunHadLinesExecuted = previousCoverage.executionCounts.length > 0;

      for (Map.Entry lineAndInfo : lineToLineData.entrySet()) {
         Integer line = lineAndInfo.getKey();
         LineCoverageData previousLineInfo = previousInfo.get(line);

         if (previousLineInfo != null) {
            LineCoverageData lineInfo = lineAndInfo.getValue();

            if (lineInfo == null) {
               lineInfo = new LineCoverageData();
               lineAndInfo.setValue(lineInfo);
            }

            lineInfo.addCountsFromPreviousTestRun(previousLineInfo);

            if (previousRunHadLinesExecuted) {
               createExecutionCountsArrayIfNeeded(previousCoverage);
               executionCounts[line] += previousCoverage.executionCounts[line];
            }
         }
      }

      for (Map.Entry lineAndInfo : previousInfo.entrySet()) {
         Integer line = lineAndInfo.getKey();

         if (!lineToLineData.containsKey(line)) {
            LineCoverageData previousLineInfo = lineAndInfo.getValue();
            lineToLineData.put(line, previousLineInfo);

            if (previousRunHadLinesExecuted) {
               createExecutionCountsArrayIfNeeded(previousCoverage);
               executionCounts[line] = previousCoverage.executionCounts[line];
            }
         }
      }
   }

   private void createExecutionCountsArrayIfNeeded(@Nonnull PerFileLineCoverage previousCoverage)
   {
      if (executionCounts == NO_EXECUTIONS_YET) {
         executionCounts = new int[previousCoverage.executionCounts.length];
      }
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy