Home | History | Annotate | Download | only in DebuggerOnDemand
      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