1 /*
   2  * Copyright (c) 2005, 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 /*
  25  * @test
  26  * @bug     4519200 6562203
  27  * @summary Confirm a Thread.stop before start complies with the spec
  28  * @author  Pete Soper
  29  *
  30  * Confirm that a thread that had its stop method invoked before start
  31  * does properly terminate with expected exception behavior.
  32  */
  33 public class StopBeforeStart {
  34 
  35     private static final int JOIN_TIMEOUT=10000;
  36 
  37     @SuppressWarnings("serial")
  38     private class MyThrowable extends Throwable { }
  39 
  40     private class Catcher implements Thread.UncaughtExceptionHandler {
  41         private final boolean nullaryStop;
  42         private Throwable theThrowable;
  43         private Throwable expectedThrowable;
  44         private boolean exceptionThrown;
  45 
  46         Catcher(boolean nullaryStop) {
  47             this.nullaryStop = nullaryStop;
  48             if (!nullaryStop) {
  49                 expectedThrowable = new MyThrowable();
  50             }
  51         }
  52 
  53         public void uncaughtException(Thread t, Throwable th) {
  54             exceptionThrown = true;
  55             theThrowable = th;
  56         }
  57 
  58         void check(String label) throws Throwable {
  59             if (!exceptionThrown) {
  60                 throw new RuntimeException(label +
  61                         " test:" + " missing uncaught exception");
  62             }
  63 
  64             if (nullaryStop) {
  65                 if (! (theThrowable instanceof ThreadDeath)) {
  66                     throw new RuntimeException(label +
  67                         " test:" + " expected ThreadDeath in uncaught handler");
  68                 }
  69             } else if (theThrowable != expectedThrowable) {
  70                 throw new RuntimeException(label +
  71                         " test:" + " wrong Throwable in uncaught handler");
  72             }
  73         }
  74     }
  75 
  76     private class MyRunnable implements Runnable {
  77         public void run() {
  78             while(true)
  79                 ;
  80         }
  81     }
  82 
  83     private class MyThread extends Thread {
  84         public void run() {
  85             while(true)
  86                 ;
  87         }
  88     }
  89 
  90 
  91     public static void main(String args[]) throws Throwable {
  92         (new StopBeforeStart()).doit();
  93         System.out.println("Test passed");
  94     }
  95 
  96     private void doit() throws Throwable {
  97 
  98         runit(false, new Thread(new MyRunnable()),"Thread");
  99         runit(true, new Thread(new MyRunnable()),"Thread");
 100         runit(false, new MyThread(),"Runnable");
 101         runit(true, new MyThread(),"Runnable");
 102     }
 103 
 104     private void runit(boolean nullaryStop, Thread thread,
 105                         String type) throws Throwable {
 106 
 107         Catcher c = new Catcher(nullaryStop);
 108         thread.setUncaughtExceptionHandler(c);
 109 
 110         if (nullaryStop) {
 111             stop(thread);
 112         } else {
 113             stop(thread, c.expectedThrowable);
 114         }
 115 
 116         thread.start();
 117         thread.join(JOIN_TIMEOUT);
 118 
 119         if (thread.getState() != Thread.State.TERMINATED) {
 120 
 121             stop(thread);
 122 
 123             // Under high load this could be a false positive
 124             throw new RuntimeException(type +
 125                         " test:" + " app thread did not terminate");
 126         }
 127 
 128         c.check(type);
 129     }
 130 
 131     @SuppressWarnings("deprecation")
 132     void stop(Thread thread) {
 133         thread.stop();
 134     }
 135 
 136     @SuppressWarnings("deprecation")
 137     void stop(Thread thread, Throwable t) {
 138         thread.stop(t);
 139     }
 140 }