1 /*
   2  * Copyright (c) 2007, 2015, 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  * @test
  26  * @bug 7150368 8003412 8000407 8031545
  27  * @summary javac should include basic ability to generate native headers
  28  * @modules jdk.compiler
  29  */
  30 
  31 import java.io.File;
  32 import java.io.IOException;
  33 import java.io.PrintWriter;
  34 import java.nio.file.Files;
  35 import java.util.ArrayList;
  36 import java.util.Arrays;
  37 import java.util.HashSet;
  38 import java.util.List;
  39 import java.util.Set;
  40 
  41 public class CompareTest {
  42     public static void main(String... args) throws Exception {
  43         new CompareTest().run();
  44     }
  45 
  46     void run() throws Exception {
  47         File srcDir = new File(System.getProperty("test.src"));
  48         File classesDir = new File("classes");
  49         classesDir.mkdirs();
  50         File javacHeaders = new File("headers.javac");
  51         javacHeaders.mkdirs();
  52         File javahHeaders = new File("headers.javah");
  53         javahHeaders.mkdirs();
  54 
  55         List<String> javacArgs = new ArrayList<String>();
  56         javacArgs.add("-d");
  57         javacArgs.add(classesDir.getPath());
  58         javacArgs.add("-h");
  59         javacArgs.add(javacHeaders.getPath());
  60         javacArgs.add("-XDjavah:full");
  61 
  62         for (File f: srcDir.listFiles()) {
  63             if (f.getName().matches("TestClass[0-9]+\\.java")) {
  64                 sourceFileCount++;
  65                 javacArgs.add(f.getPath());
  66             }
  67         }
  68 
  69         int rc = com.sun.tools.javac.Main.compile(javacArgs.toArray(new String[javacArgs.size()]));
  70         if (rc != 0)
  71             throw new Exception("javac failed; rc=" + rc);
  72 
  73         List<String> javahArgs = new ArrayList<String>();
  74         javahArgs.add("-d");
  75         javahArgs.add(javahHeaders.getPath());
  76 
  77         for (File f: classesDir.listFiles()) {
  78             if (f.getName().endsWith(".class")) {
  79                 javahArgs.add(inferBinaryName(f));
  80             }
  81         }
  82 
  83         PrintWriter pw = new PrintWriter(System.out, true);
  84         rc = com.sun.tools.javah.Main.run(javahArgs.toArray(new String[javahArgs.size()]), pw);
  85         if (rc != 0)
  86             throw new Exception("javah failed; rc=" + rc);
  87 
  88         compare(javahHeaders, javacHeaders);
  89 
  90         int javahHeaderCount = javahHeaders.list().length;
  91         int javacHeaderCount = javacHeaders.list().length;
  92 
  93         System.out.println(sourceFileCount + " .java files found");
  94         System.out.println(javacHeaderCount + " .h files generated by javac");
  95         System.out.println(javahHeaderCount + " .h files generated by javah");
  96         System.out.println(compareCount + " header files compared");
  97 
  98         if (javacHeaderCount != javahHeaderCount || javacHeaderCount != compareCount)
  99             error("inconsistent counts");
 100 
 101         if (errors > 0)
 102             throw new Exception(errors + " errors occurred");
 103     }
 104 
 105     String inferBinaryName(File file) {
 106         String name = file.getName();
 107         return name.substring(0, name.length() - ".class".length()).replace("$", ".");
 108     }
 109 
 110     /** Compare two directories.
 111      *  @param f1 The golden directory
 112      *  @param f2 The directory to be compared
 113      */
 114     void compare(File f1, File f2) {
 115         compare(f1, f2, null);
 116     }
 117 
 118     /** Compare two files or directories
 119      *  @param f1 The golden directory
 120      *  @param f2 The directory to be compared
 121      *  @param p An optional path identifying a file within the two directories
 122      */
 123     void compare(File f1, File f2, String p) {
 124         File f1p = (p == null ? f1 : new File(f1, p));
 125         File f2p = (p == null ? f2 : new File(f2, p));
 126         if (f1p.isDirectory() && f2p.isDirectory()) {
 127             Set<String> children = new HashSet<String>();
 128             children.addAll(Arrays.asList(f1p.list()));
 129             children.addAll(Arrays.asList(f2p.list()));
 130             for (String c: children) {
 131                 compare(f1, f2, new File(p, c).getPath()); // null-safe for p
 132             }
 133         }
 134         else if (f1p.isFile() && f2p.isFile()) {
 135             System.out.println("checking " + p);
 136             compareCount++;
 137             String s1 = read(f1p);
 138             String s2 = read(f2p);
 139             if (!s1.equals(s2)) {
 140                 System.out.println("File: " + f1p + "\n" + s1);
 141                 System.out.println("File: " + f2p + "\n" + s2);
 142                 error("Files differ: " + f1p + " " + f2p);
 143             }
 144         }
 145         else if (f1p.exists() && !f2p.exists())
 146             error("Only in " + f1 + ": " + p);
 147         else if (f2p.exists() && !f1p.exists())
 148             error("Only in " + f2 + ": " + p);
 149         else
 150             error("Files differ: " + f1p + " " + f2p);
 151     }
 152 
 153     private String read(File f) {
 154         try {
 155             return new String(Files.readAllBytes(f.toPath()));
 156         } catch (IOException e) {
 157             error("error reading " + f + ": " + e);
 158             return "";
 159         }
 160     }
 161 
 162     private void error(String msg) {
 163         System.out.println(msg);
 164         errors++;
 165     }
 166 
 167     private int errors;
 168     private int compareCount;
 169     private int sourceFileCount;
 170 }