1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 /** 20 * @author Aleksander V. Budniy 21 */ 22 23 /** 24 * Created on 5.06.2006 25 */ 26 package org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand; 27 28 import org.apache.harmony.jpda.tests.framework.TestErrorException; 29 import org.apache.harmony.jpda.tests.framework.TestOptions; 30 import org.apache.harmony.jpda.tests.jdwp.share.JDWPRawTestCase; 31 import org.apache.harmony.jpda.tests.jdwp.share.JDWPUnitDebuggeeProcessWrapper; 32 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 33 import org.apache.harmony.jpda.tests.share.JPDATestOptions; 34 35 /** 36 * This test case exercises possibility of debuggee to invoke debugger 37 * on demand with "onthrow" option. 38 * 39 * @see org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchDebuggee 40 * @see org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger001 41 * @see org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger002 42 */ 43 public class OnthrowDebuggerLaunchTest extends JDWPRawTestCase { 44 45 public static final String EXCEPTION_CLASS_FOR_DEBUGGER = 46 "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.ExceptionForDebugger"; 47 48 public static final String DEBUGGEE_CLASS = 49 "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchDebuggee"; 50 51 /** 52 * Test launches debuggee (without establishing synchronization connection) 53 * with options suspend=y,onuncaught=n, debuggee executes 54 * <code>OnthrowLaunchedDebugger001</code>, test establishes synch 55 * connection with debugger and in cycle receives messages from debugger. 56 */ 57 public void testDebuggerLaunch001() { 58 logWriter.println("==> testDebuggerLaunch started"); 59 60 String DEBUGGER_NAME = "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger001"; 61 String isSuspend = "y"; 62 String isOnuncaught = "n"; 63 64 performTest(DEBUGGER_NAME, isSuspend, isOnuncaught); 65 66 logWriter.println("==> testDebuggerLaunch ended"); 67 } 68 69 /** 70 * Test launches debuggee (without establishing synchronization connection) 71 * with option suspend=y,onuncaught=n, debuggee executes 72 * <code>OnthrowLaunchedDebugger002</code>, test establishes synch 73 * connection with debugger and in cycle receives messages from debugger. 74 * 75 */ 76 77 public void testDebuggerLaunch002() { 78 logWriter.println("==> testDebuggerLaunch002 started"); 79 80 String DEBUGGER_NAME = "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger002"; 81 String isSuspend = "y"; 82 String isOnuncaught = "n"; 83 84 performTest(DEBUGGER_NAME, isSuspend, isOnuncaught); 85 86 logWriter.println("==> testDebuggerLaunch002 ended"); 87 } 88 89 90 /** 91 * Test launches debuggee (without establishing synchronization connection) 92 * with option suspend=n,onuncaught=n debuggee executes 93 * <code>OnthrowLaunchedDebugger001</code>, test establishes synch 94 * connection with debugger and in cycle receives messages from debugger. 95 * 96 */ 97 public void testDebuggerLaunch003() { 98 logWriter.println("==> testDebuggerLaunch started"); 99 100 String DEBUGGER_NAME = "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger001"; 101 String isSuspend = "n"; 102 String isOnuncaught = "n"; 103 104 performTest(DEBUGGER_NAME, isSuspend, isOnuncaught); 105 106 logWriter.println("==> testDebuggerLaunch ended"); 107 } 108 109 /** 110 * Test executes debuggee (without establishing synchronization connection) 111 * with option suspend=n,onuncaught=n debuggee executes 112 * <code>OnthrowLaunchedDebugger002</code>, test establishes synch 113 * connection with debugger and in cycle receives messages from debugger. 114 * 115 */ 116 public void testDebuggerLaunch004() { 117 logWriter.println("==> testDebuggerLaunch started"); 118 119 String DEBUGGER_NAME = "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger002"; 120 String isSuspend = "n"; 121 String isOnuncaught = "n"; 122 123 performTest(DEBUGGER_NAME, isSuspend, isOnuncaught); 124 125 logWriter.println("==> testDebuggerLaunch ended"); 126 } 127 128 /** 129 * Method prepares cmd for launching debuggee and debugger. Passes 130 * debugger's cmd as parameter "launch" to debuggee's cmd. Then launches 131 * debuggee and wait for synch connection from debugger, that should be 132 * launched by debuggee. After that, method starts receiving messages in 133 * loop from debugger. Messages of three types: OK, FAIL, END. In case of 134 * FAIL or END messages, loop is ended. 135 * 136 * @param debuggerName 137 * name of debugger that debuggee will launch 138 * @param isSuspendDebuggee 139 * option defines should debuggee be suspended on start 140 * @param isOnuncaught 141 * parameter that is passed to debuggee (see JDWP agent launch 142 * options) 143 */ 144 void performTest(String debuggerName, String isSuspendDebuggee, String isOnuncaught) { 145 146 try { 147 // prepare command line for debugger and debuggee processes 148 149 String address = settings.getTransportAddress(); 150 String debuggerCmd = prepareDebuggerCmd(debuggerName, address, 151 isSuspendDebuggee, isOnuncaught); 152 logWriter.println("=> Debugger command: " + debuggerCmd); 153 154 String debuggeeCmd = prepareDebuggeeCmd(debuggerCmd, address, 155 isSuspendDebuggee, isOnuncaught); 156 logWriter.println("=> Debuggee command: " + debuggeeCmd); 157 158 // launch debuggee process, which will launch debugger process 159 160 debuggeeWrapper.launchProcessAndRedirectors(debuggeeCmd); 161 162 // listen for synch connection from launched debugger 163 164 logWriter.println("=> Listen for synch connection from launched debugger"); 165 debuggerSynchronizer.startServer(); 166 logWriter.println("=> Synch connection with launched debugger established"); 167 } catch (Exception e) { 168 throw new TestErrorException(e); 169 } 170 171 // exchange synch messages with debugger 172 173 for (;;) { 174 String message = debuggerSynchronizer.receiveMessage(); 175 if (message != null) { 176 logWriter.println("=> Message received from DEBUGGER: " + message); 177 if (message.equals("FAILURE")) { 178 logWriter.println("##FAILURE: error message received from debugger"); 179 fail("Some error received from debugger"); 180 } else if (message.equals("END")) { 181 logWriter.println("=> Debugger ends work"); 182 break; 183 } else if (!message.equals("OK")) { 184 logWriter.println("##FAILURE: unexpected message received from debugger"); 185 fail("Unexpected message received from debugger"); 186 } 187 } else { 188 logWriter.println("##FAILURE: null message received from debugger"); 189 fail("Null message received from debugger"); 190 } 191 } 192 } 193 194 //////////////////////////////////////////////////////////////////////////////////////////// 195 196 @Override 197 protected String getDebuggeeClassName() { 198 return DEBUGGEE_CLASS; 199 } 200 201 /** 202 * Creates wrapper for debuggee process. 203 */ 204 protected JDWPUnitDebuggeeProcessWrapper createDebuggeeWrapper() { 205 return new JDWPUnitDebuggeeProcessWrapper(settings, logWriter); 206 } 207 208 /** 209 * Creates wrapper for synch connection with debugger. 210 */ 211 protected JPDADebuggeeSynchronizer createDebuggerSyncronizer(){ 212 return new JPDADebuggeeSynchronizer(logWriter, settings); 213 } 214 215 /** 216 * Creates wrapper object for accessing test options; 217 */ 218 @Override 219 protected JPDATestOptions createTestOptions() { 220 return new LaunchedDebugger.JPDADebuggerOnDemandOptions(); 221 } 222 223 @Override 224 protected void internalSetUp() throws Exception { 225 super.internalSetUp(); 226 227 // set fixed address for attaching connection 228 229 String address = settings.getTransportAddress(); 230 if (address == null) { 231 settings.setTransportAddress(TestOptions.DEFAULT_ATTACHING_ADDRESS); 232 } 233 234 // set fixed port for debuggee sync connection 235 236 debuggeeSyncPort = settings.getSyncPortString(); 237 if (debuggeeSyncPort == null) { 238 debuggeeSyncPort = TestOptions.DEFAULT_STATIC_SYNC_PORT; 239 } 240 241 // prepare for synch connection with debugger 242 243 logWriter.println("=> Prepare synch connection with debugger"); 244 debuggerSynchronizer = createDebuggerSyncronizer(); 245 debuggerSyncPortNumber = debuggerSynchronizer.bindServer(); 246 247 // create wrapper for debuggee process 248 249 debuggeeWrapper = createDebuggeeWrapper(); 250 } 251 252 /** 253 * Overrides inherited method to stop started debuggee VM and close all 254 * connections. 255 */ 256 @Override 257 protected void internalTearDown() { 258 if (debuggerSynchronizer != null) { 259 logWriter.println("Close synch connection with debugger"); 260 debuggerSynchronizer.stop(); 261 } 262 263 if (debuggeeWrapper != null) { 264 debuggeeWrapper.finishProcessAndRedirectors(); 265 logWriter.println("Finished debuggee VM process and closed connection"); 266 } 267 super.internalTearDown(); 268 } 269 270 /** 271 * Prepares command line for launching debuggee. 272 * 273 * @param debuggerName name of debugger that debuggee will launch 274 * @param transportAddress address for connection with debugger 275 * @param isSuspendDebuggee should debuggee be suspended on start 276 * @param isOnuncaught should debuggee waits for uncaught exception (see JDWP agent launch options) 277 * @return command line for launching debuggee 278 */ 279 private String prepareDebuggerCmd(String debuggerName, String transportAddress, 280 String isSuspendDebuggee, String isOnuncaught) { 281 282 String cmdLine = settings.getDebuggeeJavaPath() 283 + " -cp " + settings.getDebuggeeClassPath() 284 + " -Djpda.settings.connectorKind=attach" 285 + " -Djpda.settings.debuggeeSuspend=" + isSuspendDebuggee 286 + " -Djpda.settings.transportAddress=" + transportAddress 287 + " -Djpda.settings.syncDebuggerPort=" + debuggerSyncPortNumber 288 + " -Djpda.settings.syncPort=" + debuggeeSyncPort 289 + " " + debuggerName; 290 291 return cmdLine; 292 } 293 294 /** 295 * Prepares command line for launching debuggee. 296 * 297 * @param debuggerCmd cmd to launch debugger. Value of parameter "launch" 298 * @param transportAddress address for connection with debugger 299 * @param isSuspendDebuggee should debuggee be suspended on start 300 * @param isOnuncaught should debuggee waits for uncaught exception (see JDWP agent launch options) 301 * @return command line for launching debuggee 302 */ 303 private String prepareDebuggeeCmd(String debuggerCmd, String transportAddress, 304 String isSuspendDebuggee, String isOnuncaught) { 305 306 String cmdLine = settings.getDebuggeeJavaPath() 307 + " -cp " 308 + settings.getDebuggeeClassPath() 309 + " \"" 310 + settings.getDebuggeeAgentArgument() + settings.getDebuggeeAgentName() 311 + "=transport=dt_socket,address=" + transportAddress 312 + ",server=y" 313 + ",suspend=" + isSuspendDebuggee 314 + ",onuncaught=" + isOnuncaught 315 + ",onthrow=" + EXCEPTION_CLASS_FOR_DEBUGGER 316 + ",launch=\'" + debuggerCmd + "\'" 317 + "," + settings.getDebuggeeAgentExtraOptions() 318 + "\"" 319 + " " + settings.getDebuggeeVMExtraOptions() 320 + " -Djpda.settings.syncPort=" + debuggeeSyncPort 321 + " " + getDebuggeeClassName(); 322 323 return cmdLine; 324 } 325 326 protected JDWPUnitDebuggeeProcessWrapper debuggeeWrapper; 327 328 protected JPDADebuggeeSynchronizer debuggerSynchronizer; 329 private int debuggerSyncPortNumber; 330 private String debuggeeSyncPort; 331 } 332