/* * Copyright 2016 ThoughtWorks, Inc. * * 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 com.thoughtworks.go.server.dao.sparql; import java.io.File; import java.util.Arrays; import java.util.Date; import java.util.List; import com.thoughtworks.go.config.GoConfigDao; import com.thoughtworks.go.domain.JobIdentifier; import com.thoughtworks.go.domain.Pipeline; import com.thoughtworks.go.domain.Stage; import com.thoughtworks.go.domain.StageIdentifier; import com.thoughtworks.go.domain.materials.Modification; import com.thoughtworks.go.domain.testinfo.FailingTestsInPipeline; import com.thoughtworks.go.domain.testinfo.FailureDetails; import com.thoughtworks.go.domain.testinfo.StageTestRuns; import com.thoughtworks.go.domain.testinfo.TestInformation; import com.thoughtworks.go.domain.testinfo.TestStatus; import com.thoughtworks.go.domain.testinfo.TestSuite; import com.thoughtworks.go.i18n.Localizer; import com.thoughtworks.go.server.dao.DatabaseAccessHelper; import com.thoughtworks.go.server.domain.PipelineTimeline; import com.thoughtworks.go.server.persistence.MaterialRepository; import com.thoughtworks.go.server.service.PipelineHistoryService; import com.thoughtworks.go.server.service.StageService; import com.thoughtworks.go.server.service.XmlApiService; import com.thoughtworks.go.server.service.result.SubsectionLocalizedOperationResult; import com.thoughtworks.go.server.transaction.TransactionTemplate; import com.thoughtworks.go.util.GoConfigFileHelper; import com.thoughtworks.go.util.SystemEnvironment; import com.thoughtworks.go.util.TempFiles; import com.thoughtworks.studios.shine.cruise.builder.JunitXML; import com.thoughtworks.studios.shine.cruise.stage.StagesQuery; import com.thoughtworks.studios.shine.cruise.stage.StagesQueryCache; import com.thoughtworks.studios.shine.cruise.stage.details.LazyStageGraphLoader; import com.thoughtworks.studios.shine.cruise.stage.details.StageResourceImporter; import com.thoughtworks.studios.shine.cruise.stage.details.StageStorage; import com.thoughtworks.studios.shine.net.StubGoURLRepository; import org.hamcrest.core.Is; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static com.thoughtworks.studios.shine.cruise.builder.JunitXML.junitXML; import static org.hamcrest.CoreMatchers.hasItems; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:WEB-INF/applicationContext-global.xml", "classpath:WEB-INF/applicationContext-dataLocalAccess.xml", "classpath:WEB-INF/applicationContext-acegi-security.xml" }) public class ShineDaoIntegrationTest { private ShineDao shineDao; @Autowired private Localizer localizer; private SubsectionLocalizedOperationResult result; @Autowired private StageStorage stageStorage; @Autowired private StagesQueryCache stagesQueryCache; @Autowired private StageService stageService; @Autowired private PipelineHistoryService pipelineHistoryService; @Autowired private MaterialRepository materialRepository; @Autowired private GoConfigDao goConfigDao; @Autowired private XmlApiService xmlApiService; @Autowired private TransactionTemplate transactionTemplate; @Autowired private DatabaseAccessHelper dbHelper; @Autowired private PipelineTimeline pipelineTimeline; @Autowired private SystemEnvironment systemEnvironment; private TempFiles tempFiles; private StubGoURLRepository goURLRepository; private GoConfigFileHelper configHelper = new GoConfigFileHelper(); private Pipeline pipeline; private StageIdentifier stageId; private TestFailureSetup failureSetup; @Before public void setUp() throws Exception { dbHelper.onSetUp(); configHelper.usingCruiseConfigDao(goConfigDao); configHelper.onSetUp(); result = new SubsectionLocalizedOperationResult(); tempFiles = new TempFiles(); File tempFolder = tempFiles.createUniqueFolder("artifacts"); String artifactsRoot = tempFolder.getAbsolutePath(); stageStorage.clear(); StageResourceImporter importer = new StageResourceImporter(artifactsRoot, xmlApiService, stageService, pipelineHistoryService,systemEnvironment); LazyStageGraphLoader graphLoader = new LazyStageGraphLoader(importer, stageStorage); StagesQuery stagesQuery = new StagesQuery(graphLoader, stagesQueryCache); shineDao = new ShineDao(stagesQuery, stageService, pipelineHistoryService); goURLRepository = new StubGoURLRepository("http://localhost:8153", artifactsRoot); failureSetup = new TestFailureSetup(materialRepository, dbHelper, pipelineTimeline, configHelper, transactionTemplate); TestFailureSetup.SavedStage savedStage = failureSetup.setupPipelineInstance(true, null, goURLRepository); pipeline = savedStage.pipeline; stageId = savedStage.stageId; } @After public void tearDown() throws Exception { tempFiles.cleanUp(); stagesQueryCache.clear(); dbHelper.onTearDown(); } @Test public void shouldBeAbleToRetriveFailedTestsForAStageIdentifier() throws Exception { List<TestSuite> suites = shineDao.failedTestsFor(stageId); assertThat(suites.size(), is(1)); assertThat(suites.get(0).fullName(), is("testSuite1")); List<TestInformation> tests = suites.get(0).tests(); assertThat(tests.size(), is(2)); assertThat(tests.get(0).getName(), is("test1")); assertThat(tests.get(0).getStatus(), Is.is(TestStatus.Failure)); assertThat(tests.get(0).getJobNames(), hasItems("NixBuild", "WinBuild")); assertThat(tests.get(1).getName(), is("test2")); assertThat(tests.get(1).getStatus(), is(TestStatus.Error)); assertThat(tests.get(1).getJobNames(), hasItems("WinBuild")); } @Test public void shouldBeAbleToRetriveStageTestRunsWithLazyGraphLoader() throws Exception { StageTestRuns stageTestRuns = shineDao.failedBuildHistoryForStage(stageId, result); List<FailingTestsInPipeline> failingTestsInPipelines = stageTestRuns.failingTestsInPipelines(); assertThat(failingTestsInPipelines.toString(), failingTestsInPipelines.size(), is(1)); List<TestSuite> suites = failingTestsInPipelines.get(0).failingSuites(); assertThat(suites.size(), is(1)); assertThat(suites.get(0).fullName(), is("testSuite1")); List<TestInformation> tests = suites.get(0).tests(); assertThat(tests.size(), is(2)); assertThat(tests.get(0).getName(), is("test1")); assertThat(tests.get(0).getStatus(), is(TestStatus.Failure)); assertThat(tests.get(0).getJobNames(), hasItems("NixBuild", "WinBuild")); assertThat(tests.get(1).getName(), is("test2")); assertThat(tests.get(1).getStatus(), is(TestStatus.Error)); assertThat(tests.get(1).getJobNames(), hasItems("WinBuild")); } @Test public void shouldBeAbleToPullUpStackTrace() { FailureDetails failureDetails = shineDao.failureDetailsForTest(new JobIdentifier(stageId, "WinBuild"), "testSuite1", "test1", result); assertThat(failureDetails.getMessage(), is("Something assert failed...")); assertThat(failureDetails.getStackTrace(), is("junit.framework.AssertionFailedError: Something assert failed...")); failureDetails = shineDao.failureDetailsForTest(new JobIdentifier(stageId, "WinBuild"), "testSuite1", "test2", result); assertThat(failureDetails.getMessage(), is("Something went wrong")); assertThat(failureDetails.getStackTrace(), is("com.foo.MyException: Something went wrong...")); failureDetails = shineDao.failureDetailsForTest(new JobIdentifier(stageId, "NixBuild"), "testSuite1", "test1", result); assertThat(failureDetails.getMessage(), is("Something assert failed...")); assertThat(failureDetails.getStackTrace(), is("junit.framework.AssertionFailedError: Something assert failed...")); } @Test public void shouldHandleExceptionsWhenTryingToPullUpTrace() throws Exception { stageId = failureSetup.setupPipelineInstance(false, null, goURLRepository).stageId; FailureDetails details = shineDao.failureDetailsForTest(new JobIdentifier(stageId, "job1"), "testSuite1", "test1", result); assertThat(details.getMessage(), is("NOT_YET_AVAILABLE")); assertThat(details.getStackTrace(), is("NOT_YET_AVAILABLE")); assertThat("not successful", result.isSuccessful(), is(false)); assertThat(result.replacementContent(localizer), is("Unable to retrieve failure results.")); } @Test public void shouldRetriveHistoricalFailureWithNoTests() throws Exception { failureSetup.setupPipelineInstance(true, null, goURLRepository); StageIdentifier stageId3 = failureSetup.setupPipelineInstance(true, null, goURLRepository).stageId; StageTestRuns stageTestRuns = shineDao.failedBuildHistoryForStage(stageId3, result); List<FailingTestsInPipeline> failingTestsInPipelines = stageTestRuns.failingTestsInPipelines(); assertThat(failingTestsInPipelines.size(), is(3)); } @Test public void shouldRetriveHistoricalFailureInformation() throws Exception { Pipeline pipeline1 = pipeline; TestFailureSetup.SavedStage savedStage = failureSetup.setupPipelineInstance(true, null, goURLRepository); StageIdentifier stageId2 = savedStage.stageId; Pipeline pipeline2 = savedStage.pipeline; StageTestRuns stageTestRuns = shineDao.failedBuildHistoryForStage(stageId2, result); List<FailingTestsInPipeline> failingTestsInPipelines = stageTestRuns.failingTestsInPipelines(); assertThat(failingTestsInPipelines.size(), is(2)); FailingTestsInPipeline failingPipeline2 = failingTestsInPipelines.get(0); assertThat(failingPipeline2.getLabel(), is(pipeline2.getLabel())); assertThat(failingPipeline2.failingSuites().size(), is(0)); FailingTestsInPipeline failingPipeline1 = failingTestsInPipelines.get(1); assertThat(failingPipeline1.getLabel(), is(pipeline1.getLabel())); assertThat(failingPipeline1.failingSuites().size(), is(1)); } @Test public void shouldRetriveTheRightHistoricalFailureInformationForPipelinesWithSameLabel() throws Exception { Pipeline pipeline1 = pipeline; failureSetup.setupPipelineInstance(true, pipeline1.getLabel(), goURLRepository); StageIdentifier stageId3 = failureSetup.setupPipelineInstance(true, pipeline1.getLabel(), goURLRepository).stageId; StageTestRuns stageTestRuns = shineDao.failedBuildHistoryForStage(stageId3, result); List<FailingTestsInPipeline> failingTestsInPipelines = stageTestRuns.failingTestsInPipelines(); assertThat(failingTestsInPipelines.size(), is(3)); FailingTestsInPipeline failingPipeline3 = failingTestsInPipelines.get(0); assertThat(failingPipeline3.getLabel(), is(pipeline1.getLabel())); assertThat(failingPipeline3.failingSuites().size(), is(0)); FailingTestsInPipeline failingPipeline2 = failingTestsInPipelines.get(1); assertThat(failingPipeline2.getLabel(), is(pipeline1.getLabel())); assertThat(failingPipeline2.failingSuites().size(), is(0)); FailingTestsInPipeline failingPipeline1 = failingTestsInPipelines.get(2); assertThat(failingPipeline1.getLabel(), is(pipeline1.getLabel())); List<TestSuite> suites = failingPipeline1.failingSuites(); assertThat(suites.size(), is(1)); assertThat(suites.get(0).countOfStatus(TestStatus.Error), is(1)); assertThat(suites.get(0).countOfStatus(TestStatus.Failure), is(1)); } @Test public void shouldHandleExceptionsFromSelectWhileRenderingFailingTestsForStage() throws Exception { stageId = failureSetup.setupPipelineInstance(false, null, goURLRepository).stageId; shineDao.failedBuildHistoryForStage(stageId, result); assertThat("not successful", result.isSuccessful(), is(false)); assertThat(result.replacementContent(localizer), is("Unable to retrieve failure results.")); } @Test public void shouldContainLocatorForFailedJob() throws Exception { StageTestRuns stageTestRuns = failingStageHistory(); List<FailingTestsInPipeline> failingTestsInPipelines = stageTestRuns.failingTestsInPipelines(); FailingTestsInPipeline failingPipeline7 = failingTestsInPipelines.get(0); FailingTestsInPipeline failingPipeline6 = failingTestsInPipelines.get(1); List<TestInformation> failingTests7 = failingPipeline7.failingSuites().get(0).tests(); assertThat(failingTests7.size(), is(1)); assertThat(failingTests7.get(0).getJobs().size(), is(2)); assertThat(failingTests7.get(0).getJobs().get(0).getBuildName(), is("NixBuild")); assertThat(failingTests7.get(0).getJobs().get(0).buildLocator(), is("foo-pipeline/3/bar-stage/1/NixBuild")); assertThat(failingTests7.get(0).getJobs().get(1).buildLocator(), is("foo-pipeline/3/bar-stage/1/WinBuild")); List<TestInformation> failingTests6 = failingPipeline6.failingSuites().get(0).tests(); assertThat(failingTests6.size(), is(2)); assertThat(failingTests6.get(0).getJobs().size(), is(1)); assertThat(failingTests6.get(0).getJobs().get(0).getBuildName(), is("WinBuild")); assertThat(failingTests6.get(0).getJobs().get(0).buildLocator(), is("foo-pipeline/2/bar-stage/1/WinBuild")); assertThat(failingTests6.get(1).getJobs().size(), is(1)); assertThat(failingTests6.get(1).getJobs().get(0).getBuildName(), is("WinBuild")); assertThat(failingTests6.get(1).getJobs().get(0).buildLocator(), is("foo-pipeline/2/bar-stage/1/WinBuild")); } @Test public void shouldPopulateUsersThatTriggeredTheBuild() { StageTestRuns stageTestRuns = failingStageHistory(); List<FailingTestsInPipeline> failingTestsInPipelines = stageTestRuns.failingTestsInPipelines(); List<String> users = failingTestsInPipelines.get(1).users(); assertThat(users.size(), is(2)); assertThat(users, hasItem("fooUser")); assertThat(users, hasItem("RRR & DR")); assertThat(users.size(), is(2)); users = failingTestsInPipelines.get(0).users(); assertThat(users.size(), is(1)); assertThat(users, hasItem("blahUser")); } private StageTestRuns failingStageHistory() { failureSetup.setupPipelineInstance(true, null, Arrays.asList( new Modification("fooUser", "revision 15", "loser@mail.com", new Date(), "15"), new Modification("RRR & DR", "revision 16", "boozer@mail.com", new Date(), "16")), new TestFailureSetup.TestResultsStubbing() { public void stub(Stage stage) { JunitXML junit1 = junitXML("testSuite1", 2).failed(2).errored(1); junit1.registerStubContent(goURLRepository, "pipelines/" + stage.getJobInstances().get(0).getIdentifier().artifactLocator("junit") + "/junit/"); } }, new Date()); stageId = failureSetup.setupPipelineInstance(true, null, Arrays.asList(new Modification("blahUser", "revision 17", "hello@world", new Date(), "17")), new TestFailureSetup.TestResultsStubbing() { public void stub(Stage stage) { JunitXML junit1 = junitXML("testSuite1", 2).failed(2).errored(1); junit1.registerStubContent(goURLRepository, "pipelines/" + stage.getJobInstances().get(0).getIdentifier().artifactLocator("junit") + "/junit/"); JunitXML junit2 = junitXML("testSuite1", 2).errored(1); junit2.registerStubContent(goURLRepository, "pipelines/" + stage.getJobInstances().get(1).getIdentifier().artifactLocator("junit") + "/junit/"); } }, new Date()).stageId; return shineDao.failedBuildHistoryForStage(stageId, result); } @Test public void shouldContainTotalTestCounts() throws Exception { StageTestRuns stageTestRuns = failingStageHistory(); assertThat(stageTestRuns.numberOfTests(), is(4)); } @Test public void shouldReturnTheTotalNumberOfFailuresAndErrorsForAPassedStage() { StageIdentifier stageId = failureSetup.setupPipelineInstance(false, null, Arrays.asList(new Modification("blahUser", "revision 17", "hello@world", new Date(), "17")), new TestFailureSetup.TestResultsStubbing() { public void stub(Stage stage) { dbHelper.passStage(stage); JunitXML junit1 = junitXML("testSuite1", 2).failed(2).errored(1); junit1.registerStubContent(goURLRepository, "pipelines/" + stage.getJobInstances().get(0).getIdentifier().artifactLocator("junit") + "/junit/"); JunitXML junit2 = junitXML("testSuite1", 2).errored(1); junit2.registerStubContent(goURLRepository, "pipelines/" + stage.getJobInstances().get(1).getIdentifier().artifactLocator("junit") + "/junit/"); } }, new Date()).stageId; StageTestRuns testRuns = shineDao.failedBuildHistoryForStage(stageId, result); assertThat(testRuns.numberOfTests(), is(4)); assertThat(testRuns.totalErrorCount(), is(2)); assertThat(testRuns.totalFailureCount(), is(1)); } }