--- /dev/null 2015-11-24 12:24:18.000000000 -0800 +++ new/jdk/test/java/lang/StackWalker/StackStreamTest.java 2015-11-24 12:24:18.000000000 -0800 @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.lang.StackWalker.Option.*; +import java.lang.StackWalker.StackFrame; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * @test + * @bug 8140450 + * @summary Stack Stream Test + * @run main/othervm StackStreamTest + */ +public class StackStreamTest { + public static void main(String[] argv) throws Exception { + new StackStreamTest().test(); + } + + private static Logger logger = Logger.getLogger("stackstream"); + public StackStreamTest() { + } + + public void test() { + A.a(); + } + static class A { + public static void a() { + B.b(); + } + } + static class B { + public static void b() { + C.c(); + } + } + static class C { + public static void c() { + D.d(); + } + } + static class D { + public static void d() { + E.e(); + } + } + static class E { + public static void e() { + F.f(); + } + } + static class F { + public static void f() { + logger.severe("log message"); + G.g(); + new K().k(); + } + } + + private static boolean isTestClass(StackFrame f) { + // Filter jtreg frames from the end of the stack + return f.getClassName().startsWith("StackStreamTest"); + } + + static class G { + static StackWalker STE_WALKER = StackWalker.getInstance(); + static StackWalker DEFAULT_WALKER = StackWalker.getInstance(); + + private static final List GOLDEN_CLASS_NAMES = + Arrays.asList("StackStreamTest$G", + "StackStreamTest$F", + "StackStreamTest$E", + "StackStreamTest$D", + "StackStreamTest$C", + "StackStreamTest$B", + "StackStreamTest$A", + "StackStreamTest", + "StackStreamTest"); + private static final List GOLDEN_METHOD_NAMES = + Arrays.asList("g", "f", "e", "d", "c", "b", "a", "test", "main"); + + + public static void g() { + + System.out.println("Thread dump"); + Thread.dumpStack(); + + caller(); + firstFrame(); + + // Check class names + System.out.println("check class names"); + List sfs = DEFAULT_WALKER.walk(s -> { + return s.filter(StackStreamTest::isTestClass) + .map(StackFrame::getClassName) + .collect(Collectors.toList()); + }); + equalsOrThrow("class names", sfs, GOLDEN_CLASS_NAMES); + + // Check method names + System.out.println("methodNames()"); + sfs = DEFAULT_WALKER.walk(s -> { + return s.filter(StackStreamTest::isTestClass) + .map(StackFrame::getMethodName) + .collect(Collectors.toList());} + ); + equalsOrThrow("method names", sfs, GOLDEN_METHOD_NAMES); + + Exception exc = new Exception("G.g stack"); + exc.printStackTrace(); + + System.out.println("Stream of StackTraceElement"); + StackWalker.getInstance() + .walk(s -> + { + s.map(StackFrame::toStackTraceElement) + .forEach(ste -> System.out.println("STE: " + ste)); + return null; + }); + + // Do we need this? + System.out.println("Collect StackTraceElement"); + List stacktrace = STE_WALKER.walk(s -> + { + // Filter out jtreg frames + return s.filter(StackStreamTest::isTestClass) + .collect(Collectors.mapping(StackFrame::toStackTraceElement, Collectors.toList())); + }); + int i=0; + for (StackTraceElement s : stacktrace) { + System.out.format(" %d: %s%n", i++, s); + } + + // Check STEs for correctness + checkStackTraceElements(GOLDEN_CLASS_NAMES, GOLDEN_METHOD_NAMES, stacktrace); + } + + static void checkStackTraceElements(List classNames, + List methodNames, + List stes) { + if (classNames.size() != methodNames.size() ) { + throw new RuntimeException("Test error: classNames and methodNames should be same size"); + } + if (classNames.size() != stes.size()) { + dumpSTEInfo(classNames, methodNames, stes); + throw new RuntimeException("wrong number of elements in stes"); + } + for (int i = 0; i < classNames.size() ; i++) { + if (!classNames.get(i).equals(stes.get(i).getClassName()) || + !methodNames.get(i).equals(stes.get(i).getMethodName())) { + dumpSTEInfo(classNames, methodNames, stes); + throw new RuntimeException("class & method names don't match"); + } + } + } + + static void dumpSTEInfo(List classNames, List methodNames, + List stes) { + System.out.println("Observed class, method names:"); + for (StackTraceElement ste : stes) { + System.out.println(" " + ste.getClassName() + ", " + ste.getMethodName()); + } + System.out.println("Expected class, method names:"); + for (int i = 0; i < classNames.size(); i++) { + System.out.println(" " + classNames.get(i) + ", " + methodNames.get(i)); + } + } + + static void firstFrame() { + System.out.println("first frame()"); + StackWalker sw = StackWalker.getInstance(RETAIN_CLASS_REFERENCE); + sw.forEach(e -> { + System.out.println(e.getClassName() + "," + e.getMethodName()); + }); + System.out.println("\n"); + Optional frame = sw.walk(s -> + { + return s.filter(e -> { + System.err.println(e.getClassName() + " == " + + e.getClassName().equals("StackStreamTest")); + return e.getClassName().equals("StackStreamTest"); + }).findFirst(); + }); + Class c = frame.get().getDeclaringClass(); + System.out.println("\nfirst frame: " + c); + if (c != StackStreamTest.class) { + throw new RuntimeException("Unexpected first caller class " + c); + } + } + } + + private static void equalsOrThrow(String label, List list, List expected) { + System.out.println("List: " + list); + System.out.println("Expectd: " + list); + if (!list.equals(expected)) { + System.err.println("Observed " + label); + for (T s1 : list) { + System.out.println(" " + s1); + } + System.err.println("Expected " + label); + for (T s2 : expected) { + System.out.println(" " + s2); + } + throw new RuntimeException("Error with " + label); + } + } + + + static class K { + void k() { + k1(); + } + void k1() { + k2(); + } + void k2() { + k3(); + } + void k3() { + k4(); + } + void k4() { + k5(); + } + void k5() { + k6(); + } + void k6() { + k7(); + } + void k7() { + k8(); + } + void k8() { + k9(); + } + void k9() { + k10(); + } + void k10() { + k20(); + } + void k20() { + new Caller().test(); + } + + class Caller { + void test() { + Class c = StackWalker.getInstance(RETAIN_CLASS_REFERENCE).getCallerClass(); + System.out.println("\nTesting K class : " + c); + Thread.dumpStack(); + if (c != K.class) { + throw new RuntimeException("Unexpected caller class "+ c); + } + } + } + } + + static void caller() { + Class c = StackWalker.getInstance(RETAIN_CLASS_REFERENCE).getCallerClass(); + System.out.println("\ncaller class : " + c); + if (c != G.class) { + throw new RuntimeException("Unexpected caller class "+ c); + } + } + +}