jjg@657: /* ksrini@1941: * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. jjg@657: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@657: * jjg@657: * This code is free software; you can redistribute it and/or modify it jjg@657: * under the terms of the GNU General Public License version 2 only, as jjg@657: * published by the Free Software Foundation. jjg@657: * jjg@657: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@657: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@657: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@657: * version 2 for more details (a copy is included in the LICENSE file that jjg@657: * accompanied this code). jjg@657: * jjg@657: * You should have received a copy of the GNU General Public License version jjg@657: * 2 along with this work; if not, write to the Free Software Foundation, jjg@657: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@657: * jjg@657: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jjg@657: * or visit www.oracle.com if you need additional information or have any jjg@657: * questions. jjg@657: */ jjg@657: jjg@657: /* jjg@657: * @test ksrini@1941: * @bug 6960424 8022161 ksrini@1941: * @summary new option -Xpkginfo for better control of when package-info.class ksrini@1941: * is generated, also ensures no failures if package-info.java is ksrini@1941: * not available. jjg@657: */ jjg@657: jjg@657: import java.io.*; jjg@657: import java.util.*; jjg@657: jjg@657: public class TestPkgInfo { jjg@657: enum OptKind { jjg@657: NONE(null), jjg@657: ALWAYS("-Xpkginfo:always"), jjg@657: NONEMPTY("-Xpkginfo:nonempty"), jjg@657: LEGACY("-Xpkginfo:legacy"); jjg@657: OptKind(String opt) { this.opt = opt; } jjg@657: final String opt; jjg@657: }; jjg@657: jjg@657: public static void main(String... args) throws Exception { jjg@657: new TestPkgInfo().run(args); jjg@657: } jjg@657: public void run(String... args) throws Exception { ksrini@1941: testPositive(); ksrini@1941: testNoExceptions(); ksrini@1941: } ksrini@1941: public void testPositive(String... args) throws Exception { jjg@657: boolean[] booleanValues = { false, true }; jjg@657: for (OptKind ok: OptKind.values()) { jjg@657: for (boolean sr: booleanValues) { jjg@657: for (boolean cr: booleanValues) { jjg@657: for (boolean rr: booleanValues) { jjg@657: try { jjg@657: test(ok, sr, cr, rr); jjg@657: } catch (Exception e) { jjg@657: error("Exception: " + e); jjg@657: } jjg@657: if (errors > 0) throw new AssertionError(); jjg@657: } jjg@657: } jjg@657: } jjg@657: } jjg@657: jjg@657: if (errors > 0) jjg@657: throw new Exception(errors + " errors occurred"); jjg@657: } jjg@657: ksrini@1941: /** this should throw no exceptions **/ ksrini@1941: void testNoExceptions() throws Exception { ksrini@1941: count++; ksrini@1941: System.err.println("Test " + count + ": ALWAYS nofile"); ksrini@1941: ksrini@1941: StringBuilder sb = new StringBuilder(); ksrini@1941: sb.append("package test; class Hello{}"); ksrini@1941: ksrini@1941: // test specific tmp directory ksrini@1941: File tmpDir = new File("tmp.test" + count); ksrini@1941: File classesDir = new File(tmpDir, "classes"); ksrini@1941: classesDir.mkdirs(); ksrini@1941: File javafile = new File(new File(tmpDir, "src"), "Hello.java"); ksrini@1941: writeFile(javafile, sb.toString()); ksrini@1941: // build up list of options and files to be compiled ksrini@1941: List opts = new ArrayList<>(); ksrini@1941: List files = new ArrayList<>(); ksrini@1941: ksrini@1941: opts.add("-d"); ksrini@1941: opts.add(classesDir.getPath()); ksrini@1941: opts.add("-Xpkginfo:always"); ksrini@1941: files.add(javafile); ksrini@1941: ksrini@1941: compile(opts, files); ksrini@1941: } ksrini@1941: jjg@657: void test(OptKind ok, boolean sr, boolean cr, boolean rr) throws Exception { jjg@657: count++; jjg@657: System.err.println("Test " + count + ": ok:" + ok + " sr:" + sr + " cr:" + cr + " rr:" + rr); jjg@657: jjg@657: StringBuilder sb = new StringBuilder(); jjg@657: jjg@657: // create annotated package statement with all combinations of retention policy jjg@657: if (sr) sb.append("@SR\n"); jjg@657: if (cr) sb.append("@CR\n"); jjg@657: if (rr) sb.append("@RR\n"); jjg@657: sb.append("package p;\n"); jjg@657: sb.append("\n"); jjg@657: jjg@657: sb.append("import java.lang.annotation.*;\n"); jjg@657: sb.append("@Retention(RetentionPolicy.SOURCE) @interface SR { }\n"); jjg@657: sb.append("@Retention(RetentionPolicy.CLASS) @interface CR { }\n"); jjg@657: sb.append("@Retention(RetentionPolicy.RUNTIME) @interface RR { }\n"); jjg@657: jjg@657: // test specific tmp directory jjg@657: File tmpDir = new File("tmp.test" + count); jjg@657: File classesDir = new File(tmpDir, "classes"); jjg@657: classesDir.mkdirs(); jjg@657: File pkginfo_java = new File(new File(tmpDir, "src"), "package-info.java"); jjg@657: writeFile(pkginfo_java, sb.toString()); jjg@657: jjg@657: // build up list of options and files to be compiled ksrini@1941: List opts = new ArrayList<>(); ksrini@1941: List files = new ArrayList<>(); jjg@657: jjg@657: opts.add("-d"); jjg@657: opts.add(classesDir.getPath()); jjg@657: if (ok.opt != null) jjg@657: opts.add(ok.opt); jjg@657: //opts.add("-verbose"); ksrini@1941: files.add(pkginfo_java); jjg@657: jjg@657: compile(opts, files); jjg@657: jjg@657: File pkginfo_class = new File(new File(classesDir, "p"), "package-info.class"); jjg@657: boolean exists = pkginfo_class.exists(); jjg@657: jjg@657: boolean expected; jjg@657: switch (ok) { jjg@657: case ALWAYS: jjg@657: expected = true; jjg@657: break; jjg@657: jjg@657: case LEGACY: jjg@657: case NONE: jjg@657: expected = (sr || cr || rr ); // any annotation jjg@657: break; jjg@657: jjg@657: case NONEMPTY: jjg@657: expected = (cr || rr ); // any annotation in class file jjg@657: break; jjg@657: jjg@657: default: jjg@657: throw new IllegalStateException(); jjg@657: } jjg@657: jjg@657: if (exists && !expected) jjg@657: error("package-info.class found but not expected"); jjg@657: if (!exists && expected) jjg@657: error("package-info.class expected but not found"); jjg@657: } jjg@657: jjg@657: /** Compile files with options provided. */ jjg@657: void compile(List opts, List files) throws Exception { jjg@657: System.err.println("javac: " + opts + " " + files); ksrini@1941: List args = new ArrayList<>(); jjg@657: args.addAll(opts); jjg@657: for (File f: files) jjg@657: args.add(f.getPath()); jjg@657: StringWriter sw = new StringWriter(); jjg@657: PrintWriter pw = new PrintWriter(sw); jjg@657: int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); jjg@657: pw.flush(); jjg@657: if (sw.getBuffer().length() > 0) jjg@657: System.err.println(sw.toString()); jjg@657: if (rc != 0) jjg@657: throw new Exception("compilation failed: rc=" + rc); jjg@657: } jjg@657: jjg@657: /** Write a file with a given body. */ jjg@657: void writeFile(File f, String body) throws Exception { jjg@657: if (f.getParentFile() != null) jjg@657: f.getParentFile().mkdirs(); jjg@657: Writer out = new FileWriter(f); jjg@657: try { jjg@657: out.write(body); jjg@657: } finally { jjg@657: out.close(); jjg@657: } jjg@657: } jjg@657: jjg@657: /** Report an error. */ jjg@657: void error(String msg) { jjg@657: System.err.println("Error: " + msg); jjg@657: errors++; jjg@657: } jjg@657: jjg@657: /** Test case counter. */ jjg@657: int count; jjg@657: jjg@657: /** Number of errors found. */ jjg@657: int errors; jjg@657: }