Path: blob/master/test/jdk/java/lang/invoke/LFCaching/LambdaFormTestCase.java
41152 views
/*1* Copyright (c) 2014, 2018, 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*/2223import jdk.test.lib.TimeLimitedRunner;24import jdk.test.lib.Utils;25import test.java.lang.invoke.lib.CodeCacheOverflowProcessor;26import test.java.lang.invoke.lib.Helper;2728import java.lang.invoke.MethodHandle;29import java.lang.management.GarbageCollectorMXBean;30import java.lang.management.ManagementFactory;31import java.lang.ref.Reference;32import java.lang.reflect.Field;33import java.lang.reflect.Method;34import java.util.Collection;35import java.util.List;36import java.util.function.Function;3738/**39* Lambda forms caching test case class. Contains all necessary test routines to40* test lambda forms caching in method handles returned by methods of41* MethodHandles class.42*43* @author kshefov44*/45public abstract class LambdaFormTestCase {4647private static final long TIMEOUT = Helper.IS_THOROUGH ?480L : (long) (Utils.adjustTimeout(Utils.DEFAULT_TEST_TIMEOUT) * 0.9);4950/**51* Reflection link to {@code j.l.i.MethodHandle.internalForm} method. It is52* used to get a lambda form from a method handle.53*/54protected static final Method INTERNAL_FORM;55protected static final Field KIND_FIELD;56protected static final Field REF_FIELD;57private static final List<GarbageCollectorMXBean> gcInfo;5859private static long gcCount() {60return gcInfo.stream().mapToLong(GarbageCollectorMXBean::getCollectionCount).sum();61}6263static {64try {65INTERNAL_FORM = MethodHandle.class.getDeclaredMethod("internalForm");66INTERNAL_FORM.setAccessible(true);6768KIND_FIELD = Class.forName("java.lang.invoke.LambdaForm").getDeclaredField("kind");69KIND_FIELD.setAccessible(true);7071REF_FIELD = Reference.class.getDeclaredField("referent");72REF_FIELD.setAccessible(true);73} catch (Exception ex) {74throw new Error("Unexpected exception", ex);75}7677gcInfo = ManagementFactory.getGarbageCollectorMXBeans();78if (gcInfo.size() == 0) {79throw new Error("No GarbageCollectorMXBeans found.");80}81}8283private final TestMethods testMethod;84private long gcCountAtStart;8586private static class TestRun {8788final Function<TestMethods, LambdaFormTestCase> ctor;89final Collection<TestMethods> testMethods;90final long totalIterations;91long doneIterations;92long testCounter;93long failCounter;94boolean passed;9596TestRun(Function<TestMethods, LambdaFormTestCase> ctor,97Collection<TestMethods> testMethods) {98this.ctor = ctor;99this.testMethods = testMethods;100long testCaseNum = testMethods.size();101long iterations = Math.max(1, Helper.TEST_LIMIT / testCaseNum);102System.out.printf("Number of iterations according to -DtestLimit is %d (%d cases)%n",103iterations, iterations * testCaseNum);104System.out.printf("Number of iterations is set to %d (%d cases)%n",105iterations, iterations * testCaseNum);106System.out.flush();107totalIterations = iterations;108doneIterations = 0L;109testCounter = 0L;110failCounter = 0L;111passed = true;112}113114Boolean doIteration() {115if (doneIterations >= totalIterations) {116return false;117}118System.err.println(String.format("Iteration %d:", doneIterations));119for (TestMethods testMethod : testMethods) {120LambdaFormTestCase testCase = ctor.apply(testMethod);121try {122System.err.printf("Tested LF caching feature"123+ " with MethodHandles.%s method.%n",124testCase.getTestMethod().name);125Throwable t = CodeCacheOverflowProcessor126.runMHTest(testCase::doTest);127if (t != null) {128return false;129}130System.err.println("PASSED");131} catch (OutOfMemoryError oome) {132// Don't swallow OOME so a heap dump can be created.133System.err.println("FAILED");134throw oome;135} catch (Throwable t) {136t.printStackTrace();137System.err.printf("FAILED. Caused by %s%n", t.getMessage());138passed = false;139failCounter++;140}141testCounter++;142}143doneIterations++;144return true;145}146}147148/**149* Test case constructor. Generates test cases with random method types for150* given methods form {@code j.l.i.MethodHandles} class.151*152* @param testMethod A method from {@code j.l.i.MethodHandles} class which153* returns a {@code j.l.i.MethodHandle}.154*/155protected LambdaFormTestCase(TestMethods testMethod) {156this.testMethod = testMethod;157this.gcCountAtStart = gcCount();158}159160public TestMethods getTestMethod() {161return testMethod;162}163164protected boolean noGCHappened() {165return gcCount() == gcCountAtStart;166}167168/**169* Routine that executes a test case.170*/171public abstract void doTest();172173/**174* Runs a number of test cases defined by the size of testCases list.175*176* @param ctor constructor of LambdaFormCachingTest or its child classes177* object.178* @param testMethods list of test methods179*/180public static void runTests(Function<TestMethods, LambdaFormTestCase> ctor,181Collection<TestMethods> testMethods) {182LambdaFormTestCase.TestRun run183= new LambdaFormTestCase.TestRun(ctor, testMethods);184TimeLimitedRunner runner185= new TimeLimitedRunner(TIMEOUT, 4.0d, run::doIteration);186try {187runner.call();188} catch (Exception ex) {189System.err.println("FAILED");190throw new Error("Unexpected error!", ex);191}192if (!run.passed) {193throw new Error(String.format("%d of %d test cases FAILED! %n"194+ "Rerun the test with the same \"-Dseed=\" option as in the log file!",195run.failCounter, run.testCounter));196} else {197System.err.printf("All %d test cases PASSED!%n", run.testCounter);198}199}200}201202203