|
| 1 | +// Copyright © LFV |
| 2 | +package io.github.reqstool.gradle; |
| 3 | + |
| 4 | +import java.io.IOException; |
| 5 | +import java.nio.file.Files; |
| 6 | +import java.nio.file.Path; |
| 7 | + |
| 8 | +import org.gradle.testkit.runner.BuildResult; |
| 9 | +import org.gradle.testkit.runner.GradleRunner; |
| 10 | +import org.junit.jupiter.api.Test; |
| 11 | +import org.junit.jupiter.api.io.TempDir; |
| 12 | + |
| 13 | +import static org.junit.jupiter.api.Assertions.assertFalse; |
| 14 | +import static org.junit.jupiter.api.Assertions.assertTrue; |
| 15 | + |
| 16 | +/** |
| 17 | + * Covers how the plugin joins the build lifecycle, which the fixture under |
| 18 | + * {@code tests/fixtures} cannot: the fixture declares no wiring of its own, so it only |
| 19 | + * ever exercises the case where the plugin is the sole author of these edges. |
| 20 | + * |
| 21 | + * <p> |
| 22 | + * {@code --dry-run} is deliberate. A circular dependency is raised while Gradle builds |
| 23 | + * the task graph, before any task runs, so the failure these tests guard against is |
| 24 | + * reproduced without compiling anything or resolving a single dependency. |
| 25 | + * |
| 26 | + * @see <a href= "https://github.com/reqstool/reqstool-java-gradle-plugin/issues/88">issue |
| 27 | + * #88</a> |
| 28 | + */ |
| 29 | +class BuildLifecycleWiringTest { |
| 30 | + |
| 31 | + @TempDir |
| 32 | + Path projectDir; |
| 33 | + |
| 34 | + /** |
| 35 | + * Versions 0.1.0 and 0.1.1 wired nothing, so a consumer that wanted the documented |
| 36 | + * behaviour declared it by hand. That line must not collide with the plugin's own |
| 37 | + * wiring: 0.1.2 made {@code build} finalized by {@code assembleRequirements}, which |
| 38 | + * contradicts it, and every such consumer failed at configuration time with "Circular |
| 39 | + * dependency between the following tasks". |
| 40 | + */ |
| 41 | + @Test |
| 42 | + void consumerDeclaringBuildDependsOnAssembleRequirementsStillConfigures() throws IOException { |
| 43 | + writeProject(""" |
| 44 | + tasks.named('assembleRequirements') { dependsOn(tasks.named('check')) } |
| 45 | + tasks.named('build') { dependsOn(tasks.named('assembleRequirements')) } |
| 46 | + """); |
| 47 | + |
| 48 | + BuildResult result = run(); |
| 49 | + |
| 50 | + assertFalse(result.getOutput().contains("Circular dependency"), |
| 51 | + "consumer-declared build.dependsOn(assembleRequirements) must not collide " |
| 52 | + + "with the plugin's own wiring:\n" + result.getOutput()); |
| 53 | + assertTrue(result.getOutput().contains(":assembleRequirements"), |
| 54 | + "assembleRequirements should be in the task graph for `build`:\n" + result.getOutput()); |
| 55 | + } |
| 56 | + |
| 57 | + /** The plugin on its own still puts the task into {@code build}. */ |
| 58 | + @Test |
| 59 | + void assembleRequirementsIsPartOfBuildWithoutConsumerWiring() throws IOException { |
| 60 | + writeProject(""); |
| 61 | + |
| 62 | + BuildResult result = run(); |
| 63 | + |
| 64 | + assertTrue(result.getOutput().contains(":assembleRequirements"), |
| 65 | + "assembleRequirements should run as part of `build`:\n" + result.getOutput()); |
| 66 | + } |
| 67 | + |
| 68 | + /** |
| 69 | + * The task reads the test-results XML, so it has to come after the tests rather than |
| 70 | + * merely alongside them. |
| 71 | + */ |
| 72 | + @Test |
| 73 | + void assembleRequirementsRunsAfterCheck() throws IOException { |
| 74 | + writeProject(""); |
| 75 | + |
| 76 | + String output = run().getOutput(); |
| 77 | + |
| 78 | + assertTrue(output.indexOf(":check") < output.indexOf(":assembleRequirements"), |
| 79 | + "check should be ordered before assembleRequirements:\n" + output); |
| 80 | + } |
| 81 | + |
| 82 | + private BuildResult run() { |
| 83 | + return GradleRunner.create() |
| 84 | + .withProjectDir(projectDir.toFile()) |
| 85 | + .withPluginClasspath() |
| 86 | + .withArguments("build", "--dry-run") |
| 87 | + .build(); |
| 88 | + } |
| 89 | + |
| 90 | + private void writeProject(String extraWiring) throws IOException { |
| 91 | + Files.writeString(projectDir.resolve("settings.gradle"), "rootProject.name = 'consumer'\n"); |
| 92 | + Files.writeString(projectDir.resolve("build.gradle"), """ |
| 93 | + plugins { |
| 94 | + id 'java' |
| 95 | + id 'io.github.reqstool.gradle-plugin' |
| 96 | + } |
| 97 | +
|
| 98 | + """ + extraWiring); |
| 99 | + } |
| 100 | + |
| 101 | +} |
0 commit comments