1 /*
   2  * Copyright (c) 2009, 2019, 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 
  25 package shared;
  26 
  27 import java.io.File;
  28 import java.io.FileOutputStream;
  29 import java.util.Arrays;
  30 import java.util.Map;
  31 import java.util.List;
  32 import java.util.ArrayList;
  33 
  34 /**
  35  *
  36  */
  37 public abstract class AbstractGenerator {
  38     protected final boolean dumpClasses;
  39     protected final boolean executeTests;
  40     private static int testNum = 0;
  41 
  42     protected AbstractGenerator(String[] args) {
  43         List<String> params = new ArrayList<String>(Arrays.asList(args));
  44 
  45         if (params.contains("--help")) {
  46             Utils.printHelp();
  47             System.exit(0);
  48         }
  49 
  50         dumpClasses = params.contains("--dump");
  51         executeTests = !params.contains("--noexecute");
  52 
  53         params.remove("--dump");
  54         params.remove("--noexecute");
  55 
  56         Utils.init(params);
  57     }
  58 
  59     /*******************************************************************/
  60     public static void writeToFile(File dir, Map<String, byte[]> classes) {
  61         for (String name : classes.keySet()) {
  62             try {
  63                 writeToFile(dir, name, classes.get(name));
  64             } catch (Exception e) {
  65                 throw new RuntimeException(e);
  66             }
  67         }
  68     }
  69 
  70     /*******************************************************************/
  71     public static void writeToFile(File dir, String fullName, byte[] classBytecode) {
  72         if (!dir.isDirectory()) {
  73             throw new RuntimeException("Invalid parameter: dir doesn't point to an existing directory");
  74         }
  75 
  76         File classFile =
  77             new File(
  78                     dir.getPath() + File.separator
  79                     + fullName.replaceAll("\\.", File.separator)
  80                     + ".class"
  81                     );
  82 
  83         classFile.getParentFile().mkdirs();
  84 
  85         try {
  86             FileOutputStream fos = new FileOutputStream(classFile);
  87             try {
  88                 fos.write(classBytecode);
  89             } finally {
  90                 fos.close();
  91             }
  92         } catch (Exception e) {
  93             throw new RuntimeException(e);
  94         }
  95     }
  96 
  97     protected boolean exec(Map<String, byte[]> classes, String description, String calleeClassName, String classNameC, String[] callSites) throws ClassNotFoundException {
  98         boolean isPassed = true;
  99 
 100         testNum++;
 101 
 102         String caseDescription = String.format("%4d| %s", testNum, description);
 103 
 104         // Create test executor for a single case
 105         classes.put(
 106                 ExecutorGenerator.className
 107                 , new ExecutorGenerator(
 108                         caseDescription
 109                         , calleeClassName
 110                         , classNameC
 111                     ).generateExecutor(callSites)
 112         );
 113 
 114         // Dump generated set to disk, if needed
 115         if (dumpClasses) {
 116             File dir = new File("classes" + File.separator + String.format("%04d", testNum));
 117             dir.mkdirs();
 118             writeToFile(dir, classes);
 119         }
 120 
 121         ByteArrayClassLoader loader = new ByteArrayClassLoader(classes);
 122 
 123         Class paramClass;
 124         Class targetClass;
 125         Checker checker;
 126 
 127         try {
 128             paramClass = loader.loadClass(calleeClassName);
 129             targetClass = loader.loadClass(classNameC);
 130 
 131             checker = getChecker(paramClass, targetClass);
 132         } catch (Throwable e) {
 133             String result = Checker.abbreviateResult(e.getClass().getName());
 134 
 135             System.out.printf(caseDescription);
 136 
 137             for (String site : callSites) {
 138                 System.out.printf(" %7s", result);
 139             }
 140 
 141             System.out.println("");
 142 
 143             return true;
 144         }
 145 
 146         if (executeTests) {
 147             // Check runtime behavior
 148             Caller caller = new Caller(loader, checker, paramClass, targetClass);
 149             boolean printedCaseDes = false;
 150             for (String site : callSites) {
 151                 String callResult = caller.call(site);
 152 
 153                 if (!caller.isPassed()) {
 154                     isPassed = false;
 155                     if (!printedCaseDes) {
 156                         System.out.printf(caseDescription);
 157                         printedCaseDes = true;
 158                     }
 159                     System.out.printf(" %7s", callResult);
 160                 }
 161             }
 162             if (!caller.isPassed()) {
 163                 System.out.println(" |   FAILED");
 164             }
 165         } else {
 166             for (String site : callSites) {
 167                 String result = checker.check(loader.loadClass(site));
 168                 System.out.printf(" %7s", Checker.abbreviateResult(result));
 169             }
 170         }
 171 
 172         return isPassed;
 173     }
 174 
 175     protected abstract Checker getChecker(Class paramClass, Class targetClass);
 176 }