You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dp...@apache.org on 2018/11/21 16:51:51 UTC
[ignite-teamcity-bot] branch master updated: IGNITE-10336 Fix of
chain collection to avoid missing builds - Fixes #77.
This is an automated email from the ASF dual-hosted git repository.
dpavlov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git
The following commit(s) were added to refs/heads/master by this push:
new f63df1d IGNITE-10336 Fix of chain collection to avoid missing builds - Fixes #77.
f63df1d is described below
commit f63df1df3baf71cf18fe16fd86f9e10f39d9644a
Author: Dmitriy Pavlov <dp...@apache.org>
AuthorDate: Wed Nov 21 19:51:46 2018 +0300
IGNITE-10336 Fix of chain collection to avoid missing builds - Fixes #77.
Signed-off-by: Dmitriy Pavlov <dp...@apache.org>
---
.../apache/ignite/ci/analysis/FullChainRunCtx.java | 2 +-
.../ignite/ci/analysis/mode/LatestRebuildMode.java | 2 +-
.../ci/tcbot/builds/CompareBuildsService.java | 2 +-
.../ignite/ci/tcbot/chain/BuildChainProcessor.java | 240 ++++++++++++---------
.../ci/teamcity/ignited/BuildRefCompacted.java | 7 +-
.../ignited/fatbuild/FatBuildCompacted.java | 3 +
.../org/apache/ignite/ci/web/model/Version.java | 2 +-
.../ci/tcbot/chain/BuildChainProcessorTest.java | 43 +++-
8 files changed, 185 insertions(+), 116 deletions(-)
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/FullChainRunCtx.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/FullChainRunCtx.java
index 36602c6..c9cf274 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/FullChainRunCtx.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/FullChainRunCtx.java
@@ -90,7 +90,7 @@ public class FullChainRunCtx {
+ (hasFullDurationInfo() ? "" : "+");
}
- public void addAllSuites(ArrayList<MultBuildRunCtx> suites) {
+ public void addAllSuites(List<MultBuildRunCtx> suites) {
this.buildCfgsResults.addAll(suites);
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/mode/LatestRebuildMode.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/mode/LatestRebuildMode.java
index 5083bb7..9583f5a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/mode/LatestRebuildMode.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/mode/LatestRebuildMode.java
@@ -22,6 +22,6 @@ public enum LatestRebuildMode {
NONE,
/** replace builds with Latest rebuild. */
LATEST,
- /** Collect history of builds. */
+ /** Collect history of builds. Rebuilds are applied, but have higher priority. */
ALL
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/builds/CompareBuildsService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/builds/CompareBuildsService.java
index 71715c8..e420ca4 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/builds/CompareBuildsService.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/builds/CompareBuildsService.java
@@ -80,7 +80,7 @@ public class CompareBuildsService {
MultBuildRunCtx buildCtx = new MultBuildRunCtx(build, compactor);
final FatBuildCompacted fatBuild = tcIgnited.getFatBuild(build.getId());
- buildCtx.addBuild(bcp.loadTestsAndProblems(fatBuild, tcIgnited));
+ buildCtx.addBuild(bcp.loadChanges(fatBuild, tcIgnited));
for (String testName : buildCtx.tests())
tests.add(extractTestName(testName));
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
index 14d6d2e..5142fe6 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
@@ -17,16 +17,19 @@
package org.apache.ignite.ci.tcbot.chain;
+import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.Futures;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -92,22 +95,9 @@ public class BuildChainProcessor {
if (entryPoints.isEmpty())
return res;
- Map<Integer, FatBuildCompacted> builds = new ConcurrentHashMap<>();
+ Map<Integer, Future<FatBuildCompacted>> builds = loadAllBuildsInChains(entryPoints, mode, teamcityIgnited);
- final Stream<FatBuildCompacted> entryPointsFatBuilds = entryPoints.stream()
- .filter(Objects::nonNull)
- .filter(id -> !builds.containsKey(id)) //load and propagate only new entry points
- .map(id -> builds.computeIfAbsent(id, teamcityIgnited::getFatBuild));
-
- final ExecutorService svc = tcUpdatePool.getService();
-
- final Stream<FatBuildCompacted> depsFirstLevel = entryPointsFatBuilds
- .map(ref -> svc.submit(() -> dependencies(teamcityIgnited, builds, mode, ref)))
- .collect(Collectors.toList())
- .stream()
- .flatMap(fut -> FutureUtil.getResult(fut));
-
- depsFirstLevel
+ builds.values().stream().map(FutureUtil::getResult)
.filter(b -> !b.isComposite() && b.getTestsCount() > 0)
.forEach(b ->
{
@@ -121,7 +111,7 @@ public class BuildChainProcessor {
);
if (!lrTests.isEmpty()) {
- Collections.sort(lrTests, (test0, test1) -> {
+ lrTests.sort((test0, test1) -> {
long t0 = test0.time;
long t1 = test1.time;
@@ -156,18 +146,18 @@ public class BuildChainProcessor {
/**
* @param teamcity Teamcity.
- * @param teamcityIgnited
+ * @param tcIgn Teamcity Ignited.
* @param entryPoints Entry point(s): Build(s) to start scan from.
* @param includeLatestRebuild Include latest rebuild.
* @param procLog Process logger.
* @param includeScheduledInfo Include scheduled info.
* @param failRateBranch Fail rate branch.
- * @param mode
+ * @param mode background data update mode.
*/
@AutoProfiling
public FullChainRunCtx loadFullChainContext(
IAnalyticsEnabledTeamcity teamcity,
- ITeamcityIgnited teamcityIgnited,
+ ITeamcityIgnited tcIgn,
Collection<Integer> entryPoints,
LatestRebuildMode includeLatestRebuild,
ProcessLogsMode procLog,
@@ -178,39 +168,45 @@ public class BuildChainProcessor {
if (entryPoints.isEmpty())
return new FullChainRunCtx(Build.createFakeStub());
- Map<Integer, FatBuildCompacted> builds = new ConcurrentHashMap<>();
+ Map<Integer, Future<FatBuildCompacted>> builds = loadAllBuildsInChains(entryPoints, mode, tcIgn);
- final Stream<FatBuildCompacted> entryPointsFatBuilds = entryPoints.stream()
- .filter(Objects::nonNull)
- .filter(id -> !builds.containsKey(id)) //load and propagate only new entry points
- .map(id -> builds.computeIfAbsent(id, id0 -> teamcityIgnited.getFatBuild(id0, mode)));
+ Map<String, List<Future<FatBuildCompacted>>> freshRebuilds = new ConcurrentHashMap<>();
- final ExecutorService svc = tcUpdatePool.getService();
+ groupByBuildType(builds).forEach(
+ (k, buildsForBt) -> {
+ List<Future<FatBuildCompacted>> futures = replaceWithRecent(buildsForBt,
+ entryPoints.size(),
+ includeLatestRebuild,
+ builds,
+ mode,
+ tcIgn);
- final Stream<FatBuildCompacted> depsFirstLevel = entryPointsFatBuilds
- .flatMap(ref -> dependencies(teamcityIgnited, builds, mode, ref));
+ freshRebuilds.put(k, futures);
+ }
+ );
- Stream<FatBuildCompacted> secondLevelDeps = depsFirstLevel
- .flatMap(ref -> dependencies(teamcityIgnited, builds, mode, ref));
+ List<MultBuildRunCtx> contexts = new ArrayList<>(freshRebuilds.size());
- // builds may became non unique because of race in filtering and acquiring deps
- final List<Future<Stream<FatBuildCompacted>>> phase3Submitted = secondLevelDeps
- .map((fatBuild) -> svc.submit(
- () -> replaceWithRecent(teamcityIgnited, includeLatestRebuild, mode, builds, fatBuild, entryPoints.size())))
+ freshRebuilds.forEach((bt, listBuilds) -> {
+ List<FatBuildCompacted> buildsForSuite = listBuilds.stream()
+ .map(FutureUtil::getResult)
+ .filter(buildCompacted -> !buildCompacted.isFakeStub())
.collect(Collectors.toList());
- Map<String, MultBuildRunCtx> buildsCtxMap = new ConcurrentHashMap<>();
+ if (buildsForSuite.isEmpty())
+ return;
+
+ BuildRef ref = buildsForSuite.iterator().next().toBuildRef(compactor);
- phase3Submitted.stream()
- .flatMap(fut -> FutureUtil.getResult(fut))
- .forEach((fatBuild) -> createCxt(teamcityIgnited, buildsCtxMap, fatBuild));
+ final MultBuildRunCtx ctx = new MultBuildRunCtx(ref, compactor);
- ArrayList<MultBuildRunCtx> contexts = new ArrayList<>(buildsCtxMap.values());
+ buildsForSuite.forEach(buildCompacted -> ctx.addBuild(loadChanges(buildCompacted, tcIgn)));
- contexts.forEach(multiCtx -> {
- analyzeTests(multiCtx, teamcity, procLog);
+ analyzeTests(ctx, teamcity, procLog);
- fillBuildCounts(multiCtx, teamcityIgnited, includeScheduledInfo);
+ fillBuildCounts(ctx, tcIgn, includeScheduledInfo);
+
+ contexts.add(ctx);
});
Function<MultBuildRunCtx, Float> function = ctx -> {
@@ -227,8 +223,8 @@ public class BuildChainProcessor {
};
Integer someEntryPnt = entryPoints.iterator().next();
- FatBuildCompacted build = builds.computeIfAbsent(someEntryPnt, id -> teamcityIgnited.getFatBuild(id, mode));
- FullChainRunCtx fullChainRunCtx = new FullChainRunCtx(build.toBuild(compactor));
+ Future<FatBuildCompacted> build = getOrLoadBuild(someEntryPnt, mode, builds, tcIgn);
+ FullChainRunCtx fullChainRunCtx = new FullChainRunCtx(FutureUtil.getResult(build).toBuild(compactor));
contexts.sort(Comparator.comparing(function).reversed());
@@ -237,20 +233,55 @@ public class BuildChainProcessor {
return fullChainRunCtx;
}
- @SuppressWarnings("WeakerAccess")
- @AutoProfiling
- protected void createCxt(ITeamcityIgnited teamcityIgnited,
- Map<String, MultBuildRunCtx> buildsCtxMap,
- FatBuildCompacted buildCompacted) {
- final BuildRef ref = buildCompacted.toBuildRef(compactor);
+ @NotNull
+ public Map<Integer, Future<FatBuildCompacted>> loadAllBuildsInChains(Collection<Integer> entryPoints,
+ SyncMode mode,
+ ITeamcityIgnited tcIgn) {
+ Map<Integer, Future<FatBuildCompacted>> builds = new ConcurrentHashMap<>();
+
+ Stream<Future<FatBuildCompacted>> entryPointsFatBuilds = entryPoints.stream()
+ .filter(Objects::nonNull)
+ .map(id -> getOrLoadBuild(id, mode, builds, tcIgn));
- if (buildCompacted.isFakeStub() || ref.isFakeStub())
- return;
+ Set<Integer> remainedUnloadedDeps = entryPointsFatBuilds
+ .flatMap(ref -> dependencies(ref, mode, builds, tcIgn).stream()).collect(Collectors.toSet());
- final MultBuildRunCtx ctx = buildsCtxMap.computeIfAbsent(ref.buildTypeId,
- k -> new MultBuildRunCtx(ref, compactor));
+ for (int level = 1; level < 5; level++) {
+ if (remainedUnloadedDeps.isEmpty())
+ break;
+
+ Set<Integer> depsNextLevel = remainedUnloadedDeps
+ .stream()
+ .map(builds::get)
+ .peek(val -> Preconditions.checkNotNull(val, "Build future should be in context"))
+ .flatMap(ref -> dependencies(ref, mode, builds, tcIgn).stream()).collect(Collectors.toSet());
+
+ logger.info("Level [" + level + "] dependencies:" + depsNextLevel);
+
+ remainedUnloadedDeps = depsNextLevel;
+ }
- ctx.addBuild(loadTestsAndProblems(buildCompacted, teamcityIgnited));
+ return builds;
+ }
+
+ @NotNull
+ public Map<String, List<FatBuildCompacted>> groupByBuildType(Map<Integer, Future<FatBuildCompacted>> builds) {
+ Map<String, List<FatBuildCompacted>> buildsByBt = new ConcurrentHashMap<>();
+ builds.values().forEach(bFut -> {
+ FatBuildCompacted b = FutureUtil.getResult(bFut);
+
+ String buildTypeId = b.buildTypeId(compactor);
+ if (buildTypeId == null)
+ logger.error("Invalid build type ID for build " + b.getId());
+ else
+ buildsByBt.computeIfAbsent(buildTypeId, k -> new ArrayList<>()).add(b);
+ });
+ return buildsByBt;
+ }
+
+ public Future<FatBuildCompacted> getOrLoadBuild(Integer id, SyncMode mode,
+ Map<Integer, Future<FatBuildCompacted>> builds, ITeamcityIgnited tcIgn) {
+ return builds.computeIfAbsent(id, id0 -> loadBuildAsync(id0, mode, tcIgn));
}
/**
@@ -260,51 +291,55 @@ public class BuildChainProcessor {
* @param tcIgnited
* @return Full context.
*/
- public SingleBuildRunCtx loadTestsAndProblems(@Nonnull FatBuildCompacted buildCompacted,
+ public SingleBuildRunCtx loadChanges(@Nonnull FatBuildCompacted buildCompacted,
ITeamcityIgnited tcIgnited) {
SingleBuildRunCtx ctx = new SingleBuildRunCtx(buildCompacted, compactor);
ctx.setChanges(tcIgnited.getAllChanges(buildCompacted.changes()));
- //todo support storing build.lastChanges.changes) ?
-
return ctx;
}
@SuppressWarnings("WeakerAccess")
@NotNull
@AutoProfiling
- protected Stream<FatBuildCompacted> replaceWithRecent(ITeamcityIgnited teamcityIgnited,
+ protected List<Future<FatBuildCompacted>> replaceWithRecent(List<FatBuildCompacted> builds,
+ int cntLimit,
LatestRebuildMode includeLatestRebuild,
+ Map<Integer, Future<FatBuildCompacted>> allBuildsMap,
SyncMode syncMode,
- Map<Integer, FatBuildCompacted> builds,
- FatBuildCompacted buildCompacted,
- int cntLimit) {
- if (includeLatestRebuild == LatestRebuildMode.NONE)
- return Stream.of(buildCompacted);
+ ITeamcityIgnited tcIgn) {
+ if (includeLatestRebuild == LatestRebuildMode.NONE || builds.isEmpty())
+ return completed(builds);
+
+ Optional<FatBuildCompacted> maxIdBuildOpt = builds.stream().max(Comparator.comparing(BuildRefCompacted::id));
+ if (!maxIdBuildOpt.isPresent())
+ return completed(builds);
+
+ FatBuildCompacted freshBuild = maxIdBuildOpt.get();
- final String branch = getBranchOrDefault(buildCompacted.branchName(compactor));
+ final String branch = getBranchOrDefault(freshBuild.branchName(compactor));
- final String buildTypeId = buildCompacted.buildTypeId(compactor);
- Stream<BuildRefCompacted> hist = teamcityIgnited.getAllBuildsCompacted(buildTypeId, branch)
+ final String buildTypeId = freshBuild.buildTypeId(compactor);
+ Stream<BuildRefCompacted> hist = tcIgn.getAllBuildsCompacted(buildTypeId, branch)
.stream()
- .filter(t -> !t.isCancelled(compactor))
- .filter(t -> t.isFinished(compactor));
+ .filter(bref -> !bref.isCancelled(compactor))
+ .filter(bref -> bref.isFinished(compactor));
if (includeLatestRebuild == LatestRebuildMode.LATEST) {
BuildRefCompacted recentRef = hist.max(Comparator.comparing(BuildRefCompacted::id))
- .orElse(buildCompacted);
+ .orElse(freshBuild);
- return Stream.of(recentRef)
- .map(b -> builds.computeIfAbsent(b.id(), id -> teamcityIgnited.getFatBuild(id, syncMode)));
+ return Collections.singletonList(
+ getOrLoadBuild(recentRef.id(), syncMode, allBuildsMap, tcIgn));
}
if (includeLatestRebuild == LatestRebuildMode.ALL) {
return hist
.sorted(Comparator.comparing(BuildRefCompacted::id).reversed())
.limit(cntLimit)
- // .filter(b -> !builds.containsKey(b.id())) // todo removing this causes incorrect count of failures (duplicated builds)
- .map(b -> builds.computeIfAbsent(b.id(), id -> teamcityIgnited.getFatBuild(id, syncMode)));
+ .map(bref -> getOrLoadBuild(bref.id(), syncMode, allBuildsMap, tcIgn))
+ .collect(Collectors.toList());
}
throw new UnsupportedOperationException("invalid mode " + includeLatestRebuild);
@@ -365,47 +400,40 @@ public class BuildChainProcessor {
return branch;
}
+ /**
+ * @param buildFut Chain build future.
+ * @param mode Mode.
+ * @param builds Builds.
+ * @param teamcityIgnited Teamcity ignited.
+ * @return Set of new builds found during this dependencies check round.
+ */
@NotNull
- private Stream<FatBuildCompacted> dependencies(
- ITeamcityIgnited teamcityIgnited,
- Map<Integer, FatBuildCompacted> builds,
+ private Set<Integer> dependencies(
+ Future<FatBuildCompacted> buildFut,
SyncMode mode,
- FatBuildCompacted build) {
+ Map<Integer, Future<FatBuildCompacted>> builds,
+ ITeamcityIgnited teamcityIgnited) {
+ Set<Integer> newBuilds = new HashSet<>();
- Stream<FatBuildCompacted> stream = IntStream.of(build.snapshotDependencies())
- .mapToObj(id -> {
- if (builds.containsKey(id))
- return Futures.<FatBuildCompacted>immediateFuture(null); //load and propagate only new dependencies
+ IntStream.of(FutureUtil.getResult(buildFut).snapshotDependencies())
+ .forEach(id -> builds.computeIfAbsent(id, id0 -> {
+ newBuilds.add(id0);
- if (mode == SyncMode.NONE)
- return Futures.immediateFuture(loadBuild(teamcityIgnited, builds, mode, id));
+ return loadBuildAsync(id0, mode, teamcityIgnited);
+ }));
- return tcUpdatePool.getService().submit(() -> {
- if (builds.containsKey(id))
- return null;
+ return newBuilds;
+ }
- return loadBuild(teamcityIgnited, builds, mode, id);
- });
- })
- .collect(Collectors.toList())
- .stream()
- .map(future -> FutureUtil.getResult(future))
- .filter(Objects::nonNull);
+ public Future<FatBuildCompacted> loadBuildAsync(Integer id, SyncMode mode, ITeamcityIgnited teamcityIgnited) {
+ if (mode == SyncMode.NONE)
+ return Futures.immediateFuture(teamcityIgnited.getFatBuild(id, SyncMode.NONE));
- return Stream.concat(
- Stream.of(build),
- stream);
+ return tcUpdatePool.getService().submit(() -> teamcityIgnited.getFatBuild(id, mode));
}
- @Nullable
- private FatBuildCompacted loadBuild(ITeamcityIgnited teamcityIgnited,
- Map<Integer, FatBuildCompacted> builds,
- SyncMode mode,
- int id) {
- FatBuildCompacted buildLoaded = teamcityIgnited.getFatBuild(id, mode);
-
- FatBuildCompacted prevVal = builds.putIfAbsent(id, buildLoaded);
- return prevVal == null ? buildLoaded : null;
+ private List<Future<FatBuildCompacted>> completed(List<FatBuildCompacted> builds) {
+ return builds.stream().map(Futures::immediateFuture).collect(Collectors.toList());
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java
index efda317..f6ccf03 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java
@@ -22,6 +22,7 @@ import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.ci.db.Persisted;
import org.apache.ignite.ci.tcmodel.hist.BuildRef;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.ci.tcmodel.hist.BuildRef.*;
@@ -93,7 +94,7 @@ public class BuildRefCompacted {
}
protected void fillBuildRefFields(IStringCompactor compactor, BuildRef res) {
- res.setId(id < 0 ? null : id);
+ res.setId(getId());
res.buildTypeId = buildTypeId(compactor);
res.branchName = branchName(compactor);
res.status = compactor.getStringFromId(status);
@@ -101,6 +102,10 @@ public class BuildRefCompacted {
res.href = getHrefForId(id());
}
+ @Nullable public Integer getId() {
+ return id < 0 ? null : id;
+ }
+
public String buildTypeId(IStringCompactor compactor) {
return compactor.getStringFromId(buildTypeId);
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
index 95e88ad..419de92 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
@@ -330,6 +330,9 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
*
*/
public boolean isFakeStub() {
+ if (getId() == null)
+ return true;
+
Boolean flag = getFlag(FAKE_BUILD_F);
return flag != null && flag;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java
index 51ce92e..c406e7f 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java
@@ -23,7 +23,7 @@ package org.apache.ignite.ci.web.model;
public static final String GITHUB_REF = "https://github.com/apache/ignite-teamcity-bot";
/** TC Bot Version. */
- public static final String VERSION = "20181120";
+ public static final String VERSION = "20181121";
/** TC Bot Version. */
public String version = VERSION;
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java
index 2e2ec97..c09ea1c 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java
@@ -45,7 +45,6 @@ import org.apache.ignite.ci.teamcity.ignited.InMemoryStringCompactor;
import org.apache.ignite.ci.teamcity.ignited.SyncMode;
import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
import org.jetbrains.annotations.NotNull;
-import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
@@ -60,8 +59,15 @@ import static org.mockito.Mockito.when;
* Test for chain processor
*/
public class BuildChainProcessorTest {
+ /** Unique failed test, prefix for test name. This name will be unique each time. */
public static final String UNIQUE_FAILED_TEST = "uniqueFailedTest";
+
+ /** Test failing every time. */
public static final String TEST_FAILING_EVERY_TIME = "testFailingEveryTime";
+
+ /** Pds 1 build type ID. */
+ public static final String PDS_1_BT_ID = "Pds1";
+
/** Injector. */
private Injector injector = Guice.createInjector(new AbstractModule() {
@Override protected void configure() {
@@ -73,7 +79,6 @@ public class BuildChainProcessorTest {
/**
*
*/
- @Ignore
@Test
public void testAllBuildsArePresentInMergedBuilds() {
IStringCompactor c = injector.getInstance(IStringCompactor.class);
@@ -102,14 +107,42 @@ public class BuildChainProcessorTest {
else
assertTrue(suite.failedTests() >= 1);
- List<ITestFailures> tests = suite.getFailedTests();
- for (ITestFailures test : tests) {
+ for (ITestFailures test : suite.getFailedTests()) {
if (test.getName().startsWith(UNIQUE_FAILED_TEST))
assertEquals(1, test.failuresCount());
else if (test.getName().equals(TEST_FAILING_EVERY_TIME))
assertEquals(10, test.failuresCount());
}
}
+
+ //Adding successfull re-runs
+ for (int j = 0; j < 10; j++) {
+ FatBuildCompacted pds1 = testFatBuild(c, 130 + j, PDS_1_BT_ID);
+ pds1.buildTypeName(UNIQUE_FAILED_TEST, c);
+
+ TestOccurrenceFull t1 = new TestOccurrenceFull();
+ t1.name = UNIQUE_FAILED_TEST + j;
+ t1.status = TestOccurrence.STATUS_SUCCESS;
+ pds1.addTests(c, Lists.newArrayList(t1));
+
+ builds.put(pds1.id(), pds1);
+ }
+
+ FullChainRunCtx ctx2 = bcp.loadFullChainContext(tcOldMock(), tcIgnited,
+ entry,
+ LatestRebuildMode.ALL, ProcessLogsMode.SUITE_NOT_COMPLETE, false, ITeamcity.DEFAULT, SyncMode.NONE);
+ List<MultBuildRunCtx> suites2 = ctx2.failedChildSuites().collect(Collectors.toList());
+
+ assertTrue(!suites2.isEmpty());
+
+ for (MultBuildRunCtx suite : suites2) {
+ System.out.println(suite.getFailedTestsNames().collect(Collectors.toList()));
+
+ if (suite.suiteName() != null && suite.suiteName().startsWith(UNIQUE_FAILED_TEST)) {
+ for (ITestFailures test : suite.getFailedTests())
+ assertTrue("Failure found but should be hidden by re-run " + test.getName(), false);
+ }
+ }
}
/**
@@ -144,7 +177,7 @@ public class BuildChainProcessorTest {
builds.put(root.id(), root);
- FatBuildCompacted pds1 = testFatBuild(c, 100 + i, "Pds1");
+ FatBuildCompacted pds1 = testFatBuild(c, 100 + i, PDS_1_BT_ID);
pds1.buildTypeName(UNIQUE_FAILED_TEST, c);
TestOccurrenceFull t1 = new TestOccurrenceFull();