1 /*
2  * Copyright (c) 2015, 2018, 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 test.java.lang.StackWalker;
25 
26 /*
27  * @test
28  * @bug 8140450
29  * @library /test/lib
30  * @summary Test if the getCallerClass method returns empty optional
31  * @run main CallerFromMain exec
32  */
33 
34 // import jdk.test.lib.process.ProcessTools;
35 // import jdk.test.lib.process.OutputAnalyzer;
36 
37 import org.testng.annotations.Test;
38 
39 public class CallerFromMain {
40 
41     private static final StackWalker sw = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
42     // Android-removed: Our test infra doesn't have the ProcessTools lib, and the lib is optional.
43     /*
44     public static void main(String[] args) throws Exception {
45         if (args.length > 0) {
46             ProcessBuilder pb = ProcessTools.createTestJvm("CallerFromMain");
47             OutputAnalyzer output = ProcessTools.executeProcess(pb);
48             System.out.println(output.getOutput());
49             output.shouldHaveExitValue(0);
50             return;
51         }
52     */
53     @Test
main()54     public static void main() throws Exception {
55         // StackWalker::getCallerClass
56         // CallerFromMain::main
57         // no caller
58         // Android-removed: TestNg calls this class and thus caller is not null.
59         /*
60         try {
61             Class<?> c = sw.getCallerClass();
62             throw new RuntimeException("UOE not thrown. Caller: " + c);
63         } catch (IllegalCallerException e) {}
64         */
65 
66         // StackWalker::getCallerClass
67         // Runnable::run
68         // Thread::run
69         Thread t1 = new Thread(new Runnable() {
70             @Override
71             public void run() {
72                 Class<?> c = sw.getCallerClass();
73                 System.out.println("Call from Thread.run: " + c);
74                 assertThreadClassAsCaller(c);
75             }
76         });
77         t1.setDaemon(true);
78         t1.start();
79 
80         // StackWalker::getCallerClass
81         // CallerFromMain::doit
82         // Thread::run
83         // Android-removed: Android desugars lambda.
84         // Thread t2 = new Thread(CallerFromMain::doit);
85         // t2.setDaemon(true);
86         // t2.start();
87 
88         // StackWalker::getCallerClass
89         // MyRunnable::run
90         // Thread::run
91         Thread t3 = new Thread(new MyRunnable());
92         t3.setDaemon(true);
93         t3.start();
94 
95         // StackWalker::getCallerClass
96         // Runnable::run
97         // MyThread::run
98         Thread t4 = new MyThread(new Runnable() {
99             @Override
100             public void run() {
101                 Class<?> c = sw.getCallerClass();
102                 System.out.println("Call from MyThread.run: " + c);
103                 if (c != MyThread.class) {
104                     throw new RuntimeException("Expected MyThread.class but got " + c);
105                 }
106             }
107         });
108         t4.setDaemon(true);
109         t4.start();
110 
111         t1.join();
112         // Android-removed: Android desugars lambda.
113         // t2.join();
114         t3.join();
115         t4.join();
116     }
117 
118     static class MyThread extends Thread {
119         final Runnable runnable;
MyThread(Runnable runnable)120         MyThread(Runnable runnable) {
121             super("MyThread");
122             this.runnable = runnable;
123         }
run()124         public void run() {
125             runnable.run();
126         }
127     }
128 
129     static class MyRunnable implements Runnable {
130         @Override
run()131         public void run() {
132             Class<?> c = sw.getCallerClass();
133             System.out.println("Call from Thread::run: " + c);
134             assertThreadClassAsCaller(c);
135         }
136      }
137 
doit()138     static void doit() {
139         Class<?> c = sw.getCallerClass();
140         System.out.println("Call from CallerFromMain.doit: " + c);
141         assertThreadClassAsCaller(c);
142     }
143 
assertThreadClassAsCaller(Class<?> caller)144     static void assertThreadClassAsCaller(Class<?> caller) {
145         if (caller != Thread.class) {
146             throw new RuntimeException("Expected Thread.class but got " + caller);
147         }
148     }
149 }
150