/*************************GO-LICENSE-START*********************************
* Copyright 2014 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.
*************************GO-LICENSE-END***********************************/
package com.thoughtworks.go.config;
import java.util.List;
import com.rits.cloning.Cloner;
import com.thoughtworks.go.domain.BaseCollection;
import com.thoughtworks.go.domain.ConfigErrors;
import com.thoughtworks.go.helper.GoConfigMother;
import com.thoughtworks.go.helper.JobConfigMother;
import com.thoughtworks.go.helper.MaterialConfigsMother;
import com.thoughtworks.go.helper.PipelineConfigMother;
import org.junit.Test;
import static java.util.Arrays.asList;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
public class GoConfigParallelGraphWalkerTest {
@Test
public void shouldWalkCruiseConfigObjectsParallelly() {
CruiseConfig cruiseConfig = GoConfigMother.configWithPipelines("bad pipeline name");
CruiseConfig rawCruiseConfig = new Cloner().deepClone(cruiseConfig);
MagicalGoConfigXmlLoader.validate(cruiseConfig);
cruiseConfig.copyErrorsTo(rawCruiseConfig);
assertThat(rawCruiseConfig.pipelineConfigByName(new CaseInsensitiveString("bad pipeline name")).errors(),
is(cruiseConfig.pipelineConfigByName(new CaseInsensitiveString("bad pipeline name")).errors()));
}
@Test
public void shouldHandlePipelinesWithTemplates() {
CruiseConfig cruiseConfig = GoConfigMother.configWithPipelines("pipeline-1");
cruiseConfig.getTemplates().add(
new PipelineTemplateConfig(new CaseInsensitiveString("template-1"), new StageConfig(new CaseInsensitiveString("invalid stage name"), new JobConfigs(new JobConfig("job-1"))
)));
PipelineConfig pipelineWithTemplate = new PipelineConfig(new CaseInsensitiveString("pipeline-with-template"), MaterialConfigsMother.defaultMaterialConfigs());
pipelineWithTemplate.setTemplateName(new CaseInsensitiveString("template-1"));
cruiseConfig.getGroups().get(0).add(pipelineWithTemplate);
CruiseConfig rawCruiseConfig = new Cloner().deepClone(cruiseConfig);
MagicalGoConfigXmlLoader.validate(cruiseConfig);
cruiseConfig.copyErrorsTo(rawCruiseConfig);
assertThat(rawCruiseConfig.pipelineConfigByName(new CaseInsensitiveString("pipeline-with-template")).errors().isEmpty(), is(true));
assertThat(cruiseConfig.pipelineConfigByName(new CaseInsensitiveString("pipeline-with-template")).getStage(new CaseInsensitiveString("invalid stage name")).errors().isEmpty(), is(false));
assertThat(rawCruiseConfig.getTemplateByName(new CaseInsensitiveString("template-1")).errors().isEmpty(), is(true));
}
@Test
public void shouldAddErrorsToRawCruiseConfigWhenTemplateHasErrors() {
CruiseConfig cruiseConfig = GoConfigMother.configWithPipelines("pipeline-1");
cruiseConfig.getTemplates().add(
new PipelineTemplateConfig(new CaseInsensitiveString("invalid template name"), new StageConfig(new CaseInsensitiveString("stage-1"), new JobConfigs(new JobConfig("job-1"))
)));
PipelineConfig pipelineWithTemplate = new PipelineConfig(new CaseInsensitiveString("pipeline-with-template"), MaterialConfigsMother.defaultMaterialConfigs());
pipelineWithTemplate.setTemplateName(new CaseInsensitiveString("invalid template name"));
cruiseConfig.getGroups().get(0).add(pipelineWithTemplate);
CruiseConfig rawCruiseConfig = new Cloner().deepClone(cruiseConfig);
MagicalGoConfigXmlLoader.validate(cruiseConfig);
cruiseConfig.copyErrorsTo(rawCruiseConfig);
ConfigErrors templateErrors = rawCruiseConfig.getTemplateByName(new CaseInsensitiveString("invalid template name")).errors();
assertThat(templateErrors.getAll().size(), is(1));
assertThat(templateErrors.getAll().get(0),
is("Invalid template name 'invalid template name'. 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 shouldNotTryAndCopyErrorsFromAnObjectWithANullField() throws Exception {
AValidatableObjectWithAField badObjectWithNullField = new AValidatableObjectWithAField(null);
badObjectWithNullField.addError("blah", "Bad");
AValidatableObjectWithAField goodObjectWithNonNullField = new AValidatableObjectWithAField(new SomeOtherObject("1"));
BasicCruiseConfig.copyErrors(badObjectWithNullField, goodObjectWithNonNullField);
assertThat(goodObjectWithNonNullField.errors().getAll().size(), is(1));
assertThat(goodObjectWithNonNullField.errors().firstError(), is("Bad"));
}
@Test
public void shouldCopyErrorsToCorrectObjectBasedOnEqualityRatherThanIndex() {
AValidatableObjectWithAList badObjectWith2ObjectsInList = new AValidatableObjectWithAList();
SomeOtherObject soo1 = new SomeOtherObject("1");
soo1.addError("a", "b");
badObjectWith2ObjectsInList.add(soo1);
SomeOtherObject soo2 = new SomeOtherObject("2");
soo2.addError("x", "y");
badObjectWith2ObjectsInList.add(soo2);
AValidatableObjectWithAList goodObjectWith2ObjectsInList = new AValidatableObjectWithAList();
goodObjectWith2ObjectsInList.add(new SomeOtherObject("2"));
BasicCruiseConfig.copyErrors(badObjectWith2ObjectsInList, goodObjectWith2ObjectsInList);
assertThat(goodObjectWith2ObjectsInList.getSomeOtherObjectList().size(), is(1));
assertThat(goodObjectWith2ObjectsInList.getSomeOtherObjectList().get(0).errors().getAll().size(), is(1));
assertThat(goodObjectWith2ObjectsInList.getSomeOtherObjectList().get(0).errors().firstError(), is("y"));
}
@Test
public void shouldCopyErrorsForFieldsOnPipelineConfig(){
PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("pipeline", MaterialConfigsMother.defaultMaterialConfigs(), new JobConfigs(JobConfigMother.createJobConfigWithJobNameAndEmptyResources()));
pipelineConfig.setVariables(new EnvironmentVariablesConfig(asList(new EnvironmentVariableConfig("name", "value"))));
PipelineConfig pipelineWithErrors = new Cloner().deepClone(pipelineConfig);
pipelineWithErrors.getVariables().get(0).addError("name", "error on environment variable");
pipelineWithErrors.first().addError("name", "error on stage");
pipelineWithErrors.first().getJobs().first().addError("name", "error on job");
BasicCruiseConfig.copyErrors(pipelineWithErrors, pipelineConfig);
assertThat(pipelineConfig.getVariables().get(0).errors().on("name"), is("error on environment variable"));
assertThat(pipelineConfig.first().errors().on("name"), is("error on stage"));
assertThat(pipelineConfig.first().getJobs().first().errors().on("name"), is("error on job"));
}
private class AValidatableObjectWithAList implements Validatable {
private ConfigErrors configErrors = new ConfigErrors();
private SomeOtherObjectList someOtherObjectList = new SomeOtherObjectList();
@Override
public void validate(ValidationContext validationContext) {
}
@Override
public ConfigErrors errors() {
return configErrors;
}
@Override
public void addError(String fieldName, String message) {
configErrors.add(fieldName, message);
}
public void add(SomeOtherObject soo) {
someOtherObjectList.add(soo);
}
public List<SomeOtherObject> getSomeOtherObjectList() {
return someOtherObjectList;
}
}
private class SomeOtherObjectList extends BaseCollection<SomeOtherObject> {
}
private class AValidatableObjectWithAField implements Validatable {
private ConfigErrors configErrors = new ConfigErrors();
private SomeOtherObject someOtherObject;
private AValidatableObjectWithAField(SomeOtherObject someOtherObject) {
this.someOtherObject = someOtherObject;
}
@Override
public void validate(ValidationContext validationContext) {
}
@Override
public ConfigErrors errors() {
return configErrors;
}
@Override
public void addError(String fieldName, String message) {
configErrors.add(fieldName, message);
}
}
private class SomeOtherObject implements Validatable {
private ConfigErrors configErrors = new ConfigErrors();
private String id;
private SomeOtherObject(String id) {
this.id = id;
}
@Override
public void validate(ValidationContext validationContext) {
}
@Override
public ConfigErrors errors() {
return configErrors;
}
@Override
public void addError(String fieldName, String message) {
configErrors.add(fieldName, message);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SomeOtherObject that = (SomeOtherObject) o;
if (id != null ? !id.equals(that.id) : that.id != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
}