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

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

The newest version!
package org.conqat.engine.sourcecode.coverage;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;

import org.conqat.lib.commons.assertion.CCSMAssert;
import org.conqat.lib.commons.collections.CollectionUtils;
import org.conqat.lib.commons.collections.UnmodifiableList;
import org.conqat.lib.commons.string.StringUtils;
import org.conqat.lib.commons.test.IndexValueClass;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
 * Probe for a decision, e.g. an "if" statement, which carries two execution counters
 */
@IndexValueClass(containedInBackup = true)
public class DecisionProbe extends CoverageProbeBase {

	private static final long serialVersionUID = 1L;

	@JsonProperty("trueExecutionCount")
	private int trueExecutionCount;

	@JsonProperty("falseExecutionCount")
	private int falseExecutionCount;

	@JsonProperty("configurations")
	private final List configurations = new ArrayList<>();

	@JsonProperty("conditions")
	private final List conditions = new ArrayList<>();

	@JsonCreator
	public DecisionProbe(@JsonProperty("line") int line, @JsonProperty("trueExecutionCount") int trueExecutionCount,
			@JsonProperty("falseExecutionCount") int falseExecutionCount) {
		super(line);
		this.trueExecutionCount = trueExecutionCount;
		this.falseExecutionCount = falseExecutionCount;
	}

	/** @see #falseExecutionCount */
	public int getFalseExecutionCount() {
		return falseExecutionCount;
	}

	/** @see #trueExecutionCount */
	public int getTrueExecutionCount() {
		return trueExecutionCount;
	}

	/** Adds the given configuration to this probe */
	public void addConfiguration(DecisionProbeConfiguration configuration) {
		configurations.add(configuration);
	}

	/** Adds the given condition to this probe */
	public void addCondition(McDcCondition condition) {
		conditions.add(condition);
	}

	/** @see #conditions */
	public UnmodifiableList getConditions() {
		return CollectionUtils.asUnmodifiable(conditions);
	}

	/** @see #configurations */
	public UnmodifiableList getConfigurations() {
		return CollectionUtils.asUnmodifiable(configurations);
	}

	@Override
	public String toString() {
		StringBuilder result = new StringBuilder("Decision in line " + getLine() + "\n");
		result.append(StringUtils.concat(configurations, "\n"));
		result.append(StringUtils.concat(conditions, "\n"));
		return result.toString();
	}

	@Override
	@JsonIgnore
	public int getCoverableCount() {
		// CTC++ counts one coverable point for each possible outcome of the overall
		// decision (true/false) + one coverable point for each atomic condition
		return 2 + getConditions().size();
	}

	@Override
	@JsonIgnore
	public int getCoveredCount() {
		int coveredCount = 0;
		if (trueExecutionCount > 0) {
			coveredCount++;
		}
		if (falseExecutionCount > 0) {
			coveredCount++;
		}
		for (McDcCondition condition : conditions) {
			if (condition.isFulfilled()) {
				coveredCount++;
			}
		}
		return coveredCount;
	}

	@Override
	public boolean mergeWith(CoverageProbeBase other) {
		CCSMAssert.isInstanceOf(other, DecisionProbe.class);
		DecisionProbe sourceDecisionProbe = (DecisionProbe) other;
		trueExecutionCount += sourceDecisionProbe.trueExecutionCount;
		falseExecutionCount += sourceDecisionProbe.falseExecutionCount;

		mergeIntoList(configurations, sourceDecisionProbe.configurations,
				DecisionProbeConfiguration::haveSameDescriptionAndDecisionValue,
				(target, source) -> target.increaseExecutionCount(source.getExecutionCount()));
		mergeIntoList(conditions, sourceDecisionProbe.conditions,
				(target, source) -> target.getDescription().equals(source.getDescription()),
				(target, source) -> target.setFulfilled(target.isFulfilled() || source.isFulfilled()));

		// we deem merging of decision probes to be unsafe, as we do not really parse
		// the content of the probes, but rather use string equality only
		return false;
	}

	/**
	 * Merges all elements from source into target. For this a matching element w.r.t. equalsChecker is
	 * searched. If this is found, the merge function is applied, otherwise the element is just added to
	 * the target list.
	 */
	private static  void mergeIntoList(List targets, List sources, BiFunction equalsChecker,
			BiConsumer targetSourceMerger) {
		for (T source : sources) {
			Optional match = targets.stream().filter(target -> equalsChecker.apply(source, target)).findFirst();
			if (!match.isPresent()) {
				targets.add(source);
			} else {
				targetSourceMerger.accept(match.get(), source);
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy