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/24 21:00:01 UTC

[ignite-teamcity-bot] branch ignite-9542-new-run-stripe updated: IGNITE-9542: New Run stripe implementation: invocation data taken into account in test

This is an automated email from the ASF dual-hosted git repository.

dpavlov pushed a commit to branch ignite-9542-new-run-stripe
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git


The following commit(s) were added to refs/heads/ignite-9542-new-run-stripe by this push:
     new e19905b  IGNITE-9542: New Run stripe implementation: invocation data taken into account in test
e19905b is described below

commit e19905b01950867290f46fa6420300e6397d6c5a
Author: Dmitriy Pavlov <dp...@apache.org>
AuthorDate: Sat Nov 24 23:59:58 2018 +0300

    IGNITE-9542: New Run stripe implementation: invocation data taken into account in test
---
 .../ignited/fatbuild/FatBuildCompacted.java        |  13 ++-
 .../ci/teamcity/ignited/runhist/Invocation.java    |  37 ++++++++
 .../teamcity/ignited/runhist/InvocationData.java   | 101 +++++++++++++++++++++
 .../teamcity/ignited/runhist/RunHistCompacted.java |  37 +++++---
 .../ignite/ci/web/model/current/TestFailure.java   |   2 +
 .../ci/tcbot/chain/PrChainsProcessorTest.java      |  99 +++++++++++++-------
 .../ci/teamcity/ignited/TeamcityIgnitedMock.java   |  34 +++++--
 7 files changed, 262 insertions(+), 61 deletions(-)

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 bd4ec17..8c8b7d4 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
@@ -210,9 +210,8 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
 
         if (snapshotDeps != null) {
             List<BuildRef> snapshotDependencies = new ArrayList<>();
-            for (int i = 0; i < snapshotDeps.length; i++) {
-                int depId = snapshotDeps[i];
 
+            for (int depId : snapshotDeps) {
                 BuildRef ref = new BuildRef();
                 ref.setId(depId);
                 ref.href = getHrefForId(depId);
@@ -231,7 +230,7 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
      * @param compactor Compactor.
      * @param page Page.
      */
-    public void addTests(IStringCompactor compactor, List<TestOccurrenceFull> page) {
+    public FatBuildCompacted addTests(IStringCompactor compactor, List<TestOccurrenceFull> page) {
         for (TestOccurrenceFull next : page) {
             TestCompacted compacted = new TestCompacted(compactor, next);
 
@@ -240,6 +239,8 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
 
             tests.add(compacted);
         }
+
+        return this;
     }
 
     /**
@@ -289,7 +290,11 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
 
     /** Start date. */
     @Nullable public Date getStartDate() {
-        return startDate > 0 ? new Date(startDate) : null;
+        return getStartDateTs() > 0 ? new Date(getStartDateTs()) : null;
+    }
+
+    public long getStartDateTs() {
+        return startDate;
     }
 
     /** {@inheritDoc} */
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/Invocation.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/Invocation.java
new file mode 100644
index 0000000..8089af3
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/Invocation.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.ignite.ci.teamcity.ignited.runhist;
+
+import com.google.common.base.MoreObjects;
+
+public class Invocation {
+    int buildId;
+    byte status;
+
+    public Invocation(Integer buildId) {
+        this.buildId = buildId;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("buildId", buildId)
+                .add("status", status)
+                .toString();
+    }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/InvocationData.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/InvocationData.java
new file mode 100644
index 0000000..62eb3d5
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/InvocationData.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.ignite.ci.teamcity.ignited.runhist;
+
+import com.google.common.base.MoreObjects;
+import org.apache.ignite.ci.analysis.RunStat;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.TestCompacted;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class InvocationData {
+    public static final int MUTED = RunStat.RunStatus.RES_MUTED_FAILURE.getCode();
+    public static final int FAILURE = RunStat.RunStatus.RES_FAILURE.getCode();
+    public static final int OK = RunStat.RunStatus.RES_OK.getCode();
+    /**
+     * Runs registered all the times.
+     */
+    private int allHistRuns;
+
+    /**
+     * Failures registered all the times.
+     */
+    private int allHistFailures;
+
+    private Map<Integer, Invocation> invocationMap = new TreeMap<>();
+
+    public int allHistRuns() {
+        return allHistRuns;
+    }
+
+    public void add(IStringCompactor c, TestCompacted testCompacted, int build, long startDate) {
+
+
+        final boolean failedTest = testCompacted.isFailedTest(c);
+
+        final Invocation invocation = invocationMap.computeIfAbsent(build, Invocation::new);
+
+        final int failCode = failedTest
+                ? (testCompacted.isIgnoredTest() || testCompacted.isMutedTest())
+                        ? MUTED
+                        : FAILURE
+                : OK;
+
+        invocation.status = (byte) failCode;
+
+        allHistRuns++;
+        if (failedTest)
+            allHistFailures++;
+    }
+
+    public int allHistFailures() {
+        return allHistFailures;
+    }
+
+    public int notMutedRunsCount() {
+        return (int)
+                invocationMap.values()
+                        .stream()
+                        .filter(invocation -> invocation.status != MUTED)
+                        .count();
+    }
+
+    public int failuresCount() {
+        return (int)
+                invocationMap.values()
+                        .stream()
+                        .filter(invocation -> invocation.status == FAILURE)
+                        .count();
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("allHistRuns", allHistRuns)
+                .add("allHistFailures", allHistFailures)
+                .add("invocationMap", invocationMap)
+                .toString();
+    }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistCompacted.java
index 417d60c..1fe4175 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistCompacted.java
@@ -17,12 +17,16 @@
 
 package org.apache.ignite.ci.teamcity.ignited.runhist;
 
+import com.google.common.base.MoreObjects;
 import com.google.common.collect.Lists;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.ci.analysis.IVersionedEntity;
 import org.apache.ignite.ci.teamcity.ignited.IRunHistory;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.TestCompacted;
 
 import javax.annotation.Nullable;
+import java.util.Date;
 import java.util.List;
 
 public class RunHistCompacted implements IVersionedEntity, IRunHistory {
@@ -39,16 +43,7 @@ public class RunHistCompacted implements IVersionedEntity, IRunHistory {
     @QuerySqlField(orderedGroups = {@QuerySqlField.Group(name = "tstAndSrv", order = 1)})
     private int srvId;
 
-    /**
-     * Runs registered all the times.
-     */
-    private int allHistRuns;
-
-    /**
-     * Failures registered all the times.
-     */
-    private int allHistFailures;
-
+    private InvocationData data = new InvocationData();
 
     public RunHistCompacted() {}
 
@@ -69,22 +64,22 @@ public class RunHistCompacted implements IVersionedEntity, IRunHistory {
 
     @Override
     public int getRunsCount() {
-        return 10; //todo implement
+        return data.notMutedRunsCount();
     }
 
     @Override
     public int getFailuresCount() {
-        return 10; //todo implement
+        return data.failuresCount();
     }
 
     @Override
     public int getFailuresAllHist() {
-        return allHistFailures;
+        return data.allHistFailures();
     }
 
     @Override
     public int getRunsAllHist() {
-        return allHistRuns;
+        return data.allHistRuns();
     }
 
     @Nullable
@@ -97,4 +92,18 @@ public class RunHistCompacted implements IVersionedEntity, IRunHistory {
     public String getFlakyComments() {
         return null;
     }
+
+    public void addTestRun(IStringCompactor c, TestCompacted testCompacted, int build, long startDate) {
+        data.add(c, testCompacted, build, startDate);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("nameId", testNameOrSuite)
+                .add("srvId", srvId)
+                .add("failRate", getFailPercentPrintable())
+                .add("data", data)
+                .toString();
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java
index a807e4e..c8b67e0 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java
@@ -248,6 +248,8 @@ import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.branchFo
         boolean lowFailureRate = recent != null && recent.failureRate != null &&
             Float.valueOf(recent.failureRate.replace(',', '.')) < 4.;
 
+        System.out.println(name + " " + recent.failureRate);
+
         return lowFailureRate && histBaseBranch.flakyComments == null;
     }
 
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java
index b85a8d6..591f090 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.ignite.ci.tcbot.chain;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
@@ -46,6 +47,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -58,6 +60,8 @@ import static org.mockito.Mockito.when;
 public class PrChainsProcessorTest {
     public static final String SRV_ID = "apache";
     public static final String TEST_WITH_HISTORY_FAILING_IN_MASTER = "testWithHistoryFailingInMaster";
+    public static final String TEST_WITH_HISTORY_PASSING_IN_MASTER = "testWithHistoryPassingInMaster";
+    public static final String TEST_WITHOUT_HISTORY = "testWithoutHistory";
 
     private Map<Integer, FatBuildCompacted> apacheBuilds = new ConcurrentHashMap<>();
 
@@ -109,83 +113,109 @@ public class PrChainsProcessorTest {
         assertNotNull(suitesStatuses);
         assertFalse(suitesStatuses.isEmpty());
 
-        assertTrue(suitesStatuses.stream().anyMatch(
-                s -> s.testFailures.stream().anyMatch(testFailure -> "testWithoutHistory".equals(testFailure.name))
-        ));
+        assertTrue(suitesStatuses.stream().anyMatch(containsTestFail("testWithoutHistory")));
 
         assertTrue(suitesStatuses.stream().anyMatch(s -> "Build".equals(s.suiteId)));
         assertTrue(suitesStatuses.stream().anyMatch(s -> "CancelledBuild".equals(s.suiteId)));
 
-        assertFalse(suitesStatuses.stream().anyMatch(
-                s -> s.testFailures.stream().anyMatch(testFailure -> TEST_WITH_HISTORY_FAILING_IN_MASTER.equals(testFailure.name))
-        ));
+        assertFalse(suitesStatuses.stream().anyMatch(containsTestFail(TEST_WITH_HISTORY_FAILING_IN_MASTER)));
+        assertTrue(suitesStatuses.stream().anyMatch(containsTestFail(TEST_WITH_HISTORY_PASSING_IN_MASTER)));
     }
 
-    private void initBuildChain(IStringCompactor c, String btId, String branch) {
-        final int id = 1000;
-
-        final FatBuildCompacted chain = createFailedBuild(c, btId, branch, id, 100000);
-
-        final FatBuildCompacted childBuild = createFailedBuild(c, "Cache1", branch, 1001, 100020);
-
-        TestOccurrenceFull tf = createFailedTest(1L, "testWithoutHistory");
-
-        TestOccurrenceFull tf2 = createFailedTest(2L, TEST_WITH_HISTORY_FAILING_IN_MASTER);
+    @NotNull
+    private Predicate<SuiteCurrentStatus> containsTestFail(String name) {
+        return s -> s.testFailures.stream().anyMatch(testFailure -> {
+            return name.equals(testFailure.name);
+        });
+    }
 
-        childBuild.addTests(c, Lists.newArrayList(tf, tf2));
+    private void initBuildChain(IStringCompactor c, String btId, String branch) {
 
         final FatBuildCompacted buildBuild = createFailedBuild(c, "Build", branch, 1002, 100020);
         final ProblemOccurrence compile = new ProblemOccurrence();
         compile.setType(ProblemOccurrence.TC_COMPILATION_ERROR);
         buildBuild.addProblems(c, Collections.singletonList(compile));
+
+        final FatBuildCompacted childBuild =
+                createFailedBuild(c, "Cache1", branch, 1001, 100020)
+                        .addTests(c,
+                                Lists.newArrayList(
+                                        createFailedTest(1L, TEST_WITHOUT_HISTORY),
+                                        createFailedTest(2L, TEST_WITH_HISTORY_FAILING_IN_MASTER),
+                                        createFailedTest(3L, TEST_WITH_HISTORY_PASSING_IN_MASTER)));
+
         childBuild.snapshotDependencies(new int[]{buildBuild.id()});
 
-        final Build build = createBuild("CancelledBuild", branch, 1003, 100020);
+        final Build build = createPassedBuild("CancelledBuild", branch, 1003, 100020);
+
         build.status = BuildRef.STATUS_UNKNOWN;
         build.state = BuildRef.STATE_FINISHED;
 
         final FatBuildCompacted cancelledBuild = new FatBuildCompacted(c, build);
 
+        cancelledBuild.snapshotDependencies(new int[]{buildBuild.id()});
+
+        final int id = 1000;
+
+        final FatBuildCompacted chain = createFailedBuild(c, btId, branch, id, 100000);
+
         chain.snapshotDependencies(new int[]{childBuild.id(), cancelledBuild.id()});
 
-        apacheBuilds.put(chain.id(), chain);
-        apacheBuilds.put(childBuild.id(), childBuild);
-        apacheBuilds.put(buildBuild.id(), buildBuild);
-        apacheBuilds.put(cancelledBuild.id(), cancelledBuild);
+        addBuilds(chain);
+        addBuilds(childBuild);
+        addBuilds(buildBuild);
+        addBuilds(cancelledBuild);
 
         for (int i = 0; i < 10; i++) {
-            final FatBuildCompacted masterBuild = createFailedBuild(c, "Cache1",
-                    ITeamcity.DEFAULT, 5000+i, 100000+(i*10000));
-
-            final TestOccurrenceFull testInMaster = createFailedTest(2L, TEST_WITH_HISTORY_FAILING_IN_MASTER);
+            addBuilds(createFailedBuild(c, "Cache1",
+                    ITeamcity.DEFAULT, 5000 + i, 100000 + (i * 10000))
+                    .addTests(c, Lists.newArrayList(
+                            createFailedTest(2L, TEST_WITH_HISTORY_FAILING_IN_MASTER),
+                            createPassingTest(3L, TEST_WITH_HISTORY_PASSING_IN_MASTER))));
+        }
+    }
 
-            masterBuild.addTests(c, Lists.newArrayList(testInMaster));
+    private void addBuilds(FatBuildCompacted... builds) {
+        for (FatBuildCompacted build : builds) {
+            final FatBuildCompacted oldB = apacheBuilds.put(build.id(), build);
 
-            apacheBuilds.put(masterBuild.id(), masterBuild);
+            Preconditions.checkState(oldB==null);
         }
     }
 
     @NotNull
-    private TestOccurrenceFull createFailedTest(long id1, String name) {
+    private TestOccurrenceFull createFailedTest(long id, String name) {
+        TestOccurrenceFull tf = createPassingTest(id, name);
+
+        tf.status = TestOccurrence.STATUS_FAILURE;
+
+        return tf;
+    }
+
+    @NotNull
+    private TestOccurrenceFull createPassingTest(long id, String name) {
         TestOccurrenceFull tf = new TestOccurrenceFull();
+
         tf.test = new TestRef();
 
-        tf.test.id = id1;
+        tf.test.id = id;
         tf.name = name;
-        tf.status = TestOccurrence.STATUS_FAILURE;
+        tf.status = TestOccurrence.STATUS_SUCCESS;
+
         return tf;
     }
 
     @NotNull
     public FatBuildCompacted createFailedBuild(IStringCompactor c, String btId, String branch, int id, int ageMs) {
-        final Build build = createBuild(btId, branch, id, ageMs);
+        final Build build = createPassedBuild(btId, branch, id, ageMs);
+
         build.status = BuildRef.STATUS_FAILURE;
 
         return new FatBuildCompacted(c, build);
     }
 
     @NotNull
-    public Build createBuild(String btId, String branch, int id, int ageMs) {
+    private Build createPassedBuild(String btId, String branch, int id, int ageMs) {
         final Build build = new Build();
         build.buildTypeId = btId;
         final BuildType type = new BuildType();
@@ -195,6 +225,9 @@ public class PrChainsProcessorTest {
         build.setId(id);
         build.setStartDateTs(System.currentTimeMillis() - ageMs);
         build.setBranchName(branch);
+        build.state = Build.STATE_FINISHED;
+        build.status = Build.STATUS_SUCCESS;
+
         return build;
     }
 }
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java
index 2e392c6..1cd9976 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java
@@ -59,7 +59,7 @@ public class TeamcityIgnitedMock {
                 return builds.values()
                     .stream()
                     .filter(fb -> btId.equals(fb.buildTypeId(c)))
-                    //  .filter(fb -> branch.equals(fb.branchName(c)))
+                        .filter(fb -> branch.equals(fb.branchName(c)))
                     .sorted(Comparator.comparing(BuildRefCompacted::id).reversed())
                     .collect(Collectors.toList());
             });
@@ -88,16 +88,22 @@ public class TeamcityIgnitedMock {
                     final String name = t.name;
                     final String branch = t.branch;
 
-                    if(histCache.isEmpty()) {
-                        initHistory(histCache, builds, srvId);
+                   // System.out.println("Search history " + name + " in " + branch + ": " );
+
+                    if (histCache.isEmpty()) {
+                        synchronized (histCache) {
+                            if (histCache.isEmpty()) {
+                                initHistory(c, histCache, builds, srvId);
+                            }
+                        }
                     }
 
                     final Integer tstName = c.getStringIdIfPresent(name);
-                    if(tstName==null)
+                    if (tstName == null)
                         return null;
 
                     final Integer branchId = c.getStringIdIfPresent(branch);
-                    if(branchId==null)
+                    if (branchId == null)
                         return null;
 
                     final RunHistKey key = new RunHistKey(srvId, tstName, branchId);
@@ -105,21 +111,29 @@ public class TeamcityIgnitedMock {
                     final RunHistCompacted runHistCompacted = histCache.get(key);
 
                     System.out.println("Test history " + name + " in " + branch + " => " + runHistCompacted);
+
                     return runHistCompacted;
                 });
 
         return tcIgnited;
     }
 
-    private static void initHistory(Map<RunHistKey, RunHistCompacted> histCache, Map<Integer, FatBuildCompacted> builds, int srvId) {
-        for (FatBuildCompacted next : builds.values()) {
-            next.getAllTests().forEach(t->{
-                RunHistKey histKey = new RunHistKey(srvId, t.testName(), next.branchName() );
+    private static void initHistory(IStringCompactor c, Map<RunHistKey, RunHistCompacted> resHistCache, Map<Integer, FatBuildCompacted> builds, int srvId) {
+        Map<RunHistKey, RunHistCompacted> histCache = new ConcurrentHashMap<>();
 
-                final RunHistCompacted hist = histCache.computeIfAbsent(histKey, RunHistCompacted::new);
+        for (FatBuildCompacted build : builds.values()) {
+            if(!build.isFinished(c))
+                continue;
 
+            build.getAllTests().forEach(t -> {
+                RunHistKey histKey = new RunHistKey(srvId, t.testName(), build.branchName());
 
+                final RunHistCompacted hist = histCache.computeIfAbsent(histKey, RunHistCompacted::new);
+
+                hist.addTestRun(c, t, build.id(), build.getStartDateTs());
             });
         }
+
+        resHistCache.putAll(histCache);
     }
 }