Skip to content

Commit 7294dbc

Browse files
committed
MavenRunner now uses a single ProcessRunner across an entire test class.
1 parent 5d7c3b7 commit 7294dbc

File tree

3 files changed

+63
-98
lines changed

3 files changed

+63
-98
lines changed

lib/src/main/java/com/diffplug/spotless/ProcessRunner.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2021 DiffPlug
2+
* Copyright 2020-2023 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,10 +16,12 @@
1616
package com.diffplug.spotless;
1717

1818
import java.io.ByteArrayOutputStream;
19+
import java.io.File;
1920
import java.io.IOException;
2021
import java.io.InputStream;
2122
import java.io.OutputStream;
2223
import java.nio.charset.Charset;
24+
import java.nio.charset.StandardCharsets;
2325
import java.util.Arrays;
2426
import java.util.List;
2527
import java.util.concurrent.ExecutionException;
@@ -55,13 +57,18 @@ public Result shell(String cmd) throws IOException, InterruptedException {
5557

5658
/** Executes the given shell command (using {@code cmd} on windows and {@code sh} on unix). */
5759
public Result shellWinUnix(String cmdWin, String cmdUnix) throws IOException, InterruptedException {
60+
return shellWinUnix(null, cmdWin, cmdUnix);
61+
}
62+
63+
/** Executes the given shell command (using {@code cmd} on windows and {@code sh} on unix). */
64+
public Result shellWinUnix(File cwd, String cmdWin, String cmdUnix) throws IOException, InterruptedException {
5865
List<String> args;
5966
if (FileSignature.machineIsWin()) {
6067
args = Arrays.asList("cmd", "/c", cmdWin);
6168
} else {
6269
args = Arrays.asList("sh", "-c", cmdUnix);
6370
}
64-
return exec(args);
71+
return exec(cwd, args);
6572
}
6673

6774
/** Creates a process with the given arguments. */
@@ -76,12 +83,25 @@ public Result exec(byte[] stdin, String... args) throws IOException, Interrupted
7683

7784
/** Creates a process with the given arguments. */
7885
public Result exec(List<String> args) throws IOException, InterruptedException {
79-
return exec(new byte[0], args);
86+
return exec((File) null, args);
87+
}
88+
89+
/** Creates a process with the given arguments. */
90+
public Result exec(File cwd, List<String> args) throws IOException, InterruptedException {
91+
return exec(cwd, new byte[0], args);
8092
}
8193

8294
/** Creates a process with the given arguments, the given byte array is written to stdin immediately. */
8395
public Result exec(byte[] stdin, List<String> args) throws IOException, InterruptedException {
96+
return exec(null, stdin, args);
97+
}
98+
99+
/** Creates a process with the given arguments, the given byte array is written to stdin immediately. */
100+
public Result exec(File cwd, byte[] stdin, List<String> args) throws IOException, InterruptedException {
84101
ProcessBuilder builder = new ProcessBuilder(args);
102+
if (cwd != null) {
103+
builder.directory(cwd);
104+
}
85105
Process process = builder.start();
86106
Future<byte[]> outputFut = threadStdOut.submit(() -> drainToBytes(process.getInputStream(), bufStdOut));
87107
Future<byte[]> errorFut = threadStdErr.submit(() -> drainToBytes(process.getErrorStream(), bufStdErr));
@@ -147,6 +167,14 @@ public byte[] stdErr() {
147167
return stdErr;
148168
}
149169

170+
public String stdOutUtf8() {
171+
return new String(stdOut, StandardCharsets.UTF_8);
172+
}
173+
174+
public String stdErrUtf8() {
175+
return new String(stdErr, StandardCharsets.UTF_8);
176+
}
177+
150178
/** Returns true if the exit code was not zero. */
151179
public boolean exitNotZero() {
152180
return exitCode != 0;

plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import java.nio.file.Path;
3232
import java.util.*;
3333

34+
import org.junit.jupiter.api.AfterAll;
35+
import org.junit.jupiter.api.BeforeAll;
3436
import org.junit.jupiter.api.BeforeEach;
3537

3638
import com.github.mustachejava.DefaultMustacheFactory;
@@ -40,6 +42,7 @@
4042
import com.diffplug.common.base.Unhandled;
4143
import com.diffplug.common.io.Resources;
4244
import com.diffplug.spotless.Jvm;
45+
import com.diffplug.spotless.ProcessRunner;
4346
import com.diffplug.spotless.ResourceHarness;
4447

4548
public class MavenIntegrationHarness extends ResourceHarness {
@@ -175,9 +178,22 @@ protected void writePom(String[] executions, String[] configuration, String[] de
175178

176179
protected MavenRunner mavenRunner() throws IOException {
177180
return MavenRunner.create()
181+
.withRunner(runner)
178182
.withProjectDir(rootFolder());
179183
}
180184

185+
private static ProcessRunner runner;
186+
187+
@BeforeAll
188+
static void setupRunner() throws IOException {
189+
runner = new ProcessRunner();
190+
}
191+
192+
@AfterAll
193+
static void closeRunner() throws IOException {
194+
runner.close();
195+
}
196+
181197
/**
182198
* Useful for local development. Allows debugging the Spotless Maven Plugin remotely.
183199
* Effectively translates into running {@code mvnDebug} on port 5005. The forked JVM will be

plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenRunner.java

Lines changed: 16 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,15 @@
1717

1818
import static org.assertj.core.api.Assertions.assertThat;
1919

20-
import java.io.ByteArrayOutputStream;
2120
import java.io.File;
2221
import java.io.IOException;
23-
import java.io.InputStream;
24-
import java.nio.charset.Charset;
2522
import java.util.Arrays;
2623
import java.util.HashMap;
27-
import java.util.List;
2824
import java.util.Map;
2925
import java.util.Objects;
3026

31-
import com.diffplug.common.base.Throwables;
32-
import com.diffplug.common.io.ByteStreams;
33-
import com.diffplug.spotless.FileSignature;
3427
import com.diffplug.spotless.Jvm;
28+
import com.diffplug.spotless.ProcessRunner;
3529

3630
/**
3731
* Harness for running a maven build, same idea as the
@@ -47,6 +41,7 @@ private MavenRunner() {}
4741
private File projectDir;
4842
private String[] args;
4943
private Map<String, String> environment = new HashMap<>();
44+
private ProcessRunner runner;
5045

5146
public MavenRunner withProjectDir(File projectDir) {
5247
this.projectDir = Objects.requireNonNull(projectDir);
@@ -58,110 +53,36 @@ public MavenRunner withArguments(String... args) {
5853
return this;
5954
}
6055

56+
public MavenRunner withRunner(ProcessRunner runner) {
57+
this.runner = runner;
58+
return this;
59+
}
60+
6161
public MavenRunner withRemoteDebug(int port) {
6262
String address = (Jvm.version() < 9 ? "" : "*:") + port;
6363
environment.put("MAVEN_OPTS", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" + address);
6464
return this;
6565
}
6666

67-
private Result run() throws IOException, InterruptedException {
67+
private ProcessRunner.Result run() throws IOException, InterruptedException {
6868
Objects.requireNonNull(projectDir, "Need to call withProjectDir() first");
6969
Objects.requireNonNull(args, "Need to call withArguments() first");
7070
// run maven with the given args in the given directory
71-
String argsString = String.join(" ", Arrays.asList(args));
72-
List<String> cmds = getPlatformCmds("-e " + argsString);
73-
ProcessBuilder builder = new ProcessBuilder(cmds);
74-
builder.directory(projectDir);
75-
builder.environment().putAll(environment);
76-
Process process = builder.start();
77-
// slurp and return the stdout, stderr, and exitValue
78-
Slurper output = new Slurper(process.getInputStream());
79-
Slurper error = new Slurper(process.getErrorStream());
80-
int exitValue = process.waitFor();
81-
output.join();
82-
error.join();
83-
return new Result(exitValue, output.result(), error.result());
71+
String argsString = "-e " + String.join(" ", Arrays.asList(args));
72+
return runner.shellWinUnix(projectDir, "mvnw " + argsString, "./mvnw " + argsString);
8473
}
8574

8675
/** Runs the command and asserts that exit code is 0. */
87-
public Result runNoError() throws IOException, InterruptedException {
88-
Result result = run();
89-
assertThat(result.exitValue()).as("Run without error %s", result).isEqualTo(0);
76+
public ProcessRunner.Result runNoError() throws IOException, InterruptedException {
77+
ProcessRunner.Result result = run();
78+
assertThat(result.exitCode()).as("Run without error %s", result).isEqualTo(0);
9079
return result;
9180
}
9281

9382
/** Runs the command and asserts that exit code is not 0. */
94-
public Result runHasError() throws IOException, InterruptedException {
95-
Result result = run();
96-
assertThat(result.exitValue()).as("Run with error %s", result).isNotEqualTo(0);
83+
public ProcessRunner.Result runHasError() throws IOException, InterruptedException {
84+
ProcessRunner.Result result = run();
85+
assertThat(result.exitCode()).as("Run with error %s", result).isNotEqualTo(0);
9786
return result;
9887
}
99-
100-
public static class Result {
101-
private final int exitValue;
102-
private final String output;
103-
private final String error;
104-
105-
public Result(int exitValue, String output, String error) {
106-
super();
107-
this.exitValue = exitValue;
108-
this.output = Objects.requireNonNull(output);
109-
this.error = Objects.requireNonNull(error);
110-
}
111-
112-
public int exitValue() {
113-
return exitValue;
114-
}
115-
116-
public String output() {
117-
return output;
118-
}
119-
120-
public String error() {
121-
return error;
122-
}
123-
124-
@Override
125-
public String toString() {
126-
return "Result{" +
127-
"exitValue=" + exitValue +
128-
", output='" + output + '\'' +
129-
", error='" + error + '\'' +
130-
'}';
131-
}
132-
}
133-
134-
/** Prepends any arguments necessary to run a console command. */
135-
private static List<String> getPlatformCmds(String cmd) {
136-
if (FileSignature.machineIsWin()) {
137-
return Arrays.asList("cmd", "/c", "mvnw " + cmd);
138-
} else {
139-
return Arrays.asList("/bin/sh", "-c", "./mvnw " + cmd);
140-
}
141-
}
142-
143-
private static class Slurper extends Thread {
144-
private final InputStream input;
145-
private volatile String result;
146-
147-
Slurper(InputStream input) {
148-
this.input = Objects.requireNonNull(input);
149-
start();
150-
}
151-
152-
@Override
153-
public void run() {
154-
try {
155-
ByteArrayOutputStream output = new ByteArrayOutputStream();
156-
ByteStreams.copy(input, output);
157-
result = output.toString(Charset.defaultCharset().name());
158-
} catch (Exception e) {
159-
result = Throwables.getStackTraceAsString(e);
160-
}
161-
}
162-
163-
public String result() {
164-
return result;
165-
}
166-
}
16788
}

0 commit comments

Comments
 (0)