1/* 2 * Copyright (c) 2004, 2013, 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 4919105 8004177 27 * @summary Generified basic unit test of Thread.getAllStackTraces() 28 * @author Mandy Chung 29 */ 30 31import java.util.*; 32 33public class GenerifyStackTraces { 34 35 private static Object go = new Object(); 36 private static String[] methodNames = {"run", "A", "B", "C", "Done"}; 37 private static int DONE_DEPTH = 5; 38 private static boolean testFailed = false; 39 40 private static Thread one; 41 private static boolean trace = false; 42 public static void main(String[] args) throws Exception { 43 if (args.length > 0 && args[0].equals("trace")) { 44 trace = true; 45 } 46 47 one = new ThreadOne(); 48 one.start(); 49 50 DumpThread dt = new DumpThread(); 51 dt.start(); 52 53 try { 54 one.join(); 55 } finally { 56 dt.shutdown(); 57 } 58 59 if (testFailed) { 60 throw new RuntimeException("Test Failed."); 61 } 62 } 63 64 static class DumpThread extends Thread { 65 private volatile boolean finished = false; 66 67 public void run() { 68 int depth = 2; 69 while (!finished) { 70 // At each iterator, wait until ThreadOne blocks 71 // to wait for thread dump. 72 // Then dump stack trace and notify ThreadOne to continue. 73 try { 74 sleep(2000); 75 dumpStacks(depth); 76 depth++; 77 finishDump(); 78 } catch (Exception e) { 79 e.printStackTrace(); 80 testFailed = true; 81 } 82 } 83 } 84 85 public void shutdown() throws InterruptedException { 86 finished = true; 87 this.join(); 88 } 89 } 90 91 static class ThreadOne extends Thread { 92 public void run() { 93 A(); 94 } 95 private void A() { 96 waitForDump(); 97 B(); 98 } 99 private void B() { 100 waitForDump(); 101 C(); 102 } 103 private void C() { 104 waitForDump(); 105 Done(); 106 } 107 private void Done() { 108 waitForDump(); 109 110 // Get stack trace of current thread 111 StackTraceElement[] stack = getStackTrace(); 112 try { 113 checkStack(this, stack, DONE_DEPTH); 114 } catch (Exception e) { 115 e.printStackTrace(); 116 testFailed = true; 117 } 118 } 119 120 } 121 122 123 private static void waitForDump() { 124 synchronized(go) { 125 try { 126 go.wait(); 127 } catch (Exception e) { 128 throw new RuntimeException("Unexpected exception" + e); 129 } 130 } 131 } 132 133 private static void finishDump() { 134 synchronized(go) { 135 try { 136 go.notifyAll(); 137 } catch (Exception e) { 138 throw new RuntimeException("Unexpected exception" + e); 139 } 140 } 141 } 142 143 public static void dumpStacks(int depth) throws Exception { 144 // Get stack trace of another thread 145 StackTraceElement[] stack = one.getStackTrace(); 146 checkStack(one, stack, depth); 147 148 149 // Get stack traces of all Threads 150 for (Map.Entry<Thread, StackTraceElement[]> entry : 151 Thread.getAllStackTraces().entrySet()) { 152 Thread t = entry.getKey(); 153 stack = entry.getValue(); 154 if (t == null || stack == null) { 155 throw new RuntimeException("Null thread or stacktrace returned"); 156 } 157 if (t == one) { 158 checkStack(t, stack, depth); 159 } 160 } 161 } 162 163 private static void checkStack(Thread t, StackTraceElement[] stack, 164 int depth) throws Exception { 165 if (trace) { 166 printStack(t, stack); 167 } 168 int frame = stack.length - 1; 169 for (int i = 0; i < depth && frame >= 0; i++) { 170 if (! stack[frame].getMethodName().equals(methodNames[i])) { 171 throw new RuntimeException("Expected " + methodNames[i] + 172 " in frame " + frame + " but got " + 173 stack[frame].getMethodName()); 174 } 175 frame--; 176 } 177 } 178 179 private static void printStack(Thread t, StackTraceElement[] stack) { 180 System.out.println(t + 181 " stack: (length = " + stack.length + ")"); 182 if (t != null) { 183 for (int j = 0; j < stack.length; j++) { 184 System.out.println(stack[j]); 185 } 186 System.out.println(); 187 } 188 } 189} 190