
org.gradle.integtests.tooling.r48.PhasedBuildActionCrossVersionSpec.groovy Maven / Gradle / Ivy
/*
* Copyright 2018 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.tooling.r48
import org.gradle.integtests.fixtures.executer.OutputScrapingExecutionFailure
import org.gradle.integtests.tooling.fixture.TargetGradleVersion
import org.gradle.integtests.tooling.fixture.ToolingApiSpecification
import org.gradle.integtests.tooling.fixture.ToolingApiVersion
import org.gradle.tooling.BuildActionFailureException
import org.gradle.tooling.BuildException
import org.gradle.tooling.UnsupportedVersionException
import org.gradle.tooling.events.OperationType
import org.gradle.tooling.events.ProgressEvent
import org.gradle.tooling.events.ProgressListener
import java.util.regex.Pattern
@ToolingApiVersion(">=4.8")
class PhasedBuildActionCrossVersionSpec extends ToolingApiSpecification {
def setup() {
buildFile << """
import org.gradle.tooling.provider.model.ParameterizedToolingModelBuilder
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import javax.inject.Inject
task hello {
doLast {
println "hello"
}
}
task bye(dependsOn: hello) {
doLast {
println "bye"
}
}
task defTask {
doLast {
println "default"
}
}
allprojects {
apply plugin: CustomPlugin
defaultTasks 'defTask'
}
class DefaultCustomModel implements Serializable {
private final String value;
DefaultCustomModel(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
interface CustomParameter {
void setTasks(List tasks);
List getTasks();
}
class CustomPlugin implements Plugin {
@Inject
CustomPlugin(ToolingModelBuilderRegistry registry) {
registry.register(new CustomBuilder());
}
public void apply(Project project) {
}
}
class CustomBuilder implements ParameterizedToolingModelBuilder {
boolean canBuild(String modelName) {
return modelName == '${CustomProjectsLoadedModel.name}' || modelName == '${CustomBuildFinishedModel.name}'
}
Class getParameterType() {
return CustomParameter.class;
}
Object buildAll(String modelName, Project project) {
if (modelName == '${CustomProjectsLoadedModel.name}') {
return new DefaultCustomModel('loading');
}
if (modelName == '${CustomBuildFinishedModel.name}') {
return new DefaultCustomModel('build');
}
return null
}
Object buildAll(String modelName, CustomParameter parameter, Project project) {
if (modelName == '${CustomProjectsLoadedModel.name}') {
StartParameter startParameter = project.getGradle().getStartParameter();
Set tasks = new HashSet(startParameter.getTaskNames());
tasks.addAll(parameter.getTasks());
startParameter.setTaskNames(tasks);
return new DefaultCustomModel('loadingWithTasks');
}
return null
}
}
"""
}
@TargetGradleVersion(">=4.8")
def "can run phased action"() {
IntermediateResultHandlerCollector projectsLoadedHandler = new IntermediateResultHandlerCollector()
IntermediateResultHandlerCollector buildFinishedHandler = new IntermediateResultHandlerCollector()
when:
withConnection { connection ->
connection.action().projectsLoaded(new CustomProjectsLoadedAction(null), projectsLoadedHandler)
.buildFinished(new CustomBuildFinishedAction(), buildFinishedHandler)
.build()
.run()
}
then:
projectsLoadedHandler.getResult() == "loading"
buildFinishedHandler.getResult() == "build"
}
@TargetGradleVersion(">=4.8")
def "failures from action are received and future actions not run"() {
def projectsLoadedHandler = new IntermediateResultHandlerCollector()
def buildFinishedHandler = new IntermediateResultHandlerCollector()
when:
withConnection { connection ->
def action = connection.action()
.projectsLoaded(new FailAction(), projectsLoadedHandler)
.buildFinished(new BrokenAction(), buildFinishedHandler)
.build()
collectOutputs(action)
action.run()
}
then:
BuildActionFailureException e = thrown()
e.message == "The supplied phased action failed with an exception."
e.cause instanceof RuntimeException
e.cause.message == "actionFailure"
projectsLoadedHandler.getResult() == null
buildFinishedHandler.getResult() == null
and:
def failure = OutputScrapingExecutionFailure.from(stdout.toString(), stderr.toString())
if (targetDist.toolingApiHasCauseOnPhasedActionFail) {
failure.assertHasDescription('actionFailure')
} else {
failure.assertHasCause('actionFailure')
}
assertHasConfigureFailedLogging()
}
@TargetGradleVersion(">=4.8")
def "actions are not run when configuration fails"() {
def projectsLoadedHandler = new IntermediateResultHandlerCollector()
def buildFinishedHandler = new IntermediateResultHandlerCollector()
given:
buildFile << """
throw new RuntimeException("broken")
"""
when:
withConnection { connection ->
def action = connection.action()
.projectsLoaded(new BrokenAction(), projectsLoadedHandler)
.buildFinished(new BrokenAction(), buildFinishedHandler)
.build()
collectOutputs(action)
action.run()
}
then:
BuildException e = thrown()
e.message.startsWith("Could not run phased build action using")
e.cause.message.contains("A problem occurred evaluating root project")
projectsLoadedHandler.getResult() == null
buildFinishedHandler.getResult() == null
and:
def failure = OutputScrapingExecutionFailure.from(stdout.toString(), stderr.toString())
failure.assertHasDescription("A problem occurred evaluating root project")
assertHasConfigureFailedLogging()
}
@TargetGradleVersion(">=4.8")
def "build finished action does not run when build fails"() {
def projectsLoadedHandler = new IntermediateResultHandlerCollector()
def buildFinishedHandler = new IntermediateResultHandlerCollector()
buildFile << """
task broken {
doLast { throw new RuntimeException("broken") }
}
"""
when:
withConnection { connection ->
def action = connection.action().projectsLoaded(new CustomProjectsLoadedAction(null), projectsLoadedHandler)
.buildFinished(new BrokenAction(), buildFinishedHandler)
.build()
collectOutputs(action)
action.forTasks("broken")
action.run()
}
then:
BuildException e = thrown()
e.message.startsWith("Could not run phased build action using")
e.cause.message.contains("Execution failed for task ':broken'.")
projectsLoadedHandler.getResult() == "loading"
buildFinishedHandler.getResult() == null
and:
def failure = OutputScrapingExecutionFailure.from(stdout.toString(), stderr.toString())
failure.assertHasDescription("Execution failed for task ':broken'.")
assertHasBuildFailedLogging()
}
@TargetGradleVersion(">=4.8")
def "build is interrupted immediately if action fails"() {
IntermediateResultHandlerCollector projectsLoadedHandler = new IntermediateResultHandlerCollector()
def events = ""
when:
withConnection { connection ->
connection.action().projectsLoaded(new FailAction(), projectsLoadedHandler)
.build()
.forTasks(["hello"])
.addProgressListener(new ProgressListener() {
@Override
void statusChanged(ProgressEvent event) {
events += event.getDescriptor().getDisplayName() + "\n"
}
}, OperationType.TASK)
.run()
}
then:
thrown(BuildActionFailureException)
events.empty
}
@TargetGradleVersion(">=4.8")
def "can modify task graph in projects evaluated action"() {
IntermediateResultHandlerCollector projectsLoadedHandler = new IntermediateResultHandlerCollector()
def stdOut = new ByteArrayOutputStream()
when:
withConnection { connection ->
connection.action().projectsLoaded(new CustomProjectsLoadedAction(["hello"]), projectsLoadedHandler)
.build()
.forTasks([])
.setStandardOutput(stdOut)
.run()
}
then:
projectsLoadedHandler.getResult() == "loadingWithTasks"
stdOut.toString().contains("hello")
}
@TargetGradleVersion(">=4.8")
def "can run pre-defined tasks and build finished action is run after tasks are executed"() {
IntermediateResultHandlerCollector buildFinishedHandler = new IntermediateResultHandlerCollector()
def stdOut = new ByteArrayOutputStream()
when:
withConnection { connection ->
connection.action().buildFinished(new CustomBuildFinishedAction(), buildFinishedHandler)
.build()
.forTasks("bye")
.setStandardOutput(stdOut)
.run()
}
then:
Pattern regex = Pattern.compile(".*hello.*bye.*buildFinishedAction.*", Pattern.DOTALL)
assert stdOut.toString().matches(regex)
buildFinishedHandler.getResult() == "build"
stdOut.toString().contains("hello")
stdOut.toString().contains("bye")
}
@TargetGradleVersion(">=4.8")
def "default tasks are not run if no tasks are specified"() {
IntermediateResultHandlerCollector buildFinishedHandler = new IntermediateResultHandlerCollector()
def stdOut = new ByteArrayOutputStream()
when:
withConnection { connection ->
connection.action().buildFinished(new CustomBuildFinishedAction(), buildFinishedHandler)
.build()
.setStandardOutput(stdOut)
.run()
}
then:
buildFinishedHandler.getResult() == "build"
stdOut.toString().contains("buildFinishedAction")
!stdOut.toString().contains("default")
}
@TargetGradleVersion(">=2.6 <4.8")
def "exception when not supported gradle version"() {
def version = targetDist.version.version
IntermediateResultHandlerCollector buildFinishedHandler = new IntermediateResultHandlerCollector()
when:
withConnection { connection ->
connection.action().buildFinished(new CustomBuildFinishedAction(), buildFinishedHandler)
.build()
.run()
}
then:
UnsupportedVersionException e = thrown()
e.message == "The version of Gradle you are using (${version}) does not support the PhasedBuildActionExecuter API. Support for this is available in Gradle 4.8 and all later versions."
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy