24
24
*/
25
25
package org .graalvm .compiler .core .test ;
26
26
27
+ import static org .graalvm .compiler .test .SubprocessUtil .getProcessCommandLine ;
27
28
import static org .graalvm .compiler .test .SubprocessUtil .getVMCommandLine ;
28
29
import static org .graalvm .compiler .test .SubprocessUtil .java ;
29
30
import static org .graalvm .compiler .test .SubprocessUtil .withoutDebuggerArguments ;
30
31
31
32
import java .io .IOException ;
32
33
import java .util .Arrays ;
34
+ import java .util .LinkedList ;
33
35
import java .util .List ;
34
36
import java .util .function .Predicate ;
35
37
38
40
import org .junit .Assume ;
39
41
import org .junit .Before ;
40
42
43
+ /**
44
+ * Utility class for executing Graal compiler tests in a subprocess. This can be useful for tests
45
+ * that need special VM arguments or that produce textual output or a special process termination
46
+ * status that need to be analyzed. The class to be executed may be the current class or any other
47
+ * unit test class.
48
+ * <p/>
49
+ * If the test class contains multiple {@code @Test} methods, they will all be executed in the
50
+ * subprocess, except when using one of the methods that take a {@code testSelector} argument. All
51
+ * methods in this class take a {@link Runnable} argument. If the test class is the same as the
52
+ * calling class, this runnable defines the operation to be executed in the subprocess. If the test
53
+ * class is not the same as the calling class, the runnable is irrelevant and can be a nop.
54
+ * <p/>
55
+ * The subprocess will inherit any {@code -JUnitVerbose} flag (typically set through
56
+ * {@code mx unittest --verbose}) from the parent process. If this flag is set, the standard output
57
+ * of the child process will be echoed to the standard output of the parent process. If the child
58
+ * process terminates with an error, its standard output will always be printed.
59
+ */
41
60
public abstract class SubprocessTest extends GraalCompilerTest {
42
61
43
62
@ Before
@@ -54,16 +73,24 @@ public void checkJavaAgent() {
54
73
* {@link Subprocess} instance describing the process after its successful termination.
55
74
*/
56
75
public SubprocessUtil .Subprocess launchSubprocess (Runnable runnable , String ... args ) throws InterruptedException , IOException {
57
- return launchSubprocess (null , true , getClass (), runnable , args );
76
+ return launchSubprocess (null , true , getClass (), null , runnable , args );
58
77
}
59
78
60
79
public static SubprocessUtil .Subprocess launchSubprocess (Class <? extends GraalCompilerTest > testClass , Runnable runnable , String ... args ) throws InterruptedException , IOException {
61
- return launchSubprocess (null , true , testClass , runnable , args );
80
+ return launchSubprocess (null , true , testClass , null , runnable , args );
81
+ }
82
+
83
+ public void launchSubprocess (String testSelector , Runnable runnable , String ... args ) throws InterruptedException , IOException {
84
+ launchSubprocess (null , true , getClass (), testSelector , runnable , args );
85
+ }
86
+
87
+ public static SubprocessUtil .Subprocess launchSubprocess (Predicate <List <String >> testPredicate , boolean expectNormalExit , Class <? extends GraalCompilerTest > testClass ,
88
+ Runnable runnable , String ... args ) throws InterruptedException , IOException {
89
+ return launchSubprocess (testPredicate , expectNormalExit , testClass , null , runnable , args );
62
90
}
63
91
64
- public static SubprocessUtil .Subprocess launchSubprocess (Predicate <List <String >> testPredicate , boolean expectNormalExit , Class <? extends GraalCompilerTest > testClass , Runnable runnable ,
65
- String ... args )
66
- throws InterruptedException , IOException {
92
+ public static SubprocessUtil .Subprocess launchSubprocess (Predicate <List <String >> testPredicate , boolean expectNormalExit , Class <? extends GraalCompilerTest > testClass , String testSelector ,
93
+ Runnable runnable , String ... args ) throws InterruptedException , IOException {
67
94
String recursionPropName = testClass .getSimpleName () + ".Subprocess" ;
68
95
if (Boolean .getBoolean (recursionPropName )) {
69
96
runnable .run ();
@@ -77,7 +104,18 @@ public static SubprocessUtil.Subprocess launchSubprocess(Predicate<List<String>>
77
104
if (verbose ) {
78
105
System .err .println (String .join (" " , vmArgs ));
79
106
}
80
- SubprocessUtil .Subprocess proc = java (vmArgs , "com.oracle.mxtool.junit.MxJUnitWrapper" , testClass .getName ());
107
+ List <String > mainClassAndArgs = new LinkedList <>();
108
+ mainClassAndArgs .add ("com.oracle.mxtool.junit.MxJUnitWrapper" );
109
+ String testName = testClass .getName ();
110
+ if (testSelector != null ) {
111
+ testName += "#" + testSelector ;
112
+ }
113
+ mainClassAndArgs .add (testName );
114
+ boolean junitVerbose = getProcessCommandLine ().contains ("-JUnitVerbose" );
115
+ if (junitVerbose ) {
116
+ mainClassAndArgs .add ("-JUnitVerbose" );
117
+ }
118
+ SubprocessUtil .Subprocess proc = java (vmArgs , mainClassAndArgs );
81
119
if (testPredicate != null ) {
82
120
assertTrue (testPredicate .test (proc .output ), proc .toString () + " produced unexpected output:\n \n " + String .join ("\n " , proc .output ));
83
121
}
@@ -91,6 +129,13 @@ public static SubprocessUtil.Subprocess launchSubprocess(Predicate<List<String>>
91
129
} else {
92
130
assertTrue (proc .exitCode != 0 , proc .toString () + " produced normal exit code " + proc .exitCode + ", but expected abnormal exit." );
93
131
}
132
+ if (junitVerbose ) {
133
+ System .out .println ("--- subprocess output:" );
134
+ for (String line : proc .output ) {
135
+ System .out .println (line );
136
+ }
137
+ System .out .println ("--- end subprocess output" );
138
+ }
94
139
return proc ;
95
140
}
96
141
}
0 commit comments