-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstring_template_RUNSHELL.java
More file actions
137 lines (118 loc) · 4.58 KB
/
string_template_RUNSHELL.java
File metadata and controls
137 lines (118 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
///usr/bin/env jbang "$0" "$@" ; exit $?
import org.junit.jupiter.api.Test;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
import org.junit.platform.launcher.listeners.LoggingListener;
import static java.lang.System.out;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
//JAVA 21
//NATIVE_OPTIONS --no-fallback -H:+ReportExceptionStackTraces --enable-preview --enable-monitoring
//COMPILE_OPTIONS --enable-preview --release 21
//RUNTIME_OPTIONS --enable-preview -XX:+UseZGC -XX:NativeMemoryTracking=summary -XX:+HeapDumpOnOutOfMemoryError
//DEPS org.junit:junit-bom:5.10.1@pom
//DEPS org.junit.jupiter:junit-jupiter-api
//DEPS org.junit.jupiter:junit-jupiter-engine
//DEPS org.junit.platform:junit-platform-launcher
public class string_template_RUNSHELL {
public static void main(final String... args) {
final LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectClass(string_template_RUNSHELL.class))
.build();
final Launcher launcher = LauncherFactory.create();
final LoggingListener logListener = LoggingListener.forBiConsumer((t, m) -> {
System.out.println(m.get());
if (t != null) {
t.printStackTrace();
}
;
});
final SummaryGeneratingListener execListener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(execListener, logListener);
launcher.execute(request);
execListener.getSummary().printTo(new java.io.PrintWriter(out));
}
static final boolean OS_WIN = System.getProperty("os.name").startsWith("Windows");
sealed static interface RunShellResult permits RunShellResult.Ok, RunShellResult.Fail, RunShellResult.Err {
record Ok(String stdout) implements RunShellResult {
}
record Fail(int exitCode, String stdout, String stderr) implements RunShellResult {
}
record Err(IOException e) implements RunShellResult {}
}
static final StringTemplate.Processor<RunShellResult, RuntimeException> RUNSHELL = st -> {
var shellCmd = st.interpolate();
var cmdAndArgs = OS_WIN ? new String[] { "cmd.exe", "/c", shellCmd } : new String[] { "sh", "-c", shellCmd };
Path stderrRedirectPath = null;
Process p = null;
try{
stderrRedirectPath = Files.createTempFile("RUNSHELL-", null);
p = new ProcessBuilder()
.command(cmdAndArgs)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(stderrRedirectPath.toFile())
.start();
String stdout = "";
try (var in = p.getInputStream()) {
stdout = new String(in.readAllBytes());
}
int exitCode = p.waitFor();
if (exitCode == 0) {
return new RunShellResult.Ok(stdout);
} else {
String stderr = Files.readString(stderrRedirectPath);
return new RunShellResult.Fail(exitCode, stdout, stderr);
}
} catch(IOException | InterruptedException e){
if (p != null) p.destroyForcibly();
return new RunShellResult.Err(e instanceof IOException ? (IOException) e : new IOException(e));
} finally {
if (stderrRedirectPath != null) {
try {
Files.deleteIfExists(stderrRedirectPath);
} catch (IOException ignore) {}
}
}
};
@Test
void test_run_shellcmd_stdout() {
var cmd = "java";
var args = "--help";
switch (RUNSHELL."\{cmd} \{args}") {
case RunShellResult.Ok(var stdout) -> assertTrue(stdout.contains("Usage:"));
default -> fail();
}
}
@Test
void test_run_shellcmd_stderr(){
var cmd = "java";
switch (RUNSHELL."\{cmd}") {
case RunShellResult.Fail(_, _, var stderr) -> assertTrue(stderr.contains("Usage:"));
default -> fail();
}
}
@Test
void test_run_shellcmd_stderr_redirect_to_stdout() {
var cmd = "java";
var args = "2>&1";
switch (RUNSHELL."\{cmd} \{args}") {
case RunShellResult.Fail(_, var stdout, _) -> assertTrue(stdout.contains("Usage:"));
default -> fail();
}
}
@Test
void test_run_shellcmd_quote() {
var cmd = "fd.exe";
var args = "-d 1 -g \"*.java\"";
switch (RUNSHELL."\{cmd} \{args}") {
case RunShellResult.Ok(var stdout) -> assertTrue(stdout.contains(".java"));
default -> fail();
}
}
}