Home | History | Annotate | Download | only in debuggee
      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 package org.apache.harmony.jpda.tests.jdwp.share.debuggee;
     20 
     21 import org.apache.harmony.jpda.tests.jdwp.share.JDWPInvokeMethodWithSuspensionTestCase;
     22 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
     23 import org.apache.harmony.jpda.tests.share.SyncDebuggee;
     24 
     25 /**
     26  * Debuggee for subclasses of {@link JDWPInvokeMethodWithSuspensionTestCase}.
     27  */
     28 public class InvokeMethodWithSuspensionDebuggee extends SyncDebuggee {
     29     // Information for the test.
     30     public static final String STATIC_METHOD_NAME = "invokedStaticMethod";
     31     public static final String INSTANCE_METHOD_NAME = "invokedInstanceMethod";
     32     public static final String BREAKPOINT_EVENT_THREAD_METHOD_NAME = "breakpointEventThread";
     33     public static final String BREAKPOINT_ALL_THREADS_METHOD_NAME = "breakpointAllThreads";
     34 
     35     private static volatile boolean testThreadFinished = false;
     36     private static Thread testThread = null;
     37     private static boolean enableThreadSuspensionForTesting = false;
     38 
     39     private class TestThread extends Thread {
     40         public TestThread() {
     41             super("TestThread");
     42         }
     43 
     44         @Override
     45         public void run() {
     46             logWriter.println("TestThread starts");
     47 
     48             // We're going to suspend all threads in the method below.
     49             logWriter.println("Breakpoint for event thread #2");
     50             breakpointAllThreads();
     51 
     52             // The test needs to resume us so the invoke in progress in event thread #1 can
     53             // complete.
     54             testThreadFinished = true;
     55 
     56             logWriter.println("TestThread ends");
     57         }
     58     }
     59 
     60     // Invoked to suspend main thread (event thread #1) on a breakpoint.
     61     public void breakpointEventThread() {
     62     }
     63 
     64     // Invoked to suspend test thread (event thread #2) and all others threads on a breakpoint.
     65     public void breakpointAllThreads() {
     66     }
     67 
     68     // Invoked in event thread #1. This will unblock event thread #2 that will suspend all threads
     69     // including event thread #1. This helps us check that the debugger is not blocked waiting for
     70     // this invoke.
     71     private static void causeEventThreadSuspension() {
     72         if (enableThreadSuspensionForTesting) {
     73             // Start event thread #2. It's going to hit a breakpoint and suspend us.
     74             testThread.start();
     75 
     76             // We don't use wait/notify pattern to be sure our loop is active.
     77             while (!testThreadFinished) {
     78                 try {
     79                     Thread.sleep(100);
     80                 } catch (InterruptedException e) {
     81                     e.printStackTrace();
     82                 }
     83             }
     84         }
     85     }
     86 
     87     // Static method to test ClassType.InvokeMethod.
     88     public static void invokedStaticMethod() {
     89         causeEventThreadSuspension();
     90     }
     91 
     92     // Constructor to test ClassType.NewInstance.
     93     public InvokeMethodWithSuspensionDebuggee() {
     94         causeEventThreadSuspension();
     95     }
     96 
     97     // Instance method to test ObjectReference.InvokeMethod.
     98     public void invokedInstanceMethod() {
     99         causeEventThreadSuspension();
    100     }
    101 
    102     @Override
    103     public void run() {
    104         logWriter.println("InvokeMethodWithThreadSuspensionDebuggee starts");
    105 
    106         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY);
    107 
    108         // Create test thread but do not start it now. It will be started by the invoke from
    109         // the test through JDWP.
    110         testThread = new TestThread();
    111 
    112         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
    113 
    114         enableThreadSuspensionForTesting = true;
    115 
    116         // We want to suspend the main thread on a breakpoint.
    117         logWriter.println("Breakpoint for event thread #1");
    118         breakpointEventThread();
    119 
    120         // Ensure tested thread is finished.
    121         try {
    122             testThread.join();
    123         } catch (InterruptedException e) {
    124             logWriter.printError("Failed to join tested thread", e);
    125         }
    126         testThread = null;
    127 
    128         logWriter.println("InvokeMethodWithThreadSuspensionDebuggee ends");
    129     }
    130 
    131     public static void main(String[] args) {
    132         runDebuggee(InvokeMethodWithSuspensionDebuggee.class);
    133     }
    134 }
    135