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

org.conqat.engine.sourcecode.coverage.TestCoverageUtils Maven / Gradle / Ivy

There is a newer version: 2025.1.0
Show newest version
/*-------------------------------------------------------------------------+
|                                                                          |
| Copyright 2005-2011 the ConQAT Project                                   |
|                                                                          |
| Licensed under the Apache License, Version 2.0 (the "License");          |
| you may not use this file except in compliance with the License.         |
| You may obtain a copy of the License at                                  |
|                                                                          |
|    http://www.apache.org/licenses/LICENSE-2.0                            |
|                                                                          |
| Unless required by applicable law or agreed to in writing, software      |
| distributed under the License is distributed on an "AS IS" BASIS,        |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and      |
| limitations under the License.                                           |
+-------------------------------------------------------------------------*/
package org.conqat.engine.sourcecode.coverage;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.conqat.engine.commons.findings.location.ILineAdjuster;
import org.conqat.engine.commons.findings.location.LocationAdjuster;
import org.conqat.lib.commons.collections.UnmodifiableList;
import org.conqat.lib.commons.region.SimpleRegion;

import eu.cqse.check.framework.shallowparser.framework.EShallowEntityType;
import eu.cqse.check.framework.shallowparser.framework.ShallowEntity;
import eu.cqse.check.framework.shallowparser.framework.ShallowEntityTraversalUtils;

/**
 * Utility methods for dealing with coverage information.
 */
public class TestCoverageUtils {

	private static final Logger LOGGER = LogManager.getLogger();

	/**
	 * Adjusts line coverage information for a file to coverage information for a
	 * changed file. The changes to the file are described by a location adjuster.
	 * Due to the nature of coverage, each small change could affect the coverage
	 * globally, hence this is only a rough approximation. This method is robust
	 * w.r.t lines numbers that are out of the range w.r.t. the given
	 * {@link LocationAdjuster}. Such invalid lines are logged as error to the given
	 * logger.
	 * 
	 * @param coverageInfo
	 *            this may be null and then the result is null as well.
	 */
	public static LineCoverageInfo adjustCoverageInfo(LineCoverageInfo coverageInfo, ILineAdjuster adjuster,
			String appendToErrorMessage, boolean reportInvalidLines) {
		if (coverageInfo == null) {
			return null;
		}

		LineCoverageInfo adjustedCoverageInfo = new LineCoverageInfo(coverageInfo.getTimestamp(),
				coverageInfo.isMethodAccurate());

		for (ELineCoverage lineCoverageType : ELineCoverage.values()) {
			List relevantLines = lineCoverageType.getRelevantLines(coverageInfo);
			adjustLines(relevantLines, lineCoverageType, adjustedCoverageInfo, adjuster, appendToErrorMessage,
					reportInvalidLines);
		}

		return adjustedCoverageInfo;
	}

	/**
	 * Adjusts line coverage information for a file to coverage information for a
	 * changed file. The changes to the file are described by a location adjuster.
	 * Due to the nature of coverage, each small change could affect the coverage
	 * globally, hence this is only a rough approximation. This method is robust
	 * w.r.t lines numbers that are out of the range w.r.t. the given
	 * {@link LocationAdjuster}. Such invalid lines are logged as error to the given
	 * logger.
	 * 
	 * @param coverageInfo
	 *            this may be null and then the result is null as well.
	 */
	public static LineCoverageInfo adjustCoverageInfo(LineCoverageInfo coverageInfo, ILineAdjuster adjuster,
			String appendToErrorMessage) {
		return adjustCoverageInfo(coverageInfo, adjuster, appendToErrorMessage, true);
	}

	/**
	 * Adjusts the given lines using a location adjuster and fills them into the
	 * provided coverage info. Invalid lines, i.e. lines numbers that are out of
	 * range w.r.t the given {@link LocationAdjuster} are logged as error to the
	 * given logger.
	 * 
	 * @param lines
	 *            the line numbers (one-based)
	 */
	private static void adjustLines(List lines, ELineCoverage coverageType,
			LineCoverageInfo adjustedCoverageInfo, ILineAdjuster adjuster, String appendToErrorMessage,
			boolean reportInvalidLines) {
		Set invalidLines = new HashSet<>();
		for (int line : lines) {
			SimpleRegion adjustedLines = adjuster.adjustLine(line, invalidLines);
			if (adjustedLines == null) {
				continue;
			}
			for (int adjustedLine = adjustedLines.getStart(); adjustedLine <= adjustedLines.getEnd(); ++adjustedLine) {
				adjustedCoverageInfo.addLineCoverage(adjustedLine, coverageType);
			}
		}
		if (reportInvalidLines) {
			reportInvalidLines(appendToErrorMessage, invalidLines, adjuster);
		}
	}

	private static void reportInvalidLines(String appendToErrorMessage, Set invalidLines,
			ILineAdjuster adjuster) {
		if (!invalidLines.isEmpty()) {
			LOGGER.error("Encountered invalid lines: " + invalidLines + ". Line count: "
					+ adjuster.getOriginalLineCount() + ". " + appendToErrorMessage);
		}
	}

	/**
	 * Adjusts the line information of the given probole coverage using the
	 * specified location adjuster.
	 */
	public static void adjustProbeBasedCoverage(ProbeCoverageInfo probeCoverageInfo, LocationAdjuster adjuster,
			String appendToErrorMessage, boolean reportInvalidLines) {
		if (probeCoverageInfo == null) {
			return;
		}
		Set invalidLines = new HashSet<>();
		UnmodifiableList probes = probeCoverageInfo.getProbes();
		List validProbes = new ArrayList<>();
		for (CoverageProbeBase probe : probes) {
			SimpleRegion adjustedRegion = adjuster.adjustLine(probe.getLine(), invalidLines);
			if (adjustedRegion != null) {
				validProbes.add(probe);
				probe.setLine(adjustedRegion.getStart());
			}
		}
		if (reportInvalidLines) {
			reportInvalidLines(appendToErrorMessage, invalidLines, adjuster);
		}
		probeCoverageInfo.setProbes(validProbes);
	}

	/**
	 * Adjusts the line information of the given probole coverage using the
	 * specified location adjuster.
	 */
	public static void adjustProbeBasedCoverage(ProbeCoverageInfo probeCoverageInfo, LocationAdjuster adjuster,
			String appendToErrorMessage) {
		adjustProbeBasedCoverage(probeCoverageInfo, adjuster, appendToErrorMessage, true);
	}

	/**
	 * Adjust the line-coverage to expand to full statements (= shallow entity start
	 * and end)
	 */
	public static void adjustCoverageToStatements(LineCoverageInfo coverage, List entities) {
		for (ShallowEntity shallowEntity : ShallowEntityTraversalUtils.listEntitiesOfType(entities,
				EShallowEntityType.STATEMENT)) {
			int startLine = shallowEntity.getStartLine();
			int endLine = shallowEntity.getEndLine();
			ELineCoverage lineCoverage = coverage.getLineCoverage(startLine);

			if (shallowEntity.hasChildren() || startLine == endLine || lineCoverage == null
					|| lineCoverage == ELineCoverage.NOT_COVERED) {
				continue;
			}

			for (int i = startLine + 1; i <= endLine; i++) {
				coverage.addLineCoverage(i, lineCoverage);
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy