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(" %13s | %8s | %8s | %8s |%n", "start time", "count", "generat",
 114                 "running");
 115         System.out.printf(" %13s | %8s | %8s | %8s |%n", "---", "---", "---", "---");
 116         List<TestsGenerator> generators = getTestGenerators();
 117         do {
 118             double start = System.currentTimeMillis();
 119             System.out.print("[" + LocalTime.now() + "] |");
 120             String name = "Test_" + counter;
 121             Pair<IRNode, IRNode> irTree = generateIRTree(name);
 122             System.out.printf(" %8d |", counter);
 123             long maxWaitTime = TimeUnit.MINUTES.toMillis(MINUTES_TO_WAIT);
 124             double generationTime = System.currentTimeMillis() - start;
 125             System.out.printf(" %8.0f |", generationTime);
 126             start = System.currentTimeMillis();
 127             Thread generatorThread = new Thread(() -> {
 128                 for (TestsGenerator generator : generators) {
 129                         generator.accept(irTree.first, irTree.second);
 130                 }
 131             });
 132             generatorThread.start();
 133             try {
 134                 generatorThread.join(maxWaitTime);
 135             } catch (InterruptedException ie) {
 136                 throw new Error("Test generation interrupted: " + ie, ie);
 137             }
 138             if (generatorThread.isAlive()) {
 139                 // maxTime reached, so, proceed to next test generation
 140                 generatorThread.interrupt();
 141             } else {
 142                 double runningTime = System.currentTimeMillis() - start;
 143                 System.out.printf(" %8.0f |%n", runningTime);
 144                 if (runningTime < maxWaitTime) {
 145                     ++counter;
 146                 }
 147             }
 148         } while (counter < ProductionParams.numberOfTests.value());
 149     }
 150 }