Skip to content

Commit 7b2c549

Browse files
Excavator: Migrate Groovy nebula test PalantirJavaFormatSpotlessPluginTest to the new Java Junit framework
1 parent fc7ca7b commit 7b2c549

File tree

4 files changed

+4481
-154
lines changed

4 files changed

+4481
-154
lines changed

gradle-palantir-java-format/src/test/groovy/com/palantir/javaformat/gradle/PalantirJavaFormatSpotlessPluginTest.groovy

Lines changed: 0 additions & 154 deletions
This file was deleted.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* (c) Copyright 2025 Palantir Technologies Inc. All rights reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.palantir.javaformat.gradle;
17+
18+
import com.palantir.javaformat.gradle.spotless.PalantirJavaFormatStep;
19+
import com.palantir.javaformat.java.Formatter;
20+
import java.io.BufferedReader;
21+
import java.io.File;
22+
import java.io.IOException;
23+
import java.io.InputStream;
24+
import java.io.InputStreamReader;
25+
import java.nio.charset.StandardCharsets;
26+
import java.util.Arrays;
27+
import java.util.List;
28+
import java.util.Optional;
29+
import java.util.concurrent.TimeUnit;
30+
import java.util.stream.Collectors;
31+
import java.util.stream.Stream;
32+
import nebula.test.IntegrationTestKitSpec;
33+
import nebula.test.functional.internal.classpath.ClasspathAddingInitScriptBuilder;
34+
import org.gradle.testkit.runner.internal.PluginUnderTestMetadataReading;
35+
36+
/**
37+
* {@link IntegrationTestKitSpec} currently loads <a href="https://github.com/nebula-plugins/nebula-test/blob/c5d3af9004898276bde5c68da492c6b0b4c5facc/src/main/groovy/nebula/test/IntegrationTestKitBase.groovy#L136"> more than what it needs into the classpath</a>.
38+
* This means if we run a test with {@link IntegrationTestKitSpec}'s runner, the {@link Formatter} is on the build's classpath by virtue of being in the test's classpath.
39+
* If the test applies the {@link PalantirJavaFormatPlugin}, it complains that the {@link Formatter} is <a href="https://github.com/palantir/palantir-java-format/blob/00b08d2f471d66382d6c4cd2d05f56b6bb546ad3/gradle-palantir-java-format/src/main/java/com/palantir/javaformat/gradle/spotless/PalantirJavaFormatStep.java#L83">erroneously loadable</a>.
40+
* To be clear, this complaint is entirely a result of the {@link IntegrationTestKitSpec} loading too many things onto classpath since it doesn't know what the exact plugin classpath is.
41+
* As a workaround, this runner uses the classpath produced by Gradle Test Kit in {@code plugin-under-test-metadata.properties}.
42+
* This classpath only contains the dependencies required by the plugin, as well as the plugin itself.
43+
* This means that even if we put the formatter on the {@code testClassPath}, it won't leak through to the Gradle build under test and subsequently no error from {@link PalantirJavaFormatStep}.
44+
*/
45+
public class GradlewExecutor {
46+
private File projectDir;
47+
48+
public GradlewExecutor(File projectDir) {
49+
this.projectDir = projectDir;
50+
}
51+
52+
private static List<File> getBuildPluginClasspathInjector() {
53+
return PluginUnderTestMetadataReading.readImplementationClasspath();
54+
}
55+
56+
public GradlewExecutionResult runGradlewTasks(String... tasks) {
57+
try {
58+
ProcessBuilder processBuilder = getProcessBuilder(tasks);
59+
Process process = processBuilder.start();
60+
String output = readAllInput(process.getInputStream());
61+
process.waitFor(1, TimeUnit.MINUTES);
62+
return new GradlewExecutionResult(process.exitValue(), output);
63+
} catch (InterruptedException | IOException e) {
64+
return new GradlewExecutionResult(-1, "", e);
65+
}
66+
}
67+
68+
private static String readAllInput(InputStream inputStream) {
69+
try {
70+
Stream<String> lines =
71+
new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines();
72+
return lines.collect(Collectors.joining("\n"));
73+
} catch (Exception e) {
74+
throw new RuntimeException("GradlewExecutor failed to readAllInput", e);
75+
}
76+
}
77+
78+
private ProcessBuilder getProcessBuilder(String... tasks) {
79+
File initScript = new File(projectDir, "init.gradle");
80+
ClasspathAddingInitScriptBuilder.build(initScript, getBuildPluginClasspathInjector());
81+
82+
List<String> arguments = Stream.concat(
83+
Stream.of(
84+
"./gradlew",
85+
"--init-script",
86+
initScript.toPath().toString()),
87+
Arrays.stream(tasks))
88+
.toList();
89+
90+
return new ProcessBuilder().command(arguments).directory(projectDir).redirectErrorStream(true);
91+
}
92+
93+
public record GradlewExecutionResult(boolean success, String standardOutput, Optional<Throwable> failure) {
94+
public GradlewExecutionResult(int exitValue, String output, Throwable failure) {
95+
this(exitValue == 0, output, Optional.of(failure));
96+
}
97+
98+
public GradlewExecutionResult(int exitValue, String output) {
99+
this(exitValue == 0, output, Optional.empty());
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)