jdk/test/java/lang/StackWalker/StackRecorderUtil.java
author alanb
Fri, 10 Feb 2017 09:04:39 +0000
changeset 43712 5dfd0950317c
parent 37819 8a2559d6fe5b
permissions -rw-r--r--
8173393: Module system implementation refresh (2/2017) Reviewed-by: dfuchs, psandoz, mchung, alanb Contributed-by: alan.bateman@oracle.com, mandy.chung@oracle.com, claes.redestad@oracle.com, alex.buckley@oracle.com, mark.reinhold@oracle.com, john.r.rose@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
34362
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
     1
/*
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
     2
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
     4
 *
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
     7
 * published by the Free Software Foundation.
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
     8
 *
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    13
 * accompanied this code).
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    14
 *
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    18
 *
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    21
 * questions.
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    22
 */
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    23
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    24
import java.lang.StackWalker.Option;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    25
import java.lang.StackWalker.StackFrame;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    26
import java.util.*;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    27
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    28
/**
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    29
 * Utility class for recording a stack trace for later comparison to
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    30
 * StackWalker results.
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    31
 *
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    32
 * StackTraceElement comparison does not include line number, isNativeMethod
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    33
 */
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    34
public class StackRecorderUtil implements Iterable<StackRecorderUtil.TestFrame> {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    35
    private List<TestFrame> testFrames = new LinkedList();
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    36
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    37
    private boolean compareClasses;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    38
    private boolean compareClassNames = true;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    39
    private boolean compareMethodNames = true;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    40
    private boolean compareSTEs;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    41
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    42
    public StackRecorderUtil(Set<StackWalker.Option> swOptions) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    43
        compareClasses = swOptions.contains(Option.RETAIN_CLASS_REFERENCE);
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    44
        compareSTEs = true;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    45
    }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    46
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    47
    /**
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    48
     * Add a method call to this recorded stack.
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    49
     */
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    50
    public void add(Class declaringClass, String methodName, String fileName) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    51
        testFrames.add(0, new TestFrame(declaringClass, methodName, fileName));
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    52
    }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    53
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    54
    public int frameCount() { return testFrames.size(); }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    55
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    56
    /**
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    57
     * Compare the given StackFrame returned from the StackWalker to the
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    58
     * recorded frame at the given index.
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    59
     *
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    60
     * Tests for equality, as well as functional correctness with respect to
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    61
     * the StackWalker's options (e.g. throws or doesn't throw exceptions)
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    62
     */
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    63
    public void compareFrame(int index, StackFrame sf) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    64
        TestFrame tf = testFrames.get(index);
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    65
        if (compareClasses) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    66
            if (!tf.declaringClass.equals(sf.getDeclaringClass())) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    67
                throw new RuntimeException("Expected class: " +
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    68
                  tf.declaringClass.toString() + ", but got: " +
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    69
                  sf.getDeclaringClass().toString());
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    70
            }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    71
        } else {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    72
            boolean caught = false;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    73
            try {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    74
                sf.getDeclaringClass();
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    75
            } catch (UnsupportedOperationException e) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    76
                caught = true;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    77
            }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    78
            if (!caught) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    79
                throw new RuntimeException("StackWalker did not have " +
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    80
                  "RETAIN_CLASS_REFERENCE Option, but did not throw " +
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    81
                  "UnsupportedOperationException");
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    82
            }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    83
        }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    84
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    85
        if (compareClassNames && !tf.className().equals(sf.getClassName())) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    86
            throw new RuntimeException("Expected class name: " + tf.className() +
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    87
                    ", but got: " + sf.getClassName());
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    88
        }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    89
        if (compareMethodNames && !tf.methodName.equals(sf.getMethodName())) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    90
            throw new RuntimeException("Expected method name: " + tf.methodName +
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    91
                    ", but got: " + sf.getMethodName());
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    92
        }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    93
        if (compareSTEs) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    94
            StackTraceElement ste = sf.toStackTraceElement();
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    95
            if (!(ste.getClassName().equals(tf.className()) &&
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    96
                  ste.getMethodName().equals(tf.methodName)) &&
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    97
                  ste.getFileName().equals(tf.fileName)) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    98
                throw new RuntimeException("Expected StackTraceElement info: " +
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
    99
                        tf + ", but got: " + ste);
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   100
            }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   101
            if (!Objects.equals(ste.getClassName(), sf.getClassName())
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   102
                || !Objects.equals(ste.getMethodName(), sf.getMethodName())
37819
8a2559d6fe5b 8153912: Reconsider StackFrame::getFileName and StackFrame::getLineNumber
mchung
parents: 34362
diff changeset
   103
                || !Objects.equals(ste.getFileName(), sf.getFileName())
8a2559d6fe5b 8153912: Reconsider StackFrame::getFileName and StackFrame::getLineNumber
mchung
parents: 34362
diff changeset
   104
                || !Objects.equals(ste.getLineNumber(), sf.getLineNumber())
34362
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   105
                || !Objects.equals(ste.isNativeMethod(), sf.isNativeMethod())) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   106
                throw new RuntimeException("StackFrame and StackTraceElement differ: " +
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   107
                        "sf=" + sf + ", ste=" + ste);
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   108
            }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   109
        }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   110
    }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   111
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   112
    public Iterator<TestFrame> iterator() {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   113
        return testFrames.iterator();
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   114
    }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   115
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   116
    /**
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   117
     * Class used to record stack frame information.
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   118
     */
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   119
    public static class TestFrame {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   120
        public Class declaringClass;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   121
        public String methodName;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   122
        public String fileName = null;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   123
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   124
        public TestFrame (Class declaringClass, String methodName, String fileName) {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   125
            this.declaringClass = declaringClass;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   126
            this.methodName = methodName;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   127
            this.fileName = fileName;
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   128
        }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   129
        public String className() {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   130
            return declaringClass.getName();
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   131
        }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   132
        public String toString() {
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   133
            return "TestFrame: " + className() + "." + methodName +
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   134
                    (fileName == null ? "" : "(" + fileName + ")");
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   135
        }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   136
    }
3396ae214e7d 8140450: Implement JEP 259: Stack-Walking API
mchung
parents:
diff changeset
   137
}