langtools/test/tools/javac/4241573/T4241573.java
changeset 3995 73af8b6fb8bc
child 5520 86e4b9a9da40
equal deleted inserted replaced
3994:7df1ecd5eadb 3995:73af8b6fb8bc
       
     1 /*
       
     2  * Copyright 2009 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @bug 4241573
       
    27  * @summary SourceFile attribute includes full path
       
    28  */
       
    29 
       
    30 import com.sun.tools.classfile.Attribute;
       
    31 import com.sun.tools.classfile.ClassFile;
       
    32 import com.sun.tools.classfile.SourceFile_attribute;
       
    33 import java.io.*;
       
    34 import java.util.*;
       
    35 import java.util.jar.*;
       
    36 
       
    37 public class T4241573 {
       
    38     public static void main(String... args) throws Exception {
       
    39         new T4241573().run();
       
    40     }
       
    41 
       
    42     public void run() throws Exception {
       
    43         // Selection of files to be compiled
       
    44         File absJar = createJar(new File("abs.jar").getAbsoluteFile(), "j.A");
       
    45         File relJar = createJar(new File("rel.jar"), "j.R");
       
    46         File absDir = createDir(new File("abs.dir").getAbsoluteFile(), "d.A");
       
    47         File relDir = createDir(new File("rel.dir"), "d.R");
       
    48         File absTestFile = writeFile(new File("AbsTest.java").getAbsoluteFile(), "class AbsTest { class Inner { } }");
       
    49         File relTestFile = writeFile(new File("RelTest.java"), "class RelTest { class Inner { } }");
       
    50         File relTest2File = writeFile(new File("p/RelTest2.java"), "package p; class RelTest2 { class Inner { } }");
       
    51         // This next class references other classes that will be found on the source path
       
    52         // and which will therefore need to be compiled as well.
       
    53         File mainFile = writeFile(new File("Main.java"),
       
    54                 "class Main { j.A ja; j.R jr; d.A da; d.R dr; }" +
       
    55                 "");
       
    56 
       
    57         String sourcePath = createPath(absJar, relJar, absDir, relDir);
       
    58         File outDir = new File("classes");
       
    59         outDir.mkdirs();
       
    60 
       
    61         String[] args = {
       
    62             "-sourcepath", sourcePath,
       
    63             "-d", outDir.getPath(),
       
    64             absTestFile.getPath(),
       
    65             relTestFile.getPath(),
       
    66             relTest2File.getPath(),
       
    67             mainFile.getPath(),
       
    68         };
       
    69         System.err.println("compile: " + Arrays.asList(args));
       
    70         StringWriter sw = new StringWriter();
       
    71         PrintWriter pw = new PrintWriter(sw);
       
    72         int rc = com.sun.tools.javac.Main.compile(args, pw);
       
    73         pw.close();
       
    74         if (rc != 0) {
       
    75             System.err.println(sw.toString());
       
    76             throw new Exception("unexpected exit from javac: " + rc);
       
    77         }
       
    78 
       
    79         Set<File> expect = getFiles(outDir,
       
    80             "d/A.class",        "d/A$Inner.class",
       
    81             "d/R.class",        "d/R$Inner.class",
       
    82             "j/A.class",        "j/A$Inner.class",
       
    83             "j/R.class",        "j/R$Inner.class",
       
    84             "AbsTest.class",    "AbsTest$Inner.class",
       
    85             "RelTest.class",    "RelTest$Inner.class",
       
    86             "p/RelTest2.class", "p/RelTest2$Inner.class",
       
    87             "Main.class" );
       
    88 
       
    89         Set<File> found = findFiles(outDir);
       
    90 
       
    91         if (!found.equals(expect)) {
       
    92             if (found.containsAll(expect))
       
    93                 throw new Exception("unexpected files found: " + diff(found, expect));
       
    94             else if (expect.containsAll(found))
       
    95                 throw new Exception("expected files not found: " + diff(expect, found));
       
    96         }
       
    97 
       
    98         for (File f: found)
       
    99             verifySourceFileAttribute(f);
       
   100 
       
   101         if (errors > 0)
       
   102             throw new Exception(errors + " errors occurred");
       
   103     }
       
   104 
       
   105     /** Check the SourceFileAttribute is the simple name of the original source file. */
       
   106     void verifySourceFileAttribute(File f) {
       
   107         System.err.println("verify: " + f);
       
   108         try {
       
   109             ClassFile cf = ClassFile.read(f);
       
   110             SourceFile_attribute sfa = (SourceFile_attribute) cf.getAttribute(Attribute.SourceFile);
       
   111             String found = sfa.getSourceFile(cf.constant_pool);
       
   112             String expect = f.getName().replaceAll("([$.].*)?\\.class", ".java");
       
   113             if (!expect.equals(found)) {
       
   114                 error("bad value found: " + found + ", expected: " + expect);
       
   115             }
       
   116         } catch (Exception e) {
       
   117             error("error reading " + f +": " + e);
       
   118         }
       
   119     }
       
   120 
       
   121     /** Create a directory containing one or more files. */
       
   122     File createDir(File dir, String... entries) throws Exception {
       
   123         if (!dir.mkdirs())
       
   124             throw new Exception("cannot create directories " + dir);
       
   125         for (String e: entries) {
       
   126             writeFile(new File(dir, getPathForEntry(e)), getBodyForEntry(e));
       
   127         }
       
   128         return dir;
       
   129     }
       
   130 
       
   131     /** Create a jar file containing one or more entries. */
       
   132     File createJar(File jar, String... entries) throws IOException {
       
   133         OutputStream out = new FileOutputStream(jar);
       
   134         try {
       
   135             JarOutputStream jos = new JarOutputStream(out);
       
   136             for (String e: entries) {
       
   137                 jos.putNextEntry(new JarEntry(getPathForEntry(e)));
       
   138                 jos.write(getBodyForEntry(e).getBytes());
       
   139             }
       
   140             jos.close();
       
   141         } finally {
       
   142             out.close();
       
   143         }
       
   144         return jar;
       
   145     }
       
   146 
       
   147     /** Return the path for an entry given to createDir or createJar. */
       
   148     String getPathForEntry(String e) {
       
   149         return e.replace(".", File.separator) + ".java";
       
   150     }
       
   151 
       
   152     /** Return the body text for an entry given to createDir or createJar. */
       
   153     String getBodyForEntry(String e) {
       
   154         int sep = e.lastIndexOf(".");
       
   155         String pkgName = e.substring(0, sep);
       
   156         String className = e.substring(sep + 1);
       
   157         return "package " + pkgName + "; public class " + className + "{ class Inner { } }";
       
   158     }
       
   159 
       
   160     /** Write a file containing the given string. Parent directories are
       
   161      * created as needed. */
       
   162     File writeFile(File f, String s) throws IOException {
       
   163         if (f.getParentFile() != null)
       
   164             f.getParentFile().mkdirs();
       
   165         FileWriter out = new FileWriter(f);
       
   166         try {
       
   167             out.write(s);
       
   168         } finally {
       
   169             out.close();
       
   170         }
       
   171         return f;
       
   172     }
       
   173 
       
   174     /** Create a path value from a list of directories and jar files. */
       
   175     String createPath(File... files) {
       
   176         StringBuilder sb = new StringBuilder();
       
   177         for (File f: files) {
       
   178             if (sb.length() > 0)
       
   179                 sb.append(File.pathSeparatorChar);
       
   180             sb.append(f.getPath());
       
   181         }
       
   182         return sb.toString();
       
   183     }
       
   184 
       
   185     /** Create a set of files from a base directory and a set of relative paths. */
       
   186     Set<File> getFiles(File dir, String... paths) {
       
   187         Set<File> files = new LinkedHashSet<File>();
       
   188         for (String p: paths)
       
   189             files.add(new File(dir, p));
       
   190         return files;
       
   191     }
       
   192 
       
   193     /** Find all the files in a directory and its subdirectories. */
       
   194     Set<File> findFiles(File dir) {
       
   195         Set<File> files = new LinkedHashSet<File>();
       
   196         findFiles(dir, files);
       
   197         return files;
       
   198     }
       
   199     // where
       
   200     void findFiles(File dir, Set<File> files) {
       
   201         for (File f: dir.listFiles()) {
       
   202             if (f.isDirectory())
       
   203                 findFiles(f, files);
       
   204             else
       
   205                 files.add(f);
       
   206         }
       
   207     }
       
   208 
       
   209     /** Return the difference of two sets, a - b. */
       
   210     <T> Set<T> diff(Set<T> a, Set<T> b) {
       
   211         if (b.isEmpty())
       
   212             return a;
       
   213         Set<T> result = new LinkedHashSet<T>(a);
       
   214         result.removeAll(b);
       
   215         return result;
       
   216     }
       
   217 
       
   218     /** Report an error. */
       
   219     void error(String msg) {
       
   220         System.err.println(msg);
       
   221         errors++;
       
   222     }
       
   223 
       
   224     int errors;
       
   225 }