test/hotspot/jtreg/runtime/InvocationTests/shared/Checker.java
author hseigel
Wed, 26 Jun 2019 09:06:32 -0400
changeset 55497 d3a33953b936
permissions -rw-r--r--
8224137: Analyze and port invocation tests to jtreg and co-locate to jdk repo Summary: Add JTReg compatible main programs to run tests for various invoke* instructions Reviewed-by: lfoltan, coleenp

/*
 * Copyright (c) 2009, 2019, 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.
 *
 */

package shared;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public abstract class Checker {
    protected Class staticTargetClass;
    protected Class dynamicTargetClass;
    protected String methodName;

    public abstract String check (Class callSite);

    public Checker(Class staticTargetClass, Class dynamicTargetClass) {
        if (!staticTargetClass.isAssignableFrom(dynamicTargetClass)) {
            throw new RuntimeException("Dynamic target class should be a subclass of the static target class.");
        }

        // **********************************************
        // NB!!! All classes are assumed to be PUBLIC !!!
        // **********************************************
        Class klass = dynamicTargetClass;
        while (klass != Object.class) {
            if (!Modifier.isPublic(klass.getModifiers())) {
                throw new AssertionError("Class "+klass.getName()+" isn't public.");
            }

            klass = klass.getSuperclass();
        }

        this.methodName = Utils.TARGET_METHOD_NAME;
        this.staticTargetClass = staticTargetClass;
        this.dynamicTargetClass = dynamicTargetClass;
    }

    protected Method getMethodInHierarchy (Class klass) {
        return getMethodInHierarchy(klass, methodName);
    }

    protected Method getMethodInHierarchy (Class klass, String name) {
        while (klass != null) {
            Method method = getDeclaredMethod (klass, name);

            if ( method != null) {
// TODO: why doesn't this check work in VM?
//                int modifiers = method.getModifiers();
//
//                if (Modifier.isPrivate(modifiers)) {
//                    if (klass == initialClass) {
//                        return method;
//                    }
//                } else {
//                    return method;
//                }
                return method;
            }
            klass = klass.getSuperclass();
        }

        return null;
    }

    protected Method getMethod (Class klass) {
        return getMethod (klass, methodName);
    }

    protected Method getDeclaredMethod (Class klass) {
        return getDeclaredMethod (klass, methodName);
    }

    static protected Method getMethod (Class klass, String name) {
        return findMethod (klass.getMethods(), name);
    }

    static protected Method getDeclaredMethod (Class klass, String name) {
        return findMethod (klass.getDeclaredMethods(), name);
    }

    static protected Method findMethod (Method[] methods, String name) {
        for (Method method : methods) {
            if (name.equals(method.getName())) {
                return method;
            }
        }

        return null;
    }

    static public String getClassPackageName(Class klass) {
        String name = klass.getName();
        return getClassPackageName(name);
    }

    static public String getClassPackageName(String name) {
        int lastDotIndex = name.lastIndexOf('.');
        if (lastDotIndex > -1) {
            return name.substring(0, lastDotIndex);
        } else {
            return "";
        }
    }

    public static String abbreviateResult(String result) {
        // Abbreviate exception names
        result = result.replaceAll("java.lang.NullPointerException", "NPE");
        result = result.replaceAll("java.lang.IllegalAccessError", "IAE");
        result = result.replaceAll("java.lang.IllegalAccessException", "IAExc");
        result = result.replaceAll("java.lang.NoSuchMethodError", "NSME");
        result = result.replaceAll("java.lang.AbstractMethodError", "AME");
        result = result.replaceAll("java.lang.IncompatibleClassChangeError", "ICCE");
        result = result.replaceAll("java.lang.VerifyError", "VE");
        result = result.replaceAll("java.lang.ClassFormatError", "CFE");

        return result;
    }

    // Check access possibility from particular call site
    protected boolean checkAccess(Class klass, Class callerClass) {
        int modifiers = klass.getModifiers();

        return checkAccess(modifiers, klass, callerClass);
    }

    protected boolean checkAccess(Method m, Class callerClass) {
        int modifiers = m.getModifiers();
        Class declaringClass = m.getDeclaringClass();

        return checkAccess(modifiers, declaringClass, callerClass);
    }

    protected boolean checkAccess(int modifiers, Class klass, Class callerClass) {
        if ( Modifier.isPublic(modifiers) ) {
            return true;
        } else if ( Modifier.isProtected(modifiers) ) {
            if (klass.isAssignableFrom(callerClass)) {
                return true;
            } else if (getClassPackageName(klass).equals(getClassPackageName(callerClass))) {
                return true;
            }
        } else if ( Modifier.isPrivate(modifiers)) {
            if (klass == callerClass) {
                return true;
            }
        } else if (getClassPackageName(klass).equals(getClassPackageName(callerClass))) {
            return true;
        } else {
            // if method isn't accessible, IllegalAccessException is thrown
            return false;
        }

        return false;
    }
}