# HG changeset patch # User ppunegov # Date 1443114784 -10800 # Node ID 71794b149055eff9978e5e5c166688e3034dcce9 # Parent 73c9bbe40ff8d4bce6859dd79549fab241671a92 8066157: JEP-JDK-8046155: Test task: method matcher Summary: MethodMatcher test and framework Reviewed-by: iignatyev, neliasso diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015, 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 compiler.compilercontrol.matcher; + +import jdk.test.lib.Pair; +import compiler.compilercontrol.share.method.MethodDescriptor; +import compiler.compilercontrol.share.method.MethodGenerator; +import pool.PoolHelper; +import sun.hotspot.WhiteBox; + +import java.lang.reflect.Executable; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/* + * @test + * @bug 8135068 + * @summary Tests CompilerCommand's method matcher + * @library /testlibrary /../../test/lib /compiler/whitebox ../share / + * @build MethodMatcherTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI compiler.compilercontrol.matcher.MethodMatcherTest + */ +public class MethodMatcherTest { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + private static final PoolHelper POOL = new PoolHelper(); + private static final List>> METHODS = + POOL.getAllMethods(); + private static final int AMOUNT = Integer.parseInt(System + .getProperty("test.amount", "25")); + + public static void main(String[] args) { + MethodGenerator gen = new MethodGenerator(); + List>> testMethods = + POOL.getAllMethods(PoolHelper.METHOD_FILTER); + for (Pair> pair : testMethods) { + for (int i = 0; i < AMOUNT; i++) { + MethodDescriptor md = gen.generateRandomDescriptor(pair.first); + check(md); + } + } + } + + /** + * Check method matcher with given test case + * + * @param methodDescriptor method descriptor to check matcher's pattern + */ + private static void check(MethodDescriptor methodDescriptor) { + System.out.println("Test case: " + methodDescriptor.getString()); + System.out.println("Regex: " + methodDescriptor.getRegexp()); + Pattern pattern = Pattern.compile(methodDescriptor.getRegexp()); + boolean isValidDesc = methodDescriptor.isValid(); + List failList = new ArrayList<>(); + // walk through all methods in pool to check match with test pattern + for (Pair> pair : METHODS) { + MethodDescriptor m = MethodGenerator.commandDescriptor(pair.first); + Matcher matcher = pattern.matcher(m.getCanonicalString()); + // get expected result + MatcherResult expected; + if (isValidDesc) { + expected = matcher.matches() ? + MatcherResult.MATCH : MatcherResult.NO_MATCH; + } else { + expected = MatcherResult.PARSING_FAILURE; + } + // get MethodMatcher's result + MatcherResult matchResult = MatcherResult.fromCode(WB.matchesMethod( + pair.first, methodDescriptor.getString())); + // compare + if (matchResult != expected) { + System.out.printf("- Method: %s%n-- FAILED: result: %s, " + + "but expected: %s%n", m.getCanonicalString(), + matchResult, expected); + failList.add(m); + } + } + int size = failList.size(); + if (size != 0) { + System.err.println("FAILED test case: " + methodDescriptor + .getString()); + if (size == METHODS.size()) { + System.err.println("-- All methods failed to match"); + } else { + for (MethodDescriptor md : failList) { + System.err.println("-- FAILED match: " + md.getString()); + } + } + throw new AssertionError("FAIL: " + methodDescriptor.getString()); + } + System.out.println("--PASSED"); + } + + /** + * Represents MethodMatcher's matching result + */ + public enum MatcherResult { + PARSING_FAILURE(-1, "Parsing failed"), + NO_MATCH(0, "No match"), + MATCH(1, "Match"); + + public final int code; + private final String message; + + private MatcherResult(int code, String message) { + this.code = code; + this.message = message; + } + + public static MatcherResult fromCode(int code) { + switch (code) { + case -1: return PARSING_FAILURE; + case 0: return NO_MATCH; + case 1: return MATCH; + default: + throw new IllegalArgumentException("MATCHER FAILURE:" + + "Wrong code: " + code); + } + } + + @Override + public String toString() { + return message; + } + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/method/ClassType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/method/ClassType.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2015, 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 compiler.compilercontrol.share.method; + +import java.lang.reflect.Executable; +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * Element represents class in method descriptor + * that consist from class package and class itself + */ +public class ClassType extends MethodElementType { + private final String[] packageDirs; + private final Class aClass; + private boolean setPackage; + + public ClassType(Executable method) { + // Use pack/subpack/Class::method separators style + super(MethodDescriptor.Separator.SLASH); + // Get package + aClass = method.getDeclaringClass(); + Package aPackage = method.getDeclaringClass().getPackage(); + if (aPackage != null) { + // split into directories + packageDirs = aPackage.getName().split("\\."); + } else { + packageDirs = null; + } + setPackage = true; + buildElement(setPackage); + } + + @Override + public boolean isValid() { + if (element.isEmpty()) { + return false; + } + boolean separatorMet = false; + char separatorChar = 0; + char[] charArray = element.toCharArray(); + for (int i = 0; i < charArray.length; i++) { + char ch = charArray[i]; + switch (ch) { + case '/': + case '.': + if (separatorMet) { + if (ch != separatorChar) { + // there are two different separators + return false; + } + } else { + separatorChar = ch; + separatorMet = true; + } + break; + case ':': + if (++i != charArray.length) { + if (charArray[i] == ':') { + // :: is invalid separator + separator = MethodDescriptor.Separator.DOUBLECOLON; + return false; + } + } + break; + // Invalid separators + case ',': + case ' ': + return false; + } + } + // set correct separator + switch (separatorChar) { + case '.': + separator = MethodDescriptor.Separator.DOT; + break; + case '/': + separator = MethodDescriptor.Separator.SLASH; + break; + default: + separator = MethodDescriptor.Separator.NONE; + break; + } + return super.isValid(); + } + + @Override + public void setSeparator(MethodDescriptor.Separator separator) { + this.separator = separator; + buildElement(setPackage); + } + + @Override + public void setPattern(MethodDescriptor.PatternType patternType) { + switch (patternType) { + case EXACT: + break; + case PREFIX: + // For prefix pattern use only class name without package + buildElement(false); + regexp = ".*" + regexp; + element = "*" + element; + break; + case ANY: + regexp = ".*"; + element = "*"; + break; + case SUFFIX: + regexp = regexp + ".*"; + element = element + "*"; + break; + case SUBSTRING: + setPattern(MethodDescriptor.PatternType.PREFIX); + setPattern(MethodDescriptor.PatternType.SUFFIX); + break; + default: + throw new IllegalArgumentException("ERROR: wrong pattern type " + + patternType); + } + } + + /** + * Builds element string and regexp. + * + * @param setPackage shows that element should have a package name + */ + private void buildElement(boolean setPackage) { + this.setPackage = setPackage; + StringBuilder elementBuilder = new StringBuilder(); + if (packageDirs != null && setPackage) { + elementBuilder.append(Arrays.stream(packageDirs) + .collect(Collectors.joining(separator.symbol))); + elementBuilder.append(separator.symbol); + } + String className = aClass.getSimpleName(); + if (setPackage) { + // Add outer classes if any + Class enclosingClass = aClass.getEnclosingClass(); + while (enclosingClass != null) { + className = enclosingClass.getSimpleName() + "$" + className; + enclosingClass = enclosingClass.getEnclosingClass(); + } + } + elementBuilder.append(className); + element = elementBuilder.toString(); + if (separator == MethodDescriptor.Separator.DOT) { + // Replace . with / to make regexp look like CommandSignature + regexp = element.replace(".", "/"); + } else { + regexp = element; + } + regexp = regexp.replace("$", "\\$"); + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/method/MethodDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/method/MethodDescriptor.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2015, 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 compiler.compilercontrol.share.method; + +import jdk.test.lib.Triple; + +import java.lang.reflect.Executable; +import java.util.function.Function; +import java.util.regex.Pattern; + +/** + * Method descriptor for Compiler Control commands. + * It represents method pattern used for matching in Compiler Control + * and CompileCommand option + */ +public class MethodDescriptor { + public final ClassType aClass; // Represents class and package + public final MethodType aMethod; // Represents method + public final SignatureType aSignature; // Represents signature + + /** + * Constructor + * + * @param method executable to build method descriptor from + */ + public MethodDescriptor(Executable method) { + aClass = new ClassType(method); + aMethod = new MethodType(method); + aSignature = new SignatureType(method); + } + + /** + * Sets signature separators for all elements + */ + public void setSeparators( + Triple separators) { + aClass.setSeparator(separators.getFirst()); + aMethod.setSeparator(separators.getSecond()); + aSignature.setSeparator(separators.getThird()); + } + + /** + * Sets custom strings for each element + */ + public void setStrings(Triple strings) { + aClass.setElement(strings.getFirst()); + aMethod.setElement(strings.getSecond()); + aSignature.setElement(strings.getThird()); + } + + /** + * Sets patterns for all elements + */ + public void setPatterns( + Triple patterns) { + aClass.setPattern(patterns.getFirst()); + aMethod.setPattern(patterns.getSecond()); + aSignature.setPattern(patterns.getThird()); + } + + /** + * Separates elements in the MethodDescriptor + */ + public static enum Separator { + SLASH("/"), + DOT("."), + COMMA(","), + DOUBLECOLON("::"), + SPACE(" "), + NONE(""); + + public final String symbol; + + Separator(String symbol) { + this.symbol = symbol; + } + + /** + * Validates method descriptor separators + * + * @param md method descriptor to validate + * @return true if descriptor's separators are valid + */ + public static boolean isValid(MethodDescriptor md) { + Separator cls = md.getClassSeparator(); + Separator method = md.getMethodSeparator(); + Separator sign = md.getSignatureSeparator(); + if (sign == SPACE || sign == NONE || sign == COMMA) { + // if it looks like java/lang/String.indexOf + if ((cls == SLASH || cls == NONE) + // allow space and comma instead of dot + && (method == DOT || method == SPACE + || method == COMMA)) { + return true; + } + // if it looks like java.lang.String::indexOf + if ((cls == DOT || cls == NONE) && method == DOUBLECOLON) { + return true; + } + } + return false; + } + } + + /** + * Type of the pattern + */ + public static enum PatternType { + PREFIX, + ANY, + SUFFIX, + SUBSTRING, + EXACT + } + + public Separator getClassSeparator() { + return aClass.getSeparator(); + } + + public Separator getMethodSeparator() { + return aMethod.getSeparator(); + } + + public Separator getSignatureSeparator() { + return aSignature.getSeparator(); + } + + /** + * Gets regular expression to match methods + * + * @return string representation of the regular expression + */ + public String getRegexp() { + // regexp should have a . as a method separator + // and / as a package/class separator + return aClass.getRegexp().replaceAll("\\.", "/") + .replaceAll("/\\*", ".*") + + Pattern.quote(Separator.DOT.symbol) + + aMethod.getRegexp() + aSignature.getRegexp(); + } + + /** + * Gets method descriptor string representation. + * This string is used as a pattern in CompilerControl and CompileCommand + */ + public String getString() { + return aClass.getElement() + getMethodSeparator().symbol + + aMethod.getElement() + getSignatureSeparator().symbol + + aSignature.getElement(); + } + + /** + * Convert method descriptor to be regexp-compatible + * + * @return string representation of the method signature + */ + public String getCanonicalString() { + return aClass.getElement().replaceAll("\\.", "/") + Separator.DOT.symbol + + aMethod.getElement() + aSignature.getElement(); + } + + /** + * Shows if this descriptor is a valid pattern for CompilerControl + * + * @return true, if descriptor is valid, false otherwise + */ + public boolean isValid() { + return aClass.isValid() && aMethod.isValid() && aSignature.isValid() + && Separator.isValid(this); + } + + /** + * Sets custom string from element mutate function + * to the appropriate element of method descriptor + */ + public void applyMutates(Triple, + Function, + Function> mutators) { + String elementString = aClass.getElement(); + aClass.setElement(mutators.getFirst().apply(elementString)); + elementString = aMethod.getElement(); + aMethod.setElement(mutators.getSecond().apply(elementString)); + elementString = aSignature.getElement(); + aSignature.setElement(mutators.getThird().apply(elementString)); + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/method/MethodElementType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/method/MethodElementType.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2015, 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 compiler.compilercontrol.share.method; + +import java.util.regex.Pattern; + +/** + * Class represents an element of the MethodDescriptor + * used as pattern for CompilerCommand method strings + */ +public abstract class MethodElementType { + private static final char[] INVALID_CHARS = { ';', '[', '(', ')', ']', + '<', '>'}; + protected String element; + protected String regexp; + protected MethodDescriptor.Separator separator; + + /** + * Constructor + */ + protected MethodElementType(MethodDescriptor.Separator separator) { + this.separator = separator; + } + + /** + * Gets element's separator + * + * @return separator instance + */ + public MethodDescriptor.Separator getSeparator() { + return separator; + } + + /** + * Sets separator for this element + * + * @param separator separator type + */ + public void setSeparator(MethodDescriptor.Separator separator) { + this.separator = separator; + } + + /** + * Gets String representation of the element + * + * @return element string + */ + public String getElement() { + return element; + } + + /** + * Sets String representation of the element + * + * @param element custom string to be used as an element + */ + public void setElement(String element) { + this.element = element; + this.regexp = Pattern.quote(element); + } + + /** + * Shows that the element is valid according to CompilerControl and JVMS specs + * + * @return true, if the element is a valid string + */ + public boolean isValid() { + for (char ch : INVALID_CHARS) { + if (element.indexOf(ch) != -1) { + return false; + } + } + // Check for * usage + if (element.equals("**")) { + return false; + } + for (int i = 0; i < element.length(); i++) { + char c = element.charAt(i); + if (c == '*' && i > 0 && i < element.length() - 1) { + // Embedded * isn't allowed + return false; + } + } + return true; + } + + /** + * Creates pattern of a given type + * + * @param patternType type of the pattern + */ + public void setPattern(MethodDescriptor.PatternType patternType) { + switch (patternType) { + case EXACT: + break; + case PREFIX: + regexp = ".*" + regexp; + element = "*" + element; + break; + case ANY: + regexp = ".*"; + element = "*"; + break; + case SUFFIX: + regexp = regexp + ".*"; + element = element + "*"; + break; + case SUBSTRING: + setPattern(MethodDescriptor.PatternType.PREFIX); + setPattern(MethodDescriptor.PatternType.SUFFIX); + break; + default: + throw new IllegalArgumentException("ERROR: wrong pattern type" + + patternType); + } + } + + /** + * Gets regular expression of this element + * + * @return string representation of regexp + */ + public String getRegexp() { + return regexp; + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2015, 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 compiler.compilercontrol.share.method; + +import compiler.compilercontrol.share.method.MethodDescriptor.PatternType; +import compiler.compilercontrol.share.method.MethodDescriptor.Separator; +import jdk.test.lib.Pair; +import jdk.test.lib.Triple; +import jdk.test.lib.Utils; +import pool.PoolHelper; + +import java.lang.reflect.Executable; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.function.Function; + +/** + * Generates combinations of method descriptors from the pool of methods + */ +public class MethodGenerator { + private static final List>> METHODS = + new PoolHelper().getAllMethods(PoolHelper.METHOD_FILTER); + // Different combinations of patterns + private static final List> PATTERNS_LIST; + // Different combinations of separators + private static final List> SEPARATORS_LIST; + // List of functions that modify elements + private static final List> ELEMENT_MUTATORS; + + static { + PATTERNS_LIST = + generate(EnumSet.allOf(PatternType.class), + EnumSet.allOf(PatternType.class), + EnumSet.of(PatternType.ANY, PatternType.EXACT)); + SEPARATORS_LIST = + generate(EnumSet.of(Separator.SLASH, Separator.DOT), + EnumSet.complementOf(EnumSet.of(Separator.NONE)), + EnumSet.of(Separator.COMMA, Separator.SPACE, + Separator.NONE)); + ELEMENT_MUTATORS = generateMutators(); + } + + // Test method + public static void main(String[] args) { + MethodGenerator methodGenerator = new MethodGenerator(); + List tests = methodGenerator.getTests(); + tests.forEach(System.out::println); + } + + /** + * Generates random method descriptor + * + * @param executable executable used to generate descriptor + * @return MethodDescriptor instance + */ + public MethodDescriptor generateRandomDescriptor(Executable executable) { + Combination patterns = + Utils.getRandomElement(PATTERNS_LIST); + Combination separators = + Utils.getRandomElement(SEPARATORS_LIST); + // Create simple mutators for signature generation + List> signMutators = new ArrayList<>(); + signMutators.add(input -> input); + signMutators.add(input -> ""); + Combination> mutators = new Combination<>( + Utils.getRandomElement(ELEMENT_MUTATORS), + Utils.getRandomElement(ELEMENT_MUTATORS), + // use only this type of mutators + Utils.getRandomElement(signMutators)); + return makeMethodDescriptor(executable, patterns, + separators, mutators); + } + + /** + * Compile command signature that looks like java/lang/String.indexOf + * http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#BABDDFII + * + * @param executable executable used to generate descriptor + * @return MethodDescriptor instance + */ + public static MethodDescriptor commandDescriptor(Executable executable) { + MethodDescriptor md = new MethodDescriptor(executable); + md.aClass.setSeparator(Separator.SLASH); + md.aMethod.setSeparator(Separator.DOT); + md.aSignature.setSeparator(Separator.NONE); + return md; + } + + /** + * Compile command signature that looks like java.lang.String::indexOf + * + * @param executable executable used to generate descriptor + * @return MethodDescriptor instance + */ + public static MethodDescriptor logDescriptor(Executable executable) { + MethodDescriptor md = new MethodDescriptor(executable); + md.aClass.setSeparator(Separator.DOT); + md.aMethod.setSeparator(Separator.DOUBLECOLON); + md.aSignature.setSeparator(Separator.NONE); + return md; + } + + /** + * Generates a list of method patterns from the pool of methods + * + * @return a list of test cases + */ + public List getTests() { + List list = new ArrayList<>(); + METHODS.forEach(pair -> list.addAll(getTests(pair.first))); + return list; + } + + /** + * Generates all combinations of method descriptors for a given executable + * + * @param executable executable for which the different combination is built + * @return list of method descriptors + */ + public List getTests(Executable executable) { + List list = new ArrayList<>(); + for (Combination patterns : PATTERNS_LIST) { + for (Combination separators : SEPARATORS_LIST) { + for (Function classGen : ELEMENT_MUTATORS) { + for (Function methodGen : + ELEMENT_MUTATORS) { + for (Function signatureGen : + ELEMENT_MUTATORS) { + list.add(makeMethodDescriptor(executable, + patterns, separators, + new Combination<>(classGen, methodGen, + signatureGen))); + } + } + } + } + } + return list; + } + + /** + * Creates method descriptor from the given executable, + * patterns and separators for its elements + */ + private MethodDescriptor makeMethodDescriptor( + Executable executable, + Combination patterns, + Combination separators, + Combination> mutators) { + MethodDescriptor methodDescriptor = new MethodDescriptor(executable); + methodDescriptor.setSeparators(separators); + methodDescriptor.applyMutates(mutators); + methodDescriptor.setPatterns(patterns); + return methodDescriptor; + } + + /** + * Creates a list of functions that change given string + */ + private static List> generateMutators() { + List> elements = new ArrayList<>(); + // Use the input itself + elements.add(input -> input); + // Use half of the input string + elements.add(input -> input.substring(input.length() / 2)); + // Add nonexistent element + elements.add(input -> "nonexistent"); + // Use left and right angle brackets + elements.add(input -> "<" + input + ">"); + // Embed * inside + elements.add(input -> embed(input, "*")); + // ** as a whole element + elements.add(input -> "**"); + // Embed JLS-invalid letters + elements.add(input -> embed(input, "@%")); + elements.add(input -> embed(input, "]")); + // Use JLS-invalid letters + elements.add(input -> "-"); + elements.add(input -> "+"); + elements.add(input -> ")" + input); + elements.add(input -> "{" + input + "}"); + // Add valid Java identifier start char + elements.add(input -> "_" + input); + elements.add(input -> "$" + input); + elements.add(input -> "0" + input); + // Unicode characters + elements.add(input -> embed(input, "\u0001")); + elements.add(input -> embed(input, "\u007F")); + // Combining character + elements.add(input -> embed(input, "\u0300")); + elements.add(input -> embed(input, "\u0306")); + // Supplementary character + elements.add(input -> new String(Character.toChars(0x1F64C))); + return elements; + } + + /** + * Embeds one string inside another one + * + * @param target target source string + * @param element string to be embedded into target string + * @return result string + */ + private static String embed(String target, String element) { + int mid = target.length() / 2; + String begin = target.substring(0, mid); + String end = target.substring(mid); + return begin + element + end; + } + + /** + * Generates triples from the given enum sets + * for each of the method elements + * + * @param classSet set of allowed elements for class + * @param methodSet set of allowed elements for method + * @param signSet set of allowed elements for signature + * @param type of generated triples + * @return list of triples + */ + private static > List> generate( + EnumSet classSet, EnumSet methodSet, EnumSet signSet) { + List> list = new ArrayList<>(); + classSet.forEach(clsElement -> + methodSet.forEach(methodElement -> + signSet.forEach(signElement -> + list.add(new Combination<>(clsElement, methodElement, + signElement)) + ) + ) + ); + return list; + } + + private static class Combination extends Triple { + public Combination(T first, T second, T third) { + super(first, second, third); + } + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/method/MethodType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/method/MethodType.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015, 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 compiler.compilercontrol.share.method; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; + +/** + * Represents a method in CompileControl method signature + */ +public class MethodType extends MethodElementType { + private static final char[] INVALID_CHARS = { '.', '/' }; + + public MethodType(Executable method) { + // Use pack/subpack/Class::method separators style + super(MethodDescriptor.Separator.DOT); + if (method instanceof Constructor) { + element = ""; + } else { + element = method.getName(); + } + regexp = element; + } + + @Override + public boolean isValid() { + for (char ch : INVALID_CHARS) { + if (element.indexOf(ch) != -1) { + return false; + } + } + if (element.isEmpty()) { + // Shouldn't be empty + return false; + } + if (element.contains("<") || element.contains(">")) { + return element.matches("(\\*)?<(cl)?init>(\\*)?"); + } + return super.isValid(); + } + + @Override + public void setPattern(MethodDescriptor.PatternType patternType) { + switch (patternType) { + case EXACT: + break; + case PREFIX: + regexp = ".*" + regexp; + element = "*" + element; + break; + case ANY: + regexp = "[^(]*"; + element = "*"; + break; + case SUFFIX: + regexp = regexp + "[^(]*"; + element = element + "*"; + break; + case SUBSTRING: + setPattern(MethodDescriptor.PatternType.PREFIX); + setPattern(MethodDescriptor.PatternType.SUFFIX); + break; + default: + throw new IllegalArgumentException("ERROR: wrong pattern type " + + patternType); + } + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/method/SignatureType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/method/SignatureType.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2015, 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 compiler.compilercontrol.share.method; + +import jdk.test.lib.Utils; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.util.Arrays; + +/** + * This class represents a signature of the method + */ +public class SignatureType extends MethodElementType { + public SignatureType(Executable method) { + super(MethodDescriptor.Separator.NONE); + // Get parameters + Class[] types = method.getParameterTypes(); + String[] parameterTypes = new String[types.length]; + for (int i = 0; i < types.length; i++) { + parameterTypes[i] = Utils.toJVMTypeSignature(types[i]); + } + // Get return value + String returnType; + if (method instanceof Method) { + returnType = Utils.toJVMTypeSignature(((Method) method) + .getReturnType()); + } else if (method instanceof Constructor) { + // Constructor returns void in VM + returnType = Utils.toJVMTypeSignature(void.class); + } else { + throw new Error(String.format("TESTBUG: wrong type of executable " + + "%s of class %s", method, method.getClass())); + } + // Create signature + setElement("(" + String.join("", parameterTypes)+ ")" + returnType); + regexp = element; + setPattern(MethodDescriptor.PatternType.EXACT); + separator = MethodDescriptor.Separator.NONE; + } + + @Override + public void setElement(String element) { + if (element.isEmpty()) { + setPattern(MethodDescriptor.PatternType.ANY); + } else { + super.setElement(element); + } + } + + @Override + public boolean isValid() { + if (element.isEmpty()) { + return true; + } + // Allowed primitive types + char[] baseTypes = {'B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z'}; // sorted + // Parsing states + boolean isArray = false; + boolean isInsideSig = false; + boolean isClass = false; + + for (char ch : element.toCharArray()) { + if (ch == '(') { + if (isInsideSig) { + // Met another ( inside + return false; + } + isInsideSig = true; + } else if (ch == ')') { + if (!isInsideSig) { + // met another ) outside + return false; + } + isInsideSig = false; + } else if (ch == 'V') { + if (isInsideSig) { + // void type is allowed only as a return value + return false; + } + } else if (ch == 'L') { + // this is a beginning of class/interface + isClass = true; + // met actual type of array + isArray = false; + } else if (ch == '[') { + isArray = true; + } else if (isClass) { + if (!Character.isJavaIdentifierPart(ch)) { + if (ch == '/' || ch == '.') { + // separator met + } else if (ch == ';') { + // end of class/interface + isClass = false; + } else { + return false; + } + } + } else if (Arrays.binarySearch(baseTypes, ch) < 0) { + // if it doesn't belong to base types + return false; + } else { + // array of a base type + isArray = false; + } + } + return !(isArray || isInsideSig || isClass); + } + + @Override + public void setPattern(MethodDescriptor.PatternType patternType) { + switch (patternType) { + case PREFIX: + case SUFFIX: + case SUBSTRING: + // These patterns are not supported in Compiler Control + // Just use ANY pattern instead + case ANY: + regexp = "\\(.*\\).*"; + element = ""; + break; + case EXACT: + break; + default: + throw new IllegalArgumentException("ERROR: wrong pattern type " + + patternType); + } + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/pool/MethodHolder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/pool/MethodHolder.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015, 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 pool; + +import jdk.test.lib.Pair; + +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +/** + * Represents a holder that contains test methods + */ +public abstract class MethodHolder { + /** + * Helper method to get executable for the specified method + * + * @param holder class that holds specified method + * @param name method name + * @param parameterTypes parameter types of the specified method + * @return {@link Method} instance + */ + public Method getMethod(MethodHolder holder, + String name, + Class... parameterTypes) { + try { + return holder.getClass().getDeclaredMethod(name, parameterTypes); + } catch (NoSuchMethodException e) { + throw new Error("TESTBUG: Can't get method " + name, e); + } + } + + /** + * Gets all test methods + * + * @return pairs of Executable and appropriate Callable + */ + public List>> getAllMethods() { + Class aClass = this.getClass(); + Object classInstance; + try { + classInstance = aClass.newInstance(); + } catch (ReflectiveOperationException e) { + throw new Error("TESTBUG: unable to get new instance", e); + } + List>> pairs = new ArrayList<>(); + { + Method method = getMethod(this, "method", int.class, String[].class, + Integer.class, byte[].class, double[][].class); + Pair> pair = new Pair<>(method, + () -> { + // Make args + int a = 0; + String[] ss = {"a", "b", "c", "d"}; + Integer i = 1; + byte[] bb = {1, 2}; + double[][] dd = { + {1.618033, 3.141592}, + {2.718281, 0.007874} + }; + // Invoke method + method.invoke(classInstance, a, ss, i, bb, dd); + return true; + }); + pairs.add(pair); + } + { + Method method = getMethod(this, "method"); + Pair> pair = new Pair<>(method, + () -> { + method.invoke(classInstance); + return true; + }); + pairs.add(pair); + } + { + Method method = getMethod(this, "smethod"); + Pair> pair = new Pair<>(method, + () -> method.invoke(classInstance)); + pairs.add(pair); + } + { + Method method = getMethod(this, "smethod", int.class, int[].class); + Pair> pair = new Pair<>(method, + () -> { + int[] array = {1, 2, 3}; + return method.invoke(classInstance, 42, array); + }); + pairs.add(pair); + } + { + Method method = getMethod(this, "smethod", Integer.class); + Pair> pair = new Pair<>(method, + () -> method.invoke(classInstance, 100)); + pairs.add(pair); + } + return pairs; + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/pool/PoolHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/pool/PoolHelper.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015, 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 pool; + +import jdk.test.lib.Pair; +import pool.MethodHolder; +import java.lang.reflect.Executable; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * This is a helper class that provides tests with methods + */ +public class PoolHelper extends MethodHolder { + private static final List>> METHODS; + + /** + * Filters only those methods who belong to Klass or its internal class + * Internal and named as "method" or is a constructor + */ + public static final Predicate METHOD_FILTER = executable -> { + String methodName = executable.getName(); + String className = executable.getDeclaringClass().getName(); + return className.matches(".*(Klass)(\\$Internal)?") && + (methodName.equals("method") || + methodName.equals(className)); // if method is + }; + + static { + METHODS = new ArrayList<>(); + List holders = new ArrayList<>(); + holders.add(new pool.sub.Klass()); + holders.add(new pool.sub.KlassDup()); + holders.add(new pool.subpack.Klass()); + holders.add(new pool.subpack.KlassDup()); + holders.add(new pool.sub.Klass.Internal()); + holders.add(new pool.subpack.KlassDup.Internal()); + for (MethodHolder holder : holders) { + METHODS.addAll(holder.getAllMethods()); + } + } + + /** + * Gets all methods from the pool using specified filter + * + * @param filter method filter + * @return pairs of Executable and appropriate Callable + */ + public List>> getAllMethods( + Predicate filter) { + return getAllMethods().stream() + .filter(pair -> filter.test(pair.first)) + .collect(Collectors.toList()); + } + + /** + * Gets all methods from the pool + * + * @return pairs of Executable and appropriate Callable + */ + @Override + public List>> getAllMethods() { + return METHODS; + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/pool/sub/Klass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/pool/sub/Klass.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015, 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 pool.sub; + +import jdk.test.lib.Pair; +import pool.MethodHolder; + +import java.lang.reflect.Executable; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +/** + * Simple class with methods to test signatures + */ +public class Klass extends MethodHolder { + public void method(int a, String[] ss, Integer i, byte[] bb, double[][] dd) { } + + public void method() { } + + public static String smethod() { + return "ABC"; + } + + public static String smethod(int iarg, int[] aarg) { + return "ABC"; + } + + public static Integer smethod(Integer arg) { + Integer var = 1024; + return arg + var; + } + + // Internal class and constructor + public static class Internal extends MethodHolder { + public Internal() { } + + public Double method(Float fl) { return Double.valueOf(fl); } + + public Double methodDup() { + return Math.exp(1.0); + } + + public static Integer smethod(Integer arg) { + Integer var = 1024; + return arg + var; + } + + @Override + public List>> getAllMethods() { + List>> pairs = new ArrayList<>(); + Pair> pair = new Pair<> + (getMethod(this, "method", Float.class), + () -> this.method(3.141592f)); + pairs.add(pair); + pair = new Pair<>(getMethod(this, "methodDup"), this::methodDup); + pairs.add(pair); + pair = new Pair<>(getMethod(this, "smethod", Integer.class), + () -> smethod(1024)); + pairs.add(pair); + try { + pair = new Pair<>(this.getClass().getConstructor(), + Internal::new); + pairs.add(pair); + } catch (NoSuchMethodException e) { + throw new Error("TESTBUG: unable to get constructor"); + } + return pairs; + } + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/pool/sub/KlassDup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/pool/sub/KlassDup.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, 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 pool.sub; + +import pool.MethodHolder; + +/** + * Simple class with methods to test signatures + * This class has Dup suffix in the name to test suffix patterns like Klass*. + * Such patterns should match both Klass and KlassDup + */ +public class KlassDup extends MethodHolder { + public void method(int a, String[] ss, Integer i, byte[] bb, double[][] dd) { } + + public void method() { } + + public static String smethod() { + return "ABC"; + } + + public static String smethod(int iarg, int[] aarg) { + return "ABC"; + } + + public static Integer smethod(Integer arg) { + Integer var = 1024; + return arg + var; + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/pool/subpack/Klass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/pool/subpack/Klass.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, 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 pool.subpack; + +import pool.MethodHolder; + +/** + * Simple class with methods to test signatures + * This is a clone of the pool.sub.Klass, but without inner class + * This class has different package name to test prefix patterns like *Klass. + * *Klass patern should match both pool.sub.Klass and pool.subpack.Klass + */ +public class Klass extends MethodHolder { + public void method(int a, String[] ss, Integer i, byte[] bb, double[][] dd) { } + + public void method() { } + + public static String smethod() { + return "ABC"; + } + + public static String smethod(int iarg, int[] aarg) { + return "ABC"; + } + + public static Integer smethod(Integer arg) { + Integer var = 1024; + return arg + var; + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/compiler/compilercontrol/share/pool/subpack/KlassDup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/pool/subpack/KlassDup.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, 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 pool.subpack; + +import jdk.test.lib.Pair; +import pool.MethodHolder; + +import java.lang.reflect.Executable; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +/** + * This is a clone of the pool.sub.Klass used to test pattern matching + * Full class name contains both suffix (Dup) and prefix (pool.subpack) + */ +public class KlassDup extends MethodHolder { + public void method(int a, String[] ss, Integer i, byte[] bb, double[][] dd) { } + + public void method() { } + + public static String smethod() { + return "ABC"; + } + + public static String smethod(int iarg, int[] aarg) { + return "ABC"; + } + + public static Integer smethod(Integer arg) { + Integer var = 1024; + return arg + var; + } + + // Internal class and constructor + public static class Internal extends MethodHolder { + public Internal() { } + + public Double method(Float fl) { return Double.valueOf(fl); } + + public Double methodDup() { + return Math.exp(1.0); + } + + public static Integer smethod(Integer arg) { + Integer var = 1024; + return arg + var; + } + + @Override + public List>> getAllMethods() { + List>> pairs = new ArrayList<>(); + Pair> pair = new Pair<> + (getMethod(this, "method", Float.class), + () -> this.method(3.141592f)); + pairs.add(pair); + pair = new Pair<>(getMethod(this, "methodDup"), this::methodDup); + pairs.add(pair); + pair = new Pair<>(getMethod(this, "smethod", Integer.class), + () -> smethod(1024)); + pairs.add(pair); + try { + pair = new Pair<>(this.getClass().getConstructor(), + Internal::new); + pairs.add(pair); + } catch (NoSuchMethodException e) { + throw new Error("TESTBUG: unable to get constructor"); + } + return pairs; + } + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/testlibrary/jdk/test/lib/Pair.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/jdk/test/lib/Pair.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, 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 jdk.test.lib; + +import java.util.Objects; + +/** + * Pair - a two element tuple + * + * @param first type + * @param second type + */ +public class Pair { + public final F first; + public final S second; + + public Pair(F first, S second) { + this.first = first; + this.second = second; + } + + @Override + public String toString() { + return "(" + first + ":" + second + ")"; + } + + @Override + public boolean equals(Object other) { + if (other instanceof Pair) { + Pair otherPair = (Pair) other; + return Objects.equals(first, otherPair.first) && + Objects.equals(second, otherPair.second); + } + return false; + } + + @Override + public int hashCode() { + if (first == null) { + return (second == null) ? 0 : second.hashCode(); + } else if (second == null) { + return first.hashCode(); + } else { + return first.hashCode() * 17 + second.hashCode(); + } + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/testlibrary/jdk/test/lib/Triple.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/jdk/test/lib/Triple.java Thu Sep 24 20:13:04 2015 +0300 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015, 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 jdk.test.lib; + +import java.util.Objects; + +/** + * Triple - a three element tuple + * + * @param first element type + * @param second element type + * @param third element type + */ +public class Triple { + private final Pair> container; + + /** + * Constructor + * + * @param first first element of the triple + * @param second second element of the triple + * @param third third element of the triple + */ + public Triple(F first, S second, T third) { + container = new Pair<>(first, new Pair<>(second, third)); + } + + /** + * Gets first element of the triple + */ + public F getFirst() { + return container.first; + } + + /** + * Gets second element of the triple + */ + public S getSecond() { + return container.second.first; + } + + /** + * Gets third element of the triple + */ + public T getThird() { + return container.second.second; + } + + @Override + public int hashCode() { + return container.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Triple) { + Triple objTriple = (Triple) obj; + return Objects.equals(container.first, objTriple.container.first) + && Objects.equals(container.second, + objTriple.container.second); + } + return false; + } + + @Override + public String toString() { + return "(" + getFirst() + " : " + getSecond() + " : " + getThird() + ")"; + } +} diff -r 73c9bbe40ff8 -r 71794b149055 hotspot/test/testlibrary/jdk/test/lib/Utils.java --- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java Thu Sep 24 18:24:10 2015 +0300 +++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java Thu Sep 24 20:13:04 2015 +0300 @@ -34,7 +34,9 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.function.BooleanSupplier; @@ -379,6 +381,28 @@ } /** + * Returns random element of non empty collection + * + * @param a type of collection element + * @param collection collection of elements + * @return random element of collection + * @throws IllegalArgumentException if collection is empty + */ + public static T getRandomElement(Collection collection) + throws IllegalArgumentException { + if (collection.isEmpty()) { + throw new IllegalArgumentException("Empty collection"); + } + Random random = getRandomInstance(); + int elementIndex = 1 + random.nextInt(collection.size() - 1); + Iterator iterator = collection.iterator(); + while (--elementIndex != 0) { + iterator.next(); + } + return iterator.next(); + } + + /** * Wait for condition to be true * * @param condition, a condition to wait for @@ -461,5 +485,41 @@ } } + /** + * Converts to VM type signature + * + * @param type Java type to convert + * @return string representation of VM type + */ + public static String toJVMTypeSignature(Class type) { + if (type.isPrimitive()) { + if (type == boolean.class) { + return "Z"; + } else if (type == byte.class) { + return "B"; + } else if (type == char.class) { + return "C"; + } else if (type == double.class) { + return "D"; + } else if (type == float.class) { + return "F"; + } else if (type == int.class) { + return "I"; + } else if (type == long.class) { + return "J"; + } else if (type == short.class) { + return "S"; + } else if (type == void.class) { + return "V"; + } else { + throw new Error("Unsupported type: " + type); + } + } + String result = type.getName().replaceAll("\\.", "/"); + if (!type.isArray()) { + return "L" + result + ";"; + } + return result; + } }