Path: blob/master/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/shared/DefMethTest.java
41161 views
/*1* Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package vm.runtime.defmeth.shared;2425import java.lang.reflect.InvocationTargetException;26import java.lang.reflect.Method;27import java.lang.reflect.Modifier;28import java.lang.reflect.Parameter;29import java.util.*;30import java.util.regex.Pattern;31import nsk.share.TestFailure;32import nsk.share.log.Log;33import nsk.share.test.TestBase;34import vm.runtime.defmeth.AccessibilityFlagsTest;35import vm.runtime.defmeth.BasicTest;36import vm.runtime.defmeth.ConflictingDefaultsTest;37import vm.runtime.defmeth.DefaultVsAbstractTest;38import vm.runtime.defmeth.MethodResolutionTest;39import vm.runtime.defmeth.ObjectMethodOverridesTest;40import vm.runtime.defmeth.PrivateMethodsTest;41import vm.runtime.defmeth.StaticMethodsTest;42import vm.runtime.defmeth.SuperCallTest;43import vm.runtime.defmeth.shared.annotation.NotApplicableFor;44import vm.runtime.defmeth.shared.builder.TestBuilder;45import vm.runtime.defmeth.shared.builder.TestBuilderFactory;46import vm.share.options.Option;47import vm.share.options.OptionSupport;48import vm.share.options.Options;49import static java.lang.String.format;50import static jdk.internal.org.objectweb.asm.Opcodes.V17;51import static jdk.internal.org.objectweb.asm.Opcodes.V1_5;5253import vm.runtime.defmeth.RedefineTest;5455/**56* Parent class for all default method tests.57*58* Contains common settings and code to run individual tests.59*60* Provides command-line interface to run arbitrary subset of61* tests on default methods with some customizations.62*/63public abstract class DefMethTest extends TestBase {64/** Classes that contain tests on default methods */65static private final List<Class<? extends DefMethTest>> classes;6667// the number of tests has failed68// note that if more than one sub-test has failed within a test,69// it will be counted as 1 failure for that test70private int numFailures;7172static {73List<Class<? extends DefMethTest>> intlList = new ArrayList<>();7475intlList.add(AccessibilityFlagsTest.class);76intlList.add(BasicTest.class);77intlList.add(ConflictingDefaultsTest.class);78intlList.add(DefaultVsAbstractTest.class);79intlList.add(MethodResolutionTest.class);80intlList.add(ObjectMethodOverridesTest.class);81intlList.add(SuperCallTest.class);82intlList.add(PrivateMethodsTest.class);83intlList.add(StaticMethodsTest.class);84intlList.add(RedefineTest.class);8586classes = Collections.unmodifiableList(intlList);87}8889public static List<Class<? extends DefMethTest>> getTests() {90return classes;91}9293@Option(name="list", default_value="false", description="list tests w/o executing them")94boolean listTests;9596@Option(name="filter", default_value="", description="filter executed tests")97String filterString;9899@Option(name="silent", default_value="false", description="silent mode - don't print anything")100boolean isSilent;101102@Option(name="failfast", default_value="false", description="fail the whole set of test on first failure")103boolean failFast;104105@Option(name="testAllModes", default_value="false", description="run each test in all possible modes")106boolean testAllModes;107108@Option(name="mode", description="invocation mode (direct, reflect, invoke)", default_value="direct")109String mode;110111private Pattern filter; // Precompiled pattern for filterString112113public static final int MIN_MAJOR_VER = V1_5;114public static final int MAX_MAJOR_VER = V17;115116/**117* Used from individual tests to get TestBuilder instances,118* which is aware of current testing configuration119*/120@Options121protected TestBuilderFactory factory = new TestBuilderFactory(this);122123private void init() {124if (isSilent) {125getLog().setInfoEnabled(false);126getLog().setWarnEnabled(false);127getLog().setDebugEnabled(false);128}129130if (filterString != null && !"".equals(filterString)) {131filter = Pattern.compile(".*" + filterString + ".*");132} else {133filter = Pattern.compile(".*"); // match everything134}135136// Test-specific config137configure();138}139140@Override141public final void run() {142init();143144boolean success = runTest();145if (!success) {146getLog().info("TEST FAILED");147setFailed(true);148} else {149getLog().info("TEST PASSED");150}151}152153protected void configure() {154// Is overriden by specific tests to do test-specific setup155}156157public Log getLog() {158return log;159}160161@Override162public String toString() {163return format("%s%s",164getClass().getSimpleName(), factory);165}166167/** Enumerate invocation modes to be tested */168private ExecutionMode[] getInvocationModes() {169if (factory.getExecutionMode() != null) {170return new ExecutionMode[] { ExecutionMode.valueOf(factory.getExecutionMode()) };171}172173if (testAllModes) {174return ExecutionMode.values();175}176177switch(mode) {178case "direct": return new ExecutionMode[] { ExecutionMode.DIRECT };179case "reflect": return new ExecutionMode[] { ExecutionMode.REFLECTION };180case "invoke_exact": return new ExecutionMode[] { ExecutionMode.INVOKE_EXACT };181case "invoke_generic": return new ExecutionMode[] { ExecutionMode.INVOKE_GENERIC };182case "indy": return new ExecutionMode[] { ExecutionMode.INDY };183case "invoke": return new ExecutionMode[] { ExecutionMode.INVOKE_WITH_ARGS,184ExecutionMode.INVOKE_EXACT,185ExecutionMode.INVOKE_GENERIC,186ExecutionMode.INDY };187case "redefinition":188throw new Error("redefinition is only a pseudo-mode");189default:190throw new Error("Unknown mode: " + mode);191}192}193194// Check whether the test is applicable to selected execution mode195private boolean shouldExecute(Method m, ExecutionMode mode) {196Class<? extends DefMethTest> test = this.getClass();197198int acc = m.getModifiers();199if (!Modifier.isPublic(acc) || Modifier.isStatic(acc) ||200m.getParameterTypes().length != 0 && !requiresTestBuilder(m)) {201return false; // not a test202}203204String testName = format("%s.%s", test.getName(), m.getName());205if (!filter.matcher(testName).matches()) {206return false; // test is filtered out207}208209if (m.isAnnotationPresent(NotApplicableFor.class)) {210for (ExecutionMode excludeFromMode : m.getAnnotation(NotApplicableFor.class).modes()) {211if (mode == excludeFromMode) {212return false; // not applicable to current execution mode213} else if (excludeFromMode == ExecutionMode.REDEFINITION &&214(factory.isRedefineClasses() || factory.isRetransformClasses())) {215return false; // Can't redefine some tests.216}217218}219}220221return true;222}223224private boolean requiresTestBuilder(Method m) {225Parameter[] params = m.getParameters();226return params.length == 1 && (params[0].getType() == TestBuilder.class);227}228229/** Information about the test being executed */230public String shortTestName;231232public static class ComparableMethod implements Comparable<ComparableMethod> {233final java.lang.reflect.Method m;234ComparableMethod(java.lang.reflect.Method m) { this.m = m; }235public int compareTo(ComparableMethod mo) {236String name = m.getName();237String mo_name = mo.m.getName();238return name.compareTo(mo_name);239}240}241242/** helper method for subclass to report the number of test failures.243* It is more important for the reflection case as an exception thrown244* deep in the call stack may not be propagated to this level.245*246* @param failures247*/248public void addFailureCount(int failures) {249numFailures += failures;250}251252/**253* Execute all tests from current class and report status.254*255* The following execution customization is supported:256* - filter tests by name using regex257*258* @return any failures occurred?259*/260public final boolean runTest() {261ExecutionMode[] invocationModes = getInvocationModes();262263try {264int totalTests = 0;265266Class<? extends DefMethTest> test = this.getClass();267268getLog().info(format("\n%s %s", test.getSimpleName(), factory.toString()));269270TreeSet<ComparableMethod> ts = new TreeSet<ComparableMethod>();271for (java.lang.reflect.Method m : test.getDeclaredMethods()) {272ts.add(new ComparableMethod(m));273}274275for (ComparableMethod cm : ts) {276java.lang.reflect.Method m = cm.m;277for (ExecutionMode mode : invocationModes) {278shortTestName = format("%s.%s", test.getSimpleName(), m.getName());279280if (!shouldExecute(m, mode)) {281continue; // skip the test due to current configuration282}283284totalTests++;285286getLog().info(shortTestName);287288if (listTests) {289continue; // just print test info290}291292// Iterate over all test modes293try {294factory.setExecutionMode(mode.name());295getLog().info(format(" %s: ", mode));296if (requiresTestBuilder(m)) {297TestBuilder b = factory.getBuilder();298m.invoke(this, b);299b.run();300} else {301m.invoke(this);302}303} catch (IllegalAccessException | IllegalArgumentException e) {304throw new TestFailure(e);305} catch (InvocationTargetException e) {306if (e.getCause() instanceof TestFailure) {307// Failure details were printed in GeneratedTest.run()/ReflectionTest.run()308} else {309if (Constants.PRINT_STACK_TRACE) {310e.printStackTrace();311}312}313addFailureCount(1);314if (failFast) {315throw new TestFailure(e.getCause());316}317}318}319}320321int passedTests = totalTests - numFailures;322getLog().info(format("%d test run: %d passed, %d failed", totalTests, passedTests, numFailures));323if (numFailures == 0) {324return true;325} else {326return false;327}328} catch (Exception | Error e) {329throw new RuntimeException(e);330}331}332333public static void runTest(Class<? extends DefMethTest> testClass,334Set<Integer> majorVerValues,335Set<Integer> flagsValues,336Set<Boolean> redefineValues,337Set<ExecutionMode> execModes) {338for (int majorVer : majorVerValues) {339for (int flags : flagsValues) {340for (boolean redefine : redefineValues) {341for (ExecutionMode mode : execModes) {342try {343DefMethTest test = testClass.getDeclaredConstructor().newInstance();344345OptionSupport.setup(test, new String[]{346"-execMode", mode.toString(),347"-ver", Integer.toString(majorVer),348"-flags", Integer.toString(flags),349"-redefine", Boolean.toString(redefine)350});351352test.run();353} catch (ReflectiveOperationException e) {354throw new TestFailure(e);355}356}357}358}359}360}361362/** Command-line interface to initiate test run */363public static void main(String[] args) {364for (Class<? extends DefMethTest> clz : classes) {365try {366DefMethTest test = clz.newInstance();367OptionSupport.setupAndRun(test, args);368} catch (InstantiationException | IllegalAccessException e) {369throw new TestFailure(e);370}371}372}373}374375376