GenerifyStackTraces.java revision 12745:f068a4ffddd2
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