/*
* 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 java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.*;
import java.util.regex.Matcher;
import com.thoughtworks.go.config.*;
import com.thoughtworks.go.config.exceptions.PipelineGroupNotFoundException;
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.remote.ConfigRepoConfig;
import com.thoughtworks.go.config.merge.MergePipelineConfigs;
import com.thoughtworks.go.config.remote.FileConfigOrigin;
import com.thoughtworks.go.config.remote.RepoConfigOrigin;
import com.thoughtworks.go.helper.MaterialConfigsMother;
import com.thoughtworks.go.helper.PipelineConfigMother;
import com.thoughtworks.go.util.Pair;
import org.junit.Test;
import static com.thoughtworks.go.helper.PipelineConfigMother.createGroup;
import static com.thoughtworks.go.helper.PipelineConfigMother.createPipelineConfig;
import static java.util.Arrays.asList;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
import static org.hamcrest.core.IsCollectionContaining.hasItems;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
public class PipelineGroupsTest {
@Test
public void shouldOnlySavePipelineToTargetGroup() {
PipelineConfigs defaultGroup = createGroup("defaultGroup", createPipelineConfig("pipeline1", "stage1"));
PipelineConfigs defaultGroup2 = createGroup("defaultGroup2", createPipelineConfig("pipeline2", "stage2"));
PipelineGroups pipelineGroups = new PipelineGroups(defaultGroup, defaultGroup2);
PipelineConfig pipelineConfig = createPipelineConfig("pipeline3", "stage1");
pipelineGroups.addPipeline("defaultGroup", pipelineConfig);
assertThat(defaultGroup, hasItem(pipelineConfig));
assertThat(defaultGroup2, not(hasItem(pipelineConfig)));
assertThat(pipelineGroups.size(), is(2));
}
@Test
public void shouldRemovePipelineFromTheGroup() throws Exception {
PipelineConfig pipelineConfig = createPipelineConfig("pipeline1", "stage1");
PipelineConfigs defaultGroup = createGroup("defaultGroup", pipelineConfig);
PipelineGroups pipelineGroups = new PipelineGroups(defaultGroup);
assertThat(pipelineGroups.size(), is(1));
pipelineGroups.deletePipeline(pipelineConfig);
assertThat(pipelineGroups.size(), is(1));
assertThat(defaultGroup.size(), is(0));
}
@Test
public void shouldSaveNewPipelineGroupOnTheTop() {
PipelineConfigs defaultGroup = createGroup("defaultGroup", createPipelineConfig("pipeline1", "stage1"));
PipelineConfigs defaultGroup2 = createGroup("defaultGroup2", createPipelineConfig("pipeline2", "stage2"));
PipelineGroups pipelineGroups = new PipelineGroups(defaultGroup, defaultGroup2);
PipelineConfig pipelineConfig = createPipelineConfig("pipeline3", "stage1");
pipelineGroups.addPipeline("defaultGroup3", pipelineConfig);
PipelineConfigs group = createGroup("defaultGroup3", pipelineConfig);
assertThat(pipelineGroups.indexOf(group), is(0));
}
@Test
public void validate_shouldMarkDuplicatePipelineGroupNamesAsError() {
PipelineConfigs first = createGroup("first", "pipeline");
PipelineConfigs dup = createGroup("first", "pipeline");
PipelineGroups groups = new PipelineGroups(first, dup);
groups.validate(null);
assertThat(first.errors().on(BasicPipelineConfigs.GROUP), is("Group with name 'first' already exists"));
assertThat(dup.errors().on(BasicPipelineConfigs.GROUP), is("Group with name 'first' already exists"));
}
@Test
public void shouldReturnTrueWhenGroupNameIsEmptyAndDefaultGroupExists() {
PipelineConfig existingPipeline = createPipelineConfig("pipeline1", "stage1");
PipelineConfigs defaultGroup = createGroup("defaultGroup", existingPipeline);
PipelineGroups pipelineGroups = new PipelineGroups(defaultGroup);
PipelineConfig newPipeline = createPipelineConfig("pipeline3", "stage1");
pipelineGroups.addPipeline("", newPipeline);
assertThat(pipelineGroups.size(), is(1));
assertThat(defaultGroup, hasItem(existingPipeline));
assertThat(defaultGroup, hasItem(newPipeline));
}
@Test
public void shouldErrorOutIfDuplicatePipelineIsAdded() {
PipelineConfig pipeline1 = createPipelineConfig("pipeline1", "stage1");
PipelineConfig pipeline2 = createPipelineConfig("pipeline1", "stage1");
PipelineConfig pipeline3 = createPipelineConfig("pipeline1", "stage1");
PipelineConfig pipeline4 = createPipelineConfig("pipeline1", "stage1");
pipeline3.setOrigin(new RepoConfigOrigin(new ConfigRepoConfig(MaterialConfigsMother.gitMaterialConfig(), "plugin"), "rev1"));
pipeline4.setOrigin(new RepoConfigOrigin(new ConfigRepoConfig(MaterialConfigsMother.svnMaterialConfig(), "plugin"), "1"));
PipelineConfigs defaultGroup = createGroup("defaultGroup", pipeline1);
PipelineConfigs anotherGroup = createGroup("anotherGroup", pipeline2);
PipelineConfigs thirdGroup = createGroup("thirdGroup", pipeline3);
PipelineConfigs fourthGroup = createGroup("fourthGroup", pipeline4);
PipelineGroups pipelineGroups = new PipelineGroups(defaultGroup, anotherGroup, thirdGroup, fourthGroup);
pipelineGroups.validate(null);
List<String> expectedSources = asList(pipeline1.getOriginDisplayName(), pipeline2.getOriginDisplayName(), pipeline3.getOriginDisplayName(), pipeline4.getOriginDisplayName());
assertDuplicateNameErrorOnPipeline(pipeline1, expectedSources, 3);
assertDuplicateNameErrorOnPipeline(pipeline2, expectedSources, 3);
assertDuplicateNameErrorOnPipeline(pipeline3, expectedSources, 3);
assertDuplicateNameErrorOnPipeline(pipeline4, expectedSources, 3);
}
private void assertDuplicateNameErrorOnPipeline(PipelineConfig pipeline, List<String> expectedSources, int sourceCount) {
assertThat(pipeline.errors().isEmpty(), is(false));
String errorMessage = pipeline.errors().on(PipelineConfig.NAME);
assertThat(errorMessage, containsString("You have defined multiple pipelines named 'pipeline1'. Pipeline names must be unique. Source(s):"));
Matcher matcher = Pattern.compile("^.*\\[(.*),\\s(.*),\\s(.*)\\].*$").matcher(errorMessage);
assertThat(matcher.matches(), is(true));
assertThat(matcher.groupCount(), is(sourceCount));
List<String> actualSources = new ArrayList<>();
for (int i = 1; i <= matcher.groupCount(); i++) {
actualSources.add(matcher.group(i));
}
assertThat(actualSources.containsAll(expectedSources), is(true));
}
@Test
public void shouldErrorOutIfDuplicatePipelineIsAddedToSameGroup() {
PipelineConfig pipeline1 = createPipelineConfig("pipeline1", "stage1");
PipelineConfig pipeline2 = createPipelineConfig("pipeline1", "stage1");
PipelineConfigs defaultGroup = createGroup("defaultGroup", pipeline1, pipeline2);
PipelineGroups pipelineGroups = new PipelineGroups(defaultGroup);
pipelineGroups.validate(null);
assertThat(pipeline1.errors().isEmpty(), is(false));
assertThat(pipeline1.errors().on(PipelineConfig.NAME), is("You have defined multiple pipelines named 'pipeline1'. Pipeline names must be unique. Source(s): [cruise-config.xml]"));
assertThat(pipeline2.errors().isEmpty(), is(false));
assertThat(pipeline2.errors().on(PipelineConfig.NAME), is("You have defined multiple pipelines named 'pipeline1'. Pipeline names must be unique. Source(s): [cruise-config.xml]"));
}
@Test
public void shouldFindAPipelineGroupByName() {
PipelineConfig pipeline = createPipelineConfig("pipeline1", "stage1");
PipelineConfigs defaultGroup = createGroup("defaultGroup", pipeline);
PipelineGroups pipelineGroups = new PipelineGroups(defaultGroup);
assertThat(pipelineGroups.findGroup("defaultGroup"), is(defaultGroup));
}
@Test(expected = PipelineGroupNotFoundException.class)
public void shouldThrowGroupNotFoundExceptionWhenSearchingForANonExistingGroup() {
PipelineConfig pipeline = createPipelineConfig("pipeline1", "stage1");
PipelineConfigs defaultGroup = createGroup("defaultGroup", pipeline);
PipelineGroups pipelineGroups = new PipelineGroups(defaultGroup);
pipelineGroups.findGroup("NonExistantGroup");
}
@Test
public void shouldGetPackageUsageInPipelines() throws Exception {
PackageMaterialConfig packageOne = new PackageMaterialConfig("package-id-one");
PackageMaterialConfig packageTwo = new PackageMaterialConfig("package-id-two");
final PipelineConfig p1 = PipelineConfigMother.pipelineConfig("pipeline1", new MaterialConfigs(packageOne, packageTwo), new JobConfigs(new JobConfig(new CaseInsensitiveString("jobName"))));
final PipelineConfig p2 = PipelineConfigMother.pipelineConfig("pipeline2", new MaterialConfigs(packageTwo), new JobConfigs(new JobConfig(new CaseInsensitiveString("jobName"))));
PipelineGroups groups = new PipelineGroups();
PipelineConfigs groupOne = new BasicPipelineConfigs(p1);
PipelineConfigs groupTwo = new BasicPipelineConfigs(p2);
groups.addAll(asList(groupOne, groupTwo));
Map<String, List<Pair<PipelineConfig,PipelineConfigs>>> packageToPipelineMap = groups.getPackageUsageInPipelines();
assertThat(packageToPipelineMap.get("package-id-one").size(), is(1));
assertThat(packageToPipelineMap.get("package-id-one"), hasItems(new Pair<>(p1, groupOne)));
assertThat(packageToPipelineMap.get("package-id-two").size(), is(2));
assertThat(packageToPipelineMap.get("package-id-two"), hasItems(new Pair<>(p1, groupOne), new Pair<>(p2, groupTwo)));
}
@Test
public void shouldComputePackageUsageInPipelinesOnlyOnce() throws Exception {
PackageMaterialConfig packageOne = new PackageMaterialConfig("package-id-one");
PackageMaterialConfig packageTwo = new PackageMaterialConfig("package-id-two");
final PipelineConfig p1 = PipelineConfigMother.pipelineConfig("pipeline1", new MaterialConfigs(packageOne, packageTwo), new JobConfigs(new JobConfig(new CaseInsensitiveString("jobName"))));
final PipelineConfig p2 = PipelineConfigMother.pipelineConfig("pipeline2", new MaterialConfigs(packageTwo), new JobConfigs(new JobConfig(new CaseInsensitiveString("jobName"))));
PipelineGroups groups = new PipelineGroups();
groups.addAll(asList(new BasicPipelineConfigs(p1), new BasicPipelineConfigs(p2)));
Map<String, List<Pair<PipelineConfig,PipelineConfigs>>> result1 = groups.getPackageUsageInPipelines();
Map<String, List<Pair<PipelineConfig,PipelineConfigs>>> result2 = groups.getPackageUsageInPipelines();
assertSame(result1, result2);
}
@Test
public void shouldGetPluggableSCMMaterialUsageInPipelines() throws Exception {
PluggableSCMMaterialConfig pluggableSCMMaterialOne = new PluggableSCMMaterialConfig("scm-id-one");
PluggableSCMMaterialConfig pluggableSCMMaterialTwo = new PluggableSCMMaterialConfig("scm-id-two");
final PipelineConfig p1 = PipelineConfigMother.pipelineConfig("pipeline1", new MaterialConfigs(pluggableSCMMaterialOne, pluggableSCMMaterialTwo), new JobConfigs(new JobConfig(new CaseInsensitiveString("jobName"))));
final PipelineConfig p2 = PipelineConfigMother.pipelineConfig("pipeline2", new MaterialConfigs(pluggableSCMMaterialTwo), new JobConfigs(new JobConfig(new CaseInsensitiveString("jobName"))));
PipelineGroups groups = new PipelineGroups();
PipelineConfigs groupOne = new BasicPipelineConfigs(p1);
PipelineConfigs groupTwo = new BasicPipelineConfigs(p2);
groups.addAll(asList(groupOne, groupTwo));
Map<String, List<Pair<PipelineConfig, PipelineConfigs>>> pluggableSCMMaterialUsageInPipelinesOne = groups.getPluggableSCMMaterialUsageInPipelines();
assertThat(pluggableSCMMaterialUsageInPipelinesOne.get("scm-id-one").size(), is(1));
assertThat(pluggableSCMMaterialUsageInPipelinesOne.get("scm-id-one"), hasItems(new Pair<>(p1, groupOne)));
assertThat(pluggableSCMMaterialUsageInPipelinesOne.get("scm-id-two").size(), is(2));
assertThat(pluggableSCMMaterialUsageInPipelinesOne.get("scm-id-two"), hasItems(new Pair<>(p1, groupOne), new Pair<>(p2, groupTwo)));
Map<String, List<Pair<PipelineConfig, PipelineConfigs>>> pluggableSCMMaterialUsageInPipelinesTwo = groups.getPluggableSCMMaterialUsageInPipelines();
assertSame(pluggableSCMMaterialUsageInPipelinesOne, pluggableSCMMaterialUsageInPipelinesTwo);
}
@Test
public void shouldGetLocalPartsWhenOriginIsNull()
{
PipelineConfigs defaultGroup = createGroup("defaultGroup", createPipelineConfig("pipeline1", "stage1"));
PipelineGroups groups = new PipelineGroups(defaultGroup);
assertThat(groups.getLocal().size(), is(1));
assertThat(groups.getLocal().get(0), is(defaultGroup));
}
@Test
public void shouldGetLocalPartsWhenOriginIsFile()
{
PipelineConfigs defaultGroup = createGroup("defaultGroup", createPipelineConfig("pipeline1", "stage1"));
defaultGroup.setOrigins(new FileConfigOrigin());
PipelineGroups groups = new PipelineGroups(defaultGroup);
assertThat(groups.getLocal().size(), is(1));
assertThat(groups.getLocal().get(0), is(defaultGroup));
}
@Test
public void shouldGetLocalPartsWhenOriginIsRepo()
{
PipelineConfigs defaultGroup = createGroup("defaultGroup", createPipelineConfig("pipeline1", "stage1"));
defaultGroup.setOrigins(new RepoConfigOrigin());
PipelineGroups groups = new PipelineGroups(defaultGroup);
assertThat(groups.getLocal().size(), is(0));
assertThat(groups.getLocal().isEmpty(), is(true));
}
@Test
public void shouldGetLocalPartsWhenOriginIsMixed()
{
PipelineConfigs localGroup = createGroup("defaultGroup", createPipelineConfig("pipeline1", "stage1"));
localGroup.setOrigins(new FileConfigOrigin());
PipelineConfigs remoteGroup = createGroup("defaultGroup", createPipelineConfig("pipeline2", "stage1"));
remoteGroup.setOrigins(new RepoConfigOrigin());
MergePipelineConfigs mergePipelineConfigs = new MergePipelineConfigs(localGroup, remoteGroup);
PipelineGroups groups = new PipelineGroups(mergePipelineConfigs);
assertThat(groups.getLocal().size(), is(1));
assertThat(groups.getLocal(), hasItem(localGroup));
}
}