langtools/test/tools/javah/compareTest/CompareTest.java
changeset 27579 d1a63c99cdd5
parent 27578 d61af14a5cf7
child 27580 ca12cdda0551
equal deleted inserted replaced
27578:d61af14a5cf7 27579:d1a63c99cdd5
     1 /*
       
     2  * Copyright (c) 2009, 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.DataInputStream;
       
    25 import java.io.File;
       
    26 import java.io.IOException;
       
    27 import java.io.InputStream;
       
    28 import java.io.PrintWriter;
       
    29 import java.io.StringWriter;
       
    30 import java.util.ArrayList;
       
    31 import java.util.Arrays;
       
    32 import java.util.Enumeration;
       
    33 import java.util.List;
       
    34 import java.util.Set;
       
    35 import java.util.TreeSet;
       
    36 import java.util.jar.JarEntry;
       
    37 import java.util.jar.JarFile;
       
    38 
       
    39 import com.sun.tools.classfile.AccessFlags;
       
    40 import com.sun.tools.classfile.ClassFile;
       
    41 import com.sun.tools.classfile.ConstantPoolException;
       
    42 import com.sun.tools.classfile.Method;
       
    43 import java.io.BufferedReader;
       
    44 import java.io.FileInputStream;
       
    45 import java.io.InputStreamReader;
       
    46 import java.util.LinkedHashSet;
       
    47 
       
    48 public class CompareTest {
       
    49     String[][] testCases = {
       
    50         { },
       
    51         { "-jni" },
       
    52 //        { "-llni" },
       
    53     };
       
    54 
       
    55     public static void main(String... args) throws Exception {
       
    56         new CompareTest().run(args);
       
    57     }
       
    58 
       
    59     public void run(String... args) throws Exception {
       
    60         old_javah_cmd = new File(args[0]);
       
    61         rt_jar = new File(args[1]);
       
    62 
       
    63         Set<String> testClasses;
       
    64         if (args.length > 2) {
       
    65             testClasses = new LinkedHashSet<String>(Arrays.asList(Arrays.copyOfRange(args, 2, args.length)));
       
    66         } else
       
    67             testClasses = getNativeClasses(new JarFile(rt_jar));
       
    68 
       
    69         for (String[] options: testCases) {
       
    70             for (String name: testClasses) {
       
    71                 test(Arrays.asList(options), rt_jar, name);
       
    72             }
       
    73         }
       
    74 
       
    75         if (errors == 0)
       
    76             System.out.println(count + " tests passed");
       
    77         else
       
    78             throw new Exception(errors + "/" + count + " tests failed");
       
    79     }
       
    80 
       
    81     public void test(List<String> options, File bootclasspath, String className)
       
    82             throws IOException, InterruptedException {
       
    83         System.err.println("test: " + options + " " + className);
       
    84         count++;
       
    85 
       
    86         testOptions = options;
       
    87         testClassName = className;
       
    88 
       
    89         File oldOutDir = initDir(file(new File("old"), className));
       
    90         int old_rc = old_javah(options, oldOutDir, bootclasspath, className);
       
    91 
       
    92         File newOutDir = initDir(file(new File("new"), className));
       
    93         int new_rc = new_javah(options, newOutDir, bootclasspath, className);
       
    94 
       
    95         if (old_rc != new_rc)
       
    96             error("return codes differ; old: " + old_rc + ", new: " + new_rc);
       
    97 
       
    98         compare(oldOutDir, newOutDir);
       
    99     }
       
   100 
       
   101     int old_javah(List<String> options, File outDir, File bootclasspath, String className)
       
   102             throws IOException, InterruptedException {
       
   103         List<String> cmd = new ArrayList<String>();
       
   104         cmd.add(old_javah_cmd.getPath());
       
   105         cmd.addAll(options);
       
   106         cmd.add("-d");
       
   107         cmd.add(outDir.getPath());
       
   108         cmd.add("-bootclasspath");
       
   109         cmd.add(bootclasspath.getPath());
       
   110         cmd.add(className);
       
   111         System.err.println("old_javah: " + cmd);
       
   112         ProcessBuilder pb = new ProcessBuilder(cmd);
       
   113         pb.redirectErrorStream(true);
       
   114         Process p = pb.start();
       
   115         BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
       
   116         String line;
       
   117         StringBuilder sb = new StringBuilder();
       
   118         while ((line = in.readLine()) != null) {
       
   119             sb.append(line);
       
   120             sb.append("\n");
       
   121         }
       
   122         System.err.println("old javah out: " + sb.toString());
       
   123         return p.waitFor();
       
   124     }
       
   125 
       
   126     int new_javah(List<String> options, File outDir, File bootclasspath, String className) {
       
   127         List<String> args = new ArrayList<String>();
       
   128         args.addAll(options);
       
   129         args.add("-d");
       
   130         args.add(outDir.getPath());
       
   131         args.add("-bootclasspath");
       
   132         args.add(bootclasspath.getPath());
       
   133         args.add(className);
       
   134         StringWriter sw = new StringWriter();
       
   135         PrintWriter pw = new PrintWriter(sw);
       
   136         int rc = com.sun.tools.javah.Main.run(args.toArray(new String[args.size()]), pw);
       
   137         pw.close();
       
   138         System.err.println("new javah out: " + sw.toString());
       
   139         return rc;
       
   140     }
       
   141 
       
   142     Set<String> getNativeClasses(JarFile jar) throws IOException, ConstantPoolException {
       
   143         System.err.println("getNativeClasses: " + jar.getName());
       
   144         Set<String> results = new TreeSet<String>();
       
   145         Enumeration<JarEntry> e = jar.entries();
       
   146         while (e.hasMoreElements()) {
       
   147             JarEntry je = e.nextElement();
       
   148             if (isNativeClass(jar, je)) {
       
   149                 String name = je.getName();
       
   150                 results.add(name.substring(0, name.length() - 6).replace("/", "."));
       
   151             }
       
   152         }
       
   153         return results;
       
   154     }
       
   155 
       
   156     boolean isNativeClass(JarFile jar, JarEntry entry) throws IOException, ConstantPoolException {
       
   157         String name = entry.getName();
       
   158         if (name.startsWith("META-INF") || !name.endsWith(".class"))
       
   159             return false;
       
   160         //String className = name.substring(0, name.length() - 6).replace("/", ".");
       
   161         //System.err.println("check " + className);
       
   162         InputStream in = jar.getInputStream(entry);
       
   163         ClassFile cf = ClassFile.read(in);
       
   164         for (int i = 0; i < cf.methods.length; i++) {
       
   165             Method m = cf.methods[i];
       
   166             if (m.access_flags.is(AccessFlags.ACC_NATIVE)) {
       
   167                 // System.err.println(className);
       
   168                 return true;
       
   169             }
       
   170         }
       
   171         return false;
       
   172     }
       
   173 
       
   174     void compare(File f1, File f2) throws IOException {
       
   175         if (f1.isFile() && f2.isFile())
       
   176             compareFiles(f1, f2);
       
   177         else if (f1.isDirectory() && f2.isDirectory())
       
   178             compareDirectories(f1, f2);
       
   179         else
       
   180             error("files differ: "
       
   181                 + f1 + " (" + getFileType(f1) + "), "
       
   182                 + f2 + " (" + getFileType(f2) + ")");
       
   183     }
       
   184 
       
   185     void compareDirectories(File d1, File d2) throws IOException {
       
   186         Set<String> list = new TreeSet<String>();
       
   187         list.addAll(Arrays.asList(d1.list()));
       
   188         list.addAll(Arrays.asList(d2.list()));
       
   189         for (String c: list)
       
   190             compare(new File(d1, c), new File(d2, c));
       
   191     }
       
   192 
       
   193     void compareFiles(File f1, File f2) throws IOException {
       
   194         byte[] c1 = readFile(f1);
       
   195         byte[] c2 = readFile(f2);
       
   196         if (!Arrays.equals(c1, c2))
       
   197             error("files differ: " + f1 + ", " + f2);
       
   198     }
       
   199 
       
   200     byte[] readFile(File file) throws IOException {
       
   201         int size = (int) file.length();
       
   202         byte[] data = new byte[size];
       
   203         DataInputStream in = new DataInputStream(new FileInputStream(file));
       
   204         try {
       
   205             in.readFully(data);
       
   206         } finally {
       
   207             in.close();
       
   208         }
       
   209         return data;
       
   210     }
       
   211 
       
   212     String getFileType(File f) {
       
   213         return f.isDirectory() ? "directory"
       
   214                 : f.isFile() ? "file"
       
   215                 : f.exists() ? "other"
       
   216                 : "not found";
       
   217     }
       
   218 
       
   219     /**
       
   220      * Set up an empty directory.
       
   221      */
       
   222     public File initDir(File dir) {
       
   223         if (dir.exists())
       
   224             deleteAll(dir);
       
   225         dir.mkdirs();
       
   226         return dir;
       
   227     }
       
   228 
       
   229     /**
       
   230      * Delete a file or a directory (including all its contents).
       
   231      */
       
   232     boolean deleteAll(File file) {
       
   233         if (file.isDirectory()) {
       
   234             for (File f: file.listFiles())
       
   235                 deleteAll(f);
       
   236         }
       
   237         return file.delete();
       
   238     }
       
   239 
       
   240     File file(File dir, String... path) {
       
   241         File f = dir;
       
   242         for (String p: path)
       
   243             f = new File(f, p);
       
   244         return f;
       
   245     }
       
   246 
       
   247     /**
       
   248      * Report an error.
       
   249      */
       
   250     void error(String msg, String... more) {
       
   251         System.err.println("test: " + testOptions + " " + testClassName);
       
   252         System.err.println("error: " + msg);
       
   253         for (String s: more)
       
   254             System.err.println(s);
       
   255         errors++;
       
   256         System.exit(1);
       
   257     }
       
   258 
       
   259     File old_javah_cmd;
       
   260     File rt_jar;
       
   261     List<String> testOptions;
       
   262     String testClassName;
       
   263     int count;
       
   264     int errors;
       
   265 }