org.gradle.internal.build.DefaultBuildLifecycleControllerTest.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2021 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.internal.build
import org.gradle.BuildListener
import org.gradle.api.internal.GradleInternal
import org.gradle.api.internal.SettingsInternal
import org.gradle.execution.BuildWorkExecutor
import org.gradle.execution.plan.ExecutionPlan
import org.gradle.execution.taskgraph.TaskExecutionGraphInternal
import org.gradle.initialization.exception.ExceptionAnalyser
import org.gradle.initialization.internal.InternalBuildFinishedListener
import org.gradle.internal.execution.BuildOutputCleanupRegistry
import org.gradle.internal.service.DefaultServiceRegistry
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.util.TestUtil
import spock.lang.Specification
import java.util.function.Consumer
import java.util.function.Function
class DefaultBuildLifecycleControllerTest extends Specification {
def buildBroadcaster = Mock(BuildListener)
def workExecutor = Mock(BuildWorkExecutor)
def workPreparer = Mock(BuildWorkPreparer)
def settingsMock = Mock(SettingsInternal.class)
def gradleMock = Mock(GradleInternal.class)
def buildModelController = Mock(BuildModelController)
def exceptionAnalyser = Mock(ExceptionAnalyser)
def buildFinishedListener = Mock(InternalBuildFinishedListener.class)
def executionPlan = Mock(ExecutionPlan)
def toolingControllerFactory = Mock(BuildToolingModelControllerFactory)
public TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider(getClass())
def failure = new RuntimeException("main")
def transformedException = new RuntimeException("transformed")
def setup() {
_ * exceptionAnalyser.transform(failure) >> transformedException
def taskGraph = Stub(TaskExecutionGraphInternal)
_ * gradleMock.taskGraph >> taskGraph
def services = new DefaultServiceRegistry()
services.add(Stub(BuildOutputCleanupRegistry))
_ * gradleMock.services >> services
_ * gradleMock.owner >> Stub(BuildState)
}
DefaultBuildLifecycleController controller() {
return new DefaultBuildLifecycleController(gradleMock, buildModelController, exceptionAnalyser, buildBroadcaster,
buildFinishedListener, workPreparer, workExecutor, toolingControllerFactory, TestUtil.stateTransitionControllerFactory())
}
void testCanFinishBuildWhenNothingHasBeenDone() {
def controller = controller()
expect:
expectBuildFinished("Configure")
def finishResult = controller.finishBuild(null)
finishResult.failures.empty
}
void testScheduleAndRunRequestedTasks() {
expect:
expectRequestedTasksScheduled()
expectTasksRun()
expectBuildFinished()
def controller = controller()
controller.prepareToScheduleTasks()
def plan = controller.newWorkGraph()
controller.populateWorkGraph(plan) { b -> b.addRequestedTasks() }
controller.finalizeWorkGraph(plan)
def executionResult = controller.executeTasks(plan)
executionResult.failures.empty
def finishResult = controller.finishBuild(null)
finishResult.failures.empty
}
void testScheduleAndRunRequestedTasksMultipleTimes() {
expect:
expectRequestedTasksScheduled()
expectTasksRun()
expectTasksScheduled()
expectTasksRun()
expectBuildFinished()
def controller = controller()
controller.prepareToScheduleTasks()
def plan1 = controller.newWorkGraph()
controller.populateWorkGraph(plan1) { b -> b.addRequestedTasks() }
controller.finalizeWorkGraph(plan1)
def executionResult = controller.executeTasks(plan1)
executionResult.failures.empty
controller.prepareToScheduleTasks()
def plan2 = controller.newWorkGraph()
controller.populateWorkGraph(plan2) {}
controller.finalizeWorkGraph(plan2)
def executionResult2 = controller.executeTasks(plan2)
executionResult2.failures.empty
def finishResult = controller.finishBuild(null)
finishResult.failures.empty
}
void testLoadSettings() {
expect:
expectSettingsBuilt()
expectBuildFinished("Configure")
def controller = controller()
controller.loadSettings()
def finishResult = controller.finishBuild(null)
finishResult.failures.empty
}
void testWithSettings() {
def action = Mock(Function)
when:
expectSettingsBuilt()
def controller = controller()
def result = controller.withSettings(action)
then:
result == "result"
and:
1 * action.apply(settingsMock) >> "result"
expect:
expectBuildFinished("Configure")
def finishResult = controller.finishBuild(null)
finishResult.failures.empty
}
void testNotifiesListenerOnLoadSettingsFailure() {
def failure = new RuntimeException()
when:
expectSettingsBuiltWithFailure(failure)
def controller = this.controller()
controller.loadSettings()
then:
def t = thrown RuntimeException
t == failure
when:
def finishResult = controller.finishBuild(null)
then:
1 * exceptionAnalyser.transform([failure]) >> transformedException
1 * buildBroadcaster.buildFinished({ it.failure == transformedException })
finishResult.failures.empty
}
void testLoadSettingsRethrowsPreviousFailure() {
def failure = new RuntimeException()
when:
expectSettingsBuiltWithFailure(failure)
def controller = this.controller()
controller.loadSettings()
then:
def t = thrown RuntimeException
t == failure
when:
controller.loadSettings()
then:
def t2 = thrown RuntimeException
t2 == failure
when:
controller.configureProjects()
then:
def t3 = thrown RuntimeException
t3 == failure
}
void testConfigureBuild() {
def controller = controller()
when:
controller.configureProjects()
then:
1 * buildModelController.configuredModel >> gradleMock
expect:
expectBuildFinished("Configure")
def finishResult = controller.finishBuild(null)
finishResult.failures.empty
}
void testWithConfiguredBuild() {
def action = Mock(Function)
def controller = controller()
when:
controller.withProjectsConfigured(action)
then:
1 * buildModelController.configuredModel >> gradleMock
1 * action.apply(gradleMock)
expect:
expectBuildFinished("Configure")
def finishResult = controller.finishBuild(null)
finishResult.failures.empty
}
void testGetConfiguredBuild() {
when:
1 * buildModelController.configuredModel >> gradleMock
def controller = controller()
def result = controller.getConfiguredBuild()
then:
result == gradleMock
expect:
expectBuildFinished("Configure")
def finishResult = controller.finishBuild(null)
finishResult.failures.empty
}
void testNotifiesListenerOnConfigureBuildFailure() {
def failure = new RuntimeException()
when:
1 * buildModelController.configuredModel >> { throw failure }
def controller = this.controller()
controller.getConfiguredBuild()
then:
def t = thrown RuntimeException
t == failure
when:
def finishResult = controller.finishBuild(null)
then:
1 * exceptionAnalyser.transform([failure]) >> transformedException
1 * buildBroadcaster.buildFinished({ it.failure == transformedException })
finishResult.failures.empty
}
void testConfigureBuildRethrowsPreviousFailure() {
def failure = new RuntimeException()
when:
1 * buildModelController.configuredModel >> { throw failure }
def controller = this.controller()
controller.configureProjects()
then:
def t = thrown RuntimeException
t == failure
when:
controller.configureProjects()
then:
def t2 = thrown RuntimeException
t2 == failure
when:
controller.loadSettings()
then:
def t3 = thrown RuntimeException
t3 == failure
}
void testCannotExecuteTasksWhenNothingHasBeenScheduled() {
when:
def controller = controller()
def workGraph = controller.newWorkGraph()
controller.executeTasks(workGraph)
then:
def t = thrown IllegalStateException
when:
def finishResult = controller.finishBuild(null)
then:
1 * buildBroadcaster.buildFinished({ it.failure == null })
finishResult.failures.empty
}
void testNotifiesListenerOnTaskSchedulingFailure() {
given:
1 * workPreparer.newExecutionPlan() >> executionPlan
1 * workPreparer.populateWorkGraph(gradleMock, executionPlan, _) >> { GradleInternal gradle, ExecutionPlan executionPlan, Consumer consumer -> consumer.accept(executionPlan) }
1 * buildModelController.scheduleRequestedTasks(executionPlan) >> { throw failure }
when:
def controller = this.controller()
controller.prepareToScheduleTasks()
def plan = controller.newWorkGraph()
controller.populateWorkGraph(plan) { b -> b.addRequestedTasks() }
then:
def t = thrown RuntimeException
t == failure
when:
def finishResult = controller.finishBuild(null)
then:
1 * exceptionAnalyser.transform([failure]) >> transformedException
1 * buildBroadcaster.buildFinished({ it.failure == transformedException && it.action == "Build" })
finishResult.failures.empty
}
void testNotifiesListenerOnTaskExecutionFailure() {
given:
expectRequestedTasksScheduled()
expectTasksRunWithFailure(failure)
when:
def controller = this.controller()
controller.prepareToScheduleTasks()
def plan = controller.newWorkGraph()
controller.populateWorkGraph(plan) { b -> b.addRequestedTasks() }
controller.finalizeWorkGraph(plan)
def executionResult = controller.executeTasks(plan)
then:
executionResult.failures == [failure]
when:
def finishResult = controller.finishBuild(null)
then:
1 * exceptionAnalyser.transform([failure]) >> transformedException
1 * buildBroadcaster.buildFinished({ it.failure == transformedException })
finishResult.failures.empty
}
void testNotifiesListenerOnBuildCompleteWithMultipleFailures() {
def failure2 = new RuntimeException()
given:
expectRequestedTasksScheduled()
expectTasksRunWithFailure(failure, failure2)
when:
def controller = this.controller()
controller.prepareToScheduleTasks()
def plan = controller.newWorkGraph()
controller.populateWorkGraph(plan) { b -> b.addRequestedTasks() }
controller.finalizeWorkGraph(plan)
def executionResult = controller.executeTasks(plan)
then:
executionResult.failures == [failure, failure2]
when:
def finishResult = controller.finishBuild(null)
then:
1 * exceptionAnalyser.transform([failure, failure2]) >> transformedException
1 * buildBroadcaster.buildFinished({ it.failure == transformedException })
finishResult.failures.empty
}
void testTransformsBuildFinishedListenerFailure() {
given:
expectRequestedTasksScheduled()
expectTasksRun()
and:
def controller = controller()
controller.prepareToScheduleTasks()
def plan = controller.newWorkGraph()
controller.populateWorkGraph(plan) { b -> b.addRequestedTasks() }
controller.finalizeWorkGraph(plan)
controller.executeTasks(plan)
when:
def finishResult = controller.finishBuild(null)
then:
1 * buildBroadcaster.buildFinished({ it.failure == null }) >> { throw failure }
finishResult.failures == [failure]
}
void testNotifiesListenersOnMultipleBuildFailuresAndBuildListenerFailure() {
def failure2 = new RuntimeException()
def failure3 = new RuntimeException()
given:
expectRequestedTasksScheduled()
expectTasksRunWithFailure(failure, failure2)
and:
def controller = controller()
controller.prepareToScheduleTasks()
def plan = controller.newWorkGraph()
controller.populateWorkGraph(plan) { b -> b.addRequestedTasks() }
controller.finalizeWorkGraph(plan)
when:
def executionResult = controller.executeTasks(plan)
then:
executionResult.failures == [failure, failure2]
when:
def finishResult = controller.finishBuild(null)
then:
1 * exceptionAnalyser.transform([failure, failure2]) >> transformedException
1 * buildBroadcaster.buildFinished({ it.failure == transformedException }) >> { throw failure3 }
finishResult.failures == [failure3]
}
void testCannotGetModelAfterFinished() {
given:
def controller = controller()
controller.finishBuild(null)
when:
controller.gradle
then:
thrown IllegalStateException
}
void testCannotLoadSettingsAfterFinished() {
given:
def controller = controller()
controller.finishBuild(null)
when:
controller.loadSettings()
then:
thrown IllegalStateException
}
void testCannotConfigureBuildAfterFinished() {
given:
def controller = controller()
controller.finishBuild(null)
when:
controller.configureProjects()
then:
thrown IllegalStateException
}
void testCannotRunMoreWorkAfterFinished() {
given:
def controller = controller()
controller.finishBuild(null)
when:
controller.prepareToScheduleTasks()
then:
thrown IllegalStateException
}
private void expectSettingsBuilt() {
1 * buildModelController.loadedSettings >> settingsMock
}
private void expectSettingsBuiltWithFailure(Throwable failure) {
1 * buildModelController.loadedSettings >> { throw failure }
}
private void expectRequestedTasksScheduled() {
1 * workPreparer.newExecutionPlan() >> executionPlan
1 * buildModelController.prepareToScheduleTasks()
1 * buildModelController.initializeWorkGraph(executionPlan)
1 * workPreparer.populateWorkGraph(gradleMock, executionPlan, _) >> { GradleInternal gradle, ExecutionPlan executionPlan, Consumer consumer -> consumer.accept(executionPlan) }
1 * buildModelController.scheduleRequestedTasks(executionPlan)
}
private void expectTasksScheduled() {
1 * workPreparer.newExecutionPlan() >> executionPlan
1 * buildModelController.prepareToScheduleTasks()
1 * buildModelController.initializeWorkGraph(executionPlan)
1 * workPreparer.populateWorkGraph(gradleMock, executionPlan, _) >> { GradleInternal gradle, ExecutionPlan executionPlan, Consumer consumer -> consumer.accept(executionPlan) }
}
private void expectTasksRun() {
1 * workExecutor.execute(gradleMock, executionPlan) >> ExecutionResult.succeeded()
}
private void expectTasksRunWithFailure(Throwable failure, Throwable other = null) {
def failures = other == null ? [failure] : [failure, other]
1 * workExecutor.execute(gradleMock, executionPlan) >> ExecutionResult.maybeFailed(failures)
}
private void expectBuildFinished(String action = "Build") {
1 * buildBroadcaster.buildFinished({ it.failure == null && it.action == action })
1 * buildFinishedListener.buildFinished(_, false)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy