/*
* Copyright 2010 the original author or authors.
*
* 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 org.gradle.integtests.fixtures;
import junit.framework.AssertionFailedError;
import org.gradle.BuildResult;
import org.gradle.GradleLauncher;
import org.gradle.StartParameter;
import org.gradle.api.GradleException;
import org.gradle.api.LocationAwareException;
import org.gradle.api.Task;
import org.gradle.api.execution.TaskExecutionGraph;
import org.gradle.api.execution.TaskExecutionGraphListener;
import org.gradle.api.execution.TaskExecutionListener;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.StandardOutputListener;
import org.gradle.api.tasks.TaskState;
import org.gradle.initialization.CommandLineParser;
import org.gradle.initialization.DefaultCommandLineConverter;
import org.hamcrest.Matcher;
import java.io.File;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.gradle.util.Matchers.containsLine;
import static org.gradle.util.Matchers.hasMessage;
import static org.gradle.util.WrapUtil.toList;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class InProcessGradleExecuter extends AbstractGradleExecuter {
private StartParameter parameter;
public InProcessGradleExecuter(StartParameter parameter) {
this.parameter = parameter;
}
@Override
public GradleExecuter reset() {
super.reset();
parameter = new StartParameter();
return this;
}
public StartParameter getParameter() {
return parameter;
}
@Override
public GradleExecuter inDirectory(File directory) {
parameter.setCurrentDir(directory);
return this;
}
@Override
public InProcessGradleExecuter withSearchUpwards() {
parameter.setSearchUpwards(true);
return this;
}
@Override
public GradleExecuter withTasks(List<String> names) {
parameter.setTaskNames(names);
return this;
}
@Override
public InProcessGradleExecuter withTaskList() {
parameter.setTaskNames(toList("tasks"));
return this;
}
@Override
public InProcessGradleExecuter withDependencyList() {
parameter.setTaskNames(toList("dependencies"));
return this;
}
@Override
public InProcessGradleExecuter usingSettingsFile(File settingsFile) {
parameter.setSettingsFile(settingsFile);
return this;
}
@Override
public GradleExecuter usingInitScript(File initScript) {
parameter.addInitScript(initScript);
return this;
}
@Override
public GradleExecuter usingBuildScript(String script) {
parameter.useEmbeddedBuildFile(script);
return this;
}
@Override
public GradleExecuter withArguments(List<String> args) {
CommandLineParser parser = new CommandLineParser();
DefaultCommandLineConverter converter = new DefaultCommandLineConverter();
converter.configure(parser);
converter.convert(parser.parse(args), parameter);
return this;
}
@Override
public GradleExecuter withUserHomeDir(File userHomeDir) {
parameter.setGradleUserHomeDir(userHomeDir);
return this;
}
@Override
protected ExecutionResult doRun() {
OutputListenerImpl outputListener = new OutputListenerImpl();
OutputListenerImpl errorListener = new OutputListenerImpl();
BuildListenerImpl buildListener = new BuildListenerImpl();
BuildResult result = doRun(outputListener, errorListener, buildListener);
result.rethrowFailure();
return new InProcessExecutionResult(buildListener.executedTasks, buildListener.skippedTasks,
outputListener.toString(), errorListener.toString());
}
@Override
protected ExecutionFailure doRunWithFailure() {
OutputListenerImpl outputListener = new OutputListenerImpl();
OutputListenerImpl errorListener = new OutputListenerImpl();
BuildListenerImpl buildListener = new BuildListenerImpl();
try {
doRun(outputListener, errorListener, buildListener).rethrowFailure();
throw new AssertionFailedError("expected build to fail but it did not.");
} catch (GradleException e) {
return new InProcessExecutionFailure(buildListener.executedTasks, buildListener.skippedTasks,
outputListener.writer.toString(), errorListener.writer.toString(), e);
}
}
private BuildResult doRun(final OutputListenerImpl outputListener, OutputListenerImpl errorListener,
BuildListenerImpl listener) {
assertCanExecute();
if (isQuiet()) {
parameter.setLogLevel(LogLevel.QUIET);
}
GradleLauncher gradleLauncher = GradleLauncher.newInstance(parameter);
gradleLauncher.addListener(listener);
gradleLauncher.addStandardOutputListener(outputListener);
gradleLauncher.addStandardErrorListener(errorListener);
try {
return gradleLauncher.run();
} finally {
System.clearProperty("test.single");
}
}
public void assertCanExecute() {
assertNull(getExecutable());
assertTrue(getEnvironmentVars().isEmpty());
}
public boolean canExecute() {
try {
assertCanExecute();
} catch (AssertionError e) {
return false;
}
return true;
}
private static class BuildListenerImpl implements TaskExecutionGraphListener {
private final List<String> executedTasks = new ArrayList<String>();
private final List<String> skippedTasks = new ArrayList<String>();
public void graphPopulated(TaskExecutionGraph graph) {
List<Task> planned = new ArrayList<Task>(graph.getAllTasks());
graph.addTaskExecutionListener(new TaskListenerImpl(planned, executedTasks, skippedTasks));
}
}
private static class OutputListenerImpl implements StandardOutputListener {
private StringWriter writer = new StringWriter();
@Override
public String toString() {
return writer.toString();
}
public void onOutput(CharSequence output) {
writer.append(output);
}
}
private static class TaskListenerImpl implements TaskExecutionListener {
private final List<Task> planned;
private final List<String> executedTasks;
private final List<String> skippedTasks;
private Task current;
public TaskListenerImpl(List<Task> planned, List<String> executedTasks, List<String> skippedTasks) {
this.planned = planned;
this.executedTasks = executedTasks;
this.skippedTasks = skippedTasks;
}
public void beforeExecute(Task task) {
assertThat(current, nullValue());
assertTrue(planned.contains(task));
current = task;
}
public void afterExecute(Task task, TaskState state) {
assertThat(task, sameInstance(current));
current = null;
executedTasks.add(task.getPath());
if (state.getSkipped()) {
skippedTasks.add(task.getPath());
}
}
}
public static class InProcessExecutionResult extends AbstractExecutionResult {
private final List<String> plannedTasks;
private final List<String> skippedTasks;
private final String output;
private final String error;
public InProcessExecutionResult(List<String> plannedTasks, List<String> skippedTasks, String output,
String error) {
this.plannedTasks = plannedTasks;
this.skippedTasks = skippedTasks;
this.output = output;
this.error = error;
}
public String getOutput() {
return output;
}
public String getError() {
return error;
}
public ExecutionResult assertTasksExecuted(String... taskPaths) {
List<String> expected = Arrays.asList(taskPaths);
assertThat(plannedTasks, equalTo(expected));
return this;
}
public ExecutionResult assertTasksSkipped(String... taskPaths) {
List<String> expected = Arrays.asList(taskPaths);
assertThat(skippedTasks, equalTo(expected));
return this;
}
public ExecutionResult assertTasksNotSkipped(String... taskPaths) {
List<String> expected = Arrays.asList(taskPaths);
List<String> notSkipped = new ArrayList<String>(plannedTasks);
notSkipped.removeAll(skippedTasks);
assertThat(notSkipped, equalTo(expected));
return this;
}
}
private static class InProcessExecutionFailure extends InProcessExecutionResult implements ExecutionFailure {
private final GradleException failure;
public InProcessExecutionFailure(List<String> tasks, List<String> skippedTasks, String output, String error,
GradleException failure) {
super(tasks, skippedTasks, output, error);
this.failure = failure;
}
public ExecutionFailure assertHasLineNumber(int lineNumber) {
assertThat(failure.getMessage(), containsString(String.format(" line: %d", lineNumber)));
return this;
}
public ExecutionFailure assertHasFileName(String filename) {
assertThat(failure.getMessage(), startsWith(String.format("%s", filename)));
return this;
}
public ExecutionFailure assertHasCause(String description) {
assertThatCause(startsWith(description));
return this;
}
public ExecutionFailure assertThatCause(final Matcher<String> matcher) {
if (failure instanceof LocationAwareException) {
LocationAwareException exception = (LocationAwareException) failure;
assertThat(exception.getReportableCauses(), hasItem(hasMessage(matcher)));
} else {
assertThat(failure.getCause(), notNullValue());
assertThat(failure.getCause().getMessage(), matcher);
}
return this;
}
public ExecutionFailure assertHasDescription(String context) {
assertThatDescription(startsWith(context));
return this;
}
public ExecutionFailure assertThatDescription(Matcher<String> matcher) {
assertThat(failure.getMessage(), containsLine(matcher));
return this;
}
}
}