org.conqat.engine.index.shared.tests.TestExecutionWithPartition Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of teamscale-commons Show documentation
Show all versions of teamscale-commons Show documentation
Provides common DTOs for Teamscale
/*
* Copyright (c) CQSE GmbH
*
* 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.index.shared.tests;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.conqat.engine.index.shared.CommitDescriptor;
import org.conqat.lib.commons.assertion.CCSMAssert;
import org.conqat.lib.commons.collections.CollectionUtils;
import org.conqat.lib.commons.js_export.ExportToTypeScript;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
/** Representation of a test execution in a partition. */
@ExportToTypeScript
public class TestExecutionWithPartition implements Serializable {
private static final long serialVersionUID = 1L;
/** The name of the JSON property name for {@link #testExecution}. */
private static final String TEST_EXECUTION_PROPERTY = "testExecution";
/** The name of the JSON property name for {@link #partition}. */
private static final String PARTITION_PROPERTY = "partition";
/** The name of the JSON property name for {@link #commit}. */
private static final String COMMIT_PROPERTY = "commit";
/** The name of the JSON property name for {@link #predecessorCommits}. */
private static final String PREDECESSOR_COMMITS_PROPERTY = "predecessorCommits";
/** The test execution. */
@JsonProperty(TEST_EXECUTION_PROPERTY)
private final TestExecution testExecution;
/** The partition. */
@JsonProperty(PARTITION_PROPERTY)
private final String partition;
/** The commit of the report upload containing the {@link #testExecution}. */
@JsonProperty(COMMIT_PROPERTY)
private final CommitDescriptor commit;
/**
* True if and only if this is a {@link TestExecutionWithPartition} created by
* {@link #merge(CommitDescriptor, Collection)}.
*/
@JsonProperty("isArtificialMergeTestExecution")
private final boolean isArtificialMergeTestExecution;
/**
* The commit of the previous report upload. May be on another branch. For a
* merge the {@link TestExecutionWithPartition#getCommit()} of the first parent
* branch is used as the predecessor if one is present.
*/
@JsonProperty(PREDECESSOR_COMMITS_PROPERTY)
private final List predecessorCommits = new ArrayList<>();
@JsonCreator
public TestExecutionWithPartition(@JsonProperty(TEST_EXECUTION_PROPERTY) TestExecution testExecution,
@JsonProperty(PARTITION_PROPERTY) String partition, @JsonProperty(COMMIT_PROPERTY) CommitDescriptor commit,
@JsonProperty(PREDECESSOR_COMMITS_PROPERTY) Collection predecessorCommits) {
this(testExecution, partition, commit, predecessorCommits, false);
}
@VisibleForTesting
TestExecutionWithPartition(TestExecution testExecution, String partition, CommitDescriptor commit,
Collection predecessorCommits, boolean isArtificialMergeTestExecution) {
Preconditions.checkState(
predecessorCommits.stream().allMatch(predecessorCommit -> predecessorCommit.compareTo(commit) < 0),
"Predecessor commits " + predecessorCommits + " can't come after commit " + commit);
this.testExecution = testExecution;
this.partition = partition;
this.commit = commit;
this.isArtificialMergeTestExecution = isArtificialMergeTestExecution;
// Ensures unique predecessor commits stable order for delta compression
predecessorCommits.stream().distinct().forEach(this.predecessorCommits::add);
Collections.sort(this.predecessorCommits);
}
/** @see #testExecution */
public TestExecution getTestExecution() {
return testExecution;
}
/** @see #partition */
public String getPartition() {
return partition;
}
/** @see #commit */
public CommitDescriptor getCommit() {
return commit;
}
/** @see #predecessorCommits */
public List getPredecessorCommits() {
return CollectionUtils.asUnmodifiable(predecessorCommits);
}
/**
* Returns true if this is a {@link TestExecutionWithPartition} which was
* created for a merge commit and doesn't represent a real test execution.
*/
public boolean isArtificialMergeTestExecution() {
return isArtificialMergeTestExecution;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TestExecutionWithPartition that = (TestExecutionWithPartition) o;
return isArtificialMergeTestExecution == that.isArtificialMergeTestExecution
&& Objects.equals(testExecution, that.testExecution) && Objects.equals(partition, that.partition)
&& Objects.equals(commit, that.commit) && Objects.equals(predecessorCommits, that.predecessorCommits);
}
@Override
public int hashCode() {
return Objects.hash(testExecution, partition, commit, isArtificialMergeTestExecution, predecessorCommits);
}
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
/**
* Merges a {@link Collection} of {@link TestExecutionWithPartition}s to a
* single one. Result is the the worst {@link ETestExecutionResult} with average
* duration in case there are is more than on {@link TestExecutionWithPartition}
* present.
*/
public static TestExecutionWithPartition merge(CommitDescriptor mergeCommit,
Collection testExecutionsWithPartition) {
Preconditions.checkArgument(!testExecutionsWithPartition.isEmpty(),
"Can't merge emtpy collection of test executions with partition.");
if (testExecutionsWithPartition.size() == 1) {
return testExecutionsWithPartition.iterator().next();
}
String uniquePartition = testExecutionsWithPartition.iterator().next().getPartition();
List testExecutions = new ArrayList<>();
Set predecessorCommits = new HashSet<>();
testExecutionsWithPartition.forEach(testExecutionWithPartition -> {
String partition = testExecutionWithPartition.getPartition();
predecessorCommits.add(testExecutionWithPartition.getCommit());
testExecutions.add(testExecutionWithPartition.getTestExecution());
CCSMAssert.isTrue(uniquePartition.equals(partition),
() -> "Can't merge test executions from separate partitions: " + uniquePartition + "," + partition);
});
TestExecution mergedTestExecution = TestExecution.merge(testExecutions);
return new TestExecutionWithPartition(mergedTestExecution, uniquePartition, mergeCommit, predecessorCommits,
true);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy