add SystemProcess as wrapper for ProcessBuilder using Strings for simplified input+output
This commit is contained in:
parent
977bd595d8
commit
93774aebe3
@ -0,0 +1,57 @@
|
|||||||
|
package net.hostsharing.hsadminng.system;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
|
||||||
|
public class SystemProcess {
|
||||||
|
private final ProcessBuilder processBuilder;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private String stdOut;
|
||||||
|
@Getter
|
||||||
|
private String stdErr;
|
||||||
|
|
||||||
|
public SystemProcess(final String... command) {
|
||||||
|
this.processBuilder = new ProcessBuilder(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int execute() throws IOException, InterruptedException {
|
||||||
|
final var process = processBuilder.start();
|
||||||
|
stdOut = fetchOutput(process.getInputStream()); // yeah, twisted ProcessBuilder API
|
||||||
|
stdErr = fetchOutput(process.getErrorStream());
|
||||||
|
return process.waitFor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int execute(final String input) throws IOException, InterruptedException {
|
||||||
|
final var process = processBuilder.start();
|
||||||
|
feedInput(input, process);
|
||||||
|
stdOut = fetchOutput(process.getInputStream()); // yeah, twisted ProcessBuilder API
|
||||||
|
stdErr = fetchOutput(process.getErrorStream());
|
||||||
|
return process.waitFor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void feedInput(final String input, final Process process) throws IOException {
|
||||||
|
try (
|
||||||
|
final OutputStreamWriter stdIn = new OutputStreamWriter(process.getOutputStream()); // yeah, twisted ProcessBuilder API
|
||||||
|
final BufferedWriter writer = new BufferedWriter(stdIn)) {
|
||||||
|
writer.write(input);
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String fetchOutput(final InputStream inputStream) throws IOException {
|
||||||
|
final var output = new StringBuilder();
|
||||||
|
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
|
||||||
|
for (String line; (line = reader.readLine()) != null; ) {
|
||||||
|
output.append(line).append(System.lineSeparator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package net.hostsharing.hsadminng.system;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.condition.EnabledOnOs;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||||
|
import static org.junit.jupiter.api.condition.OS.LINUX;
|
||||||
|
|
||||||
|
class SystemProcessTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnabledOnOs(LINUX)
|
||||||
|
void shouldExecuteAndFetchOutput() throws IOException, InterruptedException {
|
||||||
|
// given
|
||||||
|
final var process = new SystemProcess("bash", "-c", "echo 'Hello, World!'; echo 'Error!' >&2");
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var returnCode = process.execute();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(returnCode).isEqualTo(0);
|
||||||
|
assertThat(process.getStdOut()).isEqualTo("Hello, World!\n");
|
||||||
|
assertThat(process.getStdErr()).isEqualTo("Error!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnabledOnOs(LINUX)
|
||||||
|
void shouldReturnErrorCode() throws IOException, InterruptedException {
|
||||||
|
// given
|
||||||
|
final var process = new SystemProcess("false");
|
||||||
|
|
||||||
|
// when
|
||||||
|
final int returnCode = process.execute();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(returnCode).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnabledOnOs(LINUX)
|
||||||
|
void shouldExecuteAndFeedInput() throws IOException, InterruptedException {
|
||||||
|
// given
|
||||||
|
final var process = new SystemProcess("tr", "[:lower:]", "[:upper:]");
|
||||||
|
|
||||||
|
// when
|
||||||
|
final int returnCode = process.execute("Hallo");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(returnCode).isEqualTo(0);
|
||||||
|
assertThat(process.getStdOut()).isEqualTo("HALLO\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldThrowExceptionIfProgramNotFound() {
|
||||||
|
// given
|
||||||
|
final var process = new SystemProcess("non-existing program");
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var exception = catchThrowable(process::execute);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(exception).isInstanceOf(IOException.class)
|
||||||
|
.hasMessage("Cannot run program \"non-existing program\": error=2, No such file or directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBeAbleToRunMultipleTimes() throws IOException, InterruptedException {
|
||||||
|
// given
|
||||||
|
final var process = new SystemProcess("true");
|
||||||
|
|
||||||
|
// when
|
||||||
|
process.execute();
|
||||||
|
final int returnCode = process.execute();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(returnCode).isEqualTo(0);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user