diff --git a/src/test/groovy/com/palantir/gradle/versions/ConfigurationOnDemandSpec.groovy b/src/test/groovy/com/palantir/gradle/versions/ConfigurationOnDemandSpec.groovy deleted file mode 100644 index 0dbd7985e..000000000 --- a/src/test/groovy/com/palantir/gradle/versions/ConfigurationOnDemandSpec.groovy +++ /dev/null @@ -1,424 +0,0 @@ -/* - * (c) Copyright 2026 Palantir Technologies Inc. All rights reserved. - * - * 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.palantir.gradle.versions - -import org.gradle.testkit.runner.BuildResult -import org.gradle.testkit.runner.TaskOutcome -import spock.lang.Unroll - -import static com.palantir.gradle.versions.GradleTestVersions.GRADLE_VERSIONS -import static com.palantir.gradle.versions.PomUtils.makePlatformPom - -/** - * This tests the interaction of this plugin with Gradle's configuration-on-demand feature: - * https://docs.gradle.org/current/userguide/multi_project_configuration_and_execution.html#sec:configuration_on_demand - */ -@Unroll -class ConfigurationOnDemandSpec extends IntegrationSpec { - - static def PLUGIN_NAME = "com.palantir.consistent-versions" - private File mavenRepo - - /* - * Project structure (arrows indicate dependencies): - * - * upstream unrelated - * ^ ^ - * | | - * downstream1 downstream2 - */ - void setup() { - mavenRepo = generateMavenRepo( - 'com.example:dependency-of-upstream:1.2.3', - 'com.example:dependency-of-upstream:100.1.1', - 'com.example:dependency-of-downstream1:1.2.3', - 'com.example:dependency-of-downstream2:1.2.3', - 'com.example:dependency-of-unrelated:1.2.3', - 'com.example:dep-with-version-bumped-by-unrelated:1.0.0', - 'com.example:dep-with-version-bumped-by-unrelated:1.1.0', - 'com.example:transitive-test-dep:1.0.0', - 'com.example:transitive-test-dep:1.1.0', - 'com.example:transitive-test-dep:1.2.0', - ) - - makePlatformPom(mavenRepo, "org", "platform", "1.0") - - buildFile.text = """ - plugins { - id '${PLUGIN_NAME}' - } - allprojects { - repositories { - maven { url "file:///${mavenRepo.getAbsolutePath()}" } - } - } - subprojects { - tasks.register('writeClasspath') { - doLast { - println(configurations.runtimeClasspath.getFiles()) - } - } - } - - // Get rid of deprecation warnings for Gradle 7+ - versionRecommendations { - excludeConfigurations 'compile', 'runtime', 'testCompile', 'testRuntime' - } - """.stripIndent(true) - - file('versions.props').text = """ - com.example:dependency-of-upstream = 1.2.3 - com.example:dependency-of-downstream1 = 1.2.3 - com.example:dependency-of-downstream2 = 1.2.3 - com.example:dependency-of-unrelated = 1.2.3 - # 1.0.0 is a minimum, we expect this to be locked to 1.1.0 - com.example:dep-with-version-bumped-by-unrelated = 1.0.0 - """.stripIndent(true) - - addSubproject("upstream", """ - plugins { - id 'java' - } - println 'configuring upstream' - dependencies { - implementation 'com.example:dependency-of-upstream' - } - """.stripIndent(true)) - - addSubproject("downstream1", """ - plugins { - id 'java' - } - println 'configuring downstream1' - dependencies { - implementation project(':upstream') - implementation 'com.example:dependency-of-downstream1' - } - """.stripIndent(true)) - - addSubproject("downstream2", """ - plugins { - id 'java' - } - println 'configuring downstream2' - dependencies { - implementation project(':upstream') - implementation 'com.example:dependency-of-downstream2' - implementation 'com.example:dep-with-version-bumped-by-unrelated' - } - """.stripIndent(true)) - - addSubproject("unrelated", """ - plugins { - id 'java' - } - println 'configuring unrelated' - dependencies { - implementation 'com.example:dependency-of-unrelated' - implementation 'com.example:dep-with-version-bumped-by-unrelated:1.1.0' - } - """.stripIndent(true)) - - file("gradle.properties").text = """ - org.gradle.configureondemand=true - """.stripIndent(true) - } - - def '#gradleVersionNumber: can write locks'() { - setup: - gradleVersion = gradleVersionNumber - - when: - BuildResult result = runTasks('--write-locks') - - then: - result.output.contains('configuring upstream') - result.output.contains('configuring downstream1') - result.output.contains('configuring downstream2') - result.output.contains('configuring unrelated') - - new File(projectDir, "versions.lock").exists() - file("versions.lock").text.contains("com.example:dependency-of-upstream:1.2.3") - file("versions.lock").text.contains("com.example:dep-with-version-bumped-by-unrelated:1.1.0") - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: can write locks when a task in one project is specified'() { - setup: - gradleVersion = gradleVersionNumber - - when: - runTasks(':downstream1:build', '--write-locks') - - then: - new File(projectDir, "versions.lock").exists() - file("versions.lock").text.contains("com.example:dependency-of-unrelated:1.2.3") - file("versions.lock").text.contains("com.example:dep-with-version-bumped-by-unrelated:1.1.0") - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: applying the plugin does not force all projects to be configured'() { - setup: - gradleVersion = gradleVersionNumber - - when: - runTasks('--write-locks') - // Both absolute and relative formats work, as long as Gradle is run from the root project directory - BuildResult result1 = runTasks(':downstream1:build') - BuildResult result2 = runTasks('downstream1:build') - - then: - result1.output.contains('configuring upstream') - result1.output.contains('configuring downstream1') - !result1.output.contains('configuring downstream2') - !result1.output.contains('configuring unrelated') - - result2.output.contains('configuring upstream') - result2.output.contains('configuring downstream1') - !result2.output.contains('configuring downstream2') - !result2.output.contains('configuring unrelated') - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: resolving a classpath does not force all projects to be configured'() { - setup: - gradleVersion = gradleVersionNumber - - when: - runTasks('--write-locks') - BuildResult result = runTasks(':downstream1:writeClasspath') - - then: - result.output.contains('configuring upstream') - result.output.contains('configuring downstream1') - !result.output.contains('configuring downstream2') - !result.output.contains('configuring unrelated') - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: after lockfile is written, versions constraints due to non-configured projects are still respected'() { - setup: - gradleVersion = gradleVersionNumber - - when: - runTasks('--write-locks') - BuildResult result = runTasks(':downstream2:writeClasspath') - - then: - // Version used is 1.1.0 due to the unrelated project - result.output.contains('dep-with-version-bumped-by-unrelated-1.1.0.jar') - !result.output.contains('configured unrelated') - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: transitive dependencies cause upstream projects to be configured sufficiently early'() { - setup: - gradleVersion = gradleVersionNumber - addSubproject("a", """ - plugins { id 'java' } - dependencies { - implementation 'com.example:transitive-test-dep:1.0.0' - } - """.stripIndent(true)) - addSubproject("b", """ - plugins { id 'java' } - dependencies { - implementation project(':a') - } - """.stripIndent(true)) - addSubproject("c", """ - plugins { id 'java' } - dependencies { - implementation project(':b') - } - tasks.register('writeClasspathOfA') { - doLast { - println project(':a').configurations.runtimeClasspath.files - } - } - """.stripIndent(true)) - addSubproject("u", """ - plugins { id 'java' } - dependencies { - implementation 'com.example:transitive-test-dep:1.1.0' - } - """.stripIndent(true)) - - when: - runTasks('--write-locks') - BuildResult result = runTasks(':c:writeClasspathOfA') - - then: - // Version used should be 1.1.0, indicating that the version.lock constraint was applied - result.output.contains('transitive-test-dep-1.1.0.jar') - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: task dependencies cause upstream projects to be configured sufficiently early'() { - setup: - gradleVersion = gradleVersionNumber - addSubproject("a", """ - plugins { id 'java' } - dependencies { - implementation 'com.example:transitive-test-dep:1.0.0' - } - """.stripIndent(true)) - addSubproject("b", """ - tasks.register('foo') { - dependsOn ':a:writeClasspath' - } - """.stripIndent(true)) - addSubproject("c", """ - tasks.register('bar') { - dependsOn ':b:foo' - } - """.stripIndent(true)) - addSubproject("u", """ - plugins { id 'java' } - dependencies { - implementation 'com.example:transitive-test-dep:1.1.0' - } - """.stripIndent(true)) - - when: - runTasks('--write-locks') - BuildResult result = runTasks(':c:bar') - - then: - // Version used should be 1.1.0, indicating that the version.lock constraint was applied - result.output.contains('transitive-test-dep-1.1.0.jar') - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: verification tasks pass when all projects are configured'() { - setup: - gradleVersion = gradleVersionNumber - - when: - runTasks('--write-locks') - // Note: Not specifying the project causes all projects to be configured regardless of CoD - BuildResult result = runTasks('checkUnusedConstraints', 'verifyLocks') - - then: - result.output.contains('configuring upstream') - result.task(':checkUnusedConstraints').outcome == TaskOutcome.SUCCESS - result.task(':verifyLocks').outcome == TaskOutcome.SUCCESS - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: checkUnusedConstraints succeeds when not all projects are configured'() { - setup: - gradleVersion = gradleVersionNumber - - when: - runTasks('--write-locks') - BuildResult result = runTasks(':checkUnusedConstraints') - - then: - result.task(':checkUnusedConstraints').outcome == TaskOutcome.SUCCESS - result.output.contains('configuring upstream') - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: verifyLocks fails and warns when not all projects are configured'() { - setup: - gradleVersion = gradleVersionNumber - - when: - runTasks('--write-locks') - BuildResult result = runTasksAndFail(':verifyLocks') - - then: - !result.output.contains('configuring upstream') - result.task(':verifyLocks').outcome == TaskOutcome.FAILED - result.output.contains("All projects must have been configured for this task to work correctly, but due to " + - "Gradle configuration-on-demand, not all projects were configured.") - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - // As failing tasks can't be considered UP-TO-DATE, we only need to check the case where the task passing - // is followed by the task running with incomplete configuration. - def '#gradleVersionNumber: verification tasks are not UP-TO-DATE when the set of configured projects differs'() { - setup: - gradleVersion = gradleVersionNumber - - when: - runTasks('--write-locks') - runTasks('build') - - then: - runTasksAndFail(':verifyLocks') - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: the why task works when all projects are configured'() { - setup: - gradleVersion = gradleVersionNumber - - when: - runTasks('--write-locks') - BuildResult result = runTasks('why', '--hash=0805f935') - - then: - result.task(':why').outcome == TaskOutcome.SUCCESS - - where: - gradleVersionNumber << GRADLE_VERSIONS - } - - def '#gradleVersionNumber: the why task somehow forces all projects to be configured'() { - setup: - gradleVersion = gradleVersionNumber - - when: - runTasks('--write-locks') - BuildResult result = runTasks(':why', '--hash=0805f935') - - then: - result.output.contains('configuring upstream') - result.output.contains('configuring downstream1') - result.output.contains('configuring downstream2') - result.output.contains('configuring unrelated') - result.task(':why').outcome == TaskOutcome.SUCCESS - result.output.contains('com.example:dependency-of-unrelated:1.2.3\n\tprojects -> 1.2.3') - - where: - gradleVersionNumber << GRADLE_VERSIONS - } -} diff --git a/src/test/java/com/palantir/gradle/versions/ConfigurationOnDemandTest.java b/src/test/java/com/palantir/gradle/versions/ConfigurationOnDemandTest.java new file mode 100644 index 000000000..2d0446543 --- /dev/null +++ b/src/test/java/com/palantir/gradle/versions/ConfigurationOnDemandTest.java @@ -0,0 +1,366 @@ +/* + * (c) Copyright 2021 Palantir Technologies Inc. All rights reserved. + * + * 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.palantir.gradle.versions; + +import static com.palantir.gradle.testing.assertion.GradlePluginTestAssertions.assertThat; +import static org.assertj.core.api.Assertions.assertThat; + +import com.palantir.gradle.testing.execution.GradleInvoker; +import com.palantir.gradle.testing.execution.InvocationResult; +import com.palantir.gradle.testing.junit.DisabledConfigurationCache; +import com.palantir.gradle.testing.junit.GradlePluginTests; +import com.palantir.gradle.testing.maven.MavenArtifact; +import com.palantir.gradle.testing.maven.MavenRepo; +import com.palantir.gradle.testing.project.RootProject; +import com.palantir.gradle.testing.project.SubProject; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * This tests the interaction of this plugin with Gradle's configuration-on-demand feature: + * https://docs.gradle.org/current/userguide/multi_project_configuration_and_execution.html#sec:configuration_on_demand + */ +@GradlePluginTests +@DisabledConfigurationCache("configuration cache cannot be reused due to --write-locks") +class ConfigurationOnDemandTest { + + private static final String PLUGIN_NAME = "com.palantir.consistent-versions"; + + /* + * Project structure (arrows indicate dependencies): + * + * upstream unrelated + * ^ ^ + * | | + * downstream1 downstream2 + */ + @BeforeEach + void setup( + MavenRepo repo, + RootProject rootProject, + SubProject upstream, + SubProject downstream1, + SubProject downstream2, + SubProject unrelated) { + repo.publish( + MavenArtifact.of("com.example:dependency-of-upstream:1.2.3"), + MavenArtifact.of("com.example:dependency-of-upstream:100.1.1"), + MavenArtifact.of("com.example:dependency-of-downstream1:1.2.3"), + MavenArtifact.of("com.example:dependency-of-downstream2:1.2.3"), + MavenArtifact.of("com.example:dependency-of-unrelated:1.2.3"), + MavenArtifact.of("com.example:dep-with-version-bumped-by-unrelated:1.0.0"), + MavenArtifact.of("com.example:dep-with-version-bumped-by-unrelated:1.1.0"), + MavenArtifact.of("com.example:transitive-test-dep:1.0.0"), + MavenArtifact.of("com.example:transitive-test-dep:1.1.0"), + MavenArtifact.of("com.example:transitive-test-dep:1.2.0")); + + PomUtils.makePlatformPom(rootProject, repo, "org", "platform", "1.0"); + + rootProject.buildGradle().plugins().add(PLUGIN_NAME); + rootProject.buildGradle().append(""" + allprojects { + repositories { + maven { url uri("%s") } + } + } + subprojects { + tasks.register('writeClasspath') { + doLast { + println(configurations.runtimeClasspath.getFiles()) + } + } + } + + // Get rid of deprecation warnings for Gradle 7+ + versionRecommendations { + excludeConfigurations 'compile', 'runtime', 'testCompile', 'testRuntime' + } + """, repo.path()); + + rootProject.file("versions.props").overwrite(""" + com.example:dependency-of-upstream = 1.2.3 + com.example:dependency-of-downstream1 = 1.2.3 + com.example:dependency-of-downstream2 = 1.2.3 + com.example:dependency-of-unrelated = 1.2.3 + # 1.0.0 is a minimum, we expect this to be locked to 1.1.0 + com.example:dep-with-version-bumped-by-unrelated = 1.0.0 + """); + + upstream.buildGradle().plugins().add("java"); + upstream.buildGradle().append(""" + println 'configuring upstream' + dependencies { + implementation 'com.example:dependency-of-upstream' + } + """); + + downstream1.buildGradle().plugins().add("java"); + downstream1.buildGradle().append(""" + println 'configuring downstream1' + dependencies { + implementation project(':upstream') + implementation 'com.example:dependency-of-downstream1' + } + """); + + downstream2.buildGradle().plugins().add("java"); + downstream2.buildGradle().append(""" + println 'configuring downstream2' + dependencies { + implementation project(':upstream') + implementation 'com.example:dependency-of-downstream2' + implementation 'com.example:dep-with-version-bumped-by-unrelated' + } + """); + + unrelated.buildGradle().plugins().add("java"); + unrelated.buildGradle().append(""" + println 'configuring unrelated' + dependencies { + implementation 'com.example:dependency-of-unrelated' + implementation 'com.example:dep-with-version-bumped-by-unrelated:1.1.0' + } + """); + + rootProject.gradlePropertiesFile().setProperty("org.gradle.configureondemand", "true"); + } + + @Test + void can_write_locks(GradleInvoker gradle, RootProject rootProject) { + InvocationResult result = gradle.withArgs("--write-locks").buildsSuccessfully(); + + assertThat(result) + .output() + .contains("configuring upstream") + .contains("configuring downstream1") + .contains("configuring downstream2") + .contains("configuring unrelated"); + + rootProject.file("versions.lock").assertThat().exists(); + assertThat(rootProject.file("versions.lock").text()) + .contains("com.example:dependency-of-upstream:1.2.3") + .contains("com.example:dep-with-version-bumped-by-unrelated:1.1.0"); + } + + @Test + void can_write_locks_when_a_task_in_one_project_is_specified(GradleInvoker gradle, RootProject rootProject) { + gradle.withArgs(":downstream1:build", "--write-locks").buildsSuccessfully(); + + rootProject.file("versions.lock").assertThat().exists(); + assertThat(rootProject.file("versions.lock").text()) + .contains("com.example:dependency-of-unrelated:1.2.3") + .contains("com.example:dep-with-version-bumped-by-unrelated:1.1.0"); + } + + @Test + void applying_the_plugin_does_not_force_all_projects_to_be_configured(GradleInvoker gradle) { + gradle.withArgs("--write-locks").buildsSuccessfully(); + // Both absolute and relative formats work, as long as Gradle is run from the root project directory + InvocationResult result1 = gradle.withArgs(":downstream1:build").buildsSuccessfully(); + InvocationResult result2 = gradle.withArgs("downstream1:build").buildsSuccessfully(); + + assertThat(result1) + .output() + .contains("configuring upstream") + .contains("configuring downstream1") + .doesNotContain("configuring downstream2") + .doesNotContain("configuring unrelated"); + + assertThat(result2) + .output() + .contains("configuring upstream") + .contains("configuring downstream1") + .doesNotContain("configuring downstream2") + .doesNotContain("configuring unrelated"); + } + + @Test + void resolving_a_classpath_does_not_force_all_projects_to_be_configured(GradleInvoker gradle) { + gradle.withArgs("--write-locks").buildsSuccessfully(); + InvocationResult result = gradle.withArgs(":downstream1:writeClasspath").buildsSuccessfully(); + + assertThat(result) + .output() + .contains("configuring upstream") + .contains("configuring downstream1") + .doesNotContain("configuring downstream2") + .doesNotContain("configuring unrelated"); + } + + @Test + void after_lockfile_is_written_versions_constraints_due_to_non_configured_projects_are_still_respected( + GradleInvoker gradle) { + gradle.withArgs("--write-locks").buildsSuccessfully(); + InvocationResult result = gradle.withArgs(":downstream2:writeClasspath").buildsSuccessfully(); + + assertThat(result) + .output() + .as("Version used is 1.1.0 due to the unrelated project") + .contains("dep-with-version-bumped-by-unrelated-1.1.0.jar") + .doesNotContain("configured unrelated"); + } + + @Test + void transitive_dependencies_cause_upstream_projects_to_be_configured_sufficiently_early( + GradleInvoker gradle, SubProject projectA, SubProject projectB, SubProject projectC, SubProject projectU) { + projectA.buildGradle().plugins().add("java"); + projectA.buildGradle().append(""" + dependencies { + implementation 'com.example:transitive-test-dep:1.0.0' + } + """); + + projectB.buildGradle().plugins().add("java"); + projectB.buildGradle().append(""" + dependencies { + implementation project(':projectA') + } + """); + + projectC.buildGradle().plugins().add("java"); + projectC.buildGradle().append(""" + dependencies { + implementation project(':projectB') + } + tasks.register('writeClasspathOfA') { + doLast { + println project(':projectA').configurations.runtimeClasspath.files + } + } + """); + + projectU.buildGradle().plugins().add("java"); + projectU.buildGradle().append(""" + dependencies { + implementation 'com.example:transitive-test-dep:1.1.0' + } + """); + + gradle.withArgs("--write-locks").buildsSuccessfully(); + InvocationResult result = gradle.withArgs(":projectC:writeClasspathOfA").buildsSuccessfully(); + + assertThat(result) + .output() + .as("Version used should be 1.1.0, indicating that the version.lock constraint was applied") + .contains("transitive-test-dep-1.1.0.jar"); + } + + @Test + void task_dependencies_cause_upstream_projects_to_be_configured_sufficiently_early( + GradleInvoker gradle, SubProject projectA, SubProject projectB, SubProject projectC, SubProject projectU) { + projectA.buildGradle().plugins().add("java"); + projectA.buildGradle().append(""" + dependencies { + implementation 'com.example:transitive-test-dep:1.0.0' + } + """); + + projectB.buildGradle().append(""" + tasks.register('foo') { + dependsOn ':projectA:writeClasspath' + } + """); + + projectC.buildGradle().append(""" + tasks.register('bar') { + dependsOn ':projectB:foo' + } + """); + + projectU.buildGradle().plugins().add("java"); + projectU.buildGradle().append(""" + dependencies { + implementation 'com.example:transitive-test-dep:1.1.0' + } + """); + + gradle.withArgs("--write-locks").buildsSuccessfully(); + InvocationResult result = gradle.withArgs(":projectC:bar").buildsSuccessfully(); + + assertThat(result) + .output() + .as("Version used should be 1.1.0, indicating that the version.lock constraint was applied") + .contains("transitive-test-dep-1.1.0.jar"); + } + + @Test + void verification_tasks_pass_when_all_projects_are_configured(GradleInvoker gradle) { + gradle.withArgs("--write-locks").buildsSuccessfully(); + // Note: Not specifying the project causes all projects to be configured regardless of CoD + InvocationResult result = + gradle.withArgs("checkUnusedConstraints", "verifyLocks").buildsSuccessfully(); + + assertThat(result).output().contains("configuring upstream"); + assertThat(result).task(":checkUnusedConstraints").succeeded(); + assertThat(result).task(":verifyLocks").succeeded(); + } + + @Test + void checkUnusedConstraints_succeeds_when_not_all_projects_are_configured(GradleInvoker gradle) { + gradle.withArgs("--write-locks").buildsSuccessfully(); + InvocationResult result = gradle.withArgs(":checkUnusedConstraints").buildsSuccessfully(); + + assertThat(result).task(":checkUnusedConstraints").succeeded(); + assertThat(result).output().contains("configuring upstream"); + } + + @Test + void verifyLocks_fails_and_warns_when_not_all_projects_are_configured(GradleInvoker gradle) { + gradle.withArgs("--write-locks").buildsSuccessfully(); + InvocationResult result = gradle.withArgs(":verifyLocks").buildsWithFailure(); + + assertThat(result) + .output() + .doesNotContain("configuring upstream") + .contains("All projects must have been configured for this task to work correctly, but due to " + + "Gradle configuration-on-demand, not all projects were configured."); + assertThat(result).task(":verifyLocks").failed(); + } + + // As failing tasks can't be considered UP-TO-DATE, we only need to check the case where the task passing + // is followed by the task running with incomplete configuration. + @Test + void verification_tasks_are_not_up_to_date_when_the_set_of_configured_projects_differs(GradleInvoker gradle) { + gradle.withArgs("--write-locks").buildsSuccessfully(); + gradle.withArgs("build").buildsSuccessfully(); + + gradle.withArgs(":verifyLocks").buildsWithFailure(); + } + + @Test + void the_why_task_works_when_all_projects_are_configured(GradleInvoker gradle) { + gradle.withArgs("--write-locks").buildsSuccessfully(); + InvocationResult result = gradle.withArgs("why", "--hash=0805f935").buildsSuccessfully(); + + assertThat(result).task(":why").succeeded(); + } + + @Test + void the_why_task_somehow_forces_all_projects_to_be_configured(GradleInvoker gradle) { + gradle.withArgs("--write-locks").buildsSuccessfully(); + InvocationResult result = gradle.withArgs(":why", "--hash=0805f935").buildsSuccessfully(); + + assertThat(result) + .output() + .contains("configuring upstream") + .contains("configuring downstream1") + .contains("configuring downstream2") + .contains("configuring unrelated") + .contains("com.example:dependency-of-unrelated:1.2.3\n\tprojects -> 1.2.3"); + assertThat(result).task(":why").succeeded(); + } +} diff --git a/test-migration-notes/ConfigurationOnDemandSpec.html b/test-migration-notes/ConfigurationOnDemandSpec.html new file mode 100644 index 000000000..b3bd4bbd4 --- /dev/null +++ b/test-migration-notes/ConfigurationOnDemandSpec.html @@ -0,0 +1,9972 @@ + + +
+ +| + |
+ @@ -14,26 +14,33 @@
+ |
+
| + 14 + | +
+
+
+ * limitations under the License.
+
+ |
+
| + 15 + | +
+
+
+ */
+
+ |
+
| + 16 + | +
+
+
+
+ + |
+
| + 17 + | +
+
+ -
+ package com.palantir.gradle.versions
+
+ |
+
| + 18 + | +
+
+ -
+
+ + |
+
| + 19 + | +
+
+ -
+ import
+ |
+
| + 20 + | +
+
+ -
+ import org.
+ |
+
| + 21 + | +
+
+ -
+
+ |
+
| + 22 + | +
+
+ -
+
+ + |
+
| + 23 + | +
+
+ -
+ import
+ |
+
| + 24 + | +
+
+ -
+ import
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 25 + | +
+
+
+
+ + |
+
| + 26 + | +
+
+
+ /**
+
+ |
+
| + 27 + | +
+
+
+ * This tests the interaction of this plugin with Gradle's configuration-on-demand feature:
+
+ |
+
| + 28 + | +
+
+
+ * https://docs.gradle.org/current/userguide/multi_project_configuration_and_execution.html#sec:configuration_on_demand
+
+ |
+
| + 29 + | +
+
+
+ */
+
+ |
+
| + 30 + | +
+
+ -
+ @
+ |
+
| + 31 + | +
+
+ -
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 32 + | +
+
+
+
+ + |
+
| + 33 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: PLUGIN_NAME
+
+ |
+
| + 34 + | +
+
+ -
+ static
+ |
+
| + 35 + | +
+
+ -
+ // ***DELINEATOR FOR REVIEW: mavenRepo
+
+ |
+
| + 36 + | +
+
+ -
+ private File mavenRepo
+
+ |
+
| + 37 + | +
+
+
+
+ + |
+
| + 38 + | +
+
+
+ /*
+
+ |
+
| + 39 + | +
+
+
+ * Project structure (arrows indicate dependencies):
+
+ |
+
| + |
+ @@ -44,29 +51,35 @@ class ConfigurationOnDemandSpec extends IntegrationSpec {
+ |
+
| + 44 + | +
+
+
+ * downstream1 downstream2
+
+ |
+
| + 45 + | +
+
+
+ */
+
+ |
+
| + 46 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: setup
+
+ |
+
| + 47 + | +
+
+ -
+
+ |
+
| + 48 + | +
+
+ -
+
+ |
+
| + 49 + | +
+
+ -
+
+ |
+
| + 50 + | +
+
+ -
+
+ |
+
| + 51 + | +
+
+ -
+
+ |
+
| + 52 + | +
+
+ -
+
+ |
+
| + 53 + | +
+
+ -
+
+ |
+
| + 54 + | +
+
+ -
+
+ |
+
| + 55 + | +
+
+ -
+
+ |
+
| + 56 + | +
+
+ -
+
+ |
+
| + 57 + | +
+
+ -
+
+ |
+
| + 58 + | +
+
+ -
+
+ |
+
| + 59 + | +
+
+ -
+
+ |
+
| + 60 + | +
+
+ -
+
+ + |
+
| + 61 + | +
+
+ -
+
+ |
+
| + 62 + | +
+
+ -
+
+ + |
+
| + 63 + | +
+
+ -
+
+ |
+
| + 64 + | +
+
+ -
+
+ |
+
| + 65 + | +
+
+ -
+
+ |
+
| + 66 + | +
+
+ -
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 67 + | +
+
+
+ allprojects {
+
+ |
+
| + 68 + | +
+
+
+ repositories {
+
+ |
+
| + 69 + | +
+
+ -
+ maven { url "
+ |
+
| + 70 + | +
+
+
+ }
+
+ |
+
| + 71 + | +
+
+
+ }
+
+ |
+
| + 72 + | +
+
+
+ subprojects {
+
+ |
+
| + |
+ @@ -76,201 +89,199 @@ class ConfigurationOnDemandSpec extends IntegrationSpec {
+ |
+
| + 76 + | +
+
+
+ }
+
+ |
+
| + 77 + | +
+
+
+ }
+
+ |
+
| + 78 + | +
+
+
+ }
+
+ |
+
| + 79 + | +
+
+ -
+
+ |
+
| + 80 + | +
+
+
+ // Get rid of deprecation warnings for Gradle 7+
+
+ |
+
| + 81 + | +
+
+
+ versionRecommendations {
+
+ |
+
| + 82 + | +
+
+
+ excludeConfigurations 'compile', 'runtime', 'testCompile', 'testRuntime'
+
+ |
+
| + 83 + | +
+
+
+ }
+
+ |
+
| + 84 + | +
+
+ -
+
+ |
+
| + 85 + | +
+
+
+
+ + |
+
| + 86 + | +
+
+ -
+ file(
+ |
+
| + 87 + | +
+
+
+ com.example:dependency-of-upstream = 1.2.3
+
+ |
+
| + 88 + | +
+
+
+ com.example:dependency-of-downstream1 = 1.2.3
+
+ |
+
| + 89 + | +
+
+
+ com.example:dependency-of-downstream2 = 1.2.3
+
+ |
+
| + 90 + | +
+
+
+ com.example:dependency-of-unrelated = 1.2.3
+
+ |
+
| + 91 + | +
+
+
+ # 1.0.0 is a minimum, we expect this to be locked to 1.1.0
+
+ |
+
| + 92 + | +
+
+
+ com.example:dep-with-version-bumped-by-unrelated = 1.0.0
+
+ |
+
| + 93 + | +
+
+ -
+
+ |
+
| + 94 + | +
+
+
+
+ + |
+
| + 95 + | +
+
+ -
+
+ |
+
| + 96 + | +
+
+ -
+
+ |
+
| + 97 + | +
+
+ -
+ id 'java'
+
+ |
+
| + 98 + | +
+
+ -
+ }
+
+ |
+
| + 99 + | +
+
+
+ println 'configuring upstream'
+
+ |
+
| + 100 + | +
+
+
+ dependencies {
+
+ |
+
| + 101 + | +
+
+
+ implementation 'com.example:dependency-of-upstream'
+
+ |
+
| + 102 + | +
+
+
+ }
+
+ |
+
| + 103 + | +
+
+ -
+
+ |
+
| + 104 + | +
+
+
+
+ + |
+
| + 105 + | +
+
+ -
+
+ |
+
| + 106 + | +
+
+ -
+
+ |
+
| + 107 + | +
+
+ -
+ id 'java'
+
+ |
+
| + 108 + | +
+
+ -
+ }
+
+ |
+
| + 109 + | +
+
+
+ println 'configuring downstream1'
+
+ |
+
| + 110 + | +
+
+
+ dependencies {
+
+ |
+
| + 111 + | +
+
+
+ implementation project(':upstream')
+
+ |
+
| + 112 + | +
+
+
+ implementation 'com.example:dependency-of-downstream1'
+
+ |
+
| + 113 + | +
+
+
+ }
+
+ |
+
| + 114 + | +
+
+ -
+
+ |
+
| + 115 + | +
+
+
+
+ + |
+
| + 116 + | +
+
+ -
+
+ |
+
| + 117 + | +
+
+ -
+
+ |
+
| + 118 + | +
+
+ -
+ id 'java'
+
+ |
+
| + 119 + | +
+
+ -
+ }
+
+ |
+
| + 120 + | +
+
+
+ println 'configuring downstream2'
+
+ |
+
| + 121 + | +
+
+
+ dependencies {
+
+ |
+
| + 122 + | +
+
+
+ implementation project(':upstream')
+
+ |
+
| + 123 + | +
+
+
+ implementation 'com.example:dependency-of-downstream2'
+
+ |
+
| + 124 + | +
+
+
+ implementation 'com.example:dep-with-version-bumped-by-unrelated'
+
+ |
+
| + 125 + | +
+
+
+ }
+
+ |
+
| + 126 + | +
+
+ -
+
+ |
+
| + 127 + | +
+
+
+
+ + |
+
| + 128 + | +
+
+ -
+
+ |
+
| + 129 + | +
+
+ -
+
+ |
+
| + 130 + | +
+
+ -
+ id 'java'
+
+ |
+
| + 131 + | +
+
+ -
+ }
+
+ |
+
| + 132 + | +
+
+
+ println 'configuring unrelated'
+
+ |
+
| + 133 + | +
+
+
+ dependencies {
+
+ |
+
| + 134 + | +
+
+
+ implementation 'com.example:dependency-of-unrelated'
+
+ |
+
| + 135 + | +
+
+
+ implementation 'com.example:dep-with-version-bumped-by-unrelated:1.1.0'
+
+ |
+
| + 136 + | +
+
+
+ }
+
+ |
+
| + 137 + | +
+
+ -
+
+ |
+
| + 138 + | +
+
+
+
+ + |
+
| + 139 + | +
+
+ -
+
+ |
+
| + 140 + | +
+
+ -
+ org.gradle.configureondemand=true
+
+ |
+
| + 141 + | +
+
+ -
+ """.stripIndent(true)
+
+ |
+
| + 142 + | +
+
+
+ }
+
+ |
+
| + 143 + | +
+
+
+
+ + |
+
| + 144 + | +
+
+ -
+ //
+ |
+
| + 145 + | +
+
+ -
+
+ |
+
| + 146 + | +
+
+ -
+
+ |
+
| + 147 + | +
+
+ -
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 148 + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 149 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 150 + | +
+
+ -
+
+ |
+
| + 151 + | +
+
+ -
+ BuildResult result = runTasks('--write-locks')
+
+ |
+
| + 152 + | +
+
+
+
+ + |
+
| + 153 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 154 + | +
+
+ -
+
+ |
+
| + 155 + | +
+
+ -
+
+ |
+
| + 156 + | +
+
+ -
+
+ |
+
| + 157 + | +
+
+ -
+
+ |
+
| + 158 + | +
+
+ -
+
+ |
+
| + 159 + | +
+
+ -
+
+ + |
+
| + 160 + | +
+
+ -
+
+ |
+
| + 161 + | +
+
+ -
+ file("versions.lock").
+ |
+
| + 162 + | +
+
+ -
+ file("versions.lock").text
+ |
+
| + 163 + | +
+
+ -
+
+ + |
+
| + 164 + | +
+
+ -
+
+ |
+
| + 165 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 166 + | +
+
+
+ }
+
+ |
+
| + 167 + | +
+
+
+
+ + |
+
| + 168 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: can_write_locks_when_a_task_in_one_project_is_specified
+
+ |
+
| + 169 + | +
+
+ -
+
+ |
+
| + 170 + | +
+
+ -
+
+ |
+
| + 171 + | +
+
+ -
+ gradleVersion = gradleVersionNumber
+
+ |
+
| + 172 + | +
+
+ -
+
+ + |
+
| + 173 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 174 + | +
+
+ -
+
+ |
+
| + 175 + | +
+
+ -
+ runTasks(':downstream1:build', '--write-locks')
+
+ |
+
| + 176 + | +
+
+
+
+ + |
+
| + 177 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 178 + | +
+
+ -
+
+ |
+
| + 179 + | +
+
+ -
+
+ |
+
| + 180 + | +
+
+ -
+
+ |
+
| + 181 + | +
+
+ -
+
+ |
+
| + 182 + | +
+
+ -
+
+ + |
+
| + 183 + | +
+
+ -
+ where:
+
+ |
+
| + 184 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 185 + | +
+
+
+ }
+
+ |
+
| + 186 + | +
+
+
+
+ + |
+
| + 187 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: applying_the_plugin_does_not_force_all_projects_to_be_configured
+
+ |
+
| + 188 + | +
+
+ -
+
+ |
+
| + 189 + | +
+
+ -
+
+ |
+
| + 190 + | +
+
+ -
+ gradleVersion = gradleVersionNumber
+
+ |
+
| + 191 + | +
+
+ -
+
+ + |
+
| + 192 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 193 + | +
+
+ -
+
+ |
+
| + 194 + | +
+
+ -
+ runTasks('--write-locks')
+
+ |
+
| + 195 + | +
+
+
+ // Both absolute and relative formats work, as long as Gradle is run from the root project directory
+
+ |
+
| + 196 + | +
+
+ -
+
+ |
+
| + 197 + | +
+
+ -
+
+ |
+
| + 198 + | +
+
+
+
+ + |
+
| + 199 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 200 + | +
+
+ -
+
+ |
+
| + 201 + | +
+
+ -
+
+ |
+
| + 202 + | +
+
+ -
+
+ |
+
| + 203 + | +
+
+ -
+
+ |
+
| + 204 + | +
+
+ -
+
+ |
+
| + 205 + | +
+
+ -
+
+ + |
+
| + 206 + | +
+
+ -
+
+ |
+
| + 207 + | +
+
+ -
+
+ |
+
| + 208 + | +
+
+ -
+
+ |
+
| + 209 + | +
+
+ -
+
+ |
+
| + 210 + | +
+
+ -
+
+ + |
+
| + 211 + | +
+
+ -
+
+ |
+
| + 212 + | +
+
+ -
+
+ |
+
| + 213 + | +
+
+
+ }
+
+ |
+
| + 214 + | +
+
+
+
+ + |
+
| + 215 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: resolving_a_classpath_does_not_force_all_projects_to_be_configured
+
+ |
+
| + 216 + | +
+
+ -
+
+ |
+
| + 217 + | +
+
+ -
+
+ |
+
| + 218 + | +
+
+ -
+ gradleVersion = gradleVersionNumber
+
+ |
+
| + 219 + | +
+
+ -
+
+ + |
+
| + 220 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 221 + | +
+
+ -
+
+ |
+
| + 222 + | +
+
+ -
+
+ |
+
| + 223 + | +
+
+ -
+ BuildResult result = runTasks(':downstream1:writeClasspath')
+
+ |
+
| + 224 + | +
+
+
+
+ + |
+
| + 225 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 226 + | +
+
+ -
+
+ |
+
| + 227 + | +
+
+ -
+
+ |
+
| + 228 + | +
+
+ -
+
+ |
+
| + 229 + | +
+
+ -
+
+ |
+
| + 230 + | +
+
+ -
+
+ |
+
| + 231 + | +
+
+ -
+
+ + |
+
| + 232 + | +
+
+ -
+ where:
+
+ |
+
| + 233 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 234 + | +
+
+
+ }
+
+ |
+
| + 235 + | +
+
+
+
+ + |
+
| + 236 + | +
+
+ -
+ // ***DELINEATOR FOR REVIEW:
+ |
+
| + 237 + | +
+
+ -
+
+ |
+
| + 238 + | +
+
+ -
+
+ |
+
| + 239 + | +
+
+ -
+
+ |
+
| + 240 + | +
+
+ -
+
+ + |
+
| + 241 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 242 + | +
+
+ -
+
+ |
+
| + 243 + | +
+
+ -
+
+ |
+
| + 244 + | +
+
+ -
+ BuildResult result = runTasks(':downstream2:writeClasspath')
+
+ |
+
| + 245 + | +
+
+
+
+ + |
+
| + 246 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 247 + | +
+
+ -
+ then:
+
+ |
+
| + 248 + | +
+
+
+ // Version used is 1.1.0 due to the unrelated project
+
+ |
+
| + 249 + | +
+
+ -
+
+ |
+
| + 250 + | +
+
+ -
+
+ |
+
| + 251 + | +
+
+ -
+
+ + |
+
| + 252 + | +
+
+ -
+
+ |
+
| + 253 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 254 + | +
+
+
+ }
+
+ |
+
| + 255 + | +
+
+
+
+ + |
+
| + 256 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: transitive_dependencies_cause_upstream_projects_to_be_configured_sufficiently_early
+
+ |
+
| + 257 + | +
+
+ -
+
+ |
+
| + 258 + | +
+
+ -
+
+ |
+
| + 259 + | +
+
+ -
+
+ |
+
| + 260 + | +
+
+ -
+
+ |
+
| + 261 + | +
+
+ -
+
+ |
+
| + 262 + | +
+
+
+ dependencies {
+
+ |
+
| + 263 + | +
+
+
+ implementation 'com.example:transitive-test-dep:1.0.0'
+
+ |
+
| + 264 + | +
+
+
+ }
+
+ |
+
| + 265 + | +
+
+ -
+
+ |
+
| + 266 + | +
+
+ -
+
+ |
+
| + 267 + | +
+
+ -
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 268 + | +
+
+
+ dependencies {
+
+ |
+
| + 269 + | +
+
+
+ implementation project(':a')
+
+ |
+
| + 270 + | +
+
+
+ }
+
+ |
+
| + 271 + | +
+
+ -
+
+ |
+
| + 272 + | +
+
+ -
+
+ |
+
| + 273 + | +
+
+ -
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 274 + | +
+
+
+ dependencies {
+
+ |
+
| + 275 + | +
+
+
+ implementation project(':b')
+
+ |
+
| + 276 + | +
+
+
+ }
+
+ |
+
| + |
+ @@ -279,188 +290,145 @@ class ConfigurationOnDemandSpec extends IntegrationSpec {
+ |
+
| + 279 + | +
+
+
+ println project(':a').configurations.runtimeClasspath.files
+
+ |
+
| + 280 + | +
+
+
+ }
+
+ |
+
| + 281 + | +
+
+
+ }
+
+ |
+
| + 282 + | +
+
+ -
+
+ |
+
| + 283 + | +
+
+ -
+
+ |
+
| + 284 + | +
+
+ -
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 285 + | +
+
+
+ dependencies {
+
+ |
+
| + 286 + | +
+
+
+ implementation 'com.example:transitive-test-dep:1.1.0'
+
+ |
+
| + 287 + | +
+
+
+ }
+
+ |
+
| + 288 + | +
+
+ -
+
+ |
+
| + 289 + | +
+
+
+
+ + |
+
| + 290 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 291 + | +
+
+ -
+
+ |
+
| + 292 + | +
+
+ -
+
+ |
+
| + 293 + | +
+
+ -
+ BuildResult result = runTasks(':c:writeClasspathOfA')
+
+ |
+
| + 294 + | +
+
+
+
+ + |
+
| + 295 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 296 + | +
+
+ -
+ then:
+
+ |
+
| + 297 + | +
+
+
+ // Version used should be 1.1.0, indicating that the version.lock constraint was applied
+
+ |
+
| + 298 + | +
+
+ -
+ result.output.contains(
+ |
+
| + 299 + | +
+
+ -
+
+ + |
+
| + 300 + | +
+
+ -
+ where:
+
+ |
+
| + 301 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 302 + | +
+
+
+ }
+
+ |
+
| + 303 + | +
+
+
+
+ + |
+
| + 304 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: task_dependencies_cause_upstream_projects_to_be_configured_sufficiently_early
+
+ |
+
| + 305 + | +
+
+ -
+
+ |
+
| + 306 + | +
+
+ -
+
+ |
+
| + 307 + | +
+
+ -
+
+ |
+
| + 308 + | +
+
+ -
+
+ |
+
| + 309 + | +
+
+ -
+
+ |
+
| + 310 + | +
+
+
+ dependencies {
+
+ |
+
| + 311 + | +
+
+
+ implementation 'com.example:transitive-test-dep:1.0.0'
+
+ |
+
| + 312 + | +
+
+
+ }
+
+ |
+
| + 313 + | +
+
+ -
+
+ |
+
| + 314 + | +
+
+ -
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 315 + | +
+
+
+ tasks.register('foo') {
+
+ |
+
| + 316 + | +
+
+
+ dependsOn ':a:writeClasspath'
+
+ |
+
| + 317 + | +
+
+
+ }
+
+ |
+
| + 318 + | +
+
+ -
+
+ |
+
| + 319 + | +
+
+ -
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 320 + | +
+
+
+ tasks.register('bar') {
+
+ |
+
| + 321 + | +
+
+
+ dependsOn ':b:foo'
+
+ |
+
| + 322 + | +
+
+
+ }
+
+ |
+
| + 323 + | +
+
+ -
+
+ |
+
| + 324 + | +
+
+ -
+
+ |
+
| + 325 + | +
+
+ -
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 326 + | +
+
+
+ dependencies {
+
+ |
+
| + 327 + | +
+
+
+ implementation 'com.example:transitive-test-dep:1.1.0'
+
+ |
+
| + 328 + | +
+
+
+ }
+
+ |
+
| + 329 + | +
+
+ -
+
+ |
+
| + 330 + | +
+
+
+
+ + |
+
| + 331 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 332 + | +
+
+ -
+
+ |
+
| + 333 + | +
+
+ -
+
+ |
+
| + 334 + | +
+
+ -
+ BuildResult result = runTasks(':c:bar')
+
+ |
+
| + 335 + | +
+
+
+
+ + |
+
| + 336 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 337 + | +
+
+ -
+ then:
+
+ |
+
| + 338 + | +
+
+
+ // Version used should be 1.1.0, indicating that the version.lock constraint was applied
+
+ |
+
| + 339 + | +
+
+ -
+ result.output.contains(
+ |
+
| + 340 + | +
+
+ -
+
+ + |
+
| + 341 + | +
+
+ -
+ where:
+
+ |
+
| + 342 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 343 + | +
+
+
+ }
+
+ |
+
| + 344 + | +
+
+
+
+ + |
+
| + 345 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: verification_tasks_pass_when_all_projects_are_configured
+
+ |
+
| + 346 + | +
+
+ -
+
+ |
+
| + 347 + | +
+
+ -
+
+ |
+
| + 348 + | +
+
+ -
+ gradleVersion = gradleVersionNumber
+
+ |
+
| + 349 + | +
+
+ -
+
+ + |
+
| + 350 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 351 + | +
+
+ -
+
+ |
+
| + 352 + | +
+
+ -
+ runTasks('--write-locks')
+
+ |
+
| + 353 + | +
+
+
+ // Note: Not specifying the project causes all projects to be configured regardless of CoD
+
+ |
+
| + 354 + | +
+
+ -
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 355 + | +
+
+
+
+ + |
+
| + 356 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 357 + | +
+
+ -
+
+ |
+
| + 358 + | +
+
+ -
+ result.
+ |
+
| + 359 + | +
+
+ -
+ result.task(
+ |
+
| + 360 + | +
+
+ -
+ result.task(':verifyLocks').outcome == TaskOutcome.SUCCESS
+
+ |
+
| + 361 + | +
+
+ -
+
+ + |
+
| + 362 + | +
+
+ -
+ where:
+
+ |
+
| + 363 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 364 + | +
+
+
+ }
+
+ |
+
| + 365 + | +
+
+
+
+ + |
+
| + 366 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: checkUnusedConstraints_succeeds_when_not_all_projects_are_configured
+
+ |
+
| + 367 + | +
+
+ -
+
+ |
+
| + 368 + | +
+
+ -
+
+ |
+
| + 369 + | +
+
+ -
+ gradleVersion = gradleVersionNumber
+
+ |
+
| + 370 + | +
+
+ -
+
+ + |
+
| + 371 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 372 + | +
+
+ -
+
+ |
+
| + 373 + | +
+
+ -
+
+ |
+
| + 374 + | +
+
+ -
+ BuildResult result = runTasks(':checkUnusedConstraints')
+
+ |
+
| + 375 + | +
+
+
+
+ + |
+
| + 376 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 377 + | +
+
+ -
+
+ |
+
| + 378 + | +
+
+ -
+ result.
+ |
+
| + 379 + | +
+
+ -
+ result.output.contains('configuring upstream')
+
+ |
+
| + 380 + | +
+
+ -
+
+ + |
+
| + 381 + | +
+
+ -
+ where:
+
+ |
+
| + 382 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 383 + | +
+
+
+ }
+
+ |
+
| + 384 + | +
+
+
+
+ + |
+
| + 385 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: verifyLocks_fails_and_warns_when_not_all_projects_are_configured
+
+ |
+
| + 386 + | +
+
+ -
+
+ |
+
| + 387 + | +
+
+ -
+
+ |
+
| + 388 + | +
+
+ -
+ gradleVersion = gradleVersionNumber
+
+ |
+
| + 389 + | +
+
+ -
+
+ + |
+
| + 390 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 391 + | +
+
+ -
+
+ |
+
| + 392 + | +
+
+ -
+
+ |
+
| + 393 + | +
+
+ -
+ BuildResult result = runTasksAndFail(':verifyLocks')
+
+ |
+
| + 394 + | +
+
+
+
+ + |
+
| + 395 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 396 + | +
+
+ -
+
+ |
+
| + 397 + | +
+
+ -
+
+ |
+
| + 398 + | +
+
+ -
+
+ |
+
| + 399 + | +
+
+ -
+
+ |
+
| + 400 + | +
+
+ -
+
+ |
+
| + 401 + | +
+
+ -
+
+ + |
+
| + 402 + | +
+
+ -
+ where:
+
+ |
+
| + 403 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 404 + | +
+
+
+ }
+
+ |
+
| + 405 + | +
+
+
+
+ + |
+
| + 406 + | +
+
+
+ // As failing tasks can't be considered UP-TO-DATE, we only need to check the case where the task passing
+
+ |
+
| + 407 + | +
+
+
+ // is followed by the task running with incomplete configuration.
+
+ |
+
| + 408 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: verification_tasks_are_not_UP_TO_DATE_when_the_set_of_configured_projects_differs
+
+ |
+
| + 409 + | +
+
+ -
+
+ |
+
| + 410 + | +
+
+ -
+
+ |
+
| + 411 + | +
+
+ -
+ gradleVersion = gradleVersionNumber
+
+ |
+
| + 412 + | +
+
+ -
+
+ + |
+
| + 413 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 414 + | +
+
+ -
+
+ |
+
| + 415 + | +
+
+ -
+
+ |
+
| + 416 + | +
+
+ -
+ runTasks('build')
+
+ |
+
| + 417 + | +
+
+
+
+ + |
+
| + 418 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 419 + | +
+
+ -
+
+ |
+
| + 420 + | +
+
+ -
+ runTasksAndFail(':verifyLocks')
+
+ |
+
| + 421 + | +
+
+ -
+
+ + |
+
| + 422 + | +
+
+ -
+ where:
+
+ |
+
| + 423 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 424 + | +
+
+
+ }
+
+ |
+
| + 425 + | +
+
+
+
+ + |
+
| + 426 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: the_why_task_works_when_all_projects_are_configured
+
+ |
+
| + 427 + | +
+
+ -
+
+ |
+
| + 428 + | +
+
+ -
+
+ |
+
| + 429 + | +
+
+ -
+ gradleVersion = gradleVersionNumber
+
+ |
+
| + 430 + | +
+
+ -
+
+ + |
+
| + 431 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 432 + | +
+
+ -
+
+ |
+
| + 433 + | +
+
+ -
+
+ |
+
| + 434 + | +
+
+ -
+ BuildResult result = runTasks('why', '--hash=0805f935')
+
+ |
+
| + 435 + | +
+
+
+
+ + |
+
| + 436 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 437 + | +
+
+ -
+
+ |
+
| + 438 + | +
+
+ -
+ result.task(':why').outcome == TaskOutcome.SUCCESS
+
+ |
+
| + 439 + | +
+
+ -
+
+ + |
+
| + 440 + | +
+
+ -
+ where:
+
+ |
+
| + 441 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 442 + | +
+
+
+ }
+
+ |
+
| + 443 + | +
+
+
+
+ + |
+
| + 444 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: the_why_task_somehow_forces_all_projects_to_be_configured
+
+ |
+
| + 445 + | +
+
+ -
+
+ |
+
| + 446 + | +
+
+ -
+
+ |
+
| + 447 + | +
+
+ -
+ gradleVersion = gradleVersionNumber
+
+ |
+
| + 448 + | +
+
+ -
+
+ + |
+
| + 449 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 450 + | +
+
+ -
+
+ |
+
| + 451 + | +
+
+ -
+
+ |
+
| + 452 + | +
+
+ -
+ BuildResult result = runTasks(':why', '--hash=0805f935')
+
+ |
+
| + 453 + | +
+
+
+
+ + |
+
| + 454 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 455 + | +
+
+ -
+
+ |
+
| + 456 + | +
+
+ -
+
+ |
+
| + 457 + | +
+
+ -
+
+ |
+
| + 458 + | +
+
+ -
+
+ |
+
| + 459 + | +
+
+ -
+
+ |
+
| + 460 + | +
+
+ -
+
+ |
+
| + 461 + | +
+
+ -
+
+ |
+
| + 462 + | +
+
+ -
+
+ + |
+
| + 463 + | +
+
+ -
+ where:
+
+ |
+
| + 464 + | +
+
+ -
+ gradleVersionNumber << GRADLE_VERSIONS
+
+ |
+
| + 465 + | +
+
+
+ }
+
+ |
+
| + 466 + | +
+
+
+ }
+
+ |
+
| + |
+ |
+
| + 14 + | +
+
+
+ * limitations under the License.
+
+ |
+
| + 15 + | +
+
+
+ */
+
+ |
+
| + 16 + | +
+
+
+
+ + |
+
| + 17 + | +
+
+ +
+ package com.palantir.gradle.versions;
+
+ |
+
| + 18 + | +
+
+ +
+
+ + |
+
| + 19 + | +
+
+ +
+ import static com.palantir.gradle.testing.assertion.GradlePluginTestAssertions.assertThat;
+
+ |
+
| + 20 + | +
+
+ +
+ import static org.assertj.core.api.Assertions.assertThat;
+
+ |
+
| + 21 + | +
+
+ +
+
+ + |
+
| + 22 + | +
+
+ +
+ import com.palantir.gradle.testing.execution.GradleInvoker;
+
+ |
+
| + 23 + | +
+
+ +
+ import com.palantir.gradle.testing.execution.InvocationResult;
+
+ |
+
| + 24 + | +
+
+ +
+ import com.palantir.gradle.testing.junit.DisabledConfigurationCache;
+
+ |
+
| + 25 + | +
+
+ +
+ import com.palantir.gradle.testing.junit.GradlePluginTests;
+
+ |
+
| + 26 + | +
+
+ +
+ import com.palantir.gradle.testing.maven.MavenArtifact;
+
+ |
+
| + 27 + | +
+
+ +
+ import com.palantir.gradle.testing.maven.MavenRepo;
+
+ |
+
| + 28 + | +
+
+ +
+ import com.palantir.gradle.testing.project.RootProject;
+
+ |
+
| + 29 + | +
+
+ +
+ import com.palantir.gradle.testing.project.SubProject;
+
+ |
+
| + 30 + | +
+
+ +
+ import java.io.UncheckedIOException;
+
+ |
+
| + 31 + | +
+
+ +
+ import org.junit.jupiter.api.BeforeEach;
+
+ |
+
| + 32 + | +
+
+ +
+ import org.junit.jupiter.api.Test;
+
+ |
+
| + 33 + | +
+
+
+
+ + |
+
| + 34 + | +
+
+
+ /**
+
+ |
+
| + 35 + | +
+
+
+ * This tests the interaction of this plugin with Gradle's configuration-on-demand feature:
+
+ |
+
| + 36 + | +
+
+
+ * https://docs.gradle.org/current/userguide/multi_project_configuration_and_execution.html#sec:configuration_on_demand
+
+ |
+
| + 37 + | +
+
+
+ */
+
+ |
+
| + 38 + | +
+
+ +
+ @GradlePluginTests
+
+ |
+
| + 39 + | +
+
+ +
+ @DisabledConfigurationCache
+
+ |
+
| + 40 + | +
+
+ +
+ class ConfigurationOnDemandTest {
+
+ |
+
| + 41 + | +
+
+
+
+ + |
+
| + 42 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: PLUGIN_NAME
+
+ |
+
| + 43 + | +
+
+ +
+ private static final String PLUGIN_NAME = "com.palantir.consistent-versions";
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 44 + | +
+
+
+
+ + |
+
| + 45 + | +
+
+
+ /*
+
+ |
+
| + 46 + | +
+
+
+ * Project structure (arrows indicate dependencies):
+
+ |
+
| + |
+ |
+
| + 51 + | +
+
+
+ * downstream1 downstream2
+
+ |
+
| + 52 + | +
+
+
+ */
+
+ |
+
| + 53 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: setup
+
+ |
+
| + 54 + | +
+
+ +
+ @BeforeEach
+
+ |
+
| + 55 + | +
+
+ +
+ void setup(
+
+ |
+
| + 56 + | +
+
+ +
+ MavenRepo repo,
+
+ |
+
| + 57 + | +
+
+ +
+ RootProject rootProject,
+
+ |
+
| + 58 + | +
+
+ +
+ SubProject upstream,
+
+ |
+
| + 59 + | +
+
+ +
+ SubProject downstream1,
+
+ |
+
| + 60 + | +
+
+ +
+ SubProject downstream2,
+
+ |
+
| + 61 + | +
+
+ +
+ SubProject unrelated) {
+
+ |
+
| + 62 + | +
+
+ +
+ // ***DELINEATOR FOR REVIEW: mavenRepo
+
+ |
+
| + 63 + | +
+
+ +
+ repo.publish(
+
+ |
+
| + 64 + | +
+
+ +
+ MavenArtifact.of("com.example:dependency-of-upstream:1.2.3"),
+
+ |
+
| + 65 + | +
+
+ +
+ MavenArtifact.of("com.example:dependency-of-upstream:100.1.1"),
+
+ |
+
| + 66 + | +
+
+ +
+ MavenArtifact.of("com.example:dependency-of-downstream1:1.2.3"),
+
+ |
+
| + 67 + | +
+
+ +
+ MavenArtifact.of("com.example:dependency-of-downstream2:1.2.3"),
+
+ |
+
| + 68 + | +
+
+ +
+ MavenArtifact.of("com.example:dependency-of-unrelated:1.2.3"),
+
+ |
+
| + 69 + | +
+
+ +
+ MavenArtifact.of("com.example:dep-with-version-bumped-by-unrelated:1.0.0"),
+
+ |
+
| + 70 + | +
+
+ +
+ MavenArtifact.of("com.example:dep-with-version-bumped-by-unrelated:1.1.0"),
+
+ |
+
| + 71 + | +
+
+ +
+ MavenArtifact.of("com.example:transitive-test-dep:1.0.0"),
+
+ |
+
| + 72 + | +
+
+ +
+ MavenArtifact.of("com.example:transitive-test-dep:1.1.0"),
+
+ |
+
| + 73 + | +
+
+ +
+ MavenArtifact.of("com.example:transitive-test-dep:1.2.0"));
+
+ |
+
| + 74 + | +
+
+ +
+
+ + |
+
| + 75 + | +
+
+ +
+ makePlatformPom(repo, "org", "platform", "1.0");
+
+ |
+
| + 76 + | +
+
+ +
+
+ + |
+
| + 77 + | +
+
+ +
+ rootProject.buildGradle().plugins().add(PLUGIN_NAME);
+
+ |
+
| + 78 + | +
+
+ +
+ rootProject.buildGradle().withMavenRepo(repo);
+
+ |
+
| + 79 + | +
+
+ +
+ rootProject.buildGradle().append("""
+
+ |
+
| + 80 + | +
+
+
+ allprojects {
+
+ |
+
| + 81 + | +
+
+
+ repositories {
+
+ |
+
| + 82 + | +
+
+ +
+ maven { url "%s" }
+
+ |
+
| + 83 + | +
+
+
+ }
+
+ |
+
| + 84 + | +
+
+
+ }
+
+ |
+
| + 85 + | +
+
+
+ subprojects {
+
+ |
+
| + |
+ |
+
| + 89 + | +
+
+
+ }
+
+ |
+
| + 90 + | +
+
+
+ }
+
+ |
+
| + 91 + | +
+
+
+ }
+
+ |
+
| + 92 + | +
+
+ +
+
+ + |
+
| + 93 + | +
+
+
+ // Get rid of deprecation warnings for Gradle 7+
+
+ |
+
| + 94 + | +
+
+
+ versionRecommendations {
+
+ |
+
| + 95 + | +
+
+
+ excludeConfigurations 'compile', 'runtime', 'testCompile', 'testRuntime'
+
+ |
+
| + 96 + | +
+
+
+ }
+
+ |
+
| + 97 + | +
+
+ +
+ """, repo.path().toUri());
+
+ |
+
| + 98 + | +
+
+
+
+ + |
+
| + 99 + | +
+
+ +
+ rootProject.file("versions.props").overwrite("""
+
+ |
+
| + 100 + | +
+
+
+ com.example:dependency-of-upstream = 1.2.3
+
+ |
+
| + 101 + | +
+
+
+ com.example:dependency-of-downstream1 = 1.2.3
+
+ |
+
| + 102 + | +
+
+
+ com.example:dependency-of-downstream2 = 1.2.3
+
+ |
+
| + 103 + | +
+
+
+ com.example:dependency-of-unrelated = 1.2.3
+
+ |
+
| + 104 + | +
+
+
+ # 1.0.0 is a minimum, we expect this to be locked to 1.1.0
+
+ |
+
| + 105 + | +
+
+
+ com.example:dep-with-version-bumped-by-unrelated = 1.0.0
+
+ |
+
| + 106 + | +
+
+ +
+ """);
+
+ |
+
| + 107 + | +
+
+
+
+ + |
+
| + 108 + | +
+
+ +
+ upstream.buildGradle().plugins().add("java");
+
+ |
+
| + 109 + | +
+
+ +
+ upstream.buildGradle().append("""
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 110 + | +
+
+
+ println 'configuring upstream'
+
+ |
+
| + 111 + | +
+
+
+ dependencies {
+
+ |
+
| + 112 + | +
+
+
+ implementation 'com.example:dependency-of-upstream'
+
+ |
+
| + 113 + | +
+
+
+ }
+
+ |
+
| + 114 + | +
+
+ +
+ """);
+
+ |
+
| + 115 + | +
+
+
+
+ + |
+
| + 116 + | +
+
+ +
+ downstream1.buildGradle().plugins().add("java");
+
+ |
+
| + 117 + | +
+
+ +
+ downstream1.buildGradle().append("""
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 118 + | +
+
+
+ println 'configuring downstream1'
+
+ |
+
| + 119 + | +
+
+
+ dependencies {
+
+ |
+
| + 120 + | +
+
+
+ implementation project(':upstream')
+
+ |
+
| + 121 + | +
+
+
+ implementation 'com.example:dependency-of-downstream1'
+
+ |
+
| + 122 + | +
+
+
+ }
+
+ |
+
| + 123 + | +
+
+ +
+ """);
+
+ |
+
| + 124 + | +
+
+
+
+ + |
+
| + 125 + | +
+
+ +
+ downstream2.buildGradle().plugins().add("java");
+
+ |
+
| + 126 + | +
+
+ +
+ downstream2.buildGradle().append("""
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 127 + | +
+
+
+ println 'configuring downstream2'
+
+ |
+
| + 128 + | +
+
+
+ dependencies {
+
+ |
+
| + 129 + | +
+
+
+ implementation project(':upstream')
+
+ |
+
| + 130 + | +
+
+
+ implementation 'com.example:dependency-of-downstream2'
+
+ |
+
| + 131 + | +
+
+
+ implementation 'com.example:dep-with-version-bumped-by-unrelated'
+
+ |
+
| + 132 + | +
+
+
+ }
+
+ |
+
| + 133 + | +
+
+ +
+ """);
+
+ |
+
| + 134 + | +
+
+
+
+ + |
+
| + 135 + | +
+
+ +
+ unrelated.buildGradle().plugins().add("java");
+
+ |
+
| + 136 + | +
+
+ +
+ unrelated.buildGradle().append("""
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 137 + | +
+
+
+ println 'configuring unrelated'
+
+ |
+
| + 138 + | +
+
+
+ dependencies {
+
+ |
+
| + 139 + | +
+
+
+ implementation 'com.example:dependency-of-unrelated'
+
+ |
+
| + 140 + | +
+
+
+ implementation 'com.example:dep-with-version-bumped-by-unrelated:1.1.0'
+
+ |
+
| + 141 + | +
+
+
+ }
+
+ |
+
| + 142 + | +
+
+ +
+ """);
+
+ |
+
| + 143 + | +
+
+
+
+ + |
+
| + 144 + | +
+
+ +
+ rootProject.gradlePropertiesFile().appendProperty("org.gradle.configureondemand", "true");
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 145 + | +
+
+
+ }
+
+ |
+
| + 146 + | +
+
+
+
+ + |
+
| + 147 + | +
+
+ +
+ // Helper method to create a platform POM similar to PomUtils.makePlatformPom
+
+ |
+
| + 148 + | +
+
+ +
+ private void makePlatformPom(MavenRepo repo, String group, String name, String version) {
+
+ |
+
| + 149 + | +
+
+ +
+ java.nio.file.Path pomPath =
+
+ |
+
| + 150 + | +
+
+ +
+ repo.path().resolve(group).resolve(name).resolve(version).resolve("platform-1.0.pom");
+
+ |
+
| + 151 + | +
+
+ +
+
+ + |
+
| + 152 + | +
+
+ +
+ try {
+
+ |
+
| + 153 + | +
+
+ +
+ java.nio.file.Files.createDirectories(pomPath.getParent());
+
+ |
+
| + 154 + | +
+
+ +
+ java.nio.file.Files.writeString(pomPath, """
+
+ |
+
| + 155 + | +
+
+ +
+ <?xml version="1.0" encoding="UTF-8"?>
+
+ |
+
| + 156 + | +
+
+ +
+ <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+
+ |
+
| + 157 + | +
+
+ +
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ |
+
| + 158 + | +
+
+ +
+ <modelVersion>4.0.0</modelVersion>
+
+ |
+
| + 159 + | +
+
+ +
+ <packaging>pom</packaging>
+
+ |
+
| + 160 + | +
+
+ +
+ <groupId>%s</groupId>
+
+ |
+
| + 161 + | +
+
+ +
+ <artifactId>%s</artifactId>
+
+ |
+
| + 162 + | +
+
+ +
+ <version>%s</version>
+
+ |
+
| + 163 + | +
+
+ +
+ <dependencyManagement>
+
+ |
+
| + 164 + | +
+
+ +
+ <dependencies>
+
+ |
+
| + 165 + | +
+
+ +
+ </dependencies>
+
+ |
+
| + 166 + | +
+
+ +
+ </dependencyManagement>
+
+ |
+
| + 167 + | +
+
+ +
+ </project>
+
+ |
+
| + 168 + | +
+
+ +
+ """.formatted(group, name, version));
+
+ |
+
| + 169 + | +
+
+ +
+ } catch (java.io.IOException e) {
+
+ |
+
| + 170 + | +
+
+ +
+ throw new UncheckedIOException(e);
+
+ |
+
| + 171 + | +
+
+ +
+ }
+
+ |
+
| + 172 + | +
+
+ +
+ }
+
+ |
+
| + 173 + | +
+
+
+
+ + |
+
| + 174 + | +
+
+ +
+ // ***DELINEATOR FOR REVIEW: can_write_locks
+
+ |
+
| + 175 + | +
+
+ +
+ @Test
+
+ |
+
| + 176 + | +
+
+ +
+ void can_write_locks(GradleInvoker gradle, RootProject rootProject) {
+
+ |
+
| + 177 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 178 + | +
+
+ +
+ InvocationResult result = gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 179 + | +
+
+
+
+ + |
+
| + 180 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 181 + | +
+
+ +
+ assertThat(result)
+
+ |
+
| + 182 + | +
+
+ +
+ .output()
+
+ |
+
| + 183 + | +
+
+ +
+ .contains("configuring upstream")
+
+ |
+
| + 184 + | +
+
+ +
+ .contains("configuring downstream1")
+
+ |
+
| + 185 + | +
+
+ +
+ .contains("configuring downstream2")
+
+ |
+
| + 186 + | +
+
+ +
+ .contains("configuring unrelated");
+
+ |
+
| + 187 + | +
+
+ +
+
+ + |
+
| + 188 + | +
+
+ +
+ rootProject.file("versions.lock").assertThat().exists();
+
+ |
+
| + 189 + | +
+
+ +
+ assertThat(rootProject.file("versions.lock").text())
+
+ |
+
| + 190 + | +
+
+ +
+ .contains("com.example:dependency-of-upstream:1.2.3")
+
+ |
+
| + 191 + | +
+
+ +
+ .contains("com.example:dep-with-version-bumped-by-unrelated:1.1.0");
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 192 + | +
+
+
+ }
+
+ |
+
| + 193 + | +
+
+
+
+ + |
+
| + 194 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: can_write_locks_when_a_task_in_one_project_is_specified
+
+ |
+
| + 195 + | +
+
+ +
+ @Test
+
+ |
+
| + 196 + | +
+
+ +
+ void can_write_locks_when_a_task_in_one_project_is_specified(GradleInvoker gradle, RootProject rootProject) {
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 197 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 198 + | +
+
+ +
+ gradle.withArgs(":downstream1:build", "--write-locks").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 199 + | +
+
+
+
+ + |
+
| + 200 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 201 + | +
+
+ +
+ rootProject.file("versions.lock").assertThat().exists();
+
+ |
+
| + 202 + | +
+
+ +
+ assertThat(rootProject.file("versions.lock").text())
+
+ |
+
| + 203 + | +
+
+ +
+ .contains("com.example:dependency-of-unrelated:1.2.3")
+
+ |
+
| + 204 + | +
+
+ +
+ .contains("com.example:dep-with-version-bumped-by-unrelated:1.1.0");
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 205 + | +
+
+
+ }
+
+ |
+
| + 206 + | +
+
+
+
+ + |
+
| + 207 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: applying_the_plugin_does_not_force_all_projects_to_be_configured
+
+ |
+
| + 208 + | +
+
+ +
+ @Test
+
+ |
+
| + 209 + | +
+
+ +
+ void applying_the_plugin_does_not_force_all_projects_to_be_configured(GradleInvoker gradle) {
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 210 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 211 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 212 + | +
+
+
+ // Both absolute and relative formats work, as long as Gradle is run from the root project directory
+
+ |
+
| + 213 + | +
+
+ +
+ InvocationResult result1 = gradle.withArgs(":downstream1:build").buildsSuccessfully();
+
+ |
+
| + 214 + | +
+
+ +
+ InvocationResult result2 = gradle.withArgs("downstream1:build").buildsSuccessfully();
+
+ |
+
| + 215 + | +
+
+
+
+ + |
+
| + 216 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 217 + | +
+
+ +
+ assertThat(result1)
+
+ |
+
| + 218 + | +
+
+ +
+ .output()
+
+ |
+
| + 219 + | +
+
+ +
+ .contains("configuring upstream")
+
+ |
+
| + 220 + | +
+
+ +
+ .contains("configuring downstream1")
+
+ |
+
| + 221 + | +
+
+ +
+ .doesNotContain("configuring downstream2")
+
+ |
+
| + 222 + | +
+
+ +
+ .doesNotContain("configuring unrelated");
+
+ |
+
| + 223 + | +
+
+ +
+
+ + |
+
| + 224 + | +
+
+ +
+ assertThat(result2)
+
+ |
+
| + 225 + | +
+
+ +
+ .output()
+
+ |
+
| + 226 + | +
+
+ +
+ .contains("configuring upstream")
+
+ |
+
| + 227 + | +
+
+ +
+ .contains("configuring downstream1")
+
+ |
+
| + 228 + | +
+
+ +
+ .doesNotContain("configuring downstream2")
+
+ |
+
| + 229 + | +
+
+ +
+ .doesNotContain("configuring unrelated");
+
+ |
+
| + 230 + | +
+
+
+ }
+
+ |
+
| + 231 + | +
+
+
+
+ + |
+
| + 232 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: resolving_a_classpath_does_not_force_all_projects_to_be_configured
+
+ |
+
| + 233 + | +
+
+ +
+ @Test
+
+ |
+
| + 234 + | +
+
+ +
+ void resolving_a_classpath_does_not_force_all_projects_to_be_configured(GradleInvoker gradle) {
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 235 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 236 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + 237 + | +
+
+ +
+ InvocationResult result = gradle.withArgs(":downstream1:writeClasspath").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 238 + | +
+
+
+
+ + |
+
| + 239 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 240 + | +
+
+ +
+ assertThat(result)
+
+ |
+
| + 241 + | +
+
+ +
+ .output()
+
+ |
+
| + 242 + | +
+
+ +
+ .contains("configuring upstream")
+
+ |
+
| + 243 + | +
+
+ +
+ .contains("configuring downstream1")
+
+ |
+
| + 244 + | +
+
+ +
+ .doesNotContain("configuring downstream2")
+
+ |
+
| + 245 + | +
+
+ +
+ .doesNotContain("configuring unrelated");
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 246 + | +
+
+
+ }
+
+ |
+
| + 247 + | +
+
+
+
+ + |
+
| + 248 + | +
+
+ +
+ // ***DELINEATOR FOR REVIEW:
+
+ |
+
| + 249 + | +
+
+ +
+ // after_lockfile_is_written_versions_constraints_due_to_non_configured_projects_are_still_respected
+
+ |
+
| + 250 + | +
+
+ +
+ @Test
+
+ |
+
| + 251 + | +
+
+ +
+ void after_lockfile_is_written_versions_constraints_due_to_non_configured_projects_are_still_respected(
+
+ |
+
| + 252 + | +
+
+ +
+ GradleInvoker gradle) {
+
+ |
+
| + 253 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 254 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + 255 + | +
+
+ +
+ InvocationResult result = gradle.withArgs(":downstream2:writeClasspath").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 256 + | +
+
+
+
+ + |
+
| + 257 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 258 + | +
+
+
+ // Version used is 1.1.0 due to the unrelated project
+
+ |
+
| + 259 + | +
+
+ +
+ assertThat(result)
+
+ |
+
| + 260 + | +
+
+ +
+ .output()
+
+ |
+
| + 261 + | +
+
+ +
+ .contains("dep-with-version-bumped-by-unrelated-1.1.0.jar")
+
+ |
+
| + 262 + | +
+
+ +
+ .doesNotContain("configured unrelated");
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 263 + | +
+
+
+ }
+
+ |
+
| + 264 + | +
+
+
+
+ + |
+
| + 265 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: transitive_dependencies_cause_upstream_projects_to_be_configured_sufficiently_early
+
+ |
+
| + 266 + | +
+
+ +
+ @Test
+
+ |
+
| + 267 + | +
+
+ +
+ void transitive_dependencies_cause_upstream_projects_to_be_configured_sufficiently_early(
+
+ |
+
| + 268 + | +
+
+ +
+ GradleInvoker gradle, SubProject a, SubProject b, SubProject c, SubProject u) {
+
+ |
+
| + 269 + | +
+
+ +
+ a.buildGradle().plugins().add("java");
+
+ |
+
| + 270 + | +
+
+ +
+ a.buildGradle().append("""
+
+ |
+
| + 271 + | +
+
+
+ dependencies {
+
+ |
+
| + 272 + | +
+
+
+ implementation 'com.example:transitive-test-dep:1.0.0'
+
+ |
+
| + 273 + | +
+
+
+ }
+
+ |
+
| + 274 + | +
+
+ +
+ """);
+
+ |
+
| + 275 + | +
+
+ +
+
+ + |
+
| + 276 + | +
+
+ +
+ b.buildGradle().plugins().add("java");
+
+ |
+
| + 277 + | +
+
+ +
+ b.buildGradle().append("""
+
+ |
+
| + 278 + | +
+
+
+ dependencies {
+
+ |
+
| + 279 + | +
+
+
+ implementation project(':a')
+
+ |
+
| + 280 + | +
+
+
+ }
+
+ |
+
| + 281 + | +
+
+ +
+ """);
+
+ |
+
| + 282 + | +
+
+ +
+
+ + |
+
| + 283 + | +
+
+ +
+ c.buildGradle().plugins().add("java");
+
+ |
+
| + 284 + | +
+
+ +
+ c.buildGradle().append("""
+
+ |
+
| + 285 + | +
+
+
+ dependencies {
+
+ |
+
| + 286 + | +
+
+
+ implementation project(':b')
+
+ |
+
| + 287 + | +
+
+
+ }
+
+ |
+
| + |
+ |
+
| + 290 + | +
+
+
+ println project(':a').configurations.runtimeClasspath.files
+
+ |
+
| + 291 + | +
+
+
+ }
+
+ |
+
| + 292 + | +
+
+
+ }
+
+ |
+
| + 293 + | +
+
+ +
+ """);
+
+ |
+
| + 294 + | +
+
+ +
+
+ + |
+
| + 295 + | +
+
+ +
+ u.buildGradle().plugins().add("java");
+
+ |
+
| + 296 + | +
+
+ +
+ u.buildGradle().append("""
+
+ |
+
| + 297 + | +
+
+
+ dependencies {
+
+ |
+
| + 298 + | +
+
+
+ implementation 'com.example:transitive-test-dep:1.1.0'
+
+ |
+
| + 299 + | +
+
+
+ }
+
+ |
+
| + 300 + | +
+
+ +
+ """);
+
+ |
+
| + 301 + | +
+
+
+
+ + |
+
| + 302 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 303 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + 304 + | +
+
+ +
+ InvocationResult result = gradle.withArgs(":c:writeClasspathOfA").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 305 + | +
+
+
+
+ + |
+
| + 306 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 307 + | +
+
+
+ // Version used should be 1.1.0, indicating that the version.lock constraint was applied
+
+ |
+
| + 308 + | +
+
+ +
+ assertThat(result).output().contains("transitive-test-dep-1.1.0.jar");
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 309 + | +
+
+
+ }
+
+ |
+
| + 310 + | +
+
+
+
+ + |
+
| + 311 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: task_dependencies_cause_upstream_projects_to_be_configured_sufficiently_early
+
+ |
+
| + 312 + | +
+
+ +
+ @Test
+
+ |
+
| + 313 + | +
+
+ +
+ void task_dependencies_cause_upstream_projects_to_be_configured_sufficiently_early(
+
+ |
+
| + 314 + | +
+
+ +
+ GradleInvoker gradle, SubProject a, SubProject b, SubProject c, SubProject u) {
+
+ |
+
| + 315 + | +
+
+ +
+ a.buildGradle().plugins().add("java");
+
+ |
+
| + 316 + | +
+
+ +
+ a.buildGradle().append("""
+
+ |
+
| + 317 + | +
+
+
+ dependencies {
+
+ |
+
| + 318 + | +
+
+
+ implementation 'com.example:transitive-test-dep:1.0.0'
+
+ |
+
| + 319 + | +
+
+
+ }
+
+ |
+
| + 320 + | +
+
+ +
+ """);
+
+ |
+
| + 321 + | +
+
+ +
+
+ + |
+
| + 322 + | +
+
+ +
+ b.buildGradle().append("""
+
+ |
+
| + 323 + | +
+
+
+ tasks.register('foo') {
+
+ |
+
| + 324 + | +
+
+
+ dependsOn ':a:writeClasspath'
+
+ |
+
| + 325 + | +
+
+
+ }
+
+ |
+
| + 326 + | +
+
+ +
+ """);
+
+ |
+
| + 327 + | +
+
+ +
+
+ + |
+
| + 328 + | +
+
+ +
+ c.buildGradle().append("""
+
+ |
+
| + 329 + | +
+
+
+ tasks.register('bar') {
+
+ |
+
| + 330 + | +
+
+
+ dependsOn ':b:foo'
+
+ |
+
| + 331 + | +
+
+
+ }
+
+ |
+
| + 332 + | +
+
+ +
+ """);
+
+ |
+
| + 333 + | +
+
+ +
+
+ + |
+
| + 334 + | +
+
+ +
+ u.buildGradle().plugins().add("java");
+
+ |
+
| + 335 + | +
+
+ +
+ u.buildGradle().append("""
+
+ |
+
| + 336 + | +
+
+
+ dependencies {
+
+ |
+
| + 337 + | +
+
+
+ implementation 'com.example:transitive-test-dep:1.1.0'
+
+ |
+
| + 338 + | +
+
+
+ }
+
+ |
+
| + 339 + | +
+
+ +
+ """);
+
+ |
+
| + 340 + | +
+
+
+
+ + |
+
| + 341 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 342 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + 343 + | +
+
+ +
+ InvocationResult result = gradle.withArgs(":c:bar").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 344 + | +
+
+
+
+ + |
+
| + 345 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 346 + | +
+
+
+ // Version used should be 1.1.0, indicating that the version.lock constraint was applied
+
+ |
+
| + 347 + | +
+
+ +
+ assertThat(result).output().contains("transitive-test-dep-1.1.0.jar");
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 348 + | +
+
+
+ }
+
+ |
+
| + 349 + | +
+
+
+
+ + |
+
| + 350 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: verification_tasks_pass_when_all_projects_are_configured
+
+ |
+
| + 351 + | +
+
+ +
+ @Test
+
+ |
+
| + 352 + | +
+
+ +
+ void verification_tasks_pass_when_all_projects_are_configured(GradleInvoker gradle) {
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 353 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 354 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 355 + | +
+
+
+ // Note: Not specifying the project causes all projects to be configured regardless of CoD
+
+ |
+
| + 356 + | +
+
+ +
+ InvocationResult result =
+
+ |
+
| + 357 + | +
+
+ +
+ gradle.withArgs("checkUnusedConstraints", "verifyLocks").buildsSuccessfully();
+
+ |
+
| + 358 + | +
+
+
+
+ + |
+
| + 359 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 360 + | +
+
+ +
+ assertThat(result).output().contains("configuring upstream");
+
+ |
+
| + 361 + | +
+
+ +
+ assertThat(result).task(":checkUnusedConstraints").succeeded();
+
+ |
+
| + 362 + | +
+
+ +
+ assertThat(result).task(":verifyLocks").succeeded();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 363 + | +
+
+
+ }
+
+ |
+
| + 364 + | +
+
+
+
+ + |
+
| + 365 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: checkUnusedConstraints_succeeds_when_not_all_projects_are_configured
+
+ |
+
| + 366 + | +
+
+ +
+ @Test
+
+ |
+
| + 367 + | +
+
+ +
+ void checkUnusedConstraints_succeeds_when_not_all_projects_are_configured(GradleInvoker gradle) {
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 368 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 369 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + 370 + | +
+
+ +
+ InvocationResult result = gradle.withArgs(":checkUnusedConstraints").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 371 + | +
+
+
+
+ + |
+
| + 372 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 373 + | +
+
+ +
+ assertThat(result).task(":checkUnusedConstraints").succeeded();
+
+ |
+
| + 374 + | +
+
+ +
+ assertThat(result).output().contains("configuring upstream");
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 375 + | +
+
+
+ }
+
+ |
+
| + 376 + | +
+
+
+
+ + |
+
| + 377 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: verifyLocks_fails_and_warns_when_not_all_projects_are_configured
+
+ |
+
| + 378 + | +
+
+ +
+ @Test
+
+ |
+
| + 379 + | +
+
+ +
+ void verifyLocks_fails_and_warns_when_not_all_projects_are_configured(GradleInvoker gradle) {
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 380 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 381 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + 382 + | +
+
+ +
+ InvocationResult result = gradle.withArgs(":verifyLocks").buildsWithFailure();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 383 + | +
+
+
+
+ + |
+
| + 384 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 385 + | +
+
+ +
+ assertThat(result)
+
+ |
+
| + 386 + | +
+
+ +
+ .output()
+
+ |
+
| + 387 + | +
+
+ +
+ .doesNotContain("configuring upstream")
+
+ |
+
| + 388 + | +
+
+ +
+ .contains("All projects must have been configured for this task to work correctly, but due to "
+
+ |
+
| + 389 + | +
+
+ +
+ + "Gradle configuration-on-demand, not all projects were configured.");
+
+ |
+
| + 390 + | +
+
+ +
+ assertThat(result).task(":verifyLocks").failed();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 391 + | +
+
+
+ }
+
+ |
+
| + 392 + | +
+
+
+
+ + |
+
| + 393 + | +
+
+
+ // As failing tasks can't be considered UP-TO-DATE, we only need to check the case where the task passing
+
+ |
+
| + 394 + | +
+
+
+ // is followed by the task running with incomplete configuration.
+
+ |
+
| + 395 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: verification_tasks_are_not_UP_TO_DATE_when_the_set_of_configured_projects_differs
+
+ |
+
| + 396 + | +
+
+ +
+ @Test
+
+ |
+
| + 397 + | +
+
+ +
+ void verification_tasks_are_not_UP_TO_DATE_when_the_set_of_configured_projects_differs(GradleInvoker gradle) {
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 398 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 399 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + 400 + | +
+
+ +
+ gradle.withArgs("build").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 401 + | +
+
+
+
+ + |
+
| + 402 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 403 + | +
+
+ +
+ gradle.withArgs(":verifyLocks").buildsWithFailure();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 404 + | +
+
+
+ }
+
+ |
+
| + 405 + | +
+
+
+
+ + |
+
| + 406 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: the_why_task_works_when_all_projects_are_configured
+
+ |
+
| + 407 + | +
+
+ +
+ @Test
+
+ |
+
| + 408 + | +
+
+ +
+ void the_why_task_works_when_all_projects_are_configured(GradleInvoker gradle) {
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 409 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 410 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + 411 + | +
+
+ +
+ InvocationResult result = gradle.withArgs("why", "--hash=0805f935").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 412 + | +
+
+
+
+ + |
+
| + 413 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 414 + | +
+
+ +
+ assertThat(result).task(":why").succeeded();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 415 + | +
+
+
+ }
+
+ |
+
| + 416 + | +
+
+
+
+ + |
+
| + 417 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: the_why_task_somehow_forces_all_projects_to_be_configured
+
+ |
+
| + 418 + | +
+
+ +
+ @Test
+
+ |
+
| + 419 + | +
+
+ +
+ void the_why_task_somehow_forces_all_projects_to_be_configured(GradleInvoker gradle) {
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 420 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: when
+
+ |
+
| + 421 + | +
+
+ +
+ gradle.withArgs("--write-locks").buildsSuccessfully();
+
+ |
+
| + 422 + | +
+
+ +
+ InvocationResult result = gradle.withArgs(":why", "--hash=0805f935").buildsSuccessfully();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + 423 + | +
+
+
+
+ + |
+
| + 424 + | +
+
+
+ // ***DELINEATOR FOR REVIEW: then
+
+ |
+
| + 425 + | +
+
+ +
+ assertThat(result)
+
+ |
+
| + 426 + | +
+
+ +
+ .output()
+
+ |
+
| + 427 + | +
+
+ +
+ .contains("configuring upstream")
+
+ |
+
| + 428 + | +
+
+ +
+ .contains("configuring downstream1")
+
+ |
+
| + 429 + | +
+
+ +
+ .contains("configuring downstream2")
+
+ |
+
| + 430 + | +
+
+ +
+ .contains("configuring unrelated")
+
+ |
+
| + 431 + | +
+
+ +
+ .contains("com.example:dependency-of-unrelated:1.2.3\n\tprojects -> 1.2.3");
+
+ |
+
| + 432 + | +
+
+ +
+ assertThat(result).task(":why").succeeded();
+
+ |
+
| + + | +
+
+
+
+ + |
+
| + + | +
+
+
+
+ + |
+
| + 433 + | +
+
+
+ }
+
+ |
+
| + 434 + | +
+
+
+ }
+
+ |
+