1 /*
   2  * Copyright (c) 2018, 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 import java.io.IOException;
  25 import java.io.PrintWriter;
  26 import java.io.StringWriter;
  27 import java.lang.reflect.Field;
  28 import java.lang.reflect.Method;
  29 import java.net.URL;
  30 import java.net.URLClassLoader;
  31 import java.nio.file.FileVisitResult;
  32 import java.nio.file.Files;
  33 import java.nio.file.Path;
  34 import java.nio.file.Paths;
  35 import java.nio.file.SimpleFileVisitor;
  36 import java.nio.file.attribute.BasicFileAttributes;
  37 import java.util.Objects;
  38 import java.util.spi.ToolProvider;
  39 
  40 import static org.testng.Assert.assertEquals;
  41 import static org.testng.Assert.assertNotEquals;
  42 import static org.testng.Assert.assertNotNull;
  43 import static org.testng.Assert.assertTrue;
  44 import static org.testng.Assert.fail;
  45 
  46 public class JextractToolRunner {
  47     private static final ToolProvider JEXTRACT_TOOL = ToolProvider.findFirst("jextract")
  48             .orElseThrow(() ->
  49                     new RuntimeException("jextract tool not found")
  50             );
  51 
  52     private final Path inputDir;
  53     private final Path outputDir;
  54 
  55     protected JextractToolRunner() {
  56         this(null, null);
  57     }
  58 
  59     protected JextractToolRunner(Path input, Path output) {
  60         inputDir = (input != null) ? input :
  61                 Paths.get(System.getProperty("test.src", "."));
  62         outputDir = (output != null) ? output :
  63                 Paths.get(System.getProperty("test.classes", "."));
  64     }
  65 
  66     protected Path getInputFilePath(String fileName) {
  67         return inputDir.resolve(fileName).toAbsolutePath();
  68     }
  69 
  70     protected Path getOutputFilePath(String fileName) {
  71         return outputDir.resolve(fileName).toAbsolutePath();
  72     }
  73 
  74     protected static class JextractResult {
  75         private int exitCode;
  76         private String output;
  77 
  78         JextractResult(int exitCode, String output) {
  79             this.exitCode = exitCode;
  80             this.output = output;
  81         }
  82 
  83         protected JextractResult checkSuccess() {
  84             assertEquals(exitCode, 0, "Sucess excepted, failed: " + exitCode);
  85             return this;
  86         }
  87 
  88         protected JextractResult checkFailure() {
  89             assertNotEquals(exitCode, 0, "Failure excepted, succeeded!");
  90             return this;
  91         }
  92 
  93         protected JextractResult checkContainsOutput(String expected) {
  94             Objects.requireNonNull(expected);
  95             assertTrue(output.contains(expected), "Output does not contain string: " + expected);
  96             return this;
  97         }
  98 
  99         protected JextractResult checkMatchesOutput(String regex) {
 100             Objects.requireNonNull(regex);
 101             assertTrue(output.trim().matches(regex), "Output does not match regex: " + regex);
 102             return this;
 103         }
 104     }
 105 
 106     protected static JextractResult run(String... options) {
 107         StringWriter writer = new StringWriter();
 108         PrintWriter pw = new PrintWriter(writer);
 109         String[] args = new String[options.length + 1];
 110         System.arraycopy(options, 0, args, 1, options.length);
 111         args[0] = "-C-nostdinc";
 112         int result = JEXTRACT_TOOL.run(pw, pw, options);
 113         String output = writer.toString();
 114         System.err.println(output);
 115         return new JextractResult(result, output);
 116     }
 117 
 118     protected static void deleteFile(Path path) {
 119         try {
 120             Files.deleteIfExists(path);
 121         } catch (IOException ioExp) {
 122             throw new RuntimeException(ioExp);
 123         }
 124     }
 125 
 126     protected static void deleteDir(Path path) {
 127         try {
 128             Files.walkFileTree(path, new SimpleFileVisitor<>() {
 129                 @Override
 130                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
 131                     deleteFile(file);
 132                     return FileVisitResult.CONTINUE;
 133                 }
 134 
 135                 @Override
 136                 public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
 137                     deleteFile(dir);
 138                     return FileVisitResult.CONTINUE;
 139                 }
 140             });
 141         } catch (IOException ioExp) {
 142             throw new RuntimeException(ioExp);
 143         }
 144     }
 145 
 146     protected static Loader classLoader(Path... paths) {
 147         try {
 148             URL[] urls = new URL[paths.length];
 149             for (int i = 0; i < paths.length; i++) {
 150                 urls[i] = paths[i].toUri().toURL();
 151             }
 152             URLClassLoader ucl = new URLClassLoader(urls, null);
 153             return new Loader(ucl);
 154         } catch (RuntimeException re) {
 155             throw re;
 156         } catch (Exception e) {
 157             throw new RuntimeException(e);
 158         }
 159     }
 160 
 161     protected static Field findField(Class<?> cls, String name) {
 162         try {
 163             return cls.getField(name);
 164         } catch (Exception e) {
 165             System.err.println(e);
 166             return null;
 167         }
 168     }
 169 
 170     protected static Method findMethod(Class<?> cls, String name, Class<?>... argTypes) {
 171         try {
 172             return cls.getMethod(name, argTypes);
 173         } catch (Exception e) {
 174             System.err.println(e);
 175             return null;
 176         }
 177     }
 178 
 179     protected static Method findStructFieldGet(Class<?> cls, String name) {
 180         return findMethod(cls, name + "$get");
 181     }
 182 
 183     protected static Method findGlobalVariableGet(Class<?> cls, String name) {
 184         return findMethod(cls, name + "$get");
 185     }
 186 
 187     protected static Method findEnumConstGet(Class<?> cls, String name) {
 188         return findMethod(cls, name);
 189     }
 190 
 191     protected static Method findFirstMethod(Class<?> cls, String name) {
 192         try {
 193             for (Method m : cls.getMethods()) {
 194                 if (name.equals(m.getName())) {
 195                     return m;
 196                 }
 197             }
 198             return null;
 199         } catch (Exception e) {
 200             System.err.println(e);
 201             return null;
 202         }
 203     }
 204 
 205     protected Field checkIntField(Class<?> cls, String name, int value) {
 206         Field field = findField(cls, name);
 207         assertNotNull(field);
 208         assertEquals(field.getType(), int.class);
 209         try {
 210             assertEquals((int)field.get(null), value);
 211         } catch (Exception exp) {
 212             System.err.println(exp);
 213             assertTrue(false, "should not reach here");
 214         }
 215         return field;
 216     }
 217 
 218     protected Class<?> findClass(Class<?>[] clz, String name) {
 219         for (Class<?> cls: clz) {
 220             if (cls.getSimpleName().equals(name)) {
 221                 return cls;
 222             }
 223         }
 224         return null;
 225     }
 226 
 227     protected Method checkMethod(Class<?> cls, String name, Class<?> returnType, Class<?>... args) {
 228         try {
 229             Method m = cls.getDeclaredMethod(name, args);
 230             assertTrue(m.getReturnType() == returnType);
 231             return m;
 232         } catch (NoSuchMethodException nsme) {
 233             fail("Expect method " + name);
 234         }
 235         return null;
 236     }
 237 
 238     protected static class Loader implements AutoCloseable {
 239 
 240         private final URLClassLoader loader;
 241 
 242         public Loader(URLClassLoader loader) {
 243             this.loader = loader;
 244         }
 245 
 246         public Class<?> loadClass(String className) {
 247             try {
 248                 return Class.forName(className, false, loader);
 249             } catch (ClassNotFoundException e) {
 250                 // return null so caller can check if class loading
 251                 // was successful with assertNotNull/assertNull
 252                 return null;
 253             }
 254         }
 255 
 256         @Override
 257         public void close() {
 258             try {
 259                 loader.close();
 260             } catch (IOException e) {
 261                 throw new RuntimeException(e);
 262             }
 263         }
 264     }
 265 }