org.conqat.engine.sourcecode.coverage.ExecutionUnit Maven / Gradle / Ivy
Show all versions of teamscale-commons Show documentation
package org.conqat.engine.sourcecode.coverage;
import java.io.Serializable;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.conqat.engine.index.shared.tests.ETestExecutionResult;
import org.conqat.lib.commons.test.IndexValueClass;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
/**
* Represents a set of tests that are executed together. May support executing a subset of the tests
* it represents. May also always execute all tests. Examples include test binaries built for C/C++
* code or test Jar files for Java code. In the build one would execute all impacted tests for these
* execution units at once to avoid overhead.
*
* This class is a DTO used to deserialize testwise coverage reports of version 2+. Field names and
* structure may not be changed.
*/
@IndexValueClass(containedInBackup = true)
public class ExecutionUnit implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Unique name of the test case by using a path like hierarchical description, which can be shown in
* the UI.
*/
@JsonProperty("uniformPath")
private final String uniformPath;
/**
* The overall result of the execution of the execution unit. May differ from the combined result of
* tests contained in the execution unit.
*/
@JsonProperty("result")
@Nullable
private ETestExecutionResult result = null;
/** A hash determining the version of the execution unit. */
@JsonProperty("hash")
@Nullable
private String hash = null;
/** The duration in seconds it took to execute the execution unit. */
@JsonProperty("duration")
@Nullable
private Double durationSeconds = null;
/** The tests contained in the unit. */
@JsonProperty("tests")
private List tests = new ArrayList<>();
/**
* Link to an external build or test management tool that offers information about the run of the
* execution unit.
*/
@JsonProperty("externalLink")
@Nullable
private String externalLink = null;
public ExecutionUnit(String uniformPath) {
this.uniformPath = uniformPath;
}
public String getUniformPath() {
return uniformPath;
}
public @Nullable ETestExecutionResult getResult() {
return result;
}
public void setResult(@Nullable ETestExecutionResult result) {
this.result = result;
}
public @Nullable String getHash() {
return hash;
}
public void setHash(@Nullable String hash) {
this.hash = hash;
}
public @Nullable Double getDurationSeconds() {
return durationSeconds;
}
/** @return the test duration as {@link Duration} object (or null) */
public @Nullable Duration getDuration() {
if (durationSeconds == null) {
return null;
}
return Duration.ofMillis(Math.round(durationSeconds * 1000.0));
}
public void setDurationSeconds(@Nullable Double durationSeconds) {
this.durationSeconds = durationSeconds;
}
public List getTests() {
return tests;
}
public void addTest(String test) {
tests.add(test);
}
public @Nullable String getExternalLink() {
return externalLink;
}
public void setExternalLink(@Nullable String externalLink) {
this.externalLink = externalLink;
}
/**
* Merges a {@link Collection} of {@link ExecutionUnit}s to a single one. Result is the worst
* {@link ETestExecutionResult} with maximum duration in case there is more than one
* {@link ExecutionUnit} present.
*/
public static ExecutionUnit merge(Collection executionUnits) {
Preconditions.checkArgument(!executionUnits.isEmpty(), "Can't merge empty collection of execution units.");
if (executionUnits.size() == 1) {
return Iterables.getOnlyElement(executionUnits);
}
Iterator it = executionUnits.iterator();
ETestExecutionResult worstResult = ETestExecutionResult.worst(it.next().getResult(),
ETestExecutionResult.PASSED);
while (it.hasNext()) {
ExecutionUnit nextExecution = it.next();
if (ETestExecutionResult.worst(nextExecution.getResult(), worstResult) != worstResult) {
worstResult = nextExecution.getResult();
}
}
Double maxDurationSeconds = executionUnits.stream().map(ExecutionUnit::getDurationSeconds)
.filter(Objects::nonNull).max(Double::compare).orElse(null);
ExecutionUnit executionUnitFromFirstParent = executionUnits.iterator().next();
ExecutionUnit executionUnit = new ExecutionUnit(executionUnitFromFirstParent.uniformPath);
executionUnit.setResult(worstResult);
executionUnit.setDurationSeconds(maxDurationSeconds);
executionUnit.setHash(executionUnitFromFirstParent.hash);
executionUnits.stream().map(ExecutionUnit::getTests).flatMap(Collection::stream).distinct()
.forEach(executionUnit::addTest);
executionUnit.setExternalLink(executionUnitFromFirstParent.externalLink);
return executionUnit;
}
}