20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @bug 8160128 8159935
27 * @summary Tests for Aux channel, custom remote agents, custom JDI implementations.
28 * @build KullaTesting ExecutionControlTestBase
29 * @run testng UserJDIUserRemoteTest
30 */
31 import java.io.ByteArrayOutputStream;
32 import org.testng.annotations.Test;
33 import org.testng.annotations.BeforeMethod;
34 import jdk.jshell.Snippet;
35 import static jdk.jshell.Snippet.Status.OVERWRITTEN;
36 import static jdk.jshell.Snippet.Status.VALID;
37 import java.io.IOException;
38 import java.io.ObjectInput;
39 import java.io.ObjectOutput;
40 import java.io.ObjectOutputStream;
41 import java.net.ServerSocket;
42 import java.util.ArrayList;
43 import java.util.List;
44 import com.sun.jdi.VMDisconnectedException;
45 import com.sun.jdi.VirtualMachine;
46 import jdk.jshell.VarSnippet;
47 import jdk.jshell.execution.DirectExecutionControl;
48 import jdk.jshell.execution.JDIExecutionControl;
49 import jdk.jshell.execution.JDIInitiator;
50 import jdk.jshell.execution.Util;
51 import java.io.InputStream;
52 import java.io.OutputStream;
53 import java.io.PrintStream;
54 import java.net.Socket;
55
56 import java.util.HashMap;
57 import java.util.Map;
58 import java.util.function.Consumer;
59 import jdk.jshell.spi.ExecutionControl;
60 import jdk.jshell.spi.ExecutionControl.ExecutionControlException;
61 import jdk.jshell.spi.ExecutionEnv;
62 import static org.testng.Assert.assertEquals;
63 import static org.testng.Assert.fail;
64 import static jdk.jshell.execution.Util.forwardExecutionControlAndIO;
65 import static jdk.jshell.execution.Util.remoteInput;
66
67 @Test
68 public class UserJDIUserRemoteTest extends ExecutionControlTestBase {
69
70 ExecutionControl currentEC;
71 ByteArrayOutputStream auxStream;
72
73 @BeforeMethod
74 @Override
75 public void setUp() {
76 auxStream = new ByteArrayOutputStream();
77 setUp(builder -> builder.executionEngine(MyExecutionControl.create(this)));
78 }
79
80 public void testVarValue() {
81 VarSnippet dv = varKey(assertEval("double aDouble = 1.5;"));
82 String vd = getState().varValue(dv);
83 assertEquals(vd, "1.5");
84 assertEquals(auxStream.toString(), "aDouble");
85 }
129 *
130 * @return the generator
131 */
132 public static ExecutionControl.Generator create(UserJDIUserRemoteTest test) {
133 return env -> make(env, test);
134 }
135
136 /**
137 * Creates an ExecutionControl instance based on a JDI
138 * {@code ListeningConnector} or {@code LaunchingConnector}.
139 *
140 * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
141 * commands and results. This socket also transports the user
142 * input/output/error.
143 *
144 * @param env the context passed by
145 * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
146 * @return the channel
147 * @throws IOException if there are errors in set-up
148 */
149 static MyExecutionControl make(ExecutionEnv env, UserJDIUserRemoteTest test) throws IOException {
150 try (final ServerSocket listener = new ServerSocket(0)) {
151 // timeout after 60 seconds
152 listener.setSoTimeout(60000);
153 int port = listener.getLocalPort();
154
155 // Set-up the JDI connection
156 List<String> opts = new ArrayList<>(env.extraRemoteVMOptions());
157 opts.add("-classpath");
158 opts.add(System.getProperty("java.class.path")
159 + System.getProperty("path.separator")
160 + System.getProperty("user.dir"));
161 JDIInitiator jdii = new JDIInitiator(port,
162 opts, REMOTE_AGENT, true);
163 VirtualMachine vm = jdii.vm();
164 Process process = jdii.process();
165
166 List<Consumer<String>> deathListeners = new ArrayList<>();
167 deathListeners.add(s -> env.closeDown());
168 Util.detectJDIExitEvent(vm, s -> {
169 for (Consumer<String> h : deathListeners) {
170 h.accept(s);
171 }
172 });
173
174 // Set-up the commands/reslts on the socket. Piggy-back snippet
175 // output.
176 Socket socket = listener.accept();
177 // out before in -- match remote creation so we don't hang
178 ObjectOutput cmdout = new ObjectOutputStream(socket.getOutputStream());
179 Map<String, OutputStream> io = new HashMap<>();
180 io.put("out", env.userOut());
181 io.put("err", env.userErr());
182 io.put("aux", test.auxStream);
183 ObjectInput cmdin = remoteInput(socket.getInputStream(), io);
184 MyExecutionControl myec = new MyExecutionControl(cmdout, cmdin, vm, process, deathListeners);
185 test.currentEC = myec;
186 return myec;
187 }
188 }
189
190 /**
191 * Create an instance.
192 *
193 * @param out the output for commands
194 * @param in the input for responses
195 */
196 private MyExecutionControl(ObjectOutput out, ObjectInput in,
197 VirtualMachine vm, Process process,
198 List<Consumer<String>> deathListeners) {
199 super(out, in);
200 this.vm = vm;
201 this.process = process;
202 deathListeners.add(s -> disposeVM());
203 }
204
238 }
239
240 class MyRemoteExecutionControl extends DirectExecutionControl implements ExecutionControl {
241
242 static PrintStream auxPrint;
243
244 /**
245 * Launch the agent, connecting to the JShell-core over the socket specified
246 * in the command-line argument.
247 *
248 * @param args standard command-line arguments, expectation is the socket
249 * number is the only argument
250 * @throws Exception any unexpected exception
251 */
252 public static void main(String[] args) throws Exception {
253 try {
254 String loopBack = null;
255 Socket socket = new Socket(loopBack, Integer.parseInt(args[0]));
256 InputStream inStream = socket.getInputStream();
257 OutputStream outStream = socket.getOutputStream();
258 Map<String, Consumer<OutputStream>> chans = new HashMap<>();
259 chans.put("out", st -> System.setOut(new PrintStream(st, true)));
260 chans.put("err", st -> System.setErr(new PrintStream(st, true)));
261 chans.put("aux", st -> { auxPrint = new PrintStream(st, true); });
262 forwardExecutionControlAndIO(new MyRemoteExecutionControl(), inStream, outStream, chans);
263 } catch (Throwable ex) {
264 throw ex;
265 }
266 }
267
268 @Override
269 public String varValue(String className, String varName)
270 throws RunException, EngineTerminationException, InternalException {
271 auxPrint.print(varName);
272 return super.varValue(className, varName);
273 }
274
275 @Override
276 public Object extensionCommand(String className, Object arg)
277 throws RunException, EngineTerminationException, InternalException {
278 if (!arg.equals("test")) {
279 throw new InternalException("expected extensionCommand arg to be 'test' got: " + arg);
280 }
281 return "ribbit";
282 }
|
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @bug 8160128 8159935
27 * @summary Tests for Aux channel, custom remote agents, custom JDI implementations.
28 * @build KullaTesting ExecutionControlTestBase
29 * @run testng UserJDIUserRemoteTest
30 */
31 import java.io.ByteArrayOutputStream;
32 import org.testng.annotations.Test;
33 import org.testng.annotations.BeforeMethod;
34 import jdk.jshell.Snippet;
35 import static jdk.jshell.Snippet.Status.OVERWRITTEN;
36 import static jdk.jshell.Snippet.Status.VALID;
37 import java.io.IOException;
38 import java.io.ObjectInput;
39 import java.io.ObjectOutput;
40 import java.net.ServerSocket;
41 import java.util.ArrayList;
42 import java.util.List;
43 import com.sun.jdi.VMDisconnectedException;
44 import com.sun.jdi.VirtualMachine;
45 import jdk.jshell.VarSnippet;
46 import jdk.jshell.execution.DirectExecutionControl;
47 import jdk.jshell.execution.JDIExecutionControl;
48 import jdk.jshell.execution.JDIInitiator;
49 import jdk.jshell.execution.Util;
50 import java.io.InputStream;
51 import java.io.OutputStream;
52 import java.io.PrintStream;
53 import java.net.Socket;
54
55 import java.util.HashMap;
56 import java.util.Map;
57 import java.util.function.Consumer;
58 import jdk.jshell.spi.ExecutionControl;
59 import jdk.jshell.spi.ExecutionControl.ExecutionControlException;
60 import jdk.jshell.spi.ExecutionEnv;
61 import static org.testng.Assert.assertEquals;
62 import static org.testng.Assert.fail;
63 import static jdk.jshell.execution.Util.forwardExecutionControlAndIO;
64 import static jdk.jshell.execution.Util.remoteInputOutput;
65
66 @Test
67 public class UserJDIUserRemoteTest extends ExecutionControlTestBase {
68
69 ExecutionControl currentEC;
70 ByteArrayOutputStream auxStream;
71
72 @BeforeMethod
73 @Override
74 public void setUp() {
75 auxStream = new ByteArrayOutputStream();
76 setUp(builder -> builder.executionEngine(MyExecutionControl.create(this)));
77 }
78
79 public void testVarValue() {
80 VarSnippet dv = varKey(assertEval("double aDouble = 1.5;"));
81 String vd = getState().varValue(dv);
82 assertEquals(vd, "1.5");
83 assertEquals(auxStream.toString(), "aDouble");
84 }
128 *
129 * @return the generator
130 */
131 public static ExecutionControl.Generator create(UserJDIUserRemoteTest test) {
132 return env -> make(env, test);
133 }
134
135 /**
136 * Creates an ExecutionControl instance based on a JDI
137 * {@code ListeningConnector} or {@code LaunchingConnector}.
138 *
139 * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
140 * commands and results. This socket also transports the user
141 * input/output/error.
142 *
143 * @param env the context passed by
144 * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
145 * @return the channel
146 * @throws IOException if there are errors in set-up
147 */
148 static ExecutionControl make(ExecutionEnv env, UserJDIUserRemoteTest test) throws IOException {
149 try (final ServerSocket listener = new ServerSocket(0)) {
150 // timeout after 60 seconds
151 listener.setSoTimeout(60000);
152 int port = listener.getLocalPort();
153
154 // Set-up the JDI connection
155 List<String> opts = new ArrayList<>(env.extraRemoteVMOptions());
156 opts.add("-classpath");
157 opts.add(System.getProperty("java.class.path")
158 + System.getProperty("path.separator")
159 + System.getProperty("user.dir"));
160 JDIInitiator jdii = new JDIInitiator(port,
161 opts, REMOTE_AGENT, true);
162 VirtualMachine vm = jdii.vm();
163 Process process = jdii.process();
164
165 List<Consumer<String>> deathListeners = new ArrayList<>();
166 deathListeners.add(s -> env.closeDown());
167 Util.detectJDIExitEvent(vm, s -> {
168 for (Consumer<String> h : deathListeners) {
169 h.accept(s);
170 }
171 });
172
173 // Set-up the commands/reslts on the socket. Piggy-back snippet
174 // output.
175 Socket socket = listener.accept();
176 // out before in -- match remote creation so we don't hang
177 OutputStream out = socket.getOutputStream();
178 Map<String, OutputStream> outputs = new HashMap<>();
179 outputs.put("out", env.userOut());
180 outputs.put("err", env.userErr());
181 outputs.put("aux", test.auxStream);
182 Map<String, InputStream> input = new HashMap<>();
183 input.put("in", env.userIn());
184 ExecutionControl myec = remoteInputOutput(socket.getInputStream(), out, outputs, input, (objIn, objOut) -> new MyExecutionControl(objOut, objIn, vm, process, deathListeners));
185 test.currentEC = myec;
186 return myec;
187 }
188 }
189
190 /**
191 * Create an instance.
192 *
193 * @param out the output for commands
194 * @param in the input for responses
195 */
196 private MyExecutionControl(ObjectOutput out, ObjectInput in,
197 VirtualMachine vm, Process process,
198 List<Consumer<String>> deathListeners) {
199 super(out, in);
200 this.vm = vm;
201 this.process = process;
202 deathListeners.add(s -> disposeVM());
203 }
204
238 }
239
240 class MyRemoteExecutionControl extends DirectExecutionControl implements ExecutionControl {
241
242 static PrintStream auxPrint;
243
244 /**
245 * Launch the agent, connecting to the JShell-core over the socket specified
246 * in the command-line argument.
247 *
248 * @param args standard command-line arguments, expectation is the socket
249 * number is the only argument
250 * @throws Exception any unexpected exception
251 */
252 public static void main(String[] args) throws Exception {
253 try {
254 String loopBack = null;
255 Socket socket = new Socket(loopBack, Integer.parseInt(args[0]));
256 InputStream inStream = socket.getInputStream();
257 OutputStream outStream = socket.getOutputStream();
258 Map<String, Consumer<OutputStream>> outputs = new HashMap<>();
259 outputs.put("out", st -> System.setOut(new PrintStream(st, true)));
260 outputs.put("err", st -> System.setErr(new PrintStream(st, true)));
261 outputs.put("aux", st -> { auxPrint = new PrintStream(st, true); });
262 Map<String, Consumer<InputStream>> input = new HashMap<>();
263 input.put("in", st -> System.setIn(st));
264 forwardExecutionControlAndIO(new MyRemoteExecutionControl(), inStream, outStream, outputs, input);
265 } catch (Throwable ex) {
266 throw ex;
267 }
268 }
269
270 @Override
271 public String varValue(String className, String varName)
272 throws RunException, EngineTerminationException, InternalException {
273 auxPrint.print(varName);
274 return super.varValue(className, varName);
275 }
276
277 @Override
278 public Object extensionCommand(String className, Object arg)
279 throws RunException, EngineTerminationException, InternalException {
280 if (!arg.equals("test")) {
281 throw new InternalException("expected extensionCommand arg to be 'test' got: " + arg);
282 }
283 return "ribbit";
284 }
|