Skip to content
Permalink
Browse files
IGNITE-11962: Fix detection of newly contributed tests: detect new te…
…sts only, filter out init errors (new Missing status was instroduced, new test requires 4missing&4failures) - Fixes #143.

Signed-off-by: Dmitriy Pavlov <dpavlov@apache.org>
  • Loading branch information
dspavlov committed Aug 5, 2019
1 parent 63a478c commit 9456568d198d2587957388cb4716ff5dcabc8b31
Showing 8 changed files with 118 additions and 53 deletions.
@@ -1032,6 +1032,8 @@ function drawLatestRunsBlock(state, len) {
runColor = "grey";
else if (state === 3)
runColor = "black";
else if (state === 4)
runColor = "lightgrey";

return "<span style='background-color: " + runColor + "; width:" + (len * 1) + "px; height:10px; display: inline-block;'></span>";
}
@@ -22,7 +22,11 @@
public class EventTemplate implements IEventTemplate {
private final int[] beforeEvent;
private final int[] eventAndAfter;
private boolean shouldBeFirst;
private boolean includeMissing = false;
/**
* Event template eventAndAfter should be always first build in history of non-missed object.
*/
private boolean shouldBeFirstNonMissing = false;

public EventTemplate(int[] beforeEvent, int[] eventAndAfter) {
this.beforeEvent = beforeEvent;
@@ -37,17 +41,29 @@ public int[] eventAndAfter() {
return eventAndAfter;
}

public int cntEvents() {
return beforeEvent.length + eventAndAfter.length;
@Override
public boolean includeMissing() {
return includeMissing;
}

public EventTemplate setShouldBeFirst(boolean shouldBeFirst) {
this.shouldBeFirst = shouldBeFirst;
@Override
public boolean shouldBeFirstNonMissing() {
return shouldBeFirstNonMissing;
}

EventTemplate includeMissing(boolean include) {
this.includeMissing = include;

return this;
}

public boolean shouldBeFirst() {
return shouldBeFirst;
public int cntEvents() {
return beforeEvent.length + eventAndAfter.length;
}

public EventTemplate onlyForFirstNonMissing(boolean shouldBeFirst) {
this.shouldBeFirstNonMissing = shouldBeFirst;

return this;
}
}
@@ -24,10 +24,12 @@
import static org.apache.ignite.tcignited.history.RunStatus.RES_FAILURE;
import static org.apache.ignite.tcignited.history.RunStatus.RES_OK;
import static org.apache.ignite.tcignited.history.RunStatus.RES_OK_OR_FAILURE;
import static org.apache.ignite.tcignited.history.RunStatus.RES_MISSING;

public class EventTemplates {
private static final int OK = RES_OK.getCode();
private static final int FAIL = RES_FAILURE.getCode();
private static final int MISSING = RES_MISSING.getCode();

public static final EventTemplate newFailure = new EventTemplate(
new int[]{OK, OK, OK, OK, OK},
@@ -40,9 +42,9 @@ public class EventTemplates {
);

public static final EventTemplate newContributedTestFailure = new EventTemplate(
new int[]{},
new int[]{MISSING, MISSING, MISSING, MISSING},
new int[]{FAIL, FAIL, FAIL, FAIL}
).setShouldBeFirst(true);
).includeMissing(true).onlyForFirstNonMissing(true);

public static final EventTemplate newFailureForFlakyTest = new EventTemplate(
new int[]{OK, OK, OK, OK, OK},
@@ -18,15 +18,13 @@
package org.apache.ignite.ci.teamcity.ignited.runhist;

import com.google.common.base.MoreObjects;
import org.apache.ignite.tcignited.history.RunStatus;

import javax.annotation.Nonnull;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.ignite.tcignited.history.RunStatus;

import javax.annotation.Nonnull;

/**
*
*/
@@ -39,6 +37,8 @@ public class InvocationData {
public static final int OK = RunStatus.RES_OK.getCode();
/** Ok. */
public static final int CRITICAL_FAILURE = RunStatus.RES_CRITICAL_FAILURE.getCode();
/** Test is missing in suite run. */
public static final int MISSING = RunStatus.RES_MISSING.getCode();

/** Invocations map from build ID to invocation data. */
private final List<Invocation> invocationList = new ArrayList<>();
@@ -50,9 +50,9 @@ public void add(Invocation inv) {
/**
*
*/
public int notMutedRunsCount() {
public int notMutedAndNonMissingRunsCount() {
return (int)
invocations()
invocations(true)
.filter(invocation -> invocation.status() != MUTED)
.count();
}
@@ -62,7 +62,20 @@ public int notMutedRunsCount() {
*/
@Nonnull
Stream<Invocation> invocations() {
return invocationList.stream();
return invocations(false);
}


/**
* @param skipMissing Skip missing (absent) invocations.
*/
@Nonnull Stream<Invocation> invocations(boolean skipMissing) {
Stream<Invocation> stream = invocationList.stream();

if (skipMissing)
stream = stream.filter(invocation -> invocation.status() != MISSING);

return stream;
}

/**
@@ -118,4 +131,14 @@ public void sort() {
public Set<Integer> buildIds() {
return invocationList.stream().map(Invocation::buildId).collect(Collectors.toSet());
}

public void registerMissing(Integer testId, Set<Integer> suiteBuildIds) {
Set<Integer> idsPresent = buildIds();
HashSet<Integer> toAdd = new HashSet<>(suiteBuildIds);
toAdd.removeAll(idsPresent);

toAdd.forEach(id -> {
add(new Invocation(id).withStatus(MISSING));
});
}
}
@@ -18,21 +18,21 @@
package org.apache.ignite.ci.teamcity.ignited.runhist;

import com.google.common.base.MoreObjects;
import org.apache.ignite.tcbot.common.TcBotConst;
import org.apache.ignite.tcignited.history.ChangesState;
import org.apache.ignite.tcignited.history.IEventTemplate;
import org.apache.ignite.tcignited.history.IRunHistory;
import org.apache.ignite.tcignited.history.RunStatus;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.apache.ignite.tcbot.common.TcBotConst;
import org.apache.ignite.tcignited.history.ChangesState;
import org.apache.ignite.tcignited.history.IEventTemplate;
import org.apache.ignite.tcignited.history.IRunHistory;
import org.apache.ignite.tcignited.history.RunStatus;

/**
*
* In memory replacement of invocation history (RunHist/RunStat).
*/
public class RunHistCompacted implements IRunHistory {
/** Data. */
@@ -47,7 +47,7 @@ public RunHistCompacted(RunHistKey ignored) {

/** {@inheritDoc} */
@Override public int getRunsCount() {
return data.notMutedRunsCount();
return data.notMutedAndNonMissingRunsCount();
}

/** {@inheritDoc} */
@@ -80,12 +80,21 @@ public int getStatusChangesWithoutCodeModification() {
List<Invocation> latestRuns = data.invocations().collect(Collectors.toList());

for (Invocation cur : latestRuns) {
if (prev != null && cur != null) {
if (cur == null)
continue;

if (cur.status() == InvocationData.MISSING)
continue;

//todo here all previous MISSING invocations status could be checked
// (using outside build history)
if (prev != null) {
if (prev.status() != cur.status()
&& cur.changesState() == ChangesState.NONE
&& prev.changesState() != ChangesState.UNKNOWN)
statusChange++;
}

prev = cur;
}
return statusChange;
@@ -101,8 +110,8 @@ public int getStatusChangesWithoutCodeModification() {
return data.criticalFailuresCount();
}

@Override
public Set<Integer> buildIds() {
/** {@inheritDoc} */
@Override public Set<Integer> buildIds() {
return data.buildIds();
}

@@ -126,24 +135,29 @@ public Integer detectTemplate(IEventTemplate t) {
assert centralEvtBuild < template.length;
assert centralEvtBuild >= 0;

List<Invocation> histAsArr = data.invocations().collect(Collectors.toList());
boolean includeMissing = t.includeMissing();
List<Invocation> histAsArr = data.invocations(!includeMissing).collect(Collectors.toList());

if (histAsArr.size() < template.length)
return null;

Integer detectedAt = null;
if (t.shouldBeFirst()) {
//todo detect somehow test is new (e.g. status absent for test history).
detectedAt = checkTemplateAtPos(template, centralEvtBuild, histAsArr, 0);

//startIgnite from the end to find most recent
for (int idx = histAsArr.size() - template.length; idx >= 0; idx--) {
detectedAt = checkTemplateAtPos(template, centralEvtBuild, histAsArr, idx);

if (detectedAt != null)
break;
}
else {
//startIgnite from the end to find most recent
for (int idx = histAsArr.size() - template.length; idx >= 0; idx--) {
detectedAt = checkTemplateAtPos(template, centralEvtBuild, histAsArr, idx);

if (detectedAt != null)
break;
}
if (detectedAt != null && t.shouldBeFirstNonMissing()) {
Optional<Invocation> first = data.invocations(true).findFirst();
if (!first.isPresent())
return null;

if (first.get().buildId() != detectedAt)
return null;
}

return detectedAt;
@@ -206,23 +220,27 @@ public void sort() {
data.sort();
}

public void registerMissing(Integer testId, Set<Integer> buildIds) {
data.registerMissing(testId, buildIds);
}

public RunHistCompacted filterSuiteInvByParms(Map<Integer, Integer> requireParameters) {
RunHistCompacted copy = new RunHistCompacted();
RunHistCompacted cp = new RunHistCompacted();

data.invocations()
.filter(invocation -> invocation.containsParameterValue(requireParameters))
.forEach(invocation -> copy.data.add(invocation));
.filter(invocation -> invocation.containsParameterValue(requireParameters))
.forEach(invocation -> cp.data.add(invocation));

return copy;
return cp;
}

public RunHistCompacted filterByBuilds(Set<Integer> builds) {
RunHistCompacted copy = new RunHistCompacted();
RunHistCompacted cp = new RunHistCompacted();

data.invocations()
.filter(invocation -> builds.contains(invocation.buildId()))
.forEach(invocation -> copy.data.add(invocation));
.filter(invocation -> builds.contains(invocation.buildId()))
.forEach(invocation -> cp.data.add(invocation));

return copy;
return cp;
}
}
@@ -20,7 +20,6 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.ignite.Ignite;
import org.apache.ignite.ci.teamcity.ignited.runhist.Invocation;
import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistCompacted;
@@ -30,7 +29,7 @@
import org.apache.ignite.tcignited.history.SuiteInvocation;

/**
* Suite run history summary.
* Suite run history (in memory) summary with tests grouped by name.
*/
public class SuiteHistory implements ISuiteRunHistory {
/** Tests history: Test name ID->RunHistory */
@@ -46,8 +45,9 @@ public SuiteHistory(Map<Integer, SuiteInvocation> suiteRunHist) {
private SuiteHistory() {}

private void finalizeInvocations() {
//todo add missing status to tests
// testsHistory.values().registerMissing(suiteHist.buildIds());
Set<Integer> presentBuilds = suiteHist.buildIds();

testsHistory.forEach((k, t) -> t.registerMissing(k, presentBuilds));

suiteHist.sort();
testsHistory.values().forEach(RunHistCompacted::sort);
@@ -24,5 +24,7 @@ public interface IEventTemplate {

int[] eventAndAfter();

boolean shouldBeFirst();
boolean includeMissing();

boolean shouldBeFirstNonMissing();
}
@@ -34,7 +34,9 @@ public enum RunStatus {
/** Result of test execution, muted failure found. */
RES_MUTED_FAILURE(2),
/** Result of suite: Critical failure, no results. */
RES_CRITICAL_FAILURE(3);
RES_CRITICAL_FAILURE(3),
/** Test is not present in current run */
RES_MISSING(4);

/** Mapping of status int -> object. */
private static Map<Integer, RunStatus> holder = Stream.of(values()).collect(Collectors.toMap(RunStatus::getCode, i -> i));

0 comments on commit 9456568

Please sign in to comment.