/* * Copyright 2017 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; import com.thoughtworks.go.config.*; import com.thoughtworks.go.config.materials.MaterialConfigs; import com.thoughtworks.go.config.materials.Materials; import com.thoughtworks.go.config.materials.ScmMaterial; import com.thoughtworks.go.config.materials.dependency.DependencyMaterial; import com.thoughtworks.go.config.materials.dependency.DependencyMaterialConfig; import com.thoughtworks.go.config.materials.git.GitMaterial; import com.thoughtworks.go.config.materials.mercurial.HgMaterial; import com.thoughtworks.go.config.materials.perforce.P4Material; import com.thoughtworks.go.config.materials.svn.SvnMaterial; import com.thoughtworks.go.domain.*; import com.thoughtworks.go.domain.buildcause.BuildCause; import com.thoughtworks.go.domain.materials.Material; import com.thoughtworks.go.domain.materials.Modification; import com.thoughtworks.go.domain.materials.ModifiedAction; import com.thoughtworks.go.domain.materials.ModifiedFile; import com.thoughtworks.go.domain.materials.dependency.DependencyMaterialRevision; import com.thoughtworks.go.helper.*; import com.thoughtworks.go.presentation.pipelinehistory.PipelineInstanceModel; import com.thoughtworks.go.presentation.pipelinehistory.PipelineInstanceModels; import com.thoughtworks.go.presentation.pipelinehistory.StageInstanceModel; import com.thoughtworks.go.presentation.pipelinehistory.StageInstanceModels; import com.thoughtworks.go.server.cache.GoCache; import com.thoughtworks.go.server.database.DatabaseStrategy; import com.thoughtworks.go.server.domain.Username; import com.thoughtworks.go.server.materials.DependencyMaterialUpdateNotifier; import com.thoughtworks.go.server.persistence.MaterialRepository; import com.thoughtworks.go.server.service.*; import com.thoughtworks.go.server.service.support.ServerStatusService; import com.thoughtworks.go.server.transaction.TransactionTemplate; import com.thoughtworks.go.util.*; import org.apache.commons.lang.StringUtils; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.Matchers; 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 org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import javax.sql.DataSource; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; import static com.thoughtworks.go.domain.PersistentObject.NOT_PERSISTED; import static com.thoughtworks.go.helper.MaterialsMother.svnMaterial; import static com.thoughtworks.go.helper.ModificationsMother.*; import static com.thoughtworks.go.server.dao.PersistentObjectMatchers.hasSameId; import static com.thoughtworks.go.util.GoConstants.DEFAULT_APPROVED_BY; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.*; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsCollectionContaining.hasItem; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.*; @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 PipelineSqlMapDaoIntegrationTest { @Autowired private StageDao stageDao; @Autowired private PipelineSqlMapDao pipelineDao; @Autowired private JobInstanceDao jobInstanceDao; @Autowired private DataSource dataSource; @Autowired private DatabaseAccessHelper dbHelper; @Autowired private MaterialRepository materialRepository; @Autowired private GoCache goCache; @Autowired private ScheduleService scheduleService; @Autowired private TransactionTemplate transactionTemplate; @Autowired private PipelinePauseService pipelinePauseService; @Autowired private GoConfigDao goConfigDao; @Autowired private InstanceFactory instanceFactory; @Autowired private SystemEnvironment systemEnvironment; @Autowired private DatabaseStrategy database; @Autowired private DependencyMaterialUpdateNotifier notifier; @Autowired private ServerStatusService serverStatusService; @Autowired private PipelineHistoryService pipelineHistoryService; @Autowired private PipelineLockService pipelineLockService; @Autowired private GoConfigService goConfigService; private String md5 = "md5-test"; private ScheduleTestUtil u; @Before public void setup() throws Exception { dbHelper.onSetUp(); goCache.clear(); GoConfigFileHelper configHelper = new GoConfigFileHelper(); configHelper.usingCruiseConfigDao(goConfigDao); u = new ScheduleTestUtil(transactionTemplate, materialRepository, dbHelper, configHelper); notifier.disableUpdates(); } @After public void teardown() throws Exception { notifier.enableUpdates(); dbHelper.onTearDown(); } private Pipeline schedulePipelineWithStages(PipelineConfig pipelineConfig) throws Exception { BuildCause buildCause = BuildCause.createWithModifications(modifyOneFile(pipelineConfig), ""); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, buildCause, new DefaultSchedulingContext(DEFAULT_APPROVED_BY), "md5-test", new TimeProvider()); assertNotInserted(pipeline.getId()); savePipeline(pipeline); long pipelineId = pipeline.getId(); assertIsInserted(pipelineId); return pipeline; } private void savePipeline(final Pipeline pipeline) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { materialRepository.save(pipeline.getBuildCause().getMaterialRevisions()); pipelineDao.saveWithStages(pipeline); } }); } private void schedulePipelineWithoutCounter(PipelineConfig pipelineConfig) { Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createWithModifications(modifyOneFile(pipelineConfig), ""), new DefaultSchedulingContext( "anyone"), "md5-test", new TimeProvider()); save(pipeline); for (Stage stage : pipeline.getStages()) { stageDao.saveWithJobs(pipeline, stage); } } private void save(final Pipeline pipeline) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { materialRepository.save(pipeline.getBuildCause().getMaterialRevisions()); pipelineDao.save(pipeline); } }); } @Test public void shouldLoadNaturalOrder() throws SQLException { Pipeline pipeline = new Pipeline("Test", BuildCause.createManualForced(), new Stage("dev", new JobInstances(new JobInstance("unit")), "anonymous", "manual", new TimeProvider())); savePipeline(pipeline); dbHelper.updateNaturalOrder(pipeline.getId(), 2.5); PipelineInstanceModel loaded = pipelineDao.loadHistory("Test").get(0); PipelineInstanceModel loadedById = pipelineDao.loadHistory(pipeline.getId()); assertThat(loadedById.getNaturalOrder(), is(2.5)); assertThat(loaded.getNaturalOrder(), is(2.5)); assertThat(loaded.isBisect(), is(true)); } @Test public void shouldLoadStageResult() throws SQLException { Stage stage = new Stage("dev", new JobInstances(new JobInstance("unit")), "anonymous", "manual", new TimeProvider()); stage.building(); Pipeline pipeline = new Pipeline("Test", BuildCause.createManualForced(), stage); savePipeline(pipeline); PipelineInstanceModel loaded = pipelineDao.loadHistory("Test").get(0); assertThat(loaded.getStageHistory().get(0).getResult(), is(StageResult.Unknown)); PipelineInstanceModel loadedById = pipelineDao.loadHistory(pipeline.getId()); assertThat(loadedById.getStageHistory().get(0).getResult(), is(StageResult.Unknown)); } @Test public void shouldLoadStageIdentifier() throws SQLException { Stage stage = new Stage("dev", new JobInstances(new JobInstance("unit")), "anonymous", "manual", new TimeProvider()); stage.building(); Pipeline pipeline = new Pipeline("Test", BuildCause.createManualForced(), stage); savePipeline(pipeline); PipelineInstanceModel loaded = pipelineDao.loadHistory("Test").get(0); StageInstanceModel historicalStage = loaded.getStageHistory().get(0); assertThat(historicalStage.getIdentifier(), is(new StageIdentifier("Test", loaded.getCounter(), loaded.getLabel(), "dev", historicalStage.getCounter()))); PipelineInstanceModel loadedById = pipelineDao.loadHistory(pipeline.getId()); StageInstanceModel historicalStageModelById = loadedById.getStageHistory().get(0); assertThat(historicalStageModelById.getIdentifier(), is(new StageIdentifier("Test", loadedById.getCounter(), loadedById.getLabel(), "dev", historicalStage.getCounter()))); } @Test public void shouldDefaultCounterToZero() { assertThat(pipelineDao.getCounterForPipeline("pipeline-with-no-history"), is(0)); } @Test public void shouldReserveModificationsOrder() throws Exception { MaterialRevisions materialRevisions = ModificationsMother.multipleModifications(); Pipeline pipeline = new Pipeline("Test", BuildCause.createWithModifications(materialRevisions, "")); save(pipeline); Pipeline loaded = pipelineDao.loadPipeline(pipeline.getId()); ModificationsCollector mods = new ModificationsCollector(); loaded.getBuildCause().getMaterialRevisions().accept(mods); assertEquals(ModificationsMother.TODAY_CHECKIN, mods.first().getModifiedTime()); } @Test public void shouldLoadModificationsWithChangedFlagApplied() throws Exception { MaterialRevisions materialRevisions = ModificationsMother.multipleModifications(); materialRevisions.getMaterialRevision(0).markAsChanged(); Pipeline pipeline = new Pipeline("Test", BuildCause.createWithModifications(materialRevisions, "")); save(pipeline); Pipeline loaded = pipelineDao.loadPipeline(pipeline.getId()); assertThat(loaded.getBuildCause().getMaterialRevisions().getMaterialRevision(0).isChanged(), is(true)); } @Test public void shouldLoadModificationsWithNoModifiedFiles() throws Exception { List<Modification> modifications = new ArrayList<>(); Modification modification = ModificationsMother.oneModifiedFile(ModificationsMother.nextRevision()); modifications.add(modification); modifications.add(new Modification(MOD_USER, MOD_COMMENT, "foo@bar.com", YESTERDAY_CHECKIN, ModificationsMother.nextRevision())); SvnMaterial svnMaterial = MaterialsMother.svnMaterial(); MaterialRevisions revisions = new MaterialRevisions(); revisions.addRevision(svnMaterial, modifications); Pipeline pipeline = new Pipeline("Test", BuildCause.createWithModifications(revisions, "")); savePipeline(pipeline); Pipeline loaded = pipelineDao.loadPipeline(pipeline.getId()); ModificationsCollector summary = new ModificationsCollector(); loaded.getBuildCause().getMaterialRevisions().accept(summary); assertThat(summary.numberOfModifications(), is(2)); } @Test public void shouldSupportModifiedFileWithVeryLongName() { Modification modification = ModificationsMother.withModifiedFileWhoseNameLengthIsOneK(); Pipeline pipeline = new Pipeline("Test", BuildCause.createWithModifications(ModificationsMother.createSvnMaterialRevisions(modification), "")); savePipeline(pipeline); Pipeline loaded = pipelineDao.loadPipeline(pipeline.getId()); Modification loadedModification = loaded.getBuildCause().getMaterialRevisions().getMaterialRevision( 0).getModification(0); assertEquals(modification, loadedModification); } @Test public void shouldTruncateFileNameIfItIsTooLong() { Modification modification = ModificationsMother.withModifiedFileWhoseNameLengthIsMoreThanOneK(); Pipeline pipeline = new Pipeline("Test", BuildCause.createWithModifications(ModificationsMother.createSvnMaterialRevisions(modification), "")); savePipeline(pipeline); Pipeline loaded = pipelineDao.loadPipeline(pipeline.getId()); Modification loadedModification = loaded.getBuildCause().getMaterialRevisions().getMaterialRevision( 0).getModification(0); assertThat(loadedModification.getModifiedFiles().get(0).getFileName().length(), is(ModifiedFile.MAX_NAME_LENGTH)); } @Test public void shouldPersistBuildCauseMessage() throws SQLException { MaterialRevisions materialRevisions = ModificationsMother.multipleModifications(); BuildCause buildCause = BuildCause.createManualForced(materialRevisions, Username.ANONYMOUS); Pipeline pipeline = new Pipeline("Test", buildCause); save(pipeline); Pipeline loaded = pipelineDao.mostRecentPipeline("Test"); assertThat(loaded.getBuildCauseMessage(), is(buildCause.getBuildCauseMessage())); } @Test public void shouldReturnNullWhileLoadingMostRecentPipelineForNoPipelineFound() throws SQLException { Pipeline loaded = pipelineDao.mostRecentPipeline("Test"); assertThat(loaded, is(instanceOf(NullPipeline.class))); } @Test public void shouldPersistBuildCauseEnvironmentVariables() throws SQLException { MaterialRevisions materialRevisions = ModificationsMother.multipleModifications(); BuildCause buildCause = BuildCause.createManualForced(materialRevisions, Username.ANONYMOUS); EnvironmentVariablesConfig environmentVariablesConfig = new EnvironmentVariablesConfig(); environmentVariablesConfig.add(new EnvironmentVariableConfig("VAR1", "value one")); environmentVariablesConfig.add(new EnvironmentVariableConfig("VAR2", "value two")); buildCause.addOverriddenVariables(environmentVariablesConfig); Pipeline pipeline = new Pipeline("Test", buildCause); save(pipeline); Pipeline loaded = pipelineDao.mostRecentPipeline("Test"); EnvironmentVariablesConfig variables = new EnvironmentVariablesConfig(); variables.add("VAR1", "value one"); variables.add("VAR2", "value two"); assertThat(loaded.getBuildCause().getVariables(), is(variables)); assertThat(loaded.scheduleTimeVariables(), is(variables)); } @Test public void shouldPersistMaterialsWithRealPassword() throws SQLException { MaterialRevisions materialRevisions = new MaterialRevisions(); addRevision(materialRevisions, MaterialsMother.svnMaterial("http://username:password@localhost")); addRevision(materialRevisions, MaterialsMother.hgMaterial("http://username:password@localhost")); addRevision(materialRevisions, new GitMaterial("git://username:password@localhost")); addRevision(materialRevisions, new P4Material("localhost:1666", "view")); BuildCause buildCause = BuildCause.createManualForced(materialRevisions, Username.ANONYMOUS); Pipeline pipeline = new Pipeline("Test", buildCause); save(pipeline); Pipeline loaded = pipelineDao.mostRecentPipeline("Test"); Materials materials = loaded.getMaterials(); for (Material material : materials) { assertThat(((ScmMaterial) material).getUrl(), not(containsString("******"))); } } private void addRevision(MaterialRevisions materialRevisions, Material material) { materialRevisions.addRevision(material, ModificationsMother.multipleModificationList()); } @Test public void shouldSchedulePipelineWithModifications() throws Exception { Pipeline pipeline = schedulePipelineWithStages( PipelineMother.withMaterials("mingle", "dev", BuildPlanMother.withBuildPlans("functional", "unit")) ); assertModifications(pipeline); } @Test public void shouldGenerateGraphForMultipleRunsOfDownstreamPipelinesOfAGivenPipelineNameAndCounter() throws Exception { PipelineConfig shine = PipelineMother.twoBuildPlansWithResourcesAndMaterials("shine", "shineStage"); PipelineConfig cruise = PipelineMother.twoBuildPlansWithResourcesAndMaterials("cruise", "cruiseStage"); cruise.materialConfigs().clear(); cruise.addMaterialConfig(new DependencyMaterialConfig(new CaseInsensitiveString("shine"), new CaseInsensitiveString("shineStage"))); Pipeline shineInstance = dbHelper.newPipelineWithAllStagesPassed(shine); Pipeline cruiseInstance1 = dbHelper.newPipelineWithAllStagesPassed(cruise); Pipeline cruiseInstance2 = dbHelper.newPipelineWithAllStagesPassed(cruise); Pipeline cruiseInstance3 = dbHelper.newPipelineWithAllStagesPassed(cruise); PipelineDependencyGraphOld dependencyGraph = pipelineDao.pipelineGraphByNameAndCounter("shine", 1); PipelineInstanceModel upstream = dependencyGraph.pipeline(); assertPipelineEquals(shineInstance, upstream); ensureBuildCauseIsLoadedFor(upstream); assertThat(dependencyGraph.dependencies().size(), is(3)); assertThat(dependencyGraph.dependencies(), hasPipeline(cruiseInstance1)); assertThat(dependencyGraph.dependencies(), hasPipeline(cruiseInstance2)); assertThat(dependencyGraph.dependencies(), hasPipeline(cruiseInstance3)); } @Test public void shouldReturnNullIfPipelineIsNotFound() throws Exception { assertThat(pipelineDao.pipelineGraphByNameAndCounter("shine", 1), is(nullValue())); } private Matcher<PipelineInstanceModels> hasPipeline(final Pipeline pipeline) { return new BaseMatcher<PipelineInstanceModels>() { public boolean matches(Object o) { if (o instanceof PipelineInstanceModels) { PipelineInstanceModels pipelineInstanceModels = (PipelineInstanceModels) o; for (PipelineInstanceModel pipelineInstanceModel : pipelineInstanceModels) { if (pipelineInstanceModel.getName().equals(pipeline.getName()) && pipelineInstanceModel.getCounter().equals(pipeline.getCounter())) { return true; } } } return false; } public void describeTo(Description description) { description.appendText("expected pipline " + pipeline.getName() + " with counter " + pipeline.getCounter()); } }; } private void ensureBuildCauseIsLoadedFor(PipelineInstanceModel upstream) { assertThat(StringUtils.isEmpty(upstream.getRevisionOfLatestModification()), is(false)); } @Test public void shouldGeneratePipelineDependencyGraphForAllDownStreamPipelines() throws Exception { PipelineConfig shine = PipelineMother.twoBuildPlansWithResourcesAndMaterials("shine", "1stStage", "2ndStage"); PipelineConfig cruise13 = pipelineConfigFor("cruise1.3", "shine", "1stStage"); PipelineConfig cruise20 = pipelineConfigFor("cruise2.0", "shine", "2ndStage"); Pipeline shineInstance = dbHelper.newPipelineWithAllStagesPassed(shine); Pipeline cruise13Instance = dbHelper.newPipelineWithAllStagesPassed(cruise13); Pipeline cruise20Instance = dbHelper.newPipelineWithAllStagesPassed(cruise20); PipelineDependencyGraphOld dependencyGraph = pipelineDao.pipelineGraphByNameAndCounter("shine", 1); assertPipelineEquals(shineInstance, dependencyGraph.pipeline()); ensureBuildCauseIsLoadedFor(dependencyGraph.pipeline()); PipelineInstanceModels dependencies = dependencyGraph.dependencies(); assertThat(dependencies.size(), is(2)); assertPipelineEquals(cruise13Instance, dependencies.find("cruise1.3")); assertPipelineEquals(cruise20Instance, dependencies.find("cruise2.0")); } @Test public void shouldNotIncludePipelinesNotUsingUpstreamAsDependencyMaterial_evenIfADependencyRevisionGeneratedOutOfParentPipelineAppearsInPMRrangeForANonDependentPipeline() throws Exception { // shine -> cruise(depends on shine) // mingle(not related to shine) final HgMaterial mingleHg = MaterialsMother.hgMaterial(); PipelineConfig mingle = PipelineConfigMother.pipelineConfig("mingle", mingleHg.config(), new JobConfigs(new JobConfig("run-tests"))); PipelineConfig shine = PipelineMother.twoBuildPlansWithResourcesAndMaterials("shine", "compile"); Pipeline shineInstance = dbHelper.newPipelineWithAllStagesPassed(shine); PipelineConfig cruise = pipelineConfigFor("cruise", "shine", "compile"); final DependencyMaterial cruiseUpstream = new DependencyMaterial(new CaseInsensitiveString("shine"), new CaseInsensitiveString("compile")); final Modification cruiseMod = new Modification(new Date(), String.format("shine/%s/compile/%s", shineInstance.getCounter(), shineInstance.getStages().get(0).getCounter()), "shine-1", null); final Modification mingleFrom = ModificationsMother.oneModifiedFile("1234"); saveRev(mingleHg, mingleFrom); saveRev(cruiseUpstream, cruiseMod); final Modification mingleTo = ModificationsMother.oneModifiedFile("abcd"); saveRev(mingleHg, mingleTo); dbHelper.saveMaterialsWIthPassedStages(instanceFactory.createPipelineInstance(mingle, BuildCause.createManualForced( new MaterialRevisions(new MaterialRevision(mingleHg, mingleTo, mingleFrom)), Username.ANONYMOUS), new DefaultSchedulingContext(GoConstants.DEFAULT_APPROVED_BY), md5, new TimeProvider())); final Pipeline cruiseInstance = instanceFactory.createPipelineInstance(cruise, BuildCause.createManualForced( new MaterialRevisions(new MaterialRevision(cruiseUpstream, cruiseMod)), Username.ANONYMOUS), new DefaultSchedulingContext(GoConstants.DEFAULT_APPROVED_BY), md5, new TimeProvider()); dbHelper.saveMaterialsWIthPassedStages(cruiseInstance); PipelineDependencyGraphOld dependencyGraph = pipelineDao.pipelineGraphByNameAndCounter("shine", shineInstance.getCounter()); assertPipelineEquals(shineInstance, dependencyGraph.pipeline()); ensureBuildCauseIsLoadedFor(dependencyGraph.pipeline()); PipelineInstanceModels dependencies = dependencyGraph.dependencies(); assertThat(dependencies.size(), is(1)); assertPipelineEquals(cruiseInstance, dependencies.find("cruise")); } private void saveRev(final Material material, final Modification modification) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { materialRepository.saveMaterialRevision(new MaterialRevision(material, modification)); } }); } @Test public void shouldMaintainStageOrderAndHistoryAfterGettingPipelineDependencyGraph() throws Exception { PipelineConfig shineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("shine", "1stStage", "2ndStage"); Pipeline shineInstance = dbHelper.newPipelineWithFirstStageFailed(shineConfig); dbHelper.scheduleStage(shineInstance, shineConfig.get(1), 1); PipelineDependencyGraphOld dependencyGraph = pipelineDao.pipelineGraphByNameAndCounter("shine", 1); assertPipelineEquals(shineInstance, dependencyGraph.pipeline()); StageInstanceModels models = dependencyGraph.pipeline().getStageHistory(); assertThat(models.size(), is(2)); assertThat(models.get(0).getName(), is("1stStage")); assertThat(models.get(1).getName(), is("2ndStage")); } private PipelineConfig pipelineConfigFor(final String pipelineName, final String dependentOnPipeline, final String dependentOnStage) { PipelineConfig config = PipelineMother.twoBuildPlansWithResourcesAndMaterials(pipelineName, "cruiseStage"); config.materialConfigs().clear(); config.addMaterialConfig(new DependencyMaterialConfig(new CaseInsensitiveString(dependentOnPipeline), new CaseInsensitiveString(dependentOnStage))); return config; } private void assertPipelineEquals(Pipeline expected, PipelineInstanceModel actual) { assertThat(actual.getName(), is(expected.getName())); assertThat(actual.getCounter(), is(expected.getCounter())); } @Test public void shouldLoadPipelineFromStageInstanceId() throws Exception { String stageName = "dev"; PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", stageName); Pipeline mingle = schedulePipelineWithStages(mingleConfig); Stage stage = stageOf(mingle); assertThat(pipelineDao.pipelineWithModsByStageId(mingle.getName(), stage.getId()), hasSameId(mingle)); } //TODO FIXME sorted by Id is not good. // - Comment by Bobby: Sorted by Id is exactly what we want here. Please discuss. @Test public void shouldLoadMostRecentPipeline() throws Exception { String stageName = "dev"; PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", stageName); Pipeline mingle = schedulePipelineWithStages(mingleConfig); Pipeline mostRecentPipeline = pipelineDao.mostRecentPipeline(mingle.getName()); assertThat(mostRecentPipeline, hasSameId(mingle)); assertThat(mostRecentPipeline.getBuildCause().getMaterialRevisions().totalNumberOfModifications(), is(1)); } @Test public void shouldLoadMostRecentLabel() throws Exception { String stageName = "dev"; PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", stageName); Pipeline mingle = schedulePipelineWithStages(mingleConfig); String label = pipelineDao.mostRecentLabel(mingle.getName()); assertThat(label, is(mingle.getLabel())); } @Test public void shouldLoadMostRecentPipelineWithSingleStage() throws Exception { String stageName = "dev"; PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", stageName); Pipeline mingle = schedulePipelineWithStages(mingleConfig); Pipeline mostRecentPipeline = pipelineDao.mostRecentPipeline(mingle.getName()); assertThat(mostRecentPipeline, hasSameId(mingle)); assertThat(mostRecentPipeline.getStages().size(), is(1)); assertThat(mostRecentPipeline.getFirstStage().getName(), is(stageName)); assertThat(mostRecentPipeline.getBuildCause().getMaterialRevisions().totalNumberOfModifications(), is(1)); } @Test public void shouldLoadMostRecentPipelineWithMutipleSameStage() throws Exception { String stageName = "dev"; PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", stageName); Pipeline mingle = schedulePipelineWithStages(mingleConfig); Stage newInstance = rescheduleStage(stageName, mingleConfig, mingle); Pipeline mostRecentPipeline = pipelineDao.mostRecentPipeline(mingle.getName()); assertThat(mostRecentPipeline, hasSameId(mingle)); assertThat("Asserting number of stages. Stages are:\n\t" + mostRecentPipeline.getStages(), mostRecentPipeline.getStages().size(), is(1)); assertThat(mostRecentPipeline.getFirstStage().getId(), is(newInstance.getId())); assertThat(mostRecentPipeline.getBuildCause().getMaterialRevisions().totalNumberOfModifications(), is(1)); } private Stage rescheduleStage(String stageName, PipelineConfig mingleConfig, Pipeline pipeline) { Stage newInstance = instanceFactory.createStageInstance(mingleConfig.findBy(new CaseInsensitiveString(stageName)), new DefaultSchedulingContext("anyone"), md5, new TimeProvider()); return stageDao.saveWithJobs(pipeline, newInstance); } @Test public void shouldLoadPipelineHistories() throws Exception { String dev = "dev"; PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", dev); Pipeline mingle = schedulePipelineWithStages(mingleConfig); Stage firstStage = mingle.getFirstStage(); Pipeline mingle2 = schedulePipelineWithStages(mingleConfig); JobInstance instance = firstStage.getJobInstances().first(); jobInstanceDao.ignore(instance); PipelineInstanceModels pipelineHistories = pipelineDao.loadHistory(mingle.getName(), 10, 0); assertThat(pipelineHistories.size(), is(2)); StageInstanceModels stageHistories = pipelineHistories.first().getStageHistory(); assertThat(stageHistories.size(), is(1)); StageInstanceModel history = stageHistories.first(); assertThat(history.getName(), is(dev)); assertThat(history.getApprovalType(), is(GoConstants.APPROVAL_SUCCESS)); assertThat(history.getBuildHistory().size(), is(2)); assertThat(pipelineHistories.get(1).getName(), is("mingle")); } @Test public void shouldLoadPipelineHistoriesStartingAtTheSuppliedLabel() throws Exception { PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); mingleConfig.setLabelTemplate("LABEL:${COUNT}"); Pipeline pipeline1 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline2 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline3 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline4 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline5 = schedulePipelineWithStages(mingleConfig); PipelineInstanceModels pipelineHistories = pipelineDao.loadHistory(pipeline1.getName(), 2, pipeline3.getLabel()); assertThat(pipelineHistories.size(), is(2)); assertThat(pipelineHistories.get(0).getLabel(), is(pipeline3.getLabel())); assertThat(pipelineHistories.get(1).getLabel(), is(pipeline2.getLabel())); } @Test public void shouldLoadPipelineHistoriesStartingAtTheLatestPipeline() throws Exception { PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); mingleConfig.setLabelTemplate("LABEL:${COUNT}"); Pipeline pipeline1 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline2 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline3 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline4 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline5 = schedulePipelineWithStages(mingleConfig); PipelineInstanceModels pipelineHistories = pipelineDao.loadHistory(pipeline1.getName(), 2, "latest"); assertThat(pipelineHistories.size(), is(2)); assertThat(pipelineHistories.get(0).getLabel(), is(pipeline5.getLabel())); assertThat(pipelineHistories.get(1).getLabel(), is(pipeline4.getLabel())); } @Test public void shouldReturnEmptyListWhenThereIsNoPipelineHistory() throws Exception { PipelineInstanceModels pipelineHistories = pipelineDao.loadHistory("something not exist", 10, 0); assertThat(pipelineHistories.size(), is(0)); } @Test public void shouldLoadPipelineHistoryOnlyForSuppliedPipeline() throws Exception { PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); PipelineConfig otherConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("other", "dev"); schedulePipelineWithStages(mingleConfig); schedulePipelineWithStages(otherConfig); schedulePipelineWithStages(mingleConfig); schedulePipelineWithStages(otherConfig); schedulePipelineWithStages(mingleConfig); PipelineInstanceModels pipelineHistories = pipelineDao.loadHistory("mingle", 10, 0); assertThat(pipelineHistories.get(0).getName(), is("mingle")); assertThat(pipelineHistories.get(1).getName(), is("mingle")); assertThat(pipelineHistories.get(2).getName(), is("mingle")); assertThat(pipelineHistories.size(), is(3)); } @Test public void shouldSupportPipelinesWithoutCounterWhenLoadHistory() { PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); schedulePipelineWithoutCounter(mingleConfig); PipelineInstanceModels models = pipelineDao.loadHistory(CaseInsensitiveString.str(mingleConfig.name()), 10, 0); assertThat(models.size(), is(1)); } @Test public void shouldLoadAllActivePipelines() throws Exception { PipelineConfig twistConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("twist", "dev", "ft"); Pipeline twistPipeline = dbHelper.newPipelineWithAllStagesPassed(twistConfig); List<CaseInsensitiveString> allPipelineNames = goConfigDao.load().getAllPipelineNames(); if (!allPipelineNames.contains(new CaseInsensitiveString("twist"))) { goConfigDao.addPipeline(twistConfig, "pipelinesqlmapdaotest"); } PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev", "ft"); if (!allPipelineNames.contains(new CaseInsensitiveString("mingle"))) { goConfigDao.addPipeline(mingleConfig, "pipelinesqlmapdaotest"); } Pipeline firstPipeline = dbHelper.newPipelineWithAllStagesPassed(mingleConfig); Pipeline secondPipeline = dbHelper.newPipelineWithFirstStagePassed(mingleConfig); dbHelper.scheduleStage(secondPipeline, mingleConfig.get(1)); Pipeline thirdPipeline = dbHelper.newPipelineWithFirstStageScheduled(mingleConfig); PipelineInstanceModels pipelineHistories = pipelineDao.loadActivePipelines(); assertThat(pipelineHistories.size(), is(3)); assertThat(pipelineHistories.get(0).getId(), is(thirdPipeline.getId())); assertThat(pipelineHistories.get(1).getId(), is(secondPipeline.getId())); assertThat(pipelineHistories.get(2).getId(), is(twistPipeline.getId())); assertThat(pipelineHistories.get(0).getBuildCause().getMaterialRevisions().isEmpty(), is(false)); } @Test public void shouldLoadAllActivePipelinesPresentInConfigOnly() throws Exception { PipelineConfig twistConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("twist", "dev", "ft"); Pipeline twistPipeline = dbHelper.newPipelineWithAllStagesPassed(twistConfig); List<CaseInsensitiveString> allPipelineNames = goConfigDao.load().getAllPipelineNames(); if (!allPipelineNames.contains(new CaseInsensitiveString("twist"))) { goConfigDao.addPipeline(twistConfig, "pipelinesqlmapdaotest"); } PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev", "ft"); dbHelper.newPipelineWithAllStagesPassed(mingleConfig); Pipeline minglePipeline = dbHelper.newPipelineWithFirstStagePassed(mingleConfig); PipelineInstanceModels pipelineHistories = pipelineDao.loadActivePipelines(); assertThat(pipelineHistories.size(), is(1)); assertThat(pipelineHistories.get(0).getId(), is(twistPipeline.getId())); assertThat(pipelineHistories.get(0).getBuildCause().getMaterialRevisions().isEmpty(), is(false)); if (!allPipelineNames.contains(new CaseInsensitiveString("mingle"))) { goConfigDao.addPipeline(mingleConfig, "pipelinesqlmapdaotest"); } pipelineHistories = pipelineDao.loadActivePipelines(); assertThat(pipelineHistories.size(), is(2)); assertThat(pipelineHistories.get(0).getId(), is(minglePipeline.getId())); assertThat(pipelineHistories.get(1).getId(), is(twistPipeline.getId())); assertThat(pipelineHistories.get(1).getBuildCause().getMaterialRevisions().isEmpty(), is(false)); } @Test public void loadAllActivePipelinesPresentInConfigOnlyShouldBeCaseInsensitive() throws Exception { PipelineConfig twistConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("twist", "dev", "ft"); Pipeline twistPipeline = dbHelper.newPipelineWithAllStagesPassed(twistConfig); List<CaseInsensitiveString> allPipelineNames = goConfigDao.load().getAllPipelineNames(); if (!allPipelineNames.contains(new CaseInsensitiveString("twist"))) { PipelineConfig pipelineConfigWithDifferentCase = PipelineMother.createPipelineConfig("TWIST", twistConfig.materialConfigs(), "dev", "ft"); goConfigDao.addPipeline(pipelineConfigWithDifferentCase, "pipelinesqlmapdaotest"); } PipelineInstanceModels pipelineHistories = pipelineDao.loadActivePipelines(); assertThat(pipelineHistories.size(), is(1)); assertThat(pipelineHistories.get(0).getId(), is(twistPipeline.getId())); assertThat(pipelineHistories.get(0).getBuildCause().getMaterialRevisions().isEmpty(), is(false)); } @Test public void shouldLoadAllActivePipelinesPresentInConfigAndAlsoTheScheduledStagesOfPipelinesNotInConfig() throws Exception { PipelineConfig twistConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("twist", "dev", "ft"); Pipeline twistPipeline = dbHelper.newPipelineWithAllStagesPassed(twistConfig); List<CaseInsensitiveString> allPipelineNames = goConfigDao.load().getAllPipelineNames(); if (!allPipelineNames.contains(new CaseInsensitiveString("twist"))) { goConfigDao.addPipeline(twistConfig, "pipelinesqlmapdaotest"); } PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev", "ft"); if (!allPipelineNames.contains(new CaseInsensitiveString("mingle"))) { goConfigDao.addPipeline(mingleConfig, "pipelinesqlmapdaotest"); } dbHelper.newPipelineWithAllStagesPassed(mingleConfig); Pipeline secondPipeline = dbHelper.newPipelineWithFirstStagePassed(mingleConfig); dbHelper.scheduleStage(secondPipeline, mingleConfig.get(1)); Pipeline thirdPipeline = dbHelper.newPipelineWithFirstStageScheduled(mingleConfig); PipelineInstanceModels pipelineHistories = pipelineDao.loadActivePipelines(); assertThat(pipelineHistories.size(), is(3)); assertThat(pipelineHistories.get(0).getId(), is(thirdPipeline.getId())); assertThat(pipelineHistories.get(1).getId(), is(secondPipeline.getId())); assertThat(pipelineHistories.get(2).getId(), is(twistPipeline.getId())); assertThat(pipelineHistories.get(0).getBuildCause().getMaterialRevisions().isEmpty(), is(false)); } @Test public void shouldLoadAllActivePipelinesEvenWhenThereIsStageStatusChange() throws Exception { PipelineConfig twistConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("twist", "dev", "ft"); goConfigDao.addPipeline(twistConfig, "pipelinesqlmapdaotest"); Pipeline twistPipeline = dbHelper.newPipelineWithAllStagesPassed(twistConfig); PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev", "ft"); goConfigDao.addPipeline(mingleConfig, "pipelinesqlmapdaotest"); final Pipeline firstPipeline = dbHelper.newPipelineWithAllStagesPassed(mingleConfig); final Pipeline secondPipeline = dbHelper.newPipelineWithFirstStagePassed(mingleConfig); dbHelper.scheduleStage(secondPipeline, mingleConfig.get(1)); Pipeline thirdPipeline = dbHelper.newPipelineWithFirstStageScheduled(mingleConfig); Thread stageStatusChanger = new Thread() { @Override public void run() { for (; ; ) { pipelineDao.stageStatusChanged(secondPipeline.findStage("dev")); if (super.isInterrupted()) { break; } } } }; stageStatusChanger.setDaemon(true); stageStatusChanger.start(); PipelineInstanceModels pipelineHistories = pipelineDao.loadActivePipelines(); assertThat(pipelineHistories.size(), is(3)); assertThat(pipelineHistories.get(0).getId(), is(thirdPipeline.getId())); assertThat(pipelineHistories.get(1).getId(), is(secondPipeline.getId())); assertThat(pipelineHistories.get(2).getId(), is(twistPipeline.getId())); assertThat(pipelineHistories.get(0).getBuildCause().getMaterialRevisions().isEmpty(), is(false)); stageStatusChanger.interrupt(); } @Test public void shouldLoadPipelineHistoriesWithMultipleSameStage() throws Exception { String stageName = "dev"; PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", stageName); Pipeline mingle = schedulePipelineWithStages(mingleConfig); Stage newInstance = rescheduleStage(stageName, mingleConfig, mingle); PipelineInstanceModels pipelineHistories = pipelineDao.loadHistory(mingle.getName(), 10, 0); assertThat(pipelineHistories.size(), is(1)); StageInstanceModels stageHistories = pipelineHistories.first().getStageHistory(); assertThat(stageHistories.size(), is(1)); StageInstanceModel history = stageHistories.first(); assertThat(history.getName(), is(stageName)); assertThat(history.getId(), is(newInstance.getId())); assertThat(history.getBuildHistory().size(), is(2)); } private Stage stageOf(Pipeline mingle) { Stages stages = mingle.getStages(); assertThat(stages.size(), is(1)); return stages.get(0); } private void scheduleBuildInstances(Stage scheduledInstance) { JobInstances scheduledBuilds = scheduledInstance.getJobInstances(); JobInstance bi = scheduledBuilds.get(0); bi.schedule(); jobInstanceDao.updateStateAndResult(bi); bi = scheduledBuilds.get(1); bi.completing(JobResult.Passed); bi.completed(new Date()); jobInstanceDao.updateStateAndResult(bi); } @Test public void shouldSaveUserNameAsCausedBy() throws Exception { PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); BuildCause cause = BuildCause.createManualForced(modifyOneFile(pipelineConfig), Username.ANONYMOUS); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, cause, new DefaultSchedulingContext(MOD_USER), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); savePipeline(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); BuildCause buildCause = pipelineFromDB.getBuildCause(); //TODO: This is a known bug #3248 in the way that the pipeline user is stored. We should fix with the new UI. assertThat(buildCause.getBuildCauseMessage(), is("Forced by " + Username.ANONYMOUS.getDisplayName())); } @Test public void shouldReturnCorrectCount() throws Exception { PipelineConfig mingle = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); assertThat(pipelineDao.count(CaseInsensitiveString.str(mingle.name())), is(0)); dbHelper.pass(schedulePipelineWithStages(mingle)); assertThat(pipelineDao.count(CaseInsensitiveString.str(mingle.name())), is(1)); } @Test public void shouldStoreAndRetrieveSvnMaterials() throws SQLException { SvnMaterial svnMaterial = svnMaterial("svnUrl", "folder"); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(new MaterialConfigs(svnMaterial.config())); MaterialRevisions materialRevisions = new MaterialRevisions(); materialRevisions.addRevision(svnMaterial, ModificationsMother.multipleModificationList()); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(materialRevisions, Username.ANONYMOUS), new DefaultSchedulingContext( DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); savePipeline(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); final Materials materials = pipelineFromDB.getMaterials(); assertThat(materials.get(0), is(svnMaterial)); } @Test public void shouldRetrieveModificationsSortedBySavedOrder() throws SQLException { GitMaterial gitMaterial = new GitMaterial("url"); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(new MaterialConfigs(gitMaterial.config())); Modification firstModification = new Modification(new Date(), "1", "MOCK_LABEL-12", null); Modification secondModification = new Modification(new Date(), "2", "MOCK_LABEL-12", null); ArrayList<ModifiedFile> modifiedFiles = new ArrayList<ModifiedFile>() { { add(new ModifiedFile("filename", "foldername", ModifiedAction.modified)); } }; secondModification.setModifiedFiles(modifiedFiles); MaterialRevisions materialRevisions = new MaterialRevisions(); materialRevisions.addRevision(gitMaterial, firstModification, secondModification); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(materialRevisions, Username.ANONYMOUS), new DefaultSchedulingContext( DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); save(pipeline); Pipeline pipelineFromDB = pipelineDao.mostRecentPipeline(pipeline.getName()); List<MaterialRevision> revisionsFromDB = pipelineFromDB.getMaterialRevisions().getRevisions(); List<Modification> modificationsFromDB = revisionsFromDB.get(0).getModifications(); assertThat(modificationsFromDB.size(), is(2)); assertThat(modificationsFromDB.get(0).getRevision(), is("1")); assertThat(modificationsFromDB.get(1).getRevision(), is("2")); } @Test public void shouldStoreAndRetrieveDependencyMaterials() throws SQLException { DependencyMaterial dependencyMaterial = new DependencyMaterial(new CaseInsensitiveString("pipeline-name"), new CaseInsensitiveString("stage-name")); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(new MaterialConfigs(dependencyMaterial.config())); MaterialRevisions materialRevisions = new MaterialRevisions(); materialRevisions.addRevision(DependencyMaterialRevision.create("pipeline-name", -12, "1234", "stage-name", 1).convert(dependencyMaterial, new Date())); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(materialRevisions, Username.ANONYMOUS), new DefaultSchedulingContext( DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); savePipeline(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); final Materials materials = pipelineFromDB.getMaterials(); assertThat(materials.get(0), is(dependencyMaterial)); } @Test public void shouldStoreAndRetrieveDependencyMaterialsWithMaxAllowedRevision() throws SQLException { char[] name = new char[255]; for (int i = 0; i < 255; i++) { name[i] = 'a'; } final String s = new String(name); final String s1 = new String(name); DependencyMaterial dependencyMaterial = new DependencyMaterial(new CaseInsensitiveString(s), new CaseInsensitiveString(s1)); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(new MaterialConfigs(dependencyMaterial.config())); MaterialRevisions materialRevisions = new MaterialRevisions(); DependencyMaterialRevision revision = DependencyMaterialRevision.create(new String(name), -10, new String(name), new String(name), Integer.MAX_VALUE); materialRevisions.addRevision(revision.convert(dependencyMaterial, new Date())); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(materialRevisions, Username.ANONYMOUS), new DefaultSchedulingContext( DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); savePipeline(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); final Materials materials = pipelineFromDB.getMaterials(); assertThat(materials.get(0), is(dependencyMaterial)); } @Test public void shouldStoreAndRetrieveMultipleSvnMaterials() throws SQLException { SvnMaterial svnMaterial1 = svnMaterial("svnUrl1", "folder1"); SvnMaterial svnMaterial2 = svnMaterial("svnUrl2", "folder2"); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(new MaterialConfigs(svnMaterial1.config(), svnMaterial2.config())); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(modifyOneFile(pipelineConfig), Username.ANONYMOUS), new DefaultSchedulingContext( DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); savePipeline(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); Materials materials = pipelineFromDB.getMaterials(); assertThat(materials, hasItem((Material) svnMaterial1)); assertThat(materials, hasItem((Material) svnMaterial2)); } @Test public void shouldStoreAndRetrieveMaterialRevisions() throws SQLException { SvnMaterial svnMaterial1 = svnMaterial("svnUrl1", "folder1"); SvnMaterial svnMaterial2 = svnMaterial("svnUrl2", "folder2"); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(new MaterialConfigs(svnMaterial1.config(), svnMaterial2.config())); MaterialRevisions revisions = new MaterialRevisions(); revisions.addRevision(svnMaterial1, new Modification("user1", "comment1", null, new Date(), "1")); revisions.addRevision(svnMaterial2, new Modification("user2", "comment2", null, new Date(), "2")); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(revisions, Username.ANONYMOUS), new DefaultSchedulingContext(DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); save(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); BuildCause buildCause = pipelineFromDB.getBuildCause(); assertEquals(revisions, buildCause.getMaterialRevisions()); } @Test public void shouldStoreAndRetrieveHgMaterialsFromDatabase() throws SQLException { Materials materials = MaterialsMother.hgMaterials("hgUrl", "hgdir"); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(materials.convertToConfigs()); final MaterialRevisions originalMaterialRevision = multipleModificationsInHg(pipelineConfig); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(originalMaterialRevision, Username.ANONYMOUS), new DefaultSchedulingContext( DEFAULT_APPROVED_BY), md5, new TimeProvider()); save(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); final MaterialRevisions materialRevisions = pipelineFromDB.getBuildCause().getMaterialRevisions(); assertEquals(originalMaterialRevision, materialRevisions); assertThat(materialRevisions.getMaterialRevision(0).getRevision().getRevision(), is("9fdcf27f16eadc362733328dd481d8a2c29915e1")); assertThat(pipelineFromDB.getMaterials(), is(materials)); } @Test public void shouldHaveUrlInGitMaterials() throws SQLException { Materials gitMaterials = MaterialsMother.gitMaterials("gitUrl"); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(gitMaterials.convertToConfigs()); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(modifyOneFile(pipelineConfig), Username.ANONYMOUS), new DefaultSchedulingContext(DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); savePipeline(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); Materials materials = pipelineFromDB.getMaterials(); GitMaterial gitMaterial = (GitMaterial) materials.get(0); assertThat(gitMaterial.getUrl(), is("gitUrl")); } @Test public void shouldSupportBranchInGitMaterials() throws Exception { Materials branchedMaterials = MaterialsMother.gitMaterials("gitUrl", "foo"); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(branchedMaterials.convertToConfigs()); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(modifyOneFile(pipelineConfig), Username.ANONYMOUS), new DefaultSchedulingContext( DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); savePipeline(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); Materials materials = pipelineFromDB.getMaterials(); GitMaterial gitMaterial = (GitMaterial) materials.get(0); assertThat(gitMaterial.getBranch(), is("foo")); } @Test public void shouldSupportSubmoduleFolderInGitMaterials() throws Exception { Materials materials = MaterialsMother.gitMaterials("gitUrl", "submoduleFolder", null); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(materials.convertToConfigs()); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(modifyOneFile(pipelineConfig), Username.ANONYMOUS), new DefaultSchedulingContext(DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); save(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); Materials materialsFromDB = pipelineFromDB.getMaterials(); GitMaterial gitMaterial = (GitMaterial) materialsFromDB.get(0); assertThat(gitMaterial.getSubmoduleFolder(), is("submoduleFolder")); } @Test public void shouldHaveServerAndPortAndViewAndUseTicketsInP4Materials() throws SQLException { String p4view = "//depot/... //localhost/..."; Materials p4Materials = MaterialsMother.p4Materials(p4view); P4Material p4Material = (P4Material) p4Materials.first(); p4Material.setUseTickets(true); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(p4Materials.convertToConfigs()); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(modifyOneFile(pipelineConfig), Username.ANONYMOUS), new DefaultSchedulingContext( DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); savePipeline(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); Materials materials = pipelineFromDB.getMaterials(); assertThat(materials.get(0), is(p4Material)); } @Test public void shouldSupportMultipleP4Materials() throws SQLException { String p4view1 = "//depot1/... //localhost1/..."; String p4view2 = "//depot2/... //localhost2/..."; Material p4Material1 = MaterialsMother.p4Materials(p4view1).get(0); Material p4Material2 = MaterialsMother.p4Materials(p4view2).get(0); Materials materials = new Materials(p4Material1, p4Material2); PipelineConfig pipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("mingle", "dev"); pipelineConfig.setMaterialConfigs(materials.convertToConfigs()); Pipeline pipeline = instanceFactory.createPipelineInstance(pipelineConfig, BuildCause.createManualForced(modifyOneFile(pipelineConfig), Username.ANONYMOUS), new DefaultSchedulingContext( DEFAULT_APPROVED_BY), md5, new TimeProvider()); assertNotInserted(pipeline.getId()); savePipeline(pipeline); Pipeline pipelineFromDB = pipelineDao.loadPipeline(pipeline.getId()); final Materials loaded = pipelineFromDB.getMaterials(); assertThat(loaded.get(0), is(p4Material1)); assertThat(loaded.get(1), is(p4Material2)); } @Test public void shouldFindPipelineByNameAndCounterCaseInsensitively() { Pipeline pipeline = new Pipeline("Test", BuildCause.createWithEmptyModifications()); savePipeline(pipeline); Pipeline loadedId = pipelineDao.findPipelineByNameAndCounter("Test", pipeline.getCounter()); assertThat(loadedId.getId(), is(pipeline.getId())); loadedId = pipelineDao.findPipelineByNameAndCounter("tEsT", pipeline.getCounter()); assertThat(loadedId.getId(), is(pipeline.getId())); } @Test public void shouldFindTheRightPipelineWithUseOfTilde() { Pipeline correctPipeline = new Pipeline("Test", BuildCause.createWithEmptyModifications()); savePipeline(correctPipeline); Pipeline incorrectPipeline = new Pipeline("Tests", BuildCause.createWithEmptyModifications()); savePipeline(incorrectPipeline); Pipeline loadedId = pipelineDao.findPipelineByNameAndCounter(correctPipeline.getName(), correctPipeline.getCounter()); assertThat(loadedId.getId(), is(correctPipeline.getId())); loadedId = pipelineDao.findPipelineByNameAndCounter(correctPipeline.getName().toLowerCase(), correctPipeline.getCounter()); assertThat(loadedId.getId(), is(correctPipeline.getId())); } @Test public void shouldInvalidateSessionAndFetchNewPipelineByNameAndCounter_WhenPipelineIsPersisted() { Pipeline pipeline = new Pipeline("Test", BuildCause.createWithEmptyModifications()); assertThat(pipelineDao.findPipelineByNameAndCounter("Test", 1), is(nullValue())); savePipeline(pipeline); Pipeline loadedPipeline = pipelineDao.findPipelineByNameAndCounter("Test", pipeline.getCounter()); assertThat(pipelineDao.findPipelineByNameAndCounter("Test", 1), is(not(nullValue()))); assertThat(loadedPipeline.getId(), is(pipeline.getId())); } @Test public void shouldInvalidateSessionAndFetchNewPipelineByNameAndLabel_WhenPipelineIsPersisted() { Pipeline pipeline = new Pipeline("Test", BuildCause.createWithEmptyModifications()); assertThat(pipelineDao.findPipelineByNameAndLabel("Test", "1"), is(nullValue())); savePipeline(pipeline); Pipeline loadedPipeline = pipelineDao.findPipelineByNameAndLabel("Test", pipeline.getLabel()); assertThat(loadedPipeline, is(not(nullValue()))); assertThat(loadedPipeline.getId(), is(pipeline.getId())); } @Test public void shouldFindPipelineByNameAndLabel() { Pipeline pipeline = new Pipeline("Test", BuildCause.createWithEmptyModifications()); savePipeline(pipeline); Pipeline loadedId = pipelineDao.findPipelineByNameAndLabel("Test", pipeline.getLabel()); assertThat(loadedId.getId(), is(pipeline.getId())); } @Test public void findPipelineByNameAndLabelShouldReturnLatestWhenLabelRepeated() { Pipeline pipeline = new Pipeline("Test", BuildCause.createWithEmptyModifications()); savePipeline(pipeline); Pipeline newPipeline = dbHelper.save(pipeline); Pipeline loadedId = pipelineDao.findPipelineByNameAndLabel("Test", newPipeline.getLabel()); assertThat(loadedId.getId(), is(newPipeline.getId())); } @Test public void shouldSaveModificationWithChangedAsTrue() throws Exception { Pipeline pipeline = new Pipeline("Test", BuildCause.createWithModifications(revisions(true), "")); save(pipeline); Pipeline loaded = pipelineDao.loadPipeline(pipeline.getId()); assertThat(loaded.getMaterialRevisions().getMaterialRevision(0).isChanged(), is(true)); } @Test public void shouldSaveModificationWithChangedAsFalse() throws Exception { Pipeline pipeline = new Pipeline("Test", BuildCause.createWithModifications(revisions(false), "")); save(pipeline); Pipeline loaded = pipelineDao.loadPipeline(pipeline.getId()); assertThat(loaded.getMaterialRevisions().getMaterialRevision(0).isChanged(), is(false)); } @Test public void shouldSaveAndLoadPipeline() { Pipeline pipeline = new Pipeline("Test", BuildCause.createWithModifications(revisions(false), "")); pipeline.updateCounter(0); save(pipeline); Pipeline loaded = pipelineDao.loadPipeline(pipeline.getId()); assertThat(loaded.getCounter(), is(1)); } @Test public void shouldSaveMixedLabel() { Pipeline pipeline = new Pipeline("Test", "mingle-${COUNT}-${mingle}", BuildCause.createWithModifications(revisions(false), "")); pipeline.updateCounter(0); save(pipeline); Pipeline loaded = pipelineDao.loadPipeline(pipeline.getId()); assertThat(loaded.getLabel(), is("mingle-1-" + ModificationsMother.currentRevision())); } @Test public void shouldSaveAndLoadMaterialsWithName() { BuildCause buildCause = BuildCause.createWithModifications(revisions(false), ""); Pipeline pipeline = new Pipeline("Test", buildCause); save(pipeline); Pipeline loaded = pipelineDao.loadPipeline(pipeline.getId()); assertEquals(buildCause, loaded.getBuildCause()); } @Test public void shouldFindPipelineThatPassedForStage() throws Exception { PipelineConfig config = PipelineMother.createPipelineConfig("pipeline", new MaterialConfigs(MaterialConfigsMother.hgMaterialConfig()), "firstStage", "secondStage"); Pipeline pipeline0 = dbHelper.newPipelineWithAllStagesPassed(config); dbHelper.updateNaturalOrder(pipeline0.getId(), 4.0); Pipeline pipeline1 = dbHelper.newPipelineWithFirstStagePassed(config); Stage stage = dbHelper.scheduleStage(pipeline1, config.get(1)); dbHelper.failStage(stage); stage = dbHelper.scheduleStage(pipeline1, config.get(1)); dbHelper.passStage(stage); dbHelper.updateNaturalOrder(pipeline1.getId(), 5.0); Pipeline pipeline2 = dbHelper.newPipelineWithFirstStagePassed(config); stage = dbHelper.scheduleStage(pipeline2, config.get(1)); dbHelper.failStage(stage); dbHelper.updateNaturalOrder(pipeline2.getId(), 6.0); Pipeline pipeline3 = dbHelper.newPipelineWithFirstStagePassed(config); dbHelper.updateNaturalOrder(pipeline3.getId(), 7.0); Pipeline pipeline4 = dbHelper.newPipelineWithFirstStagePassed(config); stage = dbHelper.scheduleStage(pipeline4, config.get(1)); dbHelper.cancelStage(stage); dbHelper.updateNaturalOrder(pipeline4.getId(), 8.0); Pipeline pipeline5 = dbHelper.newPipelineWithFirstStagePassed(config); dbHelper.scheduleStage(pipeline5, config.get(1)); dbHelper.updateNaturalOrder(pipeline5.getId(), 9.0); Pipeline pipeline6 = dbHelper.newPipelineWithFirstStagePassed(config); stage = dbHelper.scheduleStage(pipeline6, config.get(1)); dbHelper.failStage(stage); dbHelper.updateNaturalOrder(pipeline6.getId(), 10.0); Pipeline pipeline = pipelineDao.findEarlierPipelineThatPassedForStage("pipeline", "secondStage", 10.0); assertThat(pipeline.getId(), is(pipeline1.getId())); assertThat(pipeline.getNaturalOrder(), is(5.0)); } @Test public void shouldFindPipelineThatPassedForStageAcrossStageRerunsHavingPassedStagesOtherThanLatest() throws Exception { PipelineConfig config = PipelineMother.createPipelineConfig("pipeline", new MaterialConfigs(MaterialConfigsMother.hgMaterialConfig()), "firstStage", "secondStage"); Pipeline pipeline0 = dbHelper.newPipelineWithAllStagesPassed(config); dbHelper.updateNaturalOrder(pipeline0.getId(), 4.0); Pipeline pipeline1 = dbHelper.newPipelineWithFirstStagePassed(config); Stage stage = dbHelper.scheduleStage(pipeline1, config.get(1)); dbHelper.failStage(stage); stage = dbHelper.scheduleStage(pipeline1, config.get(1)); dbHelper.passStage(stage); dbHelper.updateNaturalOrder(pipeline1.getId(), 5.0); Pipeline pipeline5 = dbHelper.newPipelineWithAllStagesPassed(config); dbHelper.updateNaturalOrder(pipeline5.getId(), 9.0); Stage failedRerun = StageMother.scheduledStage("pipeline", pipeline5.getCounter(), "secondStage", 2, "job"); failedRerun = stageDao.saveWithJobs(pipeline5, failedRerun); dbHelper.failStage(failedRerun); Pipeline pipeline6 = dbHelper.newPipelineWithFirstStagePassed(config); stage = dbHelper.scheduleStage(pipeline6, config.get(1)); dbHelper.failStage(stage); dbHelper.updateNaturalOrder(pipeline6.getId(), 10.0); Pipeline pipeline = pipelineDao.findEarlierPipelineThatPassedForStage("pipeline", "secondStage", 10.0); assertThat(pipeline.getNaturalOrder(), is(5.0)); assertThat(pipeline.getId(), is(pipeline1.getId())); } @Test public void shouldFindPipelineThatPassedForStageAcrossStageReruns() throws Exception { PipelineConfig config = PipelineMother.createPipelineConfig("pipeline", new MaterialConfigs(MaterialConfigsMother.hgMaterialConfig()), "firstStage", "secondStage"); Pipeline pipeline0 = dbHelper.newPipelineWithAllStagesPassed(config); dbHelper.updateNaturalOrder(pipeline0.getId(), 4.0); Pipeline pipeline1 = dbHelper.newPipelineWithFirstStagePassed(config); Stage stage = dbHelper.scheduleStage(pipeline1, config.get(1)); dbHelper.failStage(stage); stage = dbHelper.scheduleStage(pipeline1, config.get(1)); dbHelper.passStage(stage); dbHelper.updateNaturalOrder(pipeline1.getId(), 5.0); Stage passedStageRerun = StageMother.scheduledStage("pipeline", pipeline1.getCounter(), "secondStage", 2, "job"); passedStageRerun = stageDao.saveWithJobs(pipeline1, passedStageRerun); dbHelper.passStage(passedStageRerun); Pipeline pipeline5 = dbHelper.newPipelineWithFirstStagePassed(config); stage = dbHelper.scheduleStage(pipeline5, config.get(1)); dbHelper.failStage(stage); dbHelper.updateNaturalOrder(pipeline5.getId(), 9.0); Pipeline pipeline6 = dbHelper.newPipelineWithFirstStagePassed(config); stage = dbHelper.scheduleStage(pipeline6, config.get(1)); dbHelper.failStage(stage); dbHelper.updateNaturalOrder(pipeline6.getId(), 10.0); Pipeline pipeline = pipelineDao.findEarlierPipelineThatPassedForStage("pipeline", "secondStage", 10.0); assertThat(pipeline.getId(), is(pipeline1.getId())); assertThat(pipeline.getNaturalOrder(), is(5.0)); } @Test public void shouldReturnTheEarliestFailedPipelineIfThereAreNoPassedStageEver() throws Exception { PipelineConfig config = PipelineMother.createPipelineConfig("pipeline", new MaterialConfigs(MaterialConfigsMother.hgMaterialConfig()), "firstStage", "secondStage"); Pipeline pipeline2 = dbHelper.newPipelineWithFirstStagePassed(config); Stage stage = dbHelper.scheduleStage(pipeline2, config.get(1)); dbHelper.failStage(stage); dbHelper.updateNaturalOrder(pipeline2.getId(), 6.0); Pipeline pipeline3 = dbHelper.newPipelineWithFirstStagePassed(config); dbHelper.updateNaturalOrder(pipeline3.getId(), 7.0); Pipeline pipeline4 = dbHelper.newPipelineWithFirstStagePassed(config); stage = dbHelper.scheduleStage(pipeline4, config.get(1)); dbHelper.cancelStage(stage); dbHelper.updateNaturalOrder(pipeline4.getId(), 8.0); Pipeline pipeline5 = dbHelper.newPipelineWithFirstStagePassed(config); dbHelper.scheduleStage(pipeline5, config.get(1)); dbHelper.updateNaturalOrder(pipeline5.getId(), 9.0); Pipeline pipeline6 = dbHelper.newPipelineWithFirstStagePassed(config); stage = dbHelper.scheduleStage(pipeline6, config.get(1)); dbHelper.failStage(stage); dbHelper.updateNaturalOrder(pipeline6.getId(), 10.0); assertThat(pipelineDao.findEarlierPipelineThatPassedForStage("pipeline", "secondStage", 10.0), is(nullValue())); } @Test public void shouldReturnPageNumberOfThePageInWhichThePIMWouldBePresent() throws Exception { PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("some-pipeline", "dev"); Pipeline pipeline1 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline2 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline3 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline4 = schedulePipelineWithStages(mingleConfig); Pipeline pipeline5 = schedulePipelineWithStages(mingleConfig); assertThat(pipelineDao.getPageNumberForCounter("some-pipeline", pipeline4.getCounter(), 1), is(2)); assertThat(pipelineDao.getPageNumberForCounter("some-pipeline", pipeline5.getCounter(), 1), is(1)); assertThat(pipelineDao.getPageNumberForCounter("some-pipeline", pipeline1.getCounter(), 2), is(3)); assertThat(pipelineDao.getPageNumberForCounter("some-pipeline", pipeline2.getCounter(), 3), is(2)); assertThat(pipelineDao.getPageNumberForCounter("some-pipeline", pipeline3.getCounter(), 10), is(1)); } @Test public void shouldPauseExistingPipeline() throws Exception { PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("some-pipeline", "dev"); schedulePipelineWithStages(mingleConfig); pipelineDao.pause(mingleConfig.name().toString(), "cause", "by"); PipelinePauseInfo actual = pipelineDao.pauseState(mingleConfig.name().toString()); PipelinePauseInfo expected = new PipelinePauseInfo(true, "cause", "by"); assertThat(actual, is(expected)); } @Test public void shouldUnPauseAPausedPipeline() throws Exception { PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("some-pipeline", "dev"); schedulePipelineWithStages(mingleConfig); pipelineDao.pause(mingleConfig.name().toString(), "cause", "by"); pipelineDao.unpause(mingleConfig.name().toString()); PipelinePauseInfo actual = pipelineDao.pauseState(mingleConfig.name().toString()); PipelinePauseInfo expected = new PipelinePauseInfo(false, null, null); assertThat(actual, is(expected)); } @Test public void shouldPauseNewPipeline() throws Exception { PipelineConfig newlyAddedPipelineConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("newly-added-pipeline-config", "dev"); pipelineDao.pause(newlyAddedPipelineConfig.name().toString(), "cause", "by"); PipelinePauseInfo actual = pipelineDao.pauseState(newlyAddedPipelineConfig.name().toString()); PipelinePauseInfo expected = new PipelinePauseInfo(true, "cause", "by"); assertThat(actual, is(expected)); } @Test public void shouldReturnCurrentPauseStateOfPipeline() throws Exception { PipelineConfig mingleConfig = PipelineMother.twoBuildPlansWithResourcesAndMaterials("some-pipeline", "dev"); schedulePipelineWithStages(mingleConfig); PipelinePauseInfo expected = new PipelinePauseInfo(false, null, null); PipelinePauseInfo actual = pipelineDao.pauseState(mingleConfig.name().toString()); assertThat(actual, is(expected)); } @Test public void shouldUpdateCounter_WhenPipelineRowIsPresentWhichWasInsertedByPauseAction() { String pipelineName = "some-pipeline"; PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig(pipelineName); Username userNameAdmin = new Username(new CaseInsensitiveString("admin")); pipelinePauseService.pause(pipelineName, "some-cause", userNameAdmin); // Pause and unpause so that an entry exists for that pipeline pipelinePauseService.unpause(pipelineName); Pipeline pipeline = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); assertThat(pipelineDao.getCounterForPipeline(pipeline.getName()), is(1)); } @Test public void shouldIncrementCounter_WhenPipelineRowIsPresentWhichWasInsertedByPauseAction() throws SQLException { String pipelineName = "some-pipeline"; PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig(pipelineName); Pipeline pipeline = dbHelper.newPipelineWithAllStagesPassed(pipelineConfig); // Counter is 1 dbHelper.newPipelineWithAllStagesPassed(pipelineConfig); // Counter should be incremented assertThat(pipelineDao.getCounterForPipeline(pipeline.getName()), is(pipeline.getCounter() + 1)); } @Test public void shouldInsertCounter_WhenPipelineRowIsNotPresent() { String pipelineName = "some-pipeline"; PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig(pipelineName); Pipeline pipeline = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); assertThat(pipelineDao.getCounterForPipeline(pipeline.getName()), is(1)); } @Test public void shouldReturnStageIdIfAStageOfPipelineIdPassed() throws SQLException { String pipelineName = "some-pipeline"; PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig(pipelineName); Pipeline pipeline = dbHelper.schedulePipelineWithAllStages(pipelineConfig, ModificationsMother.modifySomeFiles(pipelineConfig)); dbHelper.pass(pipeline); String stage = pipelineConfig.get(0).name().toString(); assertThat(pipelineDao.latestPassedStageIdentifier(pipeline.getId(), stage), is(new StageIdentifier(pipelineName, pipeline.getCounter(), pipeline.getLabel(), stage, "1"))); } @Test public void shouldReturnNullStageIdIfStageOfPipelineIdNeverPassed() throws SQLException { String pipelineName = "some-pipeline"; PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig(pipelineName); Pipeline pipeline = dbHelper.schedulePipelineWithAllStages(pipelineConfig, ModificationsMother.modifySomeFiles(pipelineConfig)); dbHelper.failStage(pipeline.getFirstStage()); String stage = pipelineConfig.get(0).name().toString(); assertThat(pipelineDao.latestPassedStageIdentifier(pipeline.getId(), stage), is(StageIdentifier.NULL)); } @Test public void shouldReturnStageIdOfPassedRunIfThereWereMultipleRerunsOfAStageAndOneOfThemPassed() throws SQLException { String pipelineName = "some-pipeline"; PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig(pipelineName); Pipeline pipeline = dbHelper.schedulePipelineWithAllStages(pipelineConfig, ModificationsMother.modifySomeFiles(pipelineConfig)); dbHelper.pass(pipeline); Stage stage = dbHelper.scheduleStage(pipeline, pipelineConfig.getFirstStageConfig()); dbHelper.cancelStage(stage); String stageName = pipelineConfig.get(0).name().toString(); assertThat(pipelineDao.latestPassedStageIdentifier(pipeline.getId(), stageName), is(new StageIdentifier(pipelineName, pipeline.getCounter(), pipeline.getLabel(), stageName, "1"))); } @Test public void shouldReturnLatestPassedStageIdentifierIfMultipleRunsOfTheStageHadPassed() throws SQLException { String pipelineName = "some-pipeline"; PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig(pipelineName); Pipeline pipeline = dbHelper.schedulePipelineWithAllStages(pipelineConfig, ModificationsMother.modifySomeFiles(pipelineConfig)); dbHelper.pass(pipeline); Stage stage = dbHelper.scheduleStage(pipeline, pipelineConfig.getFirstStageConfig()); dbHelper.passStage(stage); stage = dbHelper.scheduleStage(pipeline, pipelineConfig.getFirstStageConfig()); dbHelper.cancelStage(stage); String stageName = stage.getName(); assertThat(pipelineDao.latestPassedStageIdentifier(pipeline.getId(), stageName), is(new StageIdentifier(pipelineName, pipeline.getCounter(), pipeline.getLabel(), stageName, "2"))); } @Test public void shouldReturnPipelineWithBuildCauseForJobId() { String pipelineName = "P1"; PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfigWithStages(pipelineName, "S1"); String username = "username"; BuildCause manualForced = BuildCause.createManualForced(modifyOneFile(pipelineConfig), new Username(new CaseInsensitiveString(username))); Pipeline pipeline = dbHelper.schedulePipeline(pipelineConfig, manualForced, username, new TimeProvider()); dbHelper.pass(pipeline); long jobId = pipeline.getStages().get(0).getJobInstances().get(0).getId(); Pipeline pipelineFromDB = pipelineDao.pipelineWithMaterialsAndModsByBuildId(jobId); assertThat(pipelineFromDB.getBuildCause().getApprover(), Is.is(username)); assertThat(pipelineFromDB.getBuildCause().getBuildCauseMessage(), Is.is("Forced by username")); assertThat(pipelineFromDB.getName(), Is.is(pipelineName)); } @Test public void shouldThrowExceptionWhenBuildCauseIsAskedForANonExistentPipeline() { try { pipelineDao.findBuildCauseOfPipelineByNameAndCounter("foo", 1); fail("should have thrown PipelineNotFoundException"); } catch (Exception e) { assertThat(e instanceof PipelineNotFoundException, is(true)); assertThat(e.getMessage(), is("Pipeline foo with counter 1 was not found")); } } @Test public void shouldThrowExceptionWhenBuildCauseIsAskedForAPipelineWithInvalidCounter() { String pipelineName = "P1"; PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfigWithStages(pipelineName, "S1"); String username = "username"; BuildCause manualForced = BuildCause.createManualForced(modifyOneFile(pipelineConfig), new Username(new CaseInsensitiveString(username))); Pipeline pipeline = dbHelper.schedulePipeline(pipelineConfig, manualForced, username, new TimeProvider()); dbHelper.pass(pipeline); BuildCause buildCause = pipelineDao.findBuildCauseOfPipelineByNameAndCounter(pipelineName, 1); assertThat(buildCause, is(notNullValue())); try { pipelineDao.findBuildCauseOfPipelineByNameAndCounter(pipelineName, 10); fail("should have thrown PipelineNotFoundException"); } catch (Exception e) { assertThat(e instanceof PipelineNotFoundException, is(true)); assertThat(e.getMessage(), is("Pipeline P1 with counter 10 was not found")); } } @Test public void shouldReturnListOfPipelineIdentifiersForDownstreamPipelinesBasedOnARunOfUpstreamPipeline() throws Exception { GitMaterial g1 = u.wf(new GitMaterial("g1"), "folder3"); u.checkinInOrder(g1, "g_1"); ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(g1)); ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("p2", u.m(p1)); String p1_1 = u.runAndPass(p1, "g_1"); String p2_1 = u.runAndPass(p2, p1_1); String p2_2 = u.runAndPass(p2, p1_1); List<PipelineIdentifier> pipelineIdentifiers = pipelineDao.getPipelineInstancesTriggeredWithDependencyMaterial(p2.config.name().toString(), new PipelineIdentifier(p1.config.name().toString(), 1)); assertThat(pipelineIdentifiers, hasSize(2)); assertThat(pipelineIdentifiers, contains(new PipelineIdentifier(p2.config.name().toString(), 2, "2"), new PipelineIdentifier(p2.config.name().toString(), 1, "1"))); } @Test public void shouldReturnEmptyListOfPipelineIdentifiersForUnRunDownstreamPipelinesBasedOnARunOfUpstreamPipeline() throws Exception { GitMaterial g1 = u.wf(new GitMaterial("g1"), "folder3"); u.checkinInOrder(g1, "g_1"); ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(g1)); ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("p2", u.m(p1)); String p1_1 = u.runAndPass(p1, "g_1"); List<PipelineIdentifier> pipelineIdentifiers = pipelineDao.getPipelineInstancesTriggeredWithDependencyMaterial(p2.config.name().toString(), new PipelineIdentifier(p1.config.name().toString(), 1)); assertThat(pipelineIdentifiers, is(Matchers.empty())); } @Test public void shouldReturnListOfPipelineIdentifiersBasedOnAMaterialRevisionCorrectly() throws Exception { GitMaterial g1 = u.wf(new GitMaterial("g1"), "folder3"); u.checkinInOrder(g1, "g_1", "g_2", "g_3"); ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(g1)); String p1_1 = u.runAndPass(p1, "g_2"); String p1_2 = u.runAndPass(p1, "g_3"); String p1_3 = u.runAndPass(p1, "g_2"); MaterialInstance g1Instance = materialRepository.findMaterialInstance(g1); List<PipelineIdentifier> pipelineIdentifiers = pipelineDao.getPipelineInstancesTriggeredWithDependencyMaterial(p1.config.name().toString(), g1Instance, "g_2"); assertThat(pipelineIdentifiers.size(), is(2)); assertThat(pipelineIdentifiers, contains(new PipelineIdentifier(p1.config.name().toString(), 3, "3"), new PipelineIdentifier(p1.config.name().toString(), 1, "1"))); pipelineIdentifiers = pipelineDao.getPipelineInstancesTriggeredWithDependencyMaterial(p1.config.name().toString(), g1Instance, "g_1"); assertThat(pipelineIdentifiers, is(Matchers.empty())); } @Test /* THIS IS A BUG IN VSM. STAGE RERUNS ARE NOT SUPPORTED AND DOWNSTREAMS SHOW THE RUNS MADE OUT OF PREVIOUS STAGE RUN. CHANGE TEST EXPECTATION WHEN BUG IS FIXED POST 13.2 [Mingle #7385] (DUCK & SACHIN) */ public void shouldReturnListOfDownstreamPipelineIdentifiersForARunOfUpstreamPipeline_AlthoughUpstreamHasHadAStageReRun() throws Exception { GitMaterial g1 = u.wf(new GitMaterial("g1"), "folder3"); u.checkinInOrder(g1, "g_1"); ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(g1)); ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("p2", u.m(p1)); Pipeline p1_1_s_1 = u.runAndPassAndReturnPipelineInstance(p1, u.d(0), "g_1"); Pipeline p2_1 = u.runAndPassAndReturnPipelineInstance(p2, u.d(1), p1_1_s_1.getStages().first().stageLocator()); String p1_1_s_2 = u.rerunStageAndCancel(p1_1_s_1, p1.config.get(0)); List<PipelineIdentifier> pipelineIdentifiers = pipelineDao.getPipelineInstancesTriggeredWithDependencyMaterial(p2.config.name().toString(), new PipelineIdentifier(p1.config.name().toString(), 1)); assertThat(pipelineIdentifiers, hasSize(1)); assertThat(pipelineIdentifiers, hasItem(new PipelineIdentifier(p2.config.name().toString(), 1, "1"))); } @Test public void shouldInvalidateCachedPipelineHistoryViaNameAndCounterUponStageChangeCaseInsensitively() throws Exception { GitMaterial g1 = u.wf(new GitMaterial("g1"), "folder3"); u.checkinInOrder(g1, "g_1"); ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", "s1", u.m(g1)); Pipeline p1_1 = dbHelper.schedulePipeline(p1.config, new TestingClock(new Date())); dbHelper.pass(p1_1); PipelineInstanceModel pim1 = pipelineDao.findPipelineHistoryByNameAndCounter(p1.config.name().toUpper().toString(), 1); //prime cache scheduleService.rerunStage(p1_1.getName(), p1_1.getCounter().toString(), p1_1.getStages().get(0).getName()); PipelineInstanceModel pim2 = pipelineDao.findPipelineHistoryByNameAndCounter(p1.config.name().toUpper().toString(), 1); assertThat(pim2, is(not(pim1))); assertThat(pim2.getStageHistory().get(0).getIdentifier().getStageCounter(), is("2")); } public static MaterialRevisions revisions(boolean changed) { MaterialRevisions revisions = new MaterialRevisions(); List<Modification> modifications = new ArrayList<>(); modifications.add(ModificationsMother.oneModifiedFile(ModificationsMother.currentRevision())); SvnMaterial svnMaterial = MaterialsMother.svnMaterial("http://mingle.com"); svnMaterial.setName(new CaseInsensitiveString("mingle")); MaterialRevision materialRevision = new MaterialRevision(svnMaterial, changed, modifications.toArray(new Modification[modifications.size()])); revisions.addRevision(materialRevision); return revisions; } private void assertNotInserted(long instanceId) { assertThat("Already thinks it's inserted", instanceId, is(NOT_PERSISTED)); } private void assertIsInserted(long instanceId) { assertThat("Not inserted", instanceId, is(not(0L))); } private void assertModifications(Pipeline pipeline) { assertThat(pipeline.getBuildCause().getMaterialRevisions().totalNumberOfModifications(), is(1)); } private class ModificationsCollector extends ModificationVisitorAdapter { private List<Modification> mods = new ArrayList<>(); public void visit(Modification modification) { mods.add(modification); } public Modification first() { return mods.get(0); } public int numberOfModifications() { return mods.size(); } } }