1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/tools/javah/compareTest/CompareTest.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,265 @@ 1.4 +/* 1.5 + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + */ 1.26 + 1.27 +import java.io.DataInputStream; 1.28 +import java.io.File; 1.29 +import java.io.IOException; 1.30 +import java.io.InputStream; 1.31 +import java.io.PrintWriter; 1.32 +import java.io.StringWriter; 1.33 +import java.util.ArrayList; 1.34 +import java.util.Arrays; 1.35 +import java.util.Enumeration; 1.36 +import java.util.List; 1.37 +import java.util.Set; 1.38 +import java.util.TreeSet; 1.39 +import java.util.jar.JarEntry; 1.40 +import java.util.jar.JarFile; 1.41 + 1.42 +import com.sun.tools.classfile.AccessFlags; 1.43 +import com.sun.tools.classfile.ClassFile; 1.44 +import com.sun.tools.classfile.ConstantPoolException; 1.45 +import com.sun.tools.classfile.Method; 1.46 +import java.io.BufferedReader; 1.47 +import java.io.FileInputStream; 1.48 +import java.io.InputStreamReader; 1.49 +import java.util.LinkedHashSet; 1.50 + 1.51 +public class CompareTest { 1.52 + String[][] testCases = { 1.53 + { }, 1.54 + { "-jni" }, 1.55 +// { "-llni" }, 1.56 + }; 1.57 + 1.58 + public static void main(String... args) throws Exception { 1.59 + new CompareTest().run(args); 1.60 + } 1.61 + 1.62 + public void run(String... args) throws Exception { 1.63 + old_javah_cmd = new File(args[0]); 1.64 + rt_jar = new File(args[1]); 1.65 + 1.66 + Set<String> testClasses; 1.67 + if (args.length > 2) { 1.68 + testClasses = new LinkedHashSet<String>(Arrays.asList(Arrays.copyOfRange(args, 2, args.length))); 1.69 + } else 1.70 + testClasses = getNativeClasses(new JarFile(rt_jar)); 1.71 + 1.72 + for (String[] options: testCases) { 1.73 + for (String name: testClasses) { 1.74 + test(Arrays.asList(options), rt_jar, name); 1.75 + } 1.76 + } 1.77 + 1.78 + if (errors == 0) 1.79 + System.out.println(count + " tests passed"); 1.80 + else 1.81 + throw new Exception(errors + "/" + count + " tests failed"); 1.82 + } 1.83 + 1.84 + public void test(List<String> options, File bootclasspath, String className) 1.85 + throws IOException, InterruptedException { 1.86 + System.err.println("test: " + options + " " + className); 1.87 + count++; 1.88 + 1.89 + testOptions = options; 1.90 + testClassName = className; 1.91 + 1.92 + File oldOutDir = initDir(file(new File("old"), className)); 1.93 + int old_rc = old_javah(options, oldOutDir, bootclasspath, className); 1.94 + 1.95 + File newOutDir = initDir(file(new File("new"), className)); 1.96 + int new_rc = new_javah(options, newOutDir, bootclasspath, className); 1.97 + 1.98 + if (old_rc != new_rc) 1.99 + error("return codes differ; old: " + old_rc + ", new: " + new_rc); 1.100 + 1.101 + compare(oldOutDir, newOutDir); 1.102 + } 1.103 + 1.104 + int old_javah(List<String> options, File outDir, File bootclasspath, String className) 1.105 + throws IOException, InterruptedException { 1.106 + List<String> cmd = new ArrayList<String>(); 1.107 + cmd.add(old_javah_cmd.getPath()); 1.108 + cmd.addAll(options); 1.109 + cmd.add("-d"); 1.110 + cmd.add(outDir.getPath()); 1.111 + cmd.add("-bootclasspath"); 1.112 + cmd.add(bootclasspath.getPath()); 1.113 + cmd.add(className); 1.114 + System.err.println("old_javah: " + cmd); 1.115 + ProcessBuilder pb = new ProcessBuilder(cmd); 1.116 + pb.redirectErrorStream(true); 1.117 + Process p = pb.start(); 1.118 + BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); 1.119 + String line; 1.120 + StringBuilder sb = new StringBuilder(); 1.121 + while ((line = in.readLine()) != null) { 1.122 + sb.append(line); 1.123 + sb.append("\n"); 1.124 + } 1.125 + System.err.println("old javah out: " + sb.toString()); 1.126 + return p.waitFor(); 1.127 + } 1.128 + 1.129 + int new_javah(List<String> options, File outDir, File bootclasspath, String className) { 1.130 + List<String> args = new ArrayList<String>(); 1.131 + args.addAll(options); 1.132 + args.add("-d"); 1.133 + args.add(outDir.getPath()); 1.134 + args.add("-bootclasspath"); 1.135 + args.add(bootclasspath.getPath()); 1.136 + args.add(className); 1.137 + StringWriter sw = new StringWriter(); 1.138 + PrintWriter pw = new PrintWriter(sw); 1.139 + int rc = com.sun.tools.javah.Main.run(args.toArray(new String[args.size()]), pw); 1.140 + pw.close(); 1.141 + System.err.println("new javah out: " + sw.toString()); 1.142 + return rc; 1.143 + } 1.144 + 1.145 + Set<String> getNativeClasses(JarFile jar) throws IOException, ConstantPoolException { 1.146 + System.err.println("getNativeClasses: " + jar.getName()); 1.147 + Set<String> results = new TreeSet<String>(); 1.148 + Enumeration<JarEntry> e = jar.entries(); 1.149 + while (e.hasMoreElements()) { 1.150 + JarEntry je = e.nextElement(); 1.151 + if (isNativeClass(jar, je)) { 1.152 + String name = je.getName(); 1.153 + results.add(name.substring(0, name.length() - 6).replace("/", ".")); 1.154 + } 1.155 + } 1.156 + return results; 1.157 + } 1.158 + 1.159 + boolean isNativeClass(JarFile jar, JarEntry entry) throws IOException, ConstantPoolException { 1.160 + String name = entry.getName(); 1.161 + if (name.startsWith("META-INF") || !name.endsWith(".class")) 1.162 + return false; 1.163 + //String className = name.substring(0, name.length() - 6).replace("/", "."); 1.164 + //System.err.println("check " + className); 1.165 + InputStream in = jar.getInputStream(entry); 1.166 + ClassFile cf = ClassFile.read(in); 1.167 + for (int i = 0; i < cf.methods.length; i++) { 1.168 + Method m = cf.methods[i]; 1.169 + if (m.access_flags.is(AccessFlags.ACC_NATIVE)) { 1.170 + // System.err.println(className); 1.171 + return true; 1.172 + } 1.173 + } 1.174 + return false; 1.175 + } 1.176 + 1.177 + void compare(File f1, File f2) throws IOException { 1.178 + if (f1.isFile() && f2.isFile()) 1.179 + compareFiles(f1, f2); 1.180 + else if (f1.isDirectory() && f2.isDirectory()) 1.181 + compareDirectories(f1, f2); 1.182 + else 1.183 + error("files differ: " 1.184 + + f1 + " (" + getFileType(f1) + "), " 1.185 + + f2 + " (" + getFileType(f2) + ")"); 1.186 + } 1.187 + 1.188 + void compareDirectories(File d1, File d2) throws IOException { 1.189 + Set<String> list = new TreeSet<String>(); 1.190 + list.addAll(Arrays.asList(d1.list())); 1.191 + list.addAll(Arrays.asList(d2.list())); 1.192 + for (String c: list) 1.193 + compare(new File(d1, c), new File(d2, c)); 1.194 + } 1.195 + 1.196 + void compareFiles(File f1, File f2) throws IOException { 1.197 + byte[] c1 = readFile(f1); 1.198 + byte[] c2 = readFile(f2); 1.199 + if (!Arrays.equals(c1, c2)) 1.200 + error("files differ: " + f1 + ", " + f2); 1.201 + } 1.202 + 1.203 + byte[] readFile(File file) throws IOException { 1.204 + int size = (int) file.length(); 1.205 + byte[] data = new byte[size]; 1.206 + DataInputStream in = new DataInputStream(new FileInputStream(file)); 1.207 + try { 1.208 + in.readFully(data); 1.209 + } finally { 1.210 + in.close(); 1.211 + } 1.212 + return data; 1.213 + } 1.214 + 1.215 + String getFileType(File f) { 1.216 + return f.isDirectory() ? "directory" 1.217 + : f.isFile() ? "file" 1.218 + : f.exists() ? "other" 1.219 + : "not found"; 1.220 + } 1.221 + 1.222 + /** 1.223 + * Set up an empty directory. 1.224 + */ 1.225 + public File initDir(File dir) { 1.226 + if (dir.exists()) 1.227 + deleteAll(dir); 1.228 + dir.mkdirs(); 1.229 + return dir; 1.230 + } 1.231 + 1.232 + /** 1.233 + * Delete a file or a directory (including all its contents). 1.234 + */ 1.235 + boolean deleteAll(File file) { 1.236 + if (file.isDirectory()) { 1.237 + for (File f: file.listFiles()) 1.238 + deleteAll(f); 1.239 + } 1.240 + return file.delete(); 1.241 + } 1.242 + 1.243 + File file(File dir, String... path) { 1.244 + File f = dir; 1.245 + for (String p: path) 1.246 + f = new File(f, p); 1.247 + return f; 1.248 + } 1.249 + 1.250 + /** 1.251 + * Report an error. 1.252 + */ 1.253 + void error(String msg, String... more) { 1.254 + System.err.println("test: " + testOptions + " " + testClassName); 1.255 + System.err.println("error: " + msg); 1.256 + for (String s: more) 1.257 + System.err.println(s); 1.258 + errors++; 1.259 + System.exit(1); 1.260 + } 1.261 + 1.262 + File old_javah_cmd; 1.263 + File rt_jar; 1.264 + List<String> testOptions; 1.265 + String testClassName; 1.266 + int count; 1.267 + int errors; 1.268 +}