1 /* 2 * Copyright (c) 2013, 2015, 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 package jdk.testlibrary; 25 26 import java.util.concurrent.TimeoutException; 27 28 /** 29 * Thread which catches exceptions thrown during the execution 30 * and stores them for later analysis. 31 * 32 * <pre> 33 * {@code 34 * TestThread thread = new TestThread(new XRun() { 35 * public void run() { 36 * // do something 37 * } 38 * }); 39 * thread.start(); 40 * // do something 41 * Throwable uncaught = thread.getUncaught(); 42 * } 43 * </pre> 44 */ 45 public class TestThread extends Thread { 46 47 private final Runnable runnable; 48 private volatile Throwable uncaught; 49 50 /** 51 * Returns {@link Runnable} the thread has been created with. 52 * 53 * @return The object whose {@code run} method is called 54 */ 55 public Runnable getRunnable() { 56 return runnable; 57 } 58 59 /** 60 * Creates a new {@code TestThread} object. 61 * 62 * @param target The object whose {@code run} method is called 63 * @param name The thread name 64 */ 65 public TestThread(Runnable target, String name) { 66 super(target, name); 67 this.runnable = target; 68 } 69 70 /** 71 * Creates a new {@code TestThread} object. 72 * 73 * @param target The object whose {@code run} method is called 74 */ 75 public TestThread(Runnable target) { 76 super(target); 77 this.runnable = target; 78 } 79 80 /** 81 * Creates a new {@code TestThread} object. 82 * 83 * @param group The thread group 84 * @param target The object whose {@code run} method is called 85 * @param name The thread name 86 * @param stackSize Stack size 87 */ 88 public TestThread(ThreadGroup group, Runnable target, String name, 89 long stackSize) { 90 super(group, target, name, stackSize); 91 this.runnable = target; 92 } 93 94 /** 95 * Creates a new {@code TestThread} object. 96 * 97 * @param group The thread group 98 * @param target The object whose {@code run} method is called 99 * @param name The thread name 100 */ 101 public TestThread(ThreadGroup group, Runnable target, String name) { 102 super(group, target, name); 103 this.runnable = target; 104 } 105 106 /** 107 * Creates a new {@code TestThread} object. 108 * 109 * @param group The thread group 110 * @param target The object whose {@code run} method is called 111 */ 112 public TestThread(ThreadGroup group, Runnable target) { 113 super(group, target); 114 this.runnable = target; 115 } 116 117 /** 118 * The thread executor. 119 */ 120 @Override 121 public void run() { 122 try { 123 super.run(); 124 } catch (Throwable t) { 125 uncaught = t; 126 } 127 } 128 129 /** 130 * Returns exception caught during the execution. 131 * 132 * @return {@link Throwable} 133 */ 134 public Throwable getUncaught() { 135 return uncaught; 136 } 137 138 /** 139 * Waits for {@link TestThread} to die 140 * and throws exception caught during the execution. 141 * 142 * @throws InterruptedException 143 * @throws Throwable 144 */ 145 public void joinAndThrow() throws InterruptedException, Throwable { 146 join(); 147 if (uncaught != null) { 148 throw uncaught; 149 } 150 } 151 152 /** 153 * Waits during {@code timeout} for {@link TestThread} to die 154 * and throws exception caught during the execution. 155 * 156 * @param timeout The time to wait in milliseconds 157 * @throws InterruptedException 158 * @throws Throwable 159 */ 160 public void joinAndThrow(long timeout) throws InterruptedException, 161 Throwable { 162 join(timeout); 163 if (isAlive()) { 164 throw new TimeoutException(); 165 } 166 if (uncaught != null) { 167 throw uncaught; 168 } 169 } 170 171 /** 172 * Waits for {@link TestThread} to die 173 * and returns exception caught during the execution. 174 * 175 * @return Exception caught during the execution 176 * @throws InterruptedException 177 */ 178 public Throwable joinAndReturn() throws InterruptedException { 179 join(); 180 if (uncaught != null) { 181 return uncaught; 182 } 183 return null; 184 } 185 186 /** 187 * Waits during {@code timeout} for {@link TestThread} to die 188 * and returns exception caught during the execution. 189 * 190 * @param timeout The time to wait in milliseconds 191 * @return Exception caught during the execution 192 * @throws InterruptedException 193 */ 194 public Throwable joinAndReturn(long timeout) throws InterruptedException { 195 join(timeout); 196 if (isAlive()) { 197 return new TimeoutException(); 198 } 199 if (uncaught != null) { 200 return uncaught; 201 } 202 return null; 203 } 204 }