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 8140450 8173898
27 * @summary Basic test for the StackWalker::walk method
28 * @run testng Basic
29 */
30
31 import java.lang.StackWalker.StackFrame;
32 import java.util.List;
33 import java.util.Objects;
34 import java.util.stream.Collectors;
35 import java.util.stream.Stream;
36 import static java.lang.StackWalker.Option.*;
37
38 import org.testng.annotations.DataProvider;
39 import org.testng.annotations.Test;
40 import static org.testng.Assert.*;
41
42 public class Basic {
43 private static boolean verbose = false;
44
45 @DataProvider(name = "stackDepths")
46 public static Object[][] stackDepths() {
47 return new Object[][] {
48 { new int[] { 12 }, new int[] { 4, 8, 12} },
49 { new int[] { 18 }, new int[] { 8, 16, 20} },
50 { new int[] { 32 }, new int[] { 16, 32, 64} },
51 };
52 }
53
57 */
58 @Test(dataProvider = "stackDepths")
59 public static void test(int[] depth, int[] estimates) {
60 Basic test = new Basic(depth[0]);
61 for (int estimate : estimates) {
62 test.walk(estimate);
63 }
64 }
65
66 @Test
67 public static void testWalkFromConstructor() throws Exception {
68 System.out.println("testWalkFromConstructor:");
69 List<String> found = ((ConstructorNewInstance)ConstructorNewInstance.class.getMethod("create")
70 .invoke(null)).collectedFrames();
71 assertEquals(List.of(ConstructorNewInstance.class.getName()+"::<init>",
72 ConstructorNewInstance.class.getName()+"::create",
73 Basic.class.getName()+"::testWalkFromConstructor"),
74 found);
75 }
76
77 private final int depth;
78 Basic(int depth) {
79 this.depth = depth;
80 }
81
82 /*
83 * Setup a stack builder with the expected stack depth
84 * Walk the stack and count the frames.
85 */
86 void walk(int estimate) {
87 int limit = Math.min(depth, 16);
88 List<StackFrame> frames = new StackBuilder(depth, limit).build();
89 System.out.format("depth=%d estimate=%d expected=%d walked=%d%n",
90 depth, estimate, limit, frames.size());
91 assertEquals(limit, frames.size());
92 }
93
94 static class ConstructorNewInstance {
95 static final StackWalker walker =
96 StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
115 return true;
116 }
117 // Filter out all other frames (in particular
118 // those from the test framework) in order to
119 // have predictable results.
120 return false;
121 }
122 public String frame(StackFrame f) {
123 return f.getClassName() + "::" + f.getMethodName();
124 }
125 List<String> parse(Stream<StackFrame> s) {
126 return s.filter(this::accept)
127 .map(this::frame)
128 .collect(Collectors.toList());
129 }
130 public static ConstructorNewInstance create() throws Exception {
131 return ConstructorNewInstance.class.getConstructor().newInstance();
132 }
133 }
134
135 class StackBuilder {
136 private final int stackDepth;
137 private final int limit;
138 private int depth = 0;
139 private List<StackFrame> result;
140 StackBuilder(int stackDepth, int limit) {
141 this.stackDepth = stackDepth; // build method;
142 this.limit = limit;
143 }
144 List<StackFrame> build() {
145 trace("build");
146 m1();
147 return result;
148 }
149 void m1() {
150 trace("m1");
151 m2();
152 }
153 void m2() {
154 trace("m2");
155 m3();
156 }
157 void m3() {
158 trace("m3");
159 m4();
160 }
161 void m4() {
162 trace("m4");
163 int remaining = stackDepth-depth-1;
164 if (remaining >= 4) {
165 m1();
166 } else {
167 filler(remaining);
168 }
169 }
170 void filler(int i) {
171 trace("filler");
172 if (i == 0)
173 walk();
174 else
175 filler(--i);
176 }
177
178 void walk() {
179 StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
180 result = walker.walk(s -> s.limit(limit).collect(Collectors.toList()));
181 }
182 void trace(String methodname) {
183 ++depth;
184 if (verbose)
185 System.out.format("%2d: %s%n", depth, methodname);
186 }
187 }
188
189 }
|
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 8140450 8173898
27 * @summary Basic test for the StackWalker::walk method
28 * @run testng Basic
29 */
30
31 import java.lang.StackWalker.StackFrame;
32 import java.lang.invoke.MethodType;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.stream.Collectors;
37 import java.util.stream.Stream;
38 import static java.lang.StackWalker.Option.*;
39
40 import org.testng.annotations.DataProvider;
41 import org.testng.annotations.Test;
42 import static org.testng.Assert.*;
43
44 public class Basic {
45 private static boolean verbose = false;
46
47 @DataProvider(name = "stackDepths")
48 public static Object[][] stackDepths() {
49 return new Object[][] {
50 { new int[] { 12 }, new int[] { 4, 8, 12} },
51 { new int[] { 18 }, new int[] { 8, 16, 20} },
52 { new int[] { 32 }, new int[] { 16, 32, 64} },
53 };
54 }
55
59 */
60 @Test(dataProvider = "stackDepths")
61 public static void test(int[] depth, int[] estimates) {
62 Basic test = new Basic(depth[0]);
63 for (int estimate : estimates) {
64 test.walk(estimate);
65 }
66 }
67
68 @Test
69 public static void testWalkFromConstructor() throws Exception {
70 System.out.println("testWalkFromConstructor:");
71 List<String> found = ((ConstructorNewInstance)ConstructorNewInstance.class.getMethod("create")
72 .invoke(null)).collectedFrames();
73 assertEquals(List.of(ConstructorNewInstance.class.getName()+"::<init>",
74 ConstructorNewInstance.class.getName()+"::create",
75 Basic.class.getName()+"::testWalkFromConstructor"),
76 found);
77 }
78
79 @Test
80 public static void testMethodSignature() throws Exception {
81 List<StackFrame> frames = new StackBuilder(16, 16).build();
82 Map<String, MethodType> methodTypes = StackBuilder.methodTypes();
83 for (StackFrame f : frames) {
84 MethodType type = methodTypes.get(f.getMethodName());
85 if (type != null) {
86 System.out.format("%s.%s %s%n", f.getClassName(), f.getMethodName(),
87 f.getDescriptor());
88
89 if (!f.getDescriptor().equals(type.toMethodDescriptorString())) {
90 throw new RuntimeException("Expected: " + type.toMethodDescriptorString()
91 + " got: " + f.getDescriptor());
92 }
93
94 if (!f.getMethodType().equals(type)) {
95 throw new RuntimeException("Expected: " + type
96 + " got: " + f.getMethodType());
97 }
98 }
99 }
100 }
101
102 private final int depth;
103 Basic(int depth) {
104 this.depth = depth;
105 }
106
107 /*
108 * Setup a stack builder with the expected stack depth
109 * Walk the stack and count the frames.
110 */
111 void walk(int estimate) {
112 int limit = Math.min(depth, 16);
113 List<StackFrame> frames = new StackBuilder(depth, limit).build();
114 System.out.format("depth=%d estimate=%d expected=%d walked=%d%n",
115 depth, estimate, limit, frames.size());
116 assertEquals(limit, frames.size());
117 }
118
119 static class ConstructorNewInstance {
120 static final StackWalker walker =
121 StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
140 return true;
141 }
142 // Filter out all other frames (in particular
143 // those from the test framework) in order to
144 // have predictable results.
145 return false;
146 }
147 public String frame(StackFrame f) {
148 return f.getClassName() + "::" + f.getMethodName();
149 }
150 List<String> parse(Stream<StackFrame> s) {
151 return s.filter(this::accept)
152 .map(this::frame)
153 .collect(Collectors.toList());
154 }
155 public static ConstructorNewInstance create() throws Exception {
156 return ConstructorNewInstance.class.getConstructor().newInstance();
157 }
158 }
159
160 static class StackBuilder {
161 private final int stackDepth;
162 private final int limit;
163 private int depth = 0;
164 private List<StackFrame> result;
165 StackBuilder(int stackDepth, int limit) {
166 this.stackDepth = stackDepth; // build method;
167 this.limit = limit;
168 }
169 List<StackFrame> build() {
170 trace("build");
171 m1();
172 return result;
173 }
174 void m1() {
175 trace("m1");
176 m2();
177 }
178 List m2() {
179 trace("m2");
180 m3();
181 return null;
182 }
183 int m3() {
184 trace("m3");
185 m4(null);
186 return 0;
187 }
188 void m4(Object o) {
189 trace("m4");
190 int remaining = stackDepth-depth-1;
191 if (remaining >= 4) {
192 m1();
193 } else {
194 filler(remaining);
195 }
196 }
197 void filler(int i) {
198 trace("filler");
199 if (i == 0)
200 walk();
201 else
202 filler(--i);
203 }
204
205 void walk() {
206 StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
207 result = walker.walk(s -> s.limit(limit).collect(Collectors.toList()));
208 }
209 void trace(String methodname) {
210 ++depth;
211 if (verbose)
212 System.out.format("%2d: %s%n", depth, methodname);
213 }
214
215 static Map<String, MethodType> methodTypes() throws Exception {
216 Map<String, MethodType> methodTypes = new HashMap<>();
217 methodTypes.put("m1", MethodType.methodType(void.class));
218 methodTypes.put("m2", MethodType.methodType(List.class));
219 methodTypes.put("m3",MethodType.methodType(int.class));
220 methodTypes.put("m4", MethodType.methodType(void.class, Object.class));
221 return methodTypes;
222 }
223 }
224
225 }
|