1 /* 2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package jdk.test.lib.jittester; 25 26 import jdk.test.lib.util.Pair; 27 import jdk.test.lib.jittester.factories.IRNodeBuilder; 28 import jdk.test.lib.jittester.types.TypeKlass; 29 import jdk.test.lib.jittester.utils.FixedTrees; 30 import jdk.test.lib.jittester.utils.OptionResolver; 31 import jdk.test.lib.jittester.utils.OptionResolver.Option; 32 import jdk.test.lib.jittester.utils.PseudoRandom; 33 import java.time.LocalTime; 34 import java.util.ArrayList; 35 import java.util.List; 36 import java.util.concurrent.TimeUnit; 37 import java.util.function.Function; 38 39 public class Automatic { 40 public static final int MINUTES_TO_WAIT = Integer.getInteger("jdk.test.lib.jittester", 3); 41 42 private static Pair<IRNode, IRNode> generateIRTree(String name) { 43 SymbolTable.removeAll(); 44 TypeList.removeAll(); 45 46 IRNodeBuilder builder = new IRNodeBuilder() 47 .setPrefix(name) 48 .setName(name) 49 .setLevel(0); 50 51 Long complexityLimit = ProductionParams.complexityLimit.value(); 52 IRNode privateClasses = null; 53 if (!ProductionParams.disableClasses.value()) { 54 long privateClassComlexity = (long) (complexityLimit * PseudoRandom.random()); 55 try { 56 privateClasses = builder.setComplexityLimit(privateClassComlexity) 57 .getClassDefinitionBlockFactory() 58 .produce(); 59 } catch (ProductionFailedException ex) { 60 ex.printStackTrace(System.out); 61 } 62 } 63 long mainClassComplexity = (long) (complexityLimit * PseudoRandom.random()); 64 IRNode mainClass = null; 65 try { 66 mainClass = builder.setComplexityLimit(mainClassComplexity) 67 .getMainKlassFactory() 68 .produce(); 69 TypeKlass aClass = new TypeKlass(name); 70 mainClass.getChild(1).addChild(FixedTrees.generateMainOrExecuteMethod(aClass, true)); 71 mainClass.getChild(1).addChild(FixedTrees.generateMainOrExecuteMethod(aClass, false)); 72 } catch (ProductionFailedException ex) { 73 ex.printStackTrace(System.out); 74 } 75 return new Pair<>(mainClass, privateClasses); 76 } 77 78 private static void initializeTestGenerator(String[] params) { 79 OptionResolver parser = new OptionResolver(); 80 Option<String> propertyFileOpt = parser.addStringOption('p', "property-file", 81 "conf/default.properties", "File to read properties from"); 82 ProductionParams.register(parser); 83 parser.parse(params, propertyFileOpt); 84 PseudoRandom.reset(ProductionParams.seed.value()); 85 TypesParser.parseTypesAndMethods(ProductionParams.classesFile.value(), 86 ProductionParams.excludeMethodsFile.value()); 87 if (ProductionParams.specificSeed.isSet()) { 88 PseudoRandom.setCurrentSeed(ProductionParams.specificSeed.value()); 89 } 90 } 91 92 private static List<TestsGenerator> getTestGenerators() { 93 List<TestsGenerator> result = new ArrayList<>(); 94 Class<?> factoryClass; 95 Function<String[], List<TestsGenerator>> factory; 96 String[] factoryClassNames = ProductionParams.generatorsFactories.value().split(","); 97 String[] generatorNames = ProductionParams.generators.value().split(","); 98 for (String factoryClassName : factoryClassNames) { 99 try { 100 factoryClass = Class.forName(factoryClassName); 101 factory = (Function<String[], List<TestsGenerator>>) factoryClass.newInstance(); 102 } catch (ReflectiveOperationException roe) { 103 throw new Error("Can't instantiate generators factory", roe); 104 } 105 result.addAll(factory.apply(generatorNames)); 106 } 107 return result; 108 } 109 110 public static void main(String[] args) { 111 initializeTestGenerator(args); 112 int counter = 0; 113 System.out.printf("Generating %d tests...%n", ProductionParams.numberOfTests.value()); 114 System.out.printf(" %13s | %8s | %8s | %8s |%n", "start time", "count", "generat", 115 "running"); 116 System.out.printf(" %13s | %8s | %8s | %8s |%n", "---", "---", "---", "---"); 117 List<TestsGenerator> generators = getTestGenerators(); 118 do { 119 double start = System.currentTimeMillis(); 120 System.out.print("[" + LocalTime.now() + "] |"); 121 String name = "Test_" + counter; 122 Pair<IRNode, IRNode> irTree = generateIRTree(name); 123 System.out.printf(" %8d |", counter); 124 long maxWaitTime = TimeUnit.MINUTES.toMillis(MINUTES_TO_WAIT); 125 double generationTime = System.currentTimeMillis() - start; 126 System.out.printf(" %8.0f |", generationTime); 127 start = System.currentTimeMillis(); 128 Thread generatorThread = new Thread(() -> { 129 for (TestsGenerator generator : generators) { 130 generator.accept(irTree.first, irTree.second); 131 } 132 }); 133 generatorThread.start(); 134 try { 135 generatorThread.join(maxWaitTime); 136 } catch (InterruptedException ie) { 137 throw new Error("Test generation interrupted: " + ie, ie); 138 } 139 if (generatorThread.isAlive()) { 140 // maxTime reached, so, proceed to next test generation 141 generatorThread.interrupt(); 142 } else { 143 double runningTime = System.currentTimeMillis() - start; 144 System.out.printf(" %8.0f |%n", runningTime); 145 if (runningTime < maxWaitTime) { 146 ++counter; 147 } 148 } 149 } while (counter < ProductionParams.numberOfTests.value()); 150 } 151 }