/* * Copyright 2000-2015 JetBrains s.r.o. * * 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 jetbrains.buildServer.server.rest.data; import com.google.common.base.Objects; import java.util.Date; import java.util.List; import jetbrains.buildServer.messages.Status; import jetbrains.buildServer.messages.TestMetadata; import jetbrains.buildServer.responsibility.ResponsibilityEntry; import jetbrains.buildServer.responsibility.TestNameResponsibilityFacade; import jetbrains.buildServer.responsibility.impl.TestNameResponsibilityEntryImpl; import jetbrains.buildServer.server.rest.errors.BadRequestException; import jetbrains.buildServer.server.rest.model.Fields; import jetbrains.buildServer.server.rest.model.problem.TestOccurrence; import jetbrains.buildServer.server.rest.model.problem.TypedValue; import jetbrains.buildServer.serverSide.RunningBuildEx; import jetbrains.buildServer.serverSide.SFinishedBuild; import jetbrains.buildServer.serverSide.STestRun; import jetbrains.buildServer.serverSide.TestName2Index; import jetbrains.buildServer.serverSide.impl.BuildTypeImpl; import jetbrains.buildServer.serverSide.impl.ProjectEx; import jetbrains.buildServer.tests.TestName; import jetbrains.buildServer.users.SUser; import jetbrains.buildServer.util.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * @author Yegor.Yarko * Date: 16/12/2015 */ public class TestOccurrenceFinderTest extends BaseFinderTest { @Override @BeforeMethod public void setUp() throws Exception { super.setUp(); myProject.remove(); setFinder(myTestOccurrenceFinder); } @Test public void testBasic() throws Exception { final BuildTypeImpl buildType = registerBuildType("buildConf1", "project"); final SFinishedBuild build10 = build().in(buildType).withTest("aaa", true).finish(); checkExceptionOnItemSearch(BadRequestException.class, "No_match"); checkExceptionOnItemsSearch(BadRequestException.class, "No_match"); check("build:(id:" + build10.getBuildId() + ")", build10.getFullStatistics().getAllTests().get(0)); check("build:(id:" + build10.getBuildId() + ")", TEST_MATCHER, t("aaa", Status.NORMAL, 1)); int testRunId = build10.getFullStatistics().getAllTests().get(0).getTestRunId(); check("build:(id:" + build10.getBuildId() + "),id:" + testRunId, TEST_MATCHER, t("aaa", Status.NORMAL, 1)); checkExceptionOnItemSearch(BadRequestException.class, "id:" + testRunId); checkExceptionOnItemsSearch(BadRequestException.class, "id:" + testRunId); check("build:(id:" + build10.getBuildId() + "),id:" + testRunId + 1); check("build:(id:" + build10.getBuildId() + "),test:(name:aaa)", TEST_MATCHER, t("aaa", Status.NORMAL, 1)); check("build:(id:" + build10.getBuildId() + "),test:(name:bbb)"); } @Test public void testByTest() throws Exception { final BuildTypeImpl buildType = registerBuildType("buildConf1", "project"); final SFinishedBuild build10 = build().in(buildType) .withTest("aaa", false) .withTest("bbb", true) .withTest("ccc", false) .finish(); check("build:(id:" + build10.getBuildId() + ")", TEST_MATCHER, t("aaa", Status.FAILURE, 1), t("bbb", Status.NORMAL, 2), t("ccc", Status.FAILURE, 3)); check("build:(id:" + build10.getBuildId() + "),test:(name:missingTest)", TEST_MATCHER); check("build:(id:" + build10.getBuildId() + "),test:(name:bbb)", TEST_MATCHER, t("bbb", Status.NORMAL, 2)); check("build:(id:" + build10.getBuildId() + "),test:(currentlyFailing:true)", TEST_MATCHER, t("aaa", Status.FAILURE, 1), t("ccc", Status.FAILURE, 3)); } @Test public void testSameTestInDifferentBuilds() throws Exception { final BuildTypeImpl buildType1 = registerBuildType("buildConf1", "project1"); final BuildTypeImpl buildType2 = registerBuildType("buildConf2", "project2"); final SFinishedBuild build10 = build().in(buildType1).withTest("aaa", false).finish(); final SFinishedBuild build20 = build().in(buildType2).withTest("aaa", false).finish(); check("currentlyFailing:true", TEST_MATCHER, t("aaa", Status.FAILURE, 1), t("aaa", Status.FAILURE, 1)); check("currentlyFailing:true,buildType:(id:" + buildType1.getExternalId() + ")", TEST_MATCHER, t("aaa", Status.FAILURE, 1)); STestRun testRun1 = getFinder().getItems("currentlyFailing:true").myEntries.get(0); STestRun testRun2 = getFinder().getItems("currentlyFailing:true").myEntries.get(1); assertEquals(testRun1.getBuildId(), build10.getBuildId()); assertEquals(testRun2.getBuildId(), build20.getBuildId()); check("currentlyFailing:true,currentlyInvestigated:false", TEST_MATCHER, t("aaa", Status.FAILURE, 1), t("aaa", Status.FAILURE, 1)); long nameId = myFixture.getSingletonService(TestName2Index.class).getOrSaveTestNameId("aaa"); SUser user = createUser("user"); ProjectEx project = myServer.getProjectManager().getRootProject().findProjectByName("project1"); TestNameResponsibilityEntryImpl testNameResponsibilityEntry = new TestNameResponsibilityEntryImpl(new TestName("aaa"), nameId, ResponsibilityEntry.State.TAKEN, user, user, new Date(), "Please, fix", project, ResponsibilityEntry.RemoveMethod.MANUALLY); myFixture.getSingletonService(TestNameResponsibilityFacade.class).setTestNameResponsibility(new TestName("aaa"), project.getProjectId(), testNameResponsibilityEntry); check("currentlyFailing:true,currentlyInvestigated:false", TEST_MATCHER, t("aaa", Status.FAILURE, 1)); } @Test public void testSeveralInvocations() throws Exception { final BuildTypeImpl buildType = registerBuildType("buildConf1", "project"); final SFinishedBuild build10 = build().in(buildType) .withTest("aaa", true) .withTest("aaa", true) .withTest("bbb", true) .withTest("ccc", false) .withTest("bbb", true) .withTest("aaa", false) .withTest("aaa", true) .withTest("ddd", true) .finish(); check("build:(id:" + build10.getBuildId() + ")", TEST_MATCHER, t("aaa", Status.FAILURE, 1), t("bbb", Status.NORMAL, 3), t("ccc", Status.FAILURE, 4), t("ddd", Status.NORMAL, 8)); { int testRunId = myTestOccurrenceFinder.getItems("build:(id:" + build10.getBuildId() + ")").myEntries.get(0).getTestRunId(); check("build:(id:" + build10.getBuildId() + "),id:(" + testRunId + ")", TEST_MATCHER, t("aaa", Status.FAILURE, 1)); assertEquals(testRunId, myTestOccurrenceFinder.getItems("build:(id:" + build10.getBuildId() + "),id:(" + testRunId + ")").myEntries.get(0).getTestRunId()); assertEquals(testRunId, myTestOccurrenceFinder.getItem("build:(id:" + build10.getBuildId() + "),id:(" + testRunId + ")").getTestRunId()); } check("build:(id:" + build10.getBuildId() + "),expandInvocations:true", TEST_MATCHER, t("aaa", Status.NORMAL, 1), t("aaa", Status.NORMAL, 2), t("aaa", Status.FAILURE, 6), //ordering so far is grouped by test t("aaa", Status.NORMAL, 7), t("bbb", Status.NORMAL, 3), t("bbb", Status.NORMAL, 5), t("ccc", Status.FAILURE, 4), t("ddd", Status.NORMAL, 8)); { int testRunId = myTestOccurrenceFinder.getItems("build:(id:" + build10.getBuildId() + "),expandInvocations:true").myEntries.get(2).getTestRunId(); check("build:(id:" + build10.getBuildId() + "),id:(" + testRunId + ")", TEST_MATCHER, t("aaa", Status.FAILURE, 6)); assertEquals(testRunId, myTestOccurrenceFinder.getItems("build:(id:" + build10.getBuildId() + "),id:(" + testRunId + ")").myEntries.get(0).getTestRunId()); assertEquals(testRunId, myTestOccurrenceFinder.getItem("build:(id:" + build10.getBuildId() + "),id:(" + testRunId + ")").getTestRunId()); } check("build:(id:" + build10.getBuildId() + "),test:(name:aaa)", TEST_MATCHER, t("aaa", Status.FAILURE, 1)); check("build:(id:" + build10.getBuildId() + "),test:(name:aaa),expandInvocations:true", TEST_MATCHER, t("aaa", Status.NORMAL, 1), t("aaa", Status.NORMAL, 2), t("aaa", Status.FAILURE, 6), t("aaa", Status.NORMAL, 7)); check("build:(id:" + build10.getBuildId() + "),invocations:(search:(status:FAILURE))", TEST_MATCHER, t("aaa", Status.FAILURE, 1), t("ccc", Status.FAILURE, 4)); check("build:(id:" + build10.getBuildId() + "),invocations:(search:(count:100),match:(status:SUCCESS))", TEST_MATCHER, t("bbb", Status.NORMAL, 3), t("ddd", Status.NORMAL, 8)); } @Test public void testBuildDimension() throws Exception { final BuildTypeImpl buildType = registerBuildType("buildConf1", "project"); final SFinishedBuild build10 = build().in(buildType) .withTest("aaa", true) .withTest("aaa", true) .withTest("bbb", true) .withTest("ccc", false) .withTest("bbb", true) .withTest("aaa", false) .withTest("aaa", true) .withTest("ddd", true) .finish(); final SFinishedBuild build20 = build().in(buildType) .withTest("xxx", true) .withTest("aaa", true) .finish(); check("build:(id:" + build10.getBuildId() + ")", TEST_WITH_BUILD_MATCHER, t("aaa", Status.FAILURE, 1, build10.getBuildId()), t("bbb", Status.NORMAL, 3, build10.getBuildId()), t("ccc", Status.FAILURE, 4, build10.getBuildId()), t("ddd", Status.NORMAL, 8, build10.getBuildId())); check("build:(item:(id:" + build10.getBuildId() + "),item:(id:" + build20.getBuildId() + "))", TEST_WITH_BUILD_MATCHER, t("aaa", Status.FAILURE, 1, build10.getBuildId()), t("bbb", Status.NORMAL, 3, build10.getBuildId()), t("ccc", Status.FAILURE, 4, build10.getBuildId()), t("ddd", Status.NORMAL, 8, build10.getBuildId()), t("xxx", Status.NORMAL, 1, build20.getBuildId()), t("aaa", Status.NORMAL, 2, build20.getBuildId())); } @Test public void testTestOccurrenceEntityInvocations() throws Exception { final BuildTypeImpl buildType = registerBuildType("buildConf1", "project"); final SFinishedBuild build10 = build().in(buildType) .withTest("aaa", true) .withTest("aaa", true) .withTest("bbb", true) .withTest("ccc", false) .withTest("bbb", true) .withTest("aaa", false) .withTest("aaa", true) .withTest("ddd", true) .finish(); STestRun testRunAAA = build10.getFullStatistics().getAllTests().get(0); { TestOccurrence testOccurrence = new TestOccurrence(testRunAAA, getBeanContext(myServer), new Fields("invocations($long)")); assertEquals(Integer.valueOf(4), testOccurrence.invocations.count); assertEquals(Integer.valueOf(1), testOccurrence.invocations.failed); assertNotNull(testOccurrence.invocations.items); assertEquals(4, testOccurrence.invocations.items.size()); assertEquals("SUCCESS", testOccurrence.invocations.items.get(0).status); assertEquals("FAILURE", testOccurrence.invocations.items.get(2).status); } { TestOccurrence testOccurrence = new TestOccurrence(testRunAAA, getBeanContext(myServer), new Fields("invocations($long,$locator(status:FAILURE))")); assertEquals(Integer.valueOf(1), testOccurrence.invocations.count); assertNotNull(testOccurrence.invocations.items); assertEquals(1, testOccurrence.invocations.items.size()); assertEquals("FAILURE", testOccurrence.invocations.items.get(0).status); } } @Test public void testTestOccurrenceEntity_Metadata() throws Exception { final BuildTypeImpl buildType = registerBuildType("buildConf1", "project"); final RunningBuildEx build = startBuild(buildType); myFixture.doTestPassed(build, "testName"); myFixture.doTestMetadata(build,new TestMetadata("testName", "some key", "link", "value")); myFixture.doTestMetadata(build,new TestMetadata("testName", "some key3", "number", 44f)); STestRun testRun = finishBuild().getFullStatistics().getAllTests().get(0); TestOccurrence testOccurrence = new TestOccurrence(testRun, getBeanContext(myServer), new Fields("metadata")); assertEquals(Integer.valueOf(2), testOccurrence.metadata.count); final List items = testOccurrence.metadata.typedValues; assertEquals(items.size(), 2); System.out.println("items = " + StringUtil.join("\n", items)); assertTrue(items.contains(new TypedValue("some key", "link", "value", Fields.LONG))); assertTrue(items.contains(new TypedValue("some key3", "number", String.valueOf(44f), Fields.LONG))); } private static final Matcher TEST_MATCHER = new Matcher() { @Override public boolean matches(@NotNull final TestRunData data, @NotNull final STestRun sTestRun) { return data.testName.equals(sTestRun.getTest().getName().getAsString()) && data.status.equals(sTestRun.getStatus()) && data.orderId == sTestRun.getOrderId(); } }; private static TestRunData t(final String testName, final Status status, final int orderId) { return new TestRunData(testName, status, orderId); } private static class TestRunData { protected final String testName; protected final Status status; protected final int orderId; private TestRunData(final String testName, final Status status, final int orderId) { this.testName = testName; this.status = status; this.orderId = orderId; } @Override public String toString() { return "{" + testName + ", " + status.getText() + ", " + orderId + "}"; } } private static final Matcher TEST_WITH_BUILD_MATCHER = new Matcher() { @Override public boolean matches(@NotNull final TestRunDataWithBuild data, @NotNull final STestRun sTestRun) { return TEST_MATCHER.matches(data, sTestRun) && sTestRun.getBuildId() == data.buildId; } }; private static TestRunDataWithBuild t(final String testName, final Status status, final int orderId, final long buildId) { return new TestRunDataWithBuild(testName, status, orderId, buildId); } private static class TestRunDataWithBuild extends TestRunData { private final long buildId; private TestRunDataWithBuild(final String testName, final Status status, final int orderId, final long buildId) { super(testName, status, orderId); this.buildId = buildId; } @Override public String toString() { return "{" + testName + ", " + status.getText() + ", " + orderId + ", " + buildId + "}"; } } public void check(@Nullable final String locator, STestRun... items) { //using getEqualsMatcher() sometimes fails check(locator, new Matcher() { @Override public boolean matches(@NotNull final STestRun o, @NotNull final STestRun o2) { if (o == o2) return true; if (o.getClass() != o2.getClass()) return false; return o.getOrderId() == o2.getOrderId() && o.getTestRunId() == o2.getTestRunId() && o.getDuration() == o2.getDuration() && o.getStatus() == o2.getStatus() && Objects.equal(o.getTest(), o2.getTest()) && Objects.equal(o.getBuild(),o2.getBuild()) && // Objects.equal(o.getTestOutputInfo(), o2.getTestOutputInfo()) && Objects.equal(o.getMuteInfo(), o2.getMuteInfo()); } }, getFinder(), items); } }