/* * 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.domain; import com.thoughtworks.go.config.*; import com.thoughtworks.go.config.materials.AbstractMaterialConfig; import com.thoughtworks.go.config.materials.MaterialConfigs; import com.thoughtworks.go.config.materials.PackageMaterialConfig; import com.thoughtworks.go.config.materials.PluggableSCMMaterialConfig; import com.thoughtworks.go.config.materials.dependency.DependencyMaterialConfig; import com.thoughtworks.go.config.materials.git.GitMaterialConfig; import com.thoughtworks.go.config.materials.svn.SvnMaterialConfig; import com.thoughtworks.go.config.remote.ConfigRepoConfig; import com.thoughtworks.go.config.remote.FileConfigOrigin; import com.thoughtworks.go.config.remote.RepoConfigOrigin; import com.thoughtworks.go.domain.label.PipelineLabel; import com.thoughtworks.go.domain.materials.MaterialConfig; import com.thoughtworks.go.helper.MaterialConfigsMother; import com.thoughtworks.go.helper.PipelineConfigMother; import com.thoughtworks.go.helper.StageConfigMother; import com.thoughtworks.go.security.GoCipher; import com.thoughtworks.go.util.Node; import org.bouncycastle.crypto.InvalidCipherTextException; import org.junit.Test; import java.util.*; import static com.thoughtworks.go.util.DataStructureUtils.a; import static com.thoughtworks.go.util.DataStructureUtils.m; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.*; public class PipelineConfigTest { private static final String BUILDING_PLAN_NAME = "building"; EnvironmentVariablesConfig mockEnvironmentVariablesConfig = mock(EnvironmentVariablesConfig.class); ParamsConfig mockParamsConfig = mock(ParamsConfig.class); public enum Foo { Bar, Baz; } @Test public void shouldFindByName() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("pipeline"), null, completedStage(), buildingStage()); assertThat(pipelineConfig.findBy(new CaseInsensitiveString("completed stage")).name(), is(new CaseInsensitiveString("completed stage"))); } @Test public void shouldReturnDuplicateWithoutName() { PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("somePipeline"); PipelineConfig clonedPipelineConfig = pipelineConfig.duplicate(); assertThat(clonedPipelineConfig.name(), is(new CaseInsensitiveString(""))); assertThat(clonedPipelineConfig.materialConfigs(), is(pipelineConfig.materialConfigs())); assertThat(clonedPipelineConfig.getFirstStageConfig(), is(pipelineConfig.getFirstStageConfig())); } @Test public void shouldReturnDuplicateWithPipelineNameEmptyIfFetchArtifactTaskIsFetchingFromSamePipeline() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("somePipeline", "stage", "job"); StageConfig stageConfig = pipelineConfig.get(0); JobConfig jobConfig = stageConfig.getJobs().get(0); Tasks originalTasks = jobConfig.getTasks(); originalTasks.add(new FetchTask(pipelineConfig.name(), stageConfig.name(), jobConfig.name(), "src", "dest")); originalTasks.add(new FetchTask(new CaseInsensitiveString("some_other_pipeline"), stageConfig.name(), jobConfig.name(), "src", "dest")); PipelineConfig clone = pipelineConfig.duplicate(); Tasks clonedTasks = clone.get(0).getJobs().get(0).getTasks(); assertThat(((FetchTask) clonedTasks.get(0)).getTargetPipelineName(), is(new CaseInsensitiveString(""))); assertThat(((FetchTask) clonedTasks.get(1)).getTargetPipelineName(), is(new CaseInsensitiveString("some_other_pipeline"))); assertThat(((FetchTask) originalTasks.get(0)).getTargetPipelineName(), is(pipelineConfig.name())); } @Test //#6821 public void shouldCopyOverAllEnvironmentVariablesWhileCloningAPipeline() throws InvalidCipherTextException { PipelineConfig source = PipelineConfigMother.createPipelineConfig("somePipeline", "stage", "job"); source.addEnvironmentVariable("k1", "v1"); source.addEnvironmentVariable("k2", "v2"); GoCipher goCipher = mock(GoCipher.class); when(goCipher.encrypt("secret")).thenReturn("encrypted"); source.addEnvironmentVariable(new EnvironmentVariableConfig(goCipher, "secret_key", "secret", true)); PipelineConfig cloned = source.duplicate(); EnvironmentVariablesConfig clonedEnvVariables = cloned.getPlainTextVariables(); EnvironmentVariablesConfig sourceEnvVariables = source.getPlainTextVariables(); assertThat(clonedEnvVariables.size(), is(sourceEnvVariables.size())); clonedEnvVariables.getPlainTextVariables().containsAll(sourceEnvVariables.getPlainTextVariables()); assertThat(cloned.getSecureVariables().size(), is(source.getSecureVariables().size())); assertThat(cloned.getSecureVariables().containsAll(source.getSecureVariables()), is(true)); } @Test public void shouldGetStageByName() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("pipeline"), null, completedStage(), buildingStage()); assertThat(pipelineConfig.getStage(new CaseInsensitiveString("COMpleTEd stage")).name(), is(new CaseInsensitiveString("completed stage"))); assertThat(pipelineConfig.getStage(new CaseInsensitiveString("Does-not-exist")), is(nullValue())); } @Test public void shouldReturnFalseIfThereIsNoNextStage() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("pipeline"), null, completedStage(), buildingStage()); assertThat(pipelineConfig.hasNextStage(buildingStage().name()), is(false)); } @Test public void shouldReturnFalseIfThereIsNextStage() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("pipeline"), null, completedStage(), buildingStage()); assertThat(pipelineConfig.hasNextStage(completedStage().name()), is(true)); } @Test public void shouldReturnFalseThePassInStageDoesNotExist() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("pipeline"), null, completedStage(), buildingStage()); assertThat(pipelineConfig.hasNextStage(new CaseInsensitiveString("notExist")), is(false)); } @Test public void shouldReturnTrueIfThereNoStagesDefined() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("pipeline"), null); assertThat(pipelineConfig.hasNextStage(completedStage().name()), is(false)); } @Test public void shouldGetDependenciesAsNode() throws Exception { PipelineConfig pipelineConfig = new PipelineConfig(); pipelineConfig.addMaterialConfig(new DependencyMaterialConfig(new CaseInsensitiveString("framework"), new CaseInsensitiveString("dev"))); pipelineConfig.addMaterialConfig(new DependencyMaterialConfig(new CaseInsensitiveString("middleware"), new CaseInsensitiveString("dev"))); assertThat(pipelineConfig.getDependenciesAsNode(), is(new Node( new Node.DependencyNode(new CaseInsensitiveString("framework"), new CaseInsensitiveString("dev")), new Node.DependencyNode(new CaseInsensitiveString("middleware"), new CaseInsensitiveString("dev"))))); } @Test public void shouldReturnTrueIfFirstStageIsManualApproved() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline", "stage", "build"); pipelineConfig.getFirstStageConfig().updateApproval(Approval.manualApproval()); assertThat("First stage should be manual approved", pipelineConfig.isFirstStageManualApproval(), is(true)); } @Test public void shouldThrowExceptionForEmptyPipeline() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("cruise"), new MaterialConfigs()); try { pipelineConfig.isFirstStageManualApproval(); fail("Should throw exception if pipeline has no pipeline"); } catch (IllegalStateException e) { assertThat(e.getMessage(), containsString("Pipeline [" + pipelineConfig.name() + "] doesn't have any stage")); } } @Test public void shouldThrowExceptionOnAddingTemplatesIfItAlreadyHasStages() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline", "stage", "build"); try { PipelineTemplateConfig template = new PipelineTemplateConfig(); template.add(StageConfigMother.stageConfig("first")); pipelineConfig.setTemplateName(new CaseInsensitiveString("some-template")); fail("Should throw exception because the pipeline has stages already"); } catch (RuntimeException e) { assertThat(e.getMessage(), containsString("Cannot set template 'some-template' on pipeline 'pipeline' because it already has stages defined")); } } @Test public void shouldBombWhenAddingStagesIfItAlreadyHasATemplate() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("mingle"), null); try { pipelineConfig.setTemplateName(new CaseInsensitiveString("some-template")); pipelineConfig.add(StageConfigMother.stageConfig("second")); fail("Should throw exception because pipeline already has a template"); } catch (RuntimeException e) { assertThat(e.getMessage(), containsString("Cannot add stage 'second' to pipeline 'mingle', which already references template 'some-template'.")); } } @Test public void shouldKnowIfATemplateWasApplied() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline", "stage", "build"); assertThat(pipelineConfig.hasTemplateApplied(), is(false)); pipelineConfig.clear(); PipelineTemplateConfig template = new PipelineTemplateConfig(); template.add(StageConfigMother.stageConfig("first")); pipelineConfig.usingTemplate(template); assertThat(pipelineConfig.hasTemplateApplied(), is(true)); } @Test public void shouldGetAllTemplateVariableNames() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("cruise"), new MaterialConfigs()); pipelineConfig.setLabelTemplate("pipeline-${COUNT}-${mymaterial}${hi}"); Set<String> variables = pipelineConfig.getTemplateVariables(); assertThat(variables.contains("COUNT"), is(true)); assertThat(variables.contains("mymaterial"), is(true)); assertThat(variables.contains("hi"), is(true)); } @Test public void shouldValidateCorrectPipelineLabelWithoutAnyMaterial() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("cruise"), new MaterialConfigs(),new StageConfig(new CaseInsensitiveString("first"), new JobConfigs())); pipelineConfig.setLabelTemplate("pipeline-${COUNT}-alpha"); pipelineConfig.validate(null); assertThat(pipelineConfig.errors().isEmpty(), is(true)); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), is(nullValue())); } @Test public void shouldValidateMissingLabel() { PipelineConfig pipelineConfig = createAndValidatePipelineLabel(null); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), is(PipelineConfig.BLANK_LABEL_TEMPLATE_ERROR_MESSAGE)); pipelineConfig = createAndValidatePipelineLabel(""); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), is(PipelineConfig.BLANK_LABEL_TEMPLATE_ERROR_MESSAGE)); } @Test public void shouldValidateCorrectPipelineLabelWithoutTruncationSyntax() { String labelFormat = "pipeline-${COUNT}-${git}-454"; PipelineConfig pipelineConfig = createAndValidatePipelineLabel(labelFormat); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), is(nullValue())); } @Test public void shouldValidatePipelineLabelWithNonExistingMaterial() { String labelFormat = "pipeline-${COUNT}-${NoSuchMaterial}"; PipelineConfig pipelineConfig = createAndValidatePipelineLabel(labelFormat); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), startsWith("You have defined a label template in pipeline")); } @Test public void shouldValidateCorrectPipelineLabelWithTruncationSyntax() { String labelFormat = "pipeline-${COUNT}-${git[:7]}-alpha"; PipelineConfig pipelineConfig = createAndValidatePipelineLabel(labelFormat); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), is(nullValue())); } @Test public void shouldValidatePipelineLabelWithBrokenTruncationSyntax1() { String labelFormat = "pipeline-${COUNT}-${git[:7}-alpha"; PipelineConfig pipelineConfig = createAndValidatePipelineLabel(labelFormat); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), startsWith("Invalid label.")); } @Test public void shouldValidatePipelineLabelWithBrokenTruncationSyntax2() { String labelFormat = "pipeline-${COUNT}-${git[7]}-alpha"; PipelineConfig pipelineConfig = createAndValidatePipelineLabel(labelFormat); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), startsWith("Invalid label.")); } @Test public void shouldValidateIncorrectPipelineLabelWithTruncationSyntax() { String labelFormat = "pipeline-${COUNT}-${noSuch[:7]}-alpha"; PipelineConfig pipelineConfig = createAndValidatePipelineLabel(labelFormat); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), startsWith("You have defined a label template in pipeline")); } @Test public void shouldNotAllowLabelTemplateWithLengthOfZeroInTruncationSyntax() throws Exception { String labelFormat = "pipeline-${COUNT}-${git[:0]}-alpha"; PipelineConfig pipelineConfig = createAndValidatePipelineLabel(labelFormat); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), is(String.format("Length of zero not allowed on label %s defined on pipeline %s.", labelFormat, pipelineConfig.name()))); } @Test public void shouldNotAllowLabelTemplateWithLengthOfZeroInTruncationSyntax2() throws Exception { String labelFormat = "pipeline-${COUNT}-${git[:0]}${one[:00]}-alpha"; PipelineConfig pipelineConfig = createAndValidatePipelineLabel(labelFormat); assertThat(pipelineConfig.errors().on(PipelineConfig.LABEL_TEMPLATE), is(String.format("Length of zero not allowed on label %s defined on pipeline %s.",labelFormat,pipelineConfig.name()))); } @Test public void shouldSupportTruncationSyntax() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("cruise"), new MaterialConfigs()); pipelineConfig.setLabelTemplate("pipeline-${COUNT}-${git[:7]}-alpha"); Set<String> variables = pipelineConfig.getTemplateVariables(); assertThat(variables, contains("COUNT", "git")); assertThat(variables.size(), is(2)); } @Test public void shouldSupportSpecialCharacters() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("cruise"), new MaterialConfigs()); pipelineConfig.setLabelTemplate("pipeline-${COUN_T}-${my-material}${h.i}${**}"); Set<String> variables = pipelineConfig.getTemplateVariables(); assertThat(variables, contains("COUN_T", "my-material", "h.i", "**")); } @Test public void shouldAllowColonInLabelTemplateVariable() throws Exception { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("cruise"), new MaterialConfigs()); pipelineConfig.setLabelTemplate("pipeline-${COUN_T}:${repo:package}"); Set<String> variables = pipelineConfig.getTemplateVariables(); assertThat(variables.contains("repo:package"), is(true)); } @Test public void shouldSetPipelineConfigFromConfigAttributes() { PipelineConfig pipelineConfig = new PipelineConfig(); HashMap mingleConfigMap = new HashMap(); mingleConfigMap.put("mingleconfig", "mingleconfig"); HashMap trackingToolMap = new HashMap(); trackingToolMap.put("trackingtool", "trackingtool"); HashMap timerConfigMap = new HashMap(); String cronSpec = "0 0 11 * * ?"; timerConfigMap.put(TimerConfig.TIMER_SPEC, cronSpec); Map configMap = new HashMap(); configMap.put(PipelineConfig.LABEL_TEMPLATE, "LABEL123-${COUNT}"); configMap.put(PipelineConfig.MINGLE_CONFIG, mingleConfigMap); configMap.put(PipelineConfig.TRACKING_TOOL, trackingToolMap); configMap.put(PipelineConfig.TIMER_CONFIG, timerConfigMap); pipelineConfig.setConfigAttributes(configMap); assertThat(pipelineConfig.getLabelTemplate(), is("LABEL123-${COUNT}")); assertThat(pipelineConfig.getTimer().getTimerSpec(), is(cronSpec)); assertThat(pipelineConfig.getTimer().shouldTriggerOnlyOnChanges(), is(false)); } @Test public void shouldSetPipelineConfigFromConfigAttributesForTimerConfig() { PipelineConfig pipelineConfig = new PipelineConfig(); HashMap timerConfigMap = new HashMap(); String cronSpec = "0 0 11 * * ?"; timerConfigMap.put(TimerConfig.TIMER_SPEC, cronSpec); timerConfigMap.put(TimerConfig.TIMER_ONLY_ON_CHANGES, "1"); Map configMap = new HashMap(); configMap.put(PipelineConfig.LABEL_TEMPLATE, "LABEL123-${COUNT}"); configMap.put(PipelineConfig.TIMER_CONFIG, timerConfigMap); pipelineConfig.setConfigAttributes(configMap); assertThat(pipelineConfig.getLabelTemplate(), is("LABEL123-${COUNT}")); assertThat(pipelineConfig.getTimer().getTimerSpec(), is(cronSpec)); assertThat(pipelineConfig.getTimer().shouldTriggerOnlyOnChanges(), is(true)); } @Test public void shouldSetLabelTemplateToDefaultValueIfBlankIsEnteredWhileSettingConfigAttributes() { PipelineConfig pipelineConfig = new PipelineConfig(); Map configMap = new HashMap(); configMap.put(PipelineConfig.LABEL_TEMPLATE, ""); pipelineConfig.setConfigAttributes(configMap); assertThat(pipelineConfig.getLabelTemplate(), is(PipelineLabel.COUNT_TEMPLATE)); } @Test public void shouldNotSetLockStatusOnPipelineConfigWhenLockIs0() { Map configMap = new HashMap(); configMap.put(PipelineConfig.LOCK, "0"); PipelineConfig pipelineConfig = new PipelineConfig(); pipelineConfig.setConfigAttributes(configMap); assertThat(pipelineConfig.isLock(), is(false)); } @Test public void shouldSetLockStatusOnPipelineConfigWhenLockIs1() { Map configMap = new HashMap(); configMap.put(PipelineConfig.LOCK, "1"); PipelineConfig pipelineConfig = new PipelineConfig(); pipelineConfig.setConfigAttributes(configMap); assertThat(pipelineConfig.isLock(), is(true)); } @Test public void shouldPopulateEnvironmentVariablesFromAttributeMap() { PipelineConfig pipelineConfig = new PipelineConfig(); HashMap map = new HashMap(); HashMap valueHashMap = new HashMap(); valueHashMap.put("name", "FOO"); valueHashMap.put("value", "BAR"); map.put(PipelineConfig.ENVIRONMENT_VARIABLES, valueHashMap); pipelineConfig.setVariables(mockEnvironmentVariablesConfig); pipelineConfig.setConfigAttributes(map); verify(mockEnvironmentVariablesConfig).setConfigAttributes(valueHashMap); } @Test public void shouldPopulateParamsFromAttributeMapWhenConfigurationTypeIsNotSet() { PipelineConfig pipelineConfig = new PipelineConfig(); final HashMap map = new HashMap(); final HashMap valueHashMap = new HashMap(); valueHashMap.put("param-name", "FOO"); valueHashMap.put("param-value", "BAR"); map.put(PipelineConfig.PARAMS, valueHashMap); pipelineConfig.setParams(mockParamsConfig); pipelineConfig.setConfigAttributes(map); verify(mockParamsConfig).setConfigAttributes(valueHashMap); } @Test public void shouldPopulateParamsFromAttributeMapIfConfigurationTypeIsTemplate() { PipelineConfig pipelineConfig = new PipelineConfig(); HashMap map = new HashMap(); HashMap valueHashMap = new HashMap(); valueHashMap.put("param-name", "FOO"); valueHashMap.put("param-value", "BAR"); map.put(PipelineConfig.PARAMS, valueHashMap); map.put(PipelineConfig.CONFIGURATION_TYPE, PipelineConfig.CONFIGURATION_TYPE_TEMPLATE); map.put(PipelineConfig.TEMPLATE_NAME, "template"); pipelineConfig.setParams(mockParamsConfig); pipelineConfig.setConfigAttributes(map); verify(mockParamsConfig).setConfigAttributes(valueHashMap); } @Test public void shouldNotPopulateParamsFromAttributeMapIfConfigurationTypeIsStages() { PipelineConfig pipelineConfig = new PipelineConfig(); HashMap map = new HashMap(); HashMap valueHashMap = new HashMap(); valueHashMap.put("param-name", "FOO"); valueHashMap.put("param-value", "BAR"); map.put(PipelineConfig.PARAMS, valueHashMap); map.put(PipelineConfig.CONFIGURATION_TYPE, PipelineConfig.CONFIGURATION_TYPE_STAGES); pipelineConfig.setParams(mockParamsConfig); pipelineConfig.setConfigAttributes(map); verify(mockParamsConfig, never()).setConfigAttributes(valueHashMap); } @Test public void shouldSetTheCorrectIntegrationType() { PipelineConfig pipelineConfig = new PipelineConfig(); assertThat(pipelineConfig.getIntegrationType(), is(PipelineConfig.INTEGRATION_TYPE_NONE)); pipelineConfig = new PipelineConfig(); pipelineConfig.setTrackingTool(new TrackingTool("link", "regex")); assertThat(pipelineConfig.getIntegrationType(), is(PipelineConfig.INTEGRATION_TYPE_TRACKING_TOOL)); pipelineConfig = new PipelineConfig(); pipelineConfig.setMingleConfig(new MingleConfig("baseUri", "projId")); assertThat(pipelineConfig.getIntegrationType(), is(PipelineConfig.INTEGRATION_TYPE_MINGLE)); } @Test public void shouldSetIntegrationTypeToMingleInCaseAnEmptyMingleConfigIsSubmitted() { PipelineConfig pipelineConfig = new PipelineConfig(); MingleConfig mingleConfig = new MingleConfig(); mingleConfig.addError(MingleConfig.BASE_URL, "some error"); pipelineConfig.setMingleConfig(mingleConfig); String integrationType = pipelineConfig.getIntegrationType(); assertThat(integrationType, is(PipelineConfig.INTEGRATION_TYPE_MINGLE)); } @Test public void shouldPopulateTrackingToolWhenIntegrationTypeIsTrackingToolAndLinkAndRegexAreDefined() { PipelineConfig pipelineConfig = new PipelineConfig(); pipelineConfig.setMingleConfig(new MingleConfig("baseUri", "go")); HashMap map = new HashMap(); HashMap valueHashMap = new HashMap(); valueHashMap.put("link", "GoleyLink"); valueHashMap.put("regex", "GoleyRegex"); map.put(PipelineConfig.TRACKING_TOOL, valueHashMap); map.put(PipelineConfig.INTEGRATION_TYPE, PipelineConfig.INTEGRATION_TYPE_TRACKING_TOOL); pipelineConfig.setConfigAttributes(map); assertThat(pipelineConfig.getTrackingTool(), is(new TrackingTool("GoleyLink", "GoleyRegex"))); assertThat(pipelineConfig.getMingleConfig(), is(new MingleConfig())); assertThat(pipelineConfig.getIntegrationType(), is(PipelineConfig.INTEGRATION_TYPE_TRACKING_TOOL)); } @Test public void shouldPopulateMingleConfigWhenIntegrationTypeIsMingle() { PipelineConfig pipelineConfig = new PipelineConfig(); pipelineConfig.setTrackingTool(new TrackingTool("link", "regex")); Map map = new HashMap(); HashMap valueHashMap = new HashMap(); valueHashMap.put(MingleConfig.BASE_URL, "url"); valueHashMap.put(MingleConfig.PROJECT_IDENTIFIER, "identifier"); valueHashMap.put(MqlCriteria.MQL, "criteria"); valueHashMap.put(MingleConfig.MQL_GROUPING_CONDITIONS, valueHashMap); map.put(PipelineConfig.MINGLE_CONFIG, valueHashMap); map.put(PipelineConfig.INTEGRATION_TYPE, PipelineConfig.INTEGRATION_TYPE_MINGLE); pipelineConfig.setConfigAttributes(map); assertThat(pipelineConfig.getMingleConfig(), is(new MingleConfig("url", "identifier", "criteria"))); assertThat(pipelineConfig.getTrackingTool(), is(nullValue())); assertThat(pipelineConfig.getIntegrationType(), is(PipelineConfig.INTEGRATION_TYPE_MINGLE)); } @Test public void shouldResetMingleConfigWhenIntegrationTypeIsNone() { PipelineConfig pipelineConfig = new PipelineConfig(); pipelineConfig.setMingleConfig(new MingleConfig("baseUri", "go")); Map map = new HashMap(); map.put(PipelineConfig.INTEGRATION_TYPE, PipelineConfig.INTEGRATION_TYPE_NONE); pipelineConfig.setConfigAttributes(map); assertThat(pipelineConfig.getMingleConfig(), is(new MingleConfig())); assertThat(pipelineConfig.getIntegrationType(), is(PipelineConfig.INTEGRATION_TYPE_NONE)); } @Test public void shouldResetTrackingToolWhenIntegrationTypeIsNone() { PipelineConfig pipelineConfig = new PipelineConfig(); pipelineConfig.setTrackingTool(new TrackingTool("link", "regex")); Map map = new HashMap(); map.put(PipelineConfig.INTEGRATION_TYPE, PipelineConfig.INTEGRATION_TYPE_NONE); pipelineConfig.setConfigAttributes(map); assertThat(pipelineConfig.getTrackingTool(), is(nullValue())); assertThat(pipelineConfig.getIntegrationType(), is(PipelineConfig.INTEGRATION_TYPE_NONE)); } @Test public void shouldGetTheCorrectConfigurationType() { PipelineConfig pipelineConfigWithTemplate = PipelineConfigMother.pipelineConfigWithTemplate("pipeline", "template"); assertThat(pipelineConfigWithTemplate.getConfigurationType(), is(PipelineConfig.CONFIGURATION_TYPE_TEMPLATE)); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("pipeline"); assertThat(pipelineConfig.getConfigurationType(), is(PipelineConfig.CONFIGURATION_TYPE_STAGES)); } @Test public void shouldUseTemplateWhenSetConfigAttributesContainsTemplateName() { PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("pipeline"); assertThat(pipelineConfig.hasTemplate(), is(false)); Map map = new HashMap(); map.put(PipelineConfig.CONFIGURATION_TYPE, PipelineConfig.CONFIGURATION_TYPE_TEMPLATE); map.put(PipelineConfig.TEMPLATE_NAME, "foo-template"); pipelineConfig.setConfigAttributes(map); assertThat(pipelineConfig.getConfigurationType(), is(PipelineConfig.CONFIGURATION_TYPE_TEMPLATE)); assertThat(pipelineConfig.getTemplateName(), is(new CaseInsensitiveString("foo-template"))); } @Test public void shouldIncrementIndexBy1OfGivenStage() { StageConfig moveMeStage = StageConfigMother.stageConfig("move-me"); StageConfig dontMoveMeStage = StageConfigMother.stageConfig("dont-move-me"); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("pipeline", moveMeStage, dontMoveMeStage); pipelineConfig.incrementIndex(moveMeStage); assertThat(pipelineConfig.indexOf(moveMeStage), is(1)); assertThat(pipelineConfig.indexOf(dontMoveMeStage), is(0)); } @Test public void shouldDecrementIndexBy1OfGivenStage() { StageConfig moveMeStage = StageConfigMother.stageConfig("move-me"); StageConfig dontMoveMeStage = StageConfigMother.stageConfig("dont-move-me"); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("pipeline", dontMoveMeStage, moveMeStage); pipelineConfig.decrementIndex(moveMeStage); assertThat(pipelineConfig.indexOf(moveMeStage), is(0)); assertThat(pipelineConfig.indexOf(dontMoveMeStage), is(1)); } @Test public void shouldThrowExceptionWhenTheStageIsNotFound() { StageConfig moveMeStage = StageConfigMother.stageConfig("move-me"); StageConfig dontMoveMeStage = StageConfigMother.stageConfig("dont-move-me"); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("pipeline", dontMoveMeStage); try { pipelineConfig.incrementIndex(moveMeStage); fail("Should fail to increment the index of a stage that is not found"); } catch (RuntimeException expected) { assertThat(expected.getMessage(), is("Cannot find the stage 'move-me' in pipeline 'pipeline'")); } try { pipelineConfig.decrementIndex(moveMeStage); fail("Should fail to increment the index of a stage that is not found"); } catch (RuntimeException expected) { assertThat(expected.getMessage(), is("Cannot find the stage 'move-me' in pipeline 'pipeline'")); } } @Test public void shouldReturnListOfStageConfigWhichIsApplicableForFetchArtifact() { PipelineConfig superUpstream = PipelineConfigMother.createPipelineConfigWithStages("superUpstream", "s1", "s2", "s3"); PipelineConfig upstream = PipelineConfigMother.createPipelineConfigWithStages("upstream", "s4", "s5", "s6"); upstream.addMaterialConfig(new DependencyMaterialConfig(superUpstream.name(), new CaseInsensitiveString("s2"))); PipelineConfig downstream = PipelineConfigMother.createPipelineConfigWithStages("downstream", "s7"); downstream.addMaterialConfig(new DependencyMaterialConfig(upstream.name(), new CaseInsensitiveString("s5"))); List<StageConfig> fetchableStages = upstream.validStagesForFetchArtifact(downstream, new CaseInsensitiveString("s7")); assertThat(fetchableStages.size(), is(2)); assertThat(fetchableStages, hasItem(upstream.get(0))); assertThat(fetchableStages, hasItem(upstream.get(1))); } @Test public void shouldReturnStagesBeforeCurrentForSelectedPipeline() { PipelineConfig downstream = PipelineConfigMother.createPipelineConfigWithStages("downstream", "s1", "s2"); List<StageConfig> fetchableStages = downstream.validStagesForFetchArtifact(downstream, new CaseInsensitiveString("s2")); assertThat(fetchableStages.size(), is(1)); assertThat(fetchableStages, hasItem(downstream.get(0))); } @Test public void shouldUpdateNameAndMaterialsOnAttributes() { PipelineConfig pipelineConfig = new PipelineConfig(); HashMap svnMaterialConfigMap = new HashMap(); svnMaterialConfigMap.put(SvnMaterialConfig.URL, "http://url"); svnMaterialConfigMap.put(SvnMaterialConfig.USERNAME, "loser"); svnMaterialConfigMap.put(SvnMaterialConfig.PASSWORD, "passwd"); svnMaterialConfigMap.put(SvnMaterialConfig.CHECK_EXTERNALS, false); HashMap materialConfigsMap = new HashMap(); materialConfigsMap.put(AbstractMaterialConfig.MATERIAL_TYPE, SvnMaterialConfig.TYPE); materialConfigsMap.put(SvnMaterialConfig.TYPE, svnMaterialConfigMap); HashMap attributeMap = new HashMap(); attributeMap.put(PipelineConfig.NAME, "startup"); attributeMap.put(PipelineConfig.MATERIALS, materialConfigsMap); pipelineConfig.setConfigAttributes(attributeMap); assertThat(pipelineConfig.name(), is(new CaseInsensitiveString("startup"))); assertThat(pipelineConfig.materialConfigs().get(0), is(new SvnMaterialConfig("http://url", "loser", "passwd", false))); } @Test public void shouldUpdateStageOnAttributes() { PipelineConfig pipelineConfig = new PipelineConfig(); HashMap stageMap = new HashMap(); List jobList = a(m(JobConfig.NAME, "JobName")); stageMap.put(StageConfig.NAME, "someStage"); stageMap.put(StageConfig.JOBS, jobList); HashMap attributeMap = new HashMap(); attributeMap.put(PipelineConfig.NAME, "startup"); attributeMap.put(PipelineConfig.STAGE, stageMap); pipelineConfig.setConfigAttributes(attributeMap); assertThat(pipelineConfig.name(), is(new CaseInsensitiveString("startup"))); assertThat(pipelineConfig.get(0).name(), is(new CaseInsensitiveString("someStage"))); assertThat(pipelineConfig.get(0).getJobs().first().name(), is(new CaseInsensitiveString("JobName"))); } @Test public void shouldValidatePipelineName() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("foo bar", "stage1", "job1"); pipelineConfig.validate(null); assertThat(pipelineConfig.errors().isEmpty(), is(false)); assertThat(pipelineConfig.errors().on(PipelineConfig.NAME), is("Invalid pipeline name 'foo bar'. This must be alphanumeric and can contain underscores and periods (however, it cannot start with a period). The maximum allowed length is 255 characters.")); } @Test public void shouldRemoveExistingStagesWhileDoingAStageUpdate() { PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("foo"), new MaterialConfigs(), new StageConfig(new CaseInsensitiveString("first"), new JobConfigs()), new StageConfig( new CaseInsensitiveString("second"), new JobConfigs())); HashMap stageMap = new HashMap(); List jobList = a(m(JobConfig.NAME, "JobName")); stageMap.put(StageConfig.NAME, "someStage"); stageMap.put(StageConfig.JOBS, jobList); HashMap attributeMap = new HashMap(); attributeMap.put(PipelineConfig.NAME, "startup"); attributeMap.put(PipelineConfig.STAGE, stageMap); pipelineConfig.setConfigAttributes(attributeMap); assertThat(pipelineConfig.name(), is(new CaseInsensitiveString("startup"))); assertThat(pipelineConfig.size(), is(1)); assertThat(pipelineConfig.get(0).name(), is(new CaseInsensitiveString("someStage"))); assertThat(pipelineConfig.get(0).getJobs().first().name(), is(new CaseInsensitiveString("JobName"))); } @Test public void shouldGetAllFetchTasks() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("foo bar", "stage1", "job1"); FetchTask firstFetch = new FetchTask(); JobConfig firstJob = pipelineConfig.getFirstStageConfig().getJobs().get(0); firstJob.addTask(firstFetch); firstJob.addTask(new AntTask()); JobConfig secondJob = new JobConfig(); secondJob.addTask(new ExecTask()); FetchTask secondFetch = new FetchTask(); secondJob.addTask(secondFetch); pipelineConfig.add(new StageConfig(new CaseInsensitiveString("stage-2"), new JobConfigs(secondJob))); List<FetchTask> fetchTasks = pipelineConfig.getFetchTasks(); assertThat(fetchTasks.size(), is(2)); assertThat(fetchTasks.contains(firstFetch), is(true)); assertThat(fetchTasks.contains(secondFetch), is(true)); } @Test public void shouldGetOnlyPlainTextVariables() throws InvalidCipherTextException { PipelineConfig pipelineConfig = new PipelineConfig(); EnvironmentVariableConfig username = new EnvironmentVariableConfig("username", "ram"); pipelineConfig.addEnvironmentVariable(username); GoCipher goCipher = mock(GoCipher.class); when(goCipher.encrypt("=%HG*^&*&^")).thenReturn("encrypted"); EnvironmentVariableConfig password = new EnvironmentVariableConfig(goCipher, "password", "=%HG*^&*&^", true); pipelineConfig.addEnvironmentVariable(password); EnvironmentVariablesConfig plainTextVariables = pipelineConfig.getPlainTextVariables(); assertThat(plainTextVariables, not(hasItem(password))); assertThat(plainTextVariables, hasItem(username)); } @Test public void shouldGetOnlySecureVariables() throws InvalidCipherTextException { PipelineConfig pipelineConfig = new PipelineConfig(); EnvironmentVariableConfig username = new EnvironmentVariableConfig("username", "ram"); pipelineConfig.addEnvironmentVariable(username); GoCipher goCipher = mock(GoCipher.class); when(goCipher.encrypt("=%HG*^&*&^")).thenReturn("encrypted"); EnvironmentVariableConfig password = new EnvironmentVariableConfig(goCipher, "password", "=%HG*^&*&^", true); pipelineConfig.addEnvironmentVariable(password); List<EnvironmentVariableConfig> plainTextVariables = pipelineConfig.getSecureVariables(); assertThat(plainTextVariables, hasItem(password)); assertThat(plainTextVariables, not(hasItem(username))); } @Test public void shouldTemplatizeAPipeline() { PipelineConfig config = PipelineConfigMother.createPipelineConfigWithStages("pipeline", "stage1", "stage2"); config.templatize(new CaseInsensitiveString("template")); assertThat(config.hasTemplate(), is(true)); assertThat(config.hasTemplateApplied(), is(false)); assertThat(config.getTemplateName(), is(new CaseInsensitiveString("template"))); assertThat(config.isEmpty(), is(true)); config.templatize(new CaseInsensitiveString("")); assertThat(config.hasTemplate(), is(false)); config.templatize(null); assertThat(config.hasTemplate(), is(false)); } @Test public void shouldAssignApprovalTypeOnFirstStageAsAuto() throws Exception { Map approvalAttributes = Collections.singletonMap(Approval.TYPE, Approval.SUCCESS); Map<String, Map> map = Collections.singletonMap(StageConfig.APPROVAL, approvalAttributes); PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("p1", "s1", "j1"); pipelineConfig.get(0).updateApproval(Approval.manualApproval()); pipelineConfig.setConfigAttributes(map); assertThat(pipelineConfig.get(0).getApproval().getType(), is(Approval.SUCCESS)); } @Test public void shouldAssignApprovalTypeOnFirstStageAsManual() throws Exception { Map approvalAttributes = Collections.singletonMap(Approval.TYPE, Approval.MANUAL); Map<String, Map> map = Collections.singletonMap(StageConfig.APPROVAL, approvalAttributes); PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("p1", "s1", "j1"); pipelineConfig.get(0).updateApproval(Approval.manualApproval()); pipelineConfig.setConfigAttributes(map); assertThat(pipelineConfig.get(0).getApproval().getType(), is(Approval.MANUAL)); } @Test public void shouldAssignApprovalTypeOnFirstStageAsManualAndRestOfStagesAsUntouched() throws Exception { Map approvalAttributes = Collections.singletonMap(Approval.TYPE, Approval.MANUAL); Map<String, Map> map = Collections.singletonMap(StageConfig.APPROVAL, approvalAttributes); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("p1", StageConfigMother.custom("s1", Approval.automaticApproval()), StageConfigMother.custom("s2", Approval.automaticApproval())); pipelineConfig.setConfigAttributes(map); assertThat(pipelineConfig.get(0).getApproval().getType(), is(Approval.MANUAL)); assertThat(pipelineConfig.get(1).getApproval().getType(), is(Approval.SUCCESS)); } @Test public void shouldGetPackageMaterialConfigs() throws Exception { SvnMaterialConfig svn = new SvnMaterialConfig("svn", false); PackageMaterialConfig packageMaterialOne = new PackageMaterialConfig(); PackageMaterialConfig packageMaterialTwo = new PackageMaterialConfig(); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("p1", new MaterialConfigs(svn, packageMaterialOne, packageMaterialTwo)); List<PackageMaterialConfig> packageMaterialConfigs = pipelineConfig.packageMaterialConfigs(); assertThat(packageMaterialConfigs.size(), is(2)); assertThat(packageMaterialConfigs, hasItems(packageMaterialOne, packageMaterialTwo)); } @Test public void shouldGetPluggableSCMMaterialConfigs() throws Exception { SvnMaterialConfig svn = new SvnMaterialConfig("svn", false); PluggableSCMMaterialConfig pluggableSCMMaterialOne = new PluggableSCMMaterialConfig("scm-id-1"); PluggableSCMMaterialConfig pluggableSCMMaterialTwo = new PluggableSCMMaterialConfig("scm-id-2"); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("p1", new MaterialConfigs(svn, pluggableSCMMaterialOne, pluggableSCMMaterialTwo)); List<PluggableSCMMaterialConfig> pluggableSCMMaterialConfigs = pipelineConfig.pluggableSCMMaterialConfigs(); assertThat(pluggableSCMMaterialConfigs.size(), is(2)); assertThat(pluggableSCMMaterialConfigs, hasItems(pluggableSCMMaterialOne, pluggableSCMMaterialTwo)); } @Test public void shouldReturnTrueWhenOneOfPipelineMaterialsIsTheSameAsConfigOrigin() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline", "stage", "build"); MaterialConfig material = pipelineConfig.materialConfigs().first(); pipelineConfig.setOrigin(new RepoConfigOrigin(new ConfigRepoConfig(material, "plugin"), "1233")); assertThat(pipelineConfig.isConfigOriginSameAsOneOfMaterials(),is(true)); } @Test public void shouldReturnTrueWhenOneOfPipelineMaterialsIsTheSameAsConfigOriginButDestinationIsDifferent() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline", "stage", "build"); pipelineConfig.materialConfigs().clear(); GitMaterialConfig pipeMaterialConfig = new GitMaterialConfig("http://git"); pipeMaterialConfig.setFolder("dest1"); pipelineConfig.materialConfigs().add(pipeMaterialConfig); GitMaterialConfig repoMaterialConfig = new GitMaterialConfig("http://git"); pipelineConfig.setOrigin(new RepoConfigOrigin(new ConfigRepoConfig(repoMaterialConfig,"plugin"),"1233")); assertThat(pipelineConfig.isConfigOriginSameAsOneOfMaterials(),is(true)); } @Test public void shouldReturnFalseWhenOneOfPipelineMaterialsIsNotTheSameAsConfigOrigin() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline", "stage", "build"); MaterialConfig material = new GitMaterialConfig("http://git"); pipelineConfig.setOrigin(new RepoConfigOrigin(new ConfigRepoConfig(material, "plugin"), "1233")); assertThat(pipelineConfig.isConfigOriginSameAsOneOfMaterials(),is(false)); } @Test public void shouldReturnFalseIfOneOfPipelineMaterialsIsTheSameAsConfigOrigin_WhenOriginIsFile() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline", "stage", "build"); pipelineConfig.setOrigin(new FileConfigOrigin()); assertThat(pipelineConfig.isConfigOriginSameAsOneOfMaterials(),is(false)); } @Test public void shouldReturnTrueWhenConfigRevisionIsEqualToQuery() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline", "stage", "build"); MaterialConfig material = pipelineConfig.materialConfigs().first(); pipelineConfig.setOrigin(new RepoConfigOrigin(new ConfigRepoConfig(material, "plugin"), "1233")); assertThat(pipelineConfig.isConfigOriginFromRevision("1233"),is(true)); } @Test public void shouldReturnFalseWhenConfigRevisionIsNotEqualToQuery() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline", "stage", "build"); MaterialConfig material = pipelineConfig.materialConfigs().first(); pipelineConfig.setOrigin(new RepoConfigOrigin(new ConfigRepoConfig(material, "plugin"), "1233")); assertThat(pipelineConfig.isConfigOriginFromRevision("32"),is(false)); } @Test public void shouldReturnConfigRepoOriginDisplayNameWhenOriginIsRemote() { PipelineConfig pipelineConfig = new PipelineConfig(); pipelineConfig.setOrigin(new RepoConfigOrigin(new ConfigRepoConfig(MaterialConfigsMother.gitMaterialConfig(), "plugin"), "revision1")); assertThat(pipelineConfig.getOriginDisplayName(), is("AwesomeGitMaterial at revision1")); } @Test public void shouldReturnConfigRepoOriginDisplayNameWhenOriginIsFile() { PipelineConfig pipelineConfig = new PipelineConfig(); pipelineConfig.setOrigin(new FileConfigOrigin()); assertThat(pipelineConfig.getOriginDisplayName(), is("cruise-config.xml")); } @Test public void shouldReturnConfigRepoOriginDisplayNameWhenOriginIsNotSet() { PipelineConfig pipelineConfig = new PipelineConfig(); assertThat(pipelineConfig.getOriginDisplayName(), is("cruise-config.xml")); } private StageConfig completedStage() { JobConfigs plans = new JobConfigs(); plans.add(new JobConfig("completed")); return new StageConfig(new CaseInsensitiveString("completed stage"), plans); } private StageConfig buildingStage() { JobConfigs plans = new JobConfigs(); plans.add(new JobConfig(BUILDING_PLAN_NAME)); return new StageConfig(new CaseInsensitiveString("building stage"), plans); } private PipelineConfig createAndValidatePipelineLabel(String labelFormat) { GitMaterialConfig git = new GitMaterialConfig("git@github.com:gocd/gocd.git"); git.setName(new CaseInsensitiveString("git")); PipelineConfig pipelineConfig = new PipelineConfig(new CaseInsensitiveString("cruise"), new MaterialConfigs(git)); pipelineConfig.setLabelTemplate(labelFormat); pipelineConfig.validate(null); return pipelineConfig; } }