1 #!/bin/sh
   2 
   3 #
   4 # Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
   5 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6 #
   7 # This code is free software; you can redistribute it and/or modify it
   8 # under the terms of the GNU General Public License version 2 only, as
   9 # published by the Free Software Foundation.
  10 #
  11 # This code is distributed in the hope that it will be useful, but WITHOUT
  12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14 # version 2 for more details (a copy is included in the LICENSE file that
  15 # accompanied this code).
  16 #
  17 # You should have received a copy of the GNU General Public License version
  18 # 2 along with this work; if not, write to the Free Software Foundation,
  19 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20 #
  21 # Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22 # CA 95054 USA or visit www.sun.com if you need additional information or
  23 # have any questions.
  24 #
  25 
  26 #
  27 # @test
  28 # @bug 4833089 4992454
  29 # @summary Check for proper handling of uncaught exceptions
  30 # @author Martin Buchholz
  31 #
  32 # @run shell UncaughtExceptions.sh
  33 
  34 # To run this test manually, simply do ./UncaughtExceptions.sh
  35 
  36  java="${TESTJAVA+${TESTJAVA}/bin/}java"
  37 javac="${TESTJAVA+${TESTJAVA}/bin/}javac"
  38 
  39 failed=""
  40 Fail() { echo "FAIL: $1"; failed="${failed}."; }
  41 
  42 Die() { printf "%s\n" "$*"; exit 1; }
  43 
  44 Sys() {
  45     "$@"; rc="$?";
  46     test "$rc" -eq 0 || Die "Command \"$*\" failed with exitValue $rc";
  47 }
  48 
  49 HorizontalRule() {
  50     echo "-----------------------------------------------------------------"
  51 }
  52 
  53 Bottom() {
  54     test "$#" = 1 -a "$1" = "Line" || Die "Usage: Bottom Line"
  55 
  56     HorizontalRule
  57     if test -n "$failed"; then
  58         count=`printf "%s" "$failed" | wc -c | tr -d ' '`
  59         echo "FAIL: $count tests failed"
  60         exit 1
  61     else
  62         echo "PASS: all tests gave expected results"
  63         exit 0
  64     fi
  65 }
  66 
  67 Cleanup() { Sys rm -f Seppuku* OK.class; }
  68 
  69 set -u
  70 
  71 checkOutput() {
  72     name="$1" expected="$2" got="$3"
  73     printf "$name:\n"; cat "$got"
  74     if test -z "$expected"; then
  75         test "`cat $got`" != "" && \
  76             Fail "Unexpected $name: `cat $got`"
  77     else
  78         grep "$expected" "$got" >/dev/null || \
  79             Fail "Expected \"$expected\", got `cat $got`"
  80     fi
  81 }
  82 
  83 CheckCommandResults() {
  84     expectedRC="$1" expectedOut="$2" expectedErr="$3"; shift 3
  85     saveFailed="${failed}"
  86     "$@" >TmpTest.Out 2>TmpTest.Err; rc="$?";
  87     printf "==> %s (rc=%d)\n" "$*" "$rc"
  88     checkOutput "stdout" "$expectedOut" "TmpTest.Out"
  89     checkOutput "stderr" "$expectedErr" "TmpTest.Err"
  90     test "${saveFailed}" = "${failed}" && \
  91         echo "PASS: command completed as expected"
  92     Sys rm -f TmpTest.Out TmpTest.Err
  93 }
  94 
  95 Run() {
  96     expectedRC="$1" expectedOut="$2" expectedErr="$3" mainBody="$4"
  97     cat > Seppuku.java <<EOJAVA
  98 import static java.lang.Thread.*;
  99 import static java.lang.System.*;
 100 
 101 class OK implements UncaughtExceptionHandler {
 102     public void uncaughtException(Thread t, Throwable e) {
 103         out.println("OK");
 104     }
 105 }
 106 
 107 class NeverInvoked implements UncaughtExceptionHandler {
 108     public void uncaughtException(Thread t, Throwable e) {
 109         err.println("Test failure: This handler should never be invoked!");
 110     }
 111 }
 112 
 113 public class Seppuku extends Thread implements Runnable {
 114     public static void seppuku() { throw new RuntimeException("Seppuku!"); }
 115 
 116     public void run() { seppuku(); }
 117 
 118     public static void main(String[] args) throws Exception {
 119         $mainBody
 120     }
 121 }
 122 EOJAVA
 123 
 124     Sys "$javac" "-source" "1.5" "Seppuku.java"
 125     CheckCommandResults "$expectedRC" "$expectedOut" "$expectedErr" \
 126         "$java" "Seppuku"
 127     Cleanup
 128 }
 129 
 130 #----------------------------------------------------------------
 131 # A thread is never alive after you've join()ed it.
 132 #----------------------------------------------------------------
 133 Run 0 "OK" "Exception in thread \"Thread-0\".*Seppuku" "
 134     Thread t = new Seppuku();
 135     t.start(); t.join();
 136     if (! t.isAlive())
 137         out.println(\"OK\");"
 138 
 139 #----------------------------------------------------------------
 140 # Even the main thread is mortal - here it terminates "abruptly"
 141 #----------------------------------------------------------------
 142 Run 1 "OK" "Exception in thread \"main\".*Seppuku" "
 143     final Thread mainThread = currentThread();
 144     new Thread() { public void run() {
 145         try { mainThread.join(); }
 146         catch (InterruptedException e) {}
 147         if (! mainThread.isAlive())
 148             out.println(\"OK\");
 149     }}.start();
 150     seppuku();"
 151 
 152 #----------------------------------------------------------------
 153 # Even the main thread is mortal - here it terminates normally.
 154 #----------------------------------------------------------------
 155 Run 0 "OK" "" "
 156     final Thread mainThread = currentThread();
 157     new Thread() { public void run() {
 158         try { mainThread.join(); }
 159         catch (InterruptedException e) {}
 160         if (! mainThread.isAlive())
 161             out.println(\"OK\");
 162     }}.start();"
 163 
 164 #----------------------------------------------------------------
 165 # Check uncaught exception handler mechanism on the main thread.
 166 # Check that thread-level handler overrides global default handler.
 167 #----------------------------------------------------------------
 168 Run 1 "OK" "" "
 169     currentThread().setUncaughtExceptionHandler(new OK());
 170     setDefaultUncaughtExceptionHandler(new NeverInvoked());
 171     seppuku();"
 172 
 173 Run 1 "OK" "" "
 174     setDefaultUncaughtExceptionHandler(new OK());
 175     seppuku();"
 176 
 177 #----------------------------------------------------------------
 178 # Check uncaught exception handler mechanism on non-main threads.
 179 #----------------------------------------------------------------
 180 Run 0 "OK" "" "
 181     Thread t = new Seppuku();
 182     t.setUncaughtExceptionHandler(new OK());
 183     t.start();"
 184 
 185 Run 0 "OK" "" "
 186     setDefaultUncaughtExceptionHandler(new OK());
 187     new Seppuku().start();"
 188 
 189 #----------------------------------------------------------------
 190 # Test ThreadGroup based uncaught exception handler mechanism.
 191 # Since the handler for the main thread group cannot be changed,
 192 # there are no tests for the main thread here.
 193 #----------------------------------------------------------------
 194 Run 0 "OK" "" "
 195     setDefaultUncaughtExceptionHandler(new NeverInvoked());
 196     new Thread(
 197         new ThreadGroup(\"OK\") {
 198             public void uncaughtException(Thread t, Throwable e) {
 199                 out.println(\"OK\");}},
 200         new Seppuku()
 201     ).start();"
 202 
 203 Cleanup
 204 
 205 Bottom Line