1 /*
2  * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package nsk.jdi.AttachingConnector.attachnosuspend;
25 
26 import com.sun.jdi.Bootstrap;
27 import com.sun.jdi.connect.*;
28 import com.sun.jdi.VirtualMachine;
29 import com.sun.jdi.ReferenceType;
30 
31 import java.io.*;
32 
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36 
37 import nsk.share.*;
38 import nsk.share.jpda.*;
39 import nsk.share.jdi.*;
40 
41 
42 /**
43  * The test checks that debugger may establish connection with
44  * a target VM via <code>com.sun.jdi.SocketAttach</code> connector.
45  */
46 public class attachnosuspend001 {
47     static final int PASSED = 0;
48     static final int FAILED = 2;
49     static final int JCK_STATUS_BASE = 95;
50     static final String DEBUGEE_CLASS =
51         "nsk.jdi.AttachingConnector.attachnosuspend.attachnosuspend001t";
52 
53     private Log log;
54 
55     private VirtualMachine vm;
56 
57     private int attempts;             // attempts to connect to the debugee VM
58     private int delay = 4000;         // delay between connection attempts
59 
60     IORedirector outRedirector;
61     IORedirector errRedirector;
62 
main(String argv[])63     public static void main (String argv[]) {
64         System.exit(run(argv,System.out) + JCK_STATUS_BASE);
65     }
66 
run(String argv[], PrintStream out)67     public static int run(String argv[], PrintStream out) {
68         return new attachnosuspend001().runIt(argv, out);
69     }
70 
runIt(String argv[], PrintStream out)71     private int runIt(String argv[], PrintStream out) {
72         String port;
73         String listenPort;
74         Process proc;
75         ArgumentHandler argHandler = new ArgumentHandler(argv);
76 
77 // pass if "com.sun.jdi.SocketAttach" is not implemented
78 // on this platform
79         if (argHandler.shouldPass("com.sun.jdi.SocketAttach"))
80             return PASSED;
81 
82         log = new Log(out, argHandler);
83 
84         String args[] = argHandler.getArguments();
85 
86         // treat second positional argument as delay between connection attempts
87         try {
88             delay = Integer.parseInt(args[1]);
89         } catch (NumberFormatException e) {
90             log.complain("Incorrect test parameter: timeout value must be an integer");
91             return FAILED;
92         } catch (ArrayIndexOutOfBoundsException e) {
93             // ignore: default delay will be used if no second argument present
94         }
95         // calculate number of connection attempts to not exceed WAITTIME
96         long timeout = argHandler.getWaitTime() * 60 * 1000;
97         attempts = (int)(timeout / delay);
98 
99         port = argHandler.getTransportPort();
100         listenPort = argHandler.getTransportPort();
101 
102         String java = argHandler.getLaunchExecPath()
103                         + " " + argHandler.getLaunchOptions();
104         String cmd = java +
105                 " -Xdebug -Xnoagent -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=" +
106                 listenPort + " " + DEBUGEE_CLASS;
107 
108         Binder binder = new Binder(argHandler, log);
109         log.display("command: " + cmd);
110         Debugee debugee = binder.startLocalDebugee(cmd);
111         debugee.redirectOutput(log);
112 
113         if ((vm = attachTarget(argHandler.getTestHost(), port)) == null) {
114             log.complain("TEST: Unable to attach the debugee VM");
115             debugee.close();
116             return FAILED;
117         }
118 
119         log.display("debugee VM: name=" + vm.name() + " JRE version=" +
120             vm.version() + "\n\tdescription=" + vm.description());
121 
122         debugee.setupVM(vm);
123         //debugee.waitForVMInit(timeout);
124 
125         //log.display("\nresuming debugee VM");
126         //debugee.resume();
127 
128         log.display("\nwaiting for debugee VM exit");
129         int code = debugee.waitFor();
130         if (code != (JCK_STATUS_BASE+PASSED)) {
131             log.complain("Debugee VM has crashed: exit code=" +
132                 code);
133             return FAILED;
134         }
135         log.display("debugee VM: exit code=" + code);
136         return PASSED;
137     }
138 
attachTarget(String host, String port)139     private VirtualMachine attachTarget(String host, String port) {
140         Connector.Argument arg;
141 
142         if (port == null) {
143             log.complain("TEST: port number is required!");
144             return null;
145         }
146 
147         AttachingConnector connector =
148             (AttachingConnector) findConnector("com.sun.jdi.SocketAttach");
149 
150         Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> cArgs = connector.defaultArguments();
151         Iterator cArgsValIter = cArgs.keySet().iterator();
152         while (cArgsValIter.hasNext()) {
153             String argKey = (String) cArgsValIter.next();
154             String argVal = null;
155 
156             if ((arg = (Connector.Argument) cArgs.get(argKey)) == null) {
157                 log.complain("Argument " + argKey.toString() +
158                     "is not defined for the connector: " + connector.name());
159             }
160             if (arg.name().equals("hostname") && host != null)
161                 arg.setValue(host);
162             if (arg.name().equals("port"))
163                 arg.setValue(port);
164 
165             log.display("\targument name=" + arg.name());
166             if ((argVal = arg.value()) != null)
167                 log.display("\t\tvalue="+argVal);
168             else log.display("\t\tvalue=NULL");
169         }
170 
171         // make several attemts to connect to the debugee VM until WAITTIME exceeds
172         for (int i = 0; i < attempts; i++) {
173             try {
174                 return connector.attach(cArgs);
175             } catch (IOException e) {
176                 // could not connect; sleep a few and make new attempt
177                 log.display("Connection attempt #" + i + " failed: " + e);
178                 try {
179                     Thread.currentThread().sleep(delay);
180                 } catch (InterruptedException ie) {
181                     log.complain("TEST INCOMPLETE: interrupted sleep: " + ie);
182                 }
183             } catch (IllegalConnectorArgumentsException e) {
184                 log.complain("TEST: Illegal connector arguments: " +
185                     e.getMessage());
186                 return null;
187             } catch (Exception e) {
188                 log.complain("TEST: Internal error: " + e.getMessage());
189                 return null;
190             }
191         }
192         // return null after all attempts failed
193         log.complain("FAILURE: all attempts to connect to the debugee VM failed");
194         return null;
195     }
196 
findConnector(String connectorName)197     private Connector findConnector(String connectorName) {
198         List connectors = Bootstrap.virtualMachineManager().allConnectors();
199         Iterator iter = connectors.iterator();
200 
201         while (iter.hasNext()) {
202             Connector connector = (Connector) iter.next();
203             if (connector.name().equals(connectorName)) {
204                 log.display("Connector name=" + connector.name() +
205                     "\n\tdescription=" + connector.description() +
206                     "\n\ttransport=" + connector.transport().name());
207                 return connector;
208             }
209         }
210         throw new Error("No appropriate connector");
211     }
212 }
213