Path: blob/master/test/hotspot/jtreg/compiler/compilercontrol/share/method/MethodGenerator.java
41161 views
/*1* Copyright (c) 2015, 2016, 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 compiler.compilercontrol.share.method;2425import compiler.compilercontrol.share.method.MethodDescriptor.PatternType;26import compiler.compilercontrol.share.method.MethodDescriptor.Separator;27import compiler.compilercontrol.share.pool.PoolHelper;28import jdk.test.lib.util.Pair;29import jdk.test.lib.util.Triple;30import jdk.test.lib.Utils;3132import java.lang.reflect.Executable;33import java.util.ArrayList;34import java.util.EnumSet;35import java.util.List;36import java.util.concurrent.Callable;37import java.util.function.Function;3839/**40* Generates combinations of method descriptors from the pool of methods41*/42public class MethodGenerator {43private static final List<Pair<Executable, Callable<?>>> METHODS =44new PoolHelper().getAllMethods(PoolHelper.METHOD_FILTER);45// Different combinations of patterns46private static final List<Combination<PatternType>> PATTERNS_LIST;47// Different combinations of separators48private static final List<Combination<Separator>> SEPARATORS_LIST;49// List of functions that modify elements50private static final List<Function<String, String>> ELEMENT_MUTATORS;5152static {53PATTERNS_LIST =54generate(EnumSet.allOf(PatternType.class),55EnumSet.allOf(PatternType.class),56EnumSet.of(PatternType.ANY, PatternType.EXACT));57SEPARATORS_LIST =58generate(EnumSet.of(Separator.SLASH, Separator.DOT),59EnumSet.complementOf(EnumSet.of(Separator.NONE)),60EnumSet.of(Separator.COMMA, Separator.SPACE,61Separator.NONE));62ELEMENT_MUTATORS = generateMutators();63}6465// Test method66public static void main(String[] args) {67MethodGenerator methodGenerator = new MethodGenerator();68List<MethodDescriptor> tests = methodGenerator.getTests();69tests.forEach(System.out::println);70}7172/**73* Generates random method descriptor74*75* @param executable executable used to generate descriptor76* @return MethodDescriptor instance77*/78public MethodDescriptor generateRandomDescriptor(Executable executable) {79Combination<PatternType> patterns =80Utils.getRandomElement(PATTERNS_LIST);81Combination<Separator> separators =82Utils.getRandomElement(SEPARATORS_LIST);83// Create simple mutators for signature generation84List<Function<String, String>> signMutators = new ArrayList<>();85signMutators.add(input -> input);86signMutators.add(input -> "");87Combination<Function<String, String>> mutators = new Combination<>(88Utils.getRandomElement(ELEMENT_MUTATORS),89Utils.getRandomElement(ELEMENT_MUTATORS),90// use only this type of mutators91Utils.getRandomElement(signMutators));92return makeMethodDescriptor(executable, patterns,93separators, mutators);94}9596/**97* Compile command signature that looks like java/lang/String.indexOf98* http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#BABDDFII99*100* @param executable executable used to generate descriptor101* @return MethodDescriptor instance102*/103public static MethodDescriptor commandDescriptor(Executable executable) {104MethodDescriptor md = new MethodDescriptor(executable);105md.aClass.setSeparator(Separator.SLASH);106md.aMethod.setSeparator(Separator.DOT);107md.aSignature.setSeparator(Separator.NONE);108return md;109}110111/**112* Compile command signature that looks like java.lang.String::indexOf113*114* @param executable executable used to generate descriptor115* @return MethodDescriptor instance116*/117public static MethodDescriptor logDescriptor(Executable executable) {118MethodDescriptor md = new MethodDescriptor(executable);119md.aClass.setSeparator(Separator.DOT);120md.aMethod.setSeparator(Separator.DOUBLECOLON);121md.aSignature.setSeparator(Separator.NONE);122return md;123}124125/**126* Method descriptor that matches any method. Its full signature is *.*127*128* @param executable executable used to generate descriptor129* @return MethodDescriptor instance130*/131public static MethodDescriptor anyMatchDescriptor(Executable executable) {132MethodDescriptor md = new MethodDescriptor(executable);133Combination<PatternType> patterns = new Combination<>(PatternType.ANY,134PatternType.ANY, PatternType.ANY);135md.aClass.setSeparator(Separator.SLASH);136md.aMethod.setSeparator(Separator.DOT);137md.aSignature.setSeparator(Separator.NONE);138md.setPatterns(patterns);139return md;140}141142/**143* Generates a list of method patterns from the pool of methods144*145* @return a list of test cases146*/147public List<MethodDescriptor> getTests() {148List<MethodDescriptor> list = new ArrayList<>();149METHODS.forEach(pair -> list.addAll(getTests(pair.first)));150return list;151}152153/**154* Generates all combinations of method descriptors for a given executable155*156* @param executable executable for which the different combination is built157* @return list of method descriptors158*/159public List<MethodDescriptor> getTests(Executable executable) {160List<MethodDescriptor> list = new ArrayList<>();161for (Combination<PatternType> patterns : PATTERNS_LIST) {162for (Combination<Separator> separators : SEPARATORS_LIST) {163for (Function<String, String> classGen : ELEMENT_MUTATORS) {164for (Function<String, String> methodGen :165ELEMENT_MUTATORS) {166for (Function<String, String> signatureGen :167ELEMENT_MUTATORS) {168list.add(makeMethodDescriptor(executable,169patterns, separators,170new Combination<>(classGen, methodGen,171signatureGen)));172}173}174}175}176}177return list;178}179180/**181* Creates method descriptor from the given executable,182* patterns and separators for its elements183*/184private MethodDescriptor makeMethodDescriptor(185Executable executable,186Combination<PatternType> patterns,187Combination<Separator> separators,188Combination<Function<String, String>> mutators) {189MethodDescriptor methodDescriptor = new MethodDescriptor(executable);190methodDescriptor.setSeparators(separators);191methodDescriptor.applyMutates(mutators);192methodDescriptor.setPatterns(patterns);193return methodDescriptor;194}195196/**197* Creates a list of functions that change given string198*/199private static List<Function<String, String>> generateMutators() {200List<Function<String, String>> elements = new ArrayList<>();201// Use the input itself202elements.add(input -> input);203// Use half of the input string204elements.add(input -> input.substring(input.length() / 2));205// Add nonexistent element206elements.add(input -> "nonexistent");207// Use left and right angle brackets208elements.add(input -> "<" + input + ">");209// Embed * inside210elements.add(input -> embed(input, "*"));211// ** as a whole element212elements.add(input -> "**");213// Embed JLS-invalid letters214elements.add(input -> embed(input, "@%"));215elements.add(input -> embed(input, "]"));216// Use JLS-invalid letters217elements.add(input -> "-");218elements.add(input -> "+");219elements.add(input -> ")" + input);220elements.add(input -> "{" + input + "}");221// Add valid Java identifier start char222elements.add(input -> "_" + input);223elements.add(input -> "$" + input);224elements.add(input -> "0" + input);225226/* TODO: uncomment this together with the fix for 8140631227// Unicode characters228elements.add(input -> embed(input, "\u0001"));229elements.add(input -> embed(input, "\u007F"));230// Combining character231elements.add(input -> embed(input, "\u0300"));232elements.add(input -> embed(input, "\u0306"));233// Supplementary character234elements.add(input -> new String(Character.toChars(0x1F64C)));235*/236return elements;237}238239/**240* Embeds one string inside another one241*242* @param target target source string243* @param element string to be embedded into target string244* @return result string245*/246private static String embed(String target, String element) {247int mid = target.length() / 2;248String begin = target.substring(0, mid);249String end = target.substring(mid);250return begin + element + end;251}252253/**254* Generates triples from the given enum sets255* for each of the method elements256*257* @param classSet set of allowed elements for class258* @param methodSet set of allowed elements for method259* @param signSet set of allowed elements for signature260* @param <E> type of generated triples261* @return list of triples262*/263private static <E extends Enum<E>> List<Combination<E>> generate(264EnumSet<E> classSet, EnumSet<E> methodSet, EnumSet<E> signSet) {265List<Combination<E>> list = new ArrayList<>();266classSet.forEach(clsElement ->267methodSet.forEach(methodElement ->268signSet.forEach(signElement ->269list.add(new Combination<>(clsElement, methodElement,270signElement))271)272)273);274return list;275}276277private static class Combination<T> extends Triple<T, T, T> {278public Combination(T first, T second, T third) {279super(first, second, third);280}281}282}283284285