• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015, 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 import java.lang.StackWalker.Option;
27 import java.lang.StackWalker.StackFrame;
28 import java.util.*;
29 
30 /**
31  * Utility class for recording a stack trace for later comparison to
32  * StackWalker results.
33  *
34  * StackTraceElement comparison does not include line number, isNativeMethod
35  */
36 public class StackRecorderUtil implements Iterable<StackRecorderUtil.TestFrame> {
37     private List<TestFrame> testFrames = new LinkedList();
38 
39     private boolean compareClasses;
40     private boolean compareClassNames = true;
41     private boolean compareMethodNames = true;
42     private boolean compareSTEs;
43 
StackRecorderUtil(Set<StackWalker.Option> swOptions)44     public StackRecorderUtil(Set<StackWalker.Option> swOptions) {
45         compareClasses = swOptions.contains(Option.RETAIN_CLASS_REFERENCE);
46         compareSTEs = true;
47     }
48 
49     /**
50      * Add a method call to this recorded stack.
51      */
add(Class declaringClass, String methodName, String fileName)52     public void add(Class declaringClass, String methodName, String fileName) {
53         testFrames.add(0, new TestFrame(declaringClass, methodName, fileName));
54     }
55 
frameCount()56     public int frameCount() { return testFrames.size(); }
57 
58     /**
59      * Compare the given StackFrame returned from the StackWalker to the
60      * recorded frame at the given index.
61      *
62      * Tests for equality, as well as functional correctness with respect to
63      * the StackWalker's options (e.g. throws or doesn't throw exceptions)
64      */
compareFrame(int index, StackFrame sf)65     public void compareFrame(int index, StackFrame sf) {
66         TestFrame tf = testFrames.get(index);
67         if (compareClasses) {
68             if (!tf.declaringClass.equals(sf.getDeclaringClass())) {
69                 throw new RuntimeException("Expected class: " +
70                   tf.declaringClass.toString() + ", but got: " +
71                   sf.getDeclaringClass().toString());
72             }
73         } else {
74             boolean caught = false;
75             try {
76                 sf.getDeclaringClass();
77             } catch (UnsupportedOperationException e) {
78                 caught = true;
79             }
80             if (!caught) {
81                 throw new RuntimeException("StackWalker did not have " +
82                   "RETAIN_CLASS_REFERENCE Option, but did not throw " +
83                   "UnsupportedOperationException");
84             }
85         }
86 
87         if (compareClassNames && !tf.className().equals(sf.getClassName())) {
88             throw new RuntimeException("Expected class name: " + tf.className() +
89                     ", but got: " + sf.getClassName());
90         }
91         if (compareMethodNames && !tf.methodName.equals(sf.getMethodName())) {
92             throw new RuntimeException("Expected method name: " + tf.methodName +
93                     ", but got: " + sf.getMethodName());
94         }
95         if (compareSTEs) {
96             StackTraceElement ste = sf.toStackTraceElement();
97             if (!(ste.getClassName().equals(tf.className()) &&
98                   ste.getMethodName().equals(tf.methodName)) &&
99                   ste.getFileName().equals(tf.fileName)) {
100                 throw new RuntimeException("Expected StackTraceElement info: " +
101                         tf + ", but got: " + ste);
102             }
103             if (!Objects.equals(ste.getClassName(), sf.getClassName())
104                 || !Objects.equals(ste.getMethodName(), sf.getMethodName())
105                 || !Objects.equals(ste.getFileName(), sf.getFileName())
106                 || !Objects.equals(ste.getLineNumber(), sf.getLineNumber())
107                 || !Objects.equals(ste.isNativeMethod(), sf.isNativeMethod())) {
108                 throw new RuntimeException("StackFrame and StackTraceElement differ: " +
109                         "sf=" + sf + ", ste=" + ste);
110             }
111         }
112     }
113 
iterator()114     public Iterator<TestFrame> iterator() {
115         return testFrames.iterator();
116     }
117 
118     /**
119      * Class used to record stack frame information.
120      */
121     public static class TestFrame {
122         public Class declaringClass;
123         public String methodName;
124         public String fileName = null;
125 
TestFrame(Class declaringClass, String methodName, String fileName)126         public TestFrame (Class declaringClass, String methodName, String fileName) {
127             this.declaringClass = declaringClass;
128             this.methodName = methodName;
129             this.fileName = fileName;
130         }
className()131         public String className() {
132             return declaringClass.getName();
133         }
toString()134         public String toString() {
135             return "TestFrame: " + className() + "." + methodName +
136                     (fileName == null ? "" : "(" + fileName + ")");
137         }
138     }
139 }
140