/*
* 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.service.builders;
import java.util.Arrays;
import java.util.List;
import com.thoughtworks.go.config.AntTask;
import com.thoughtworks.go.config.BuildTask;
import com.thoughtworks.go.config.ExecTask;
import com.thoughtworks.go.config.FetchTask;
import com.thoughtworks.go.config.NantTask;
import com.thoughtworks.go.config.RakeTask;
import com.thoughtworks.go.config.pluggabletask.PluggableTask;
import com.thoughtworks.go.domain.BuildLogElement;
import com.thoughtworks.go.domain.builder.Builder;
import com.thoughtworks.go.domain.KillAllChildProcessTask;
import com.thoughtworks.go.domain.NullTask;
import com.thoughtworks.go.domain.Pipeline;
import com.thoughtworks.go.domain.Task;
import com.thoughtworks.go.helper.PipelineMother;
import com.thoughtworks.go.helper.StageMother;
import com.thoughtworks.go.plugin.access.pluggabletask.TaskExtension;
import com.thoughtworks.go.server.service.UpstreamPipelineResolver;
import com.thoughtworks.go.util.command.CruiseControlException;
import com.thoughtworks.go.util.command.EnvironmentVariableContext;
import com.thoughtworks.go.work.DefaultGoPublisher;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(Theories.class)
public class BuilderFactoryTest {
private UpstreamPipelineResolver pipelineResolver;
private BuilderFactory builderFactory;
private static AntTaskBuilder antTaskBuilder = mock(AntTaskBuilder.class);
private static ExecTaskBuilder execTaskBuilder = mock(ExecTaskBuilder.class);
private static NantTaskBuilder nantTaskBuilder = mock(NantTaskBuilder.class);
private static RakeTaskBuilder rakeTaskBuilder = mock(RakeTaskBuilder.class);
private static KillAllChildProcessTaskBuilder killAllChildProcessTaskBuilder = mock(KillAllChildProcessTaskBuilder.class);
private static FetchTaskBuilder fetchTaskBuilder = mock(FetchTaskBuilder.class);
private static NullTaskBuilder nullTaskBuilder = mock(NullTaskBuilder.class);
private static PluggableTaskBuilderCreator pluggableTaskBuilderCreator = mock(PluggableTaskBuilderCreator.class);
@DataPoint public static TaskDataPoint<AntTask> antDataPoint = new TaskDataPoint<>(new AntTask(), antTaskBuilder);
@DataPoint public static TaskDataPoint<ExecTask> execDataPoint = new TaskDataPoint<>(new ExecTask(), execTaskBuilder);
@DataPoint public static TaskDataPoint<NantTask> nantDataPoint = new TaskDataPoint<>(new NantTask(), nantTaskBuilder);
@DataPoint public static TaskDataPoint<RakeTask> rakeDataPoint = new TaskDataPoint<>(new RakeTask(), rakeTaskBuilder);
@DataPoint public static TaskDataPoint<FetchTask> fetchDataPoint = new TaskDataPoint<>(new FetchTask(), fetchTaskBuilder);
@DataPoint public static TaskDataPoint<NullTask> nullDataPoint = new TaskDataPoint<>(new NullTask(), nullTaskBuilder);
@DataPoint public static TaskDataPoint<PluggableTask> pluggableTaskDataPoint = new TaskDataPoint<>(new PluggableTask(), pluggableTaskBuilderCreator);
@DataPoint public static TaskDataPoint<KillAllChildProcessTask> killAllChildProcessTaskTaskDataPoint = new TaskDataPoint<>(new KillAllChildProcessTask(), killAllChildProcessTaskBuilder);
@Before
public void setUp() throws Exception {
pipelineResolver = mock(UpstreamPipelineResolver.class);
builderFactory = new BuilderFactory(antTaskBuilder, execTaskBuilder, nantTaskBuilder, rakeTaskBuilder, pluggableTaskBuilderCreator, killAllChildProcessTaskBuilder, fetchTaskBuilder, nullTaskBuilder);
}
@Theory
public void shouldCreateABuilderUsingTheCorrectTaskBuilderForATask(TaskDataPoint taskDataPoint) throws Exception {
assertBuilderForTask(taskDataPoint.task, taskDataPoint.taskBuilder);
}
@Test
public void shouldFailIfCalledWithSomeRandomTypeOfTask() throws Exception {
Task task = someRandomNonStandardTask();
try {
Pipeline pipeline = PipelineMother.pipeline("pipeline1", StageMother.custom("stage1"));
builderFactory.builderFor(task, pipeline, pipelineResolver);
} catch (RuntimeException e) {
assertThat(e.getMessage(), is("Unexpected type of task: " + task.getClass()));
}
}
@Test
public void shouldCreateABuilderForEachTypeOfTaskWhichExists() throws Exception {
Pipeline pipeline = PipelineMother.pipeline("pipeline1", StageMother.custom("stage1"));
AntTask antTask = new AntTask();
NantTask nantTask = new NantTask();
RakeTask rakeTask = new RakeTask();
PluggableTask pluggableTask = new PluggableTask();
Builder expectedBuilderForAntTask = myFakeBuilder();
Builder expectedBuilderForNantTask = myFakeBuilder();
Builder expectedBuilderForRakeTask = myFakeBuilder();
Builder expectedBuilderForPluggableTask = myFakeBuilder();
when(antTaskBuilder.createBuilder(builderFactory, antTask, pipeline, pipelineResolver)).thenReturn(expectedBuilderForAntTask);
when(nantTaskBuilder.createBuilder(builderFactory, nantTask, pipeline, pipelineResolver)).thenReturn(expectedBuilderForNantTask);
when(rakeTaskBuilder.createBuilder(builderFactory, rakeTask, pipeline, pipelineResolver)).thenReturn(expectedBuilderForRakeTask);
when(pluggableTaskBuilderCreator.createBuilder(builderFactory, pluggableTask, pipeline, pipelineResolver)).thenReturn(expectedBuilderForPluggableTask);
List<Builder> builders = builderFactory.buildersForTasks(pipeline, listOf(antTask, nantTask, rakeTask,pluggableTask), pipelineResolver);
assertThat(builders.size(), is(4));
assertThat(builders.get(0), is(expectedBuilderForAntTask));
assertThat(builders.get(1), is(expectedBuilderForNantTask));
assertThat(builders.get(2), is(expectedBuilderForRakeTask));
assertThat(builders.get(3), is(expectedBuilderForPluggableTask));
}
private void assertBuilderForTask(Task task, TaskBuilder expectedBuilderToBeUsed) {
Pipeline pipeline = PipelineMother.pipeline("pipeline1", StageMother.custom("stage1"));
Builder expectedBuilder = myFakeBuilder();
when(expectedBuilderToBeUsed.createBuilder(builderFactory, task, pipeline, pipelineResolver)).thenReturn(expectedBuilder);
Builder builder = builderFactory.builderFor(task, pipeline, pipelineResolver);
assertThat(builder, is(expectedBuilder));
}
private Builder myFakeBuilder() {
return new Builder(null, null, null) {
@Override
public void build(BuildLogElement buildLogElement, DefaultGoPublisher publisher, EnvironmentVariableContext environmentVariableContext, TaskExtension taskExtension) throws CruiseControlException {
}
public String toString() {
return "A fake builder " + super.toString();
}
};
}
private BuildTask someRandomNonStandardTask() {
return new BuildTask() {
@Override
public String getTaskType() {
return "build";
}
@Override
public String getTypeForDisplay() {
return null;
}
@Override
public String command() {
return null;
}
@Override
public String arguments() {
return null;
}
};
}
private List<Task> listOf(Task... tasks) {
return Arrays.asList(tasks);
}
private static class TaskDataPoint<T extends Task> {
private final T task;
private final TaskBuilder<T> taskBuilder;
public TaskDataPoint(T task, TaskBuilder<T> taskBuilder) {
this.task = task;
this.taskBuilder = taskBuilder;
}
}
}