1 /*
2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3  * Copyright (c) 2018, SAP SE. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /**
26  * @test
27  * @bug 8214892
28  * @summary Test that the onjcmd option of the jdwp agent works.
29  *
30  * @author Ralf Schmelter
31  *
32  * @library /test/lib
33  * @run compile --add-exports java.base/jdk.internal.vm=ALL-UNNAMED -g OnJcmdTest.java
34  * @run main/othervm --add-exports java.base/jdk.internal.vm=ALL-UNNAMED -agentlib:jdwp=transport=dt_socket,address=localhost:0,onjcmd=y,server=y OnJcmdTest
35  */
36 
37 import java.lang.reflect.Method;
38 import java.util.Properties;
39 
40 import jdk.internal.vm.VMSupport;
41 import jdk.test.lib.JDKToolFinder;
42 import jdk.test.lib.process.OutputAnalyzer;
43 import jdk.test.lib.process.ProcessTools;
44 
45 public class OnJcmdTest {
46 
getListenerAddress()47     private static String getListenerAddress() throws Exception {
48         Properties props = VMSupport.getAgentProperties();
49         return props.getProperty("sun.jdwp.listenerAddress", null);
50     }
51 
main(String[] args)52     public static void main(String[] args) throws Throwable {
53         // First check if we get the expected errors.
54         OutputAnalyzer output = ProcessTools.executeTestJvm(
55                 "-agentlib:jdwp=transport=dt_socket,address=any,onjcmd=y");
56         output.shouldContain("Can only use onjcmd with server=y");
57         output.shouldHaveExitValue(1);
58 
59         output = ProcessTools.executeTestJvm(
60                 "-agentlib:jdwp=transport=dt_socket,address=any,onjcmd=y,onthrow=a,launch=a");
61         output.shouldContain("Cannot combine onjcmd and launch suboptions");
62         output.shouldHaveExitValue(1);
63 
64         // Make sure debugging is not yet started.
65         String prop = getListenerAddress();
66 
67         if (prop != null) {
68             throw new RuntimeException("Listener address was set to " + prop);
69         }
70 
71         // Now start it (test that it is OK to do this more than once).
72         for (int i = 0; i < 3; ++i) {
73             String jcmd = JDKToolFinder.getJDKTool("jcmd");
74             output = ProcessTools.executeProcess(jcmd,
75                     Long.toString(ProcessTools.getProcessId()),
76                     "VM.start_java_debugging");
77 
78             String exp_str = i == 0 ? "Debugging has been started." :
79                                       "Debugging is already active.";
80             output.shouldContain(exp_str);
81             output.shouldContain("Transport : dt_socket");
82             output.shouldHaveExitValue(0);
83         }
84 
85         // Now the property should be set, as the jdwp agent waits for a
86         // connection.
87         long t1 = System.currentTimeMillis();
88         long t2 = t1;
89 
90         while(t2 - t1 < 4000) {
91             prop = getListenerAddress();
92 
93             if (prop != null) {
94                 if (prop.equals("localhost:0")) {
95                     throw new RuntimeException("Port was not expanded");
96                 } else if (!prop.startsWith("dt_socket:")) {
97                     throw new RuntimeException("Invalid transport prop " + prop);
98                 }
99 
100                 return;
101             }
102 
103             Thread.sleep(50);
104             t2 = System.currentTimeMillis();
105         }
106 
107         throw new RuntimeException("Debugging backend didn't start");
108     }
109 }
110