1 /* 2 * Copyright (c) 2010, 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 6960424 8022161 27 * @summary new option -Xpkginfo for better control of when package-info.class 28 * is generated, also ensures no failures if package-info.java is 29 * not available. 30 * @modules jdk.compiler 31 */ 32 33 import java.io.*; 34 import java.util.*; 35 36 public class TestPkgInfo { 37 enum OptKind { 38 NONE(null), 39 ALWAYS("-Xpkginfo:always"), 40 NONEMPTY("-Xpkginfo:nonempty"), 41 LEGACY("-Xpkginfo:legacy"); OptKind(String opt)42 OptKind(String opt) { this.opt = opt; } 43 final String opt; 44 }; 45 main(String... args)46 public static void main(String... args) throws Exception { 47 new TestPkgInfo().run(args); 48 } run(String... args)49 public void run(String... args) throws Exception { 50 testPositive(); 51 testNoExceptions(); 52 } testPositive(String... args)53 public void testPositive(String... args) throws Exception { 54 boolean[] booleanValues = { false, true }; 55 for (OptKind ok: OptKind.values()) { 56 for (boolean sr: booleanValues) { 57 for (boolean cr: booleanValues) { 58 for (boolean rr: booleanValues) { 59 try { 60 test(ok, sr, cr, rr); 61 } catch (Exception e) { 62 error("Exception: " + e); 63 } 64 if (errors > 0) throw new AssertionError(); 65 } 66 } 67 } 68 } 69 70 if (errors > 0) 71 throw new Exception(errors + " errors occurred"); 72 } 73 74 /** this should throw no exceptions **/ testNoExceptions()75 void testNoExceptions() throws Exception { 76 count++; 77 System.err.println("Test " + count + ": ALWAYS nofile"); 78 79 StringBuilder sb = new StringBuilder(); 80 sb.append("package test; class Hello{}"); 81 82 // test specific tmp directory 83 File tmpDir = new File("tmp.test" + count); 84 File classesDir = new File(tmpDir, "classes"); 85 classesDir.mkdirs(); 86 File javafile = new File(new File(tmpDir, "src"), "Hello.java"); 87 writeFile(javafile, sb.toString()); 88 // build up list of options and files to be compiled 89 List<String> opts = new ArrayList<>(); 90 List<File> files = new ArrayList<>(); 91 92 opts.add("-d"); 93 opts.add(classesDir.getPath()); 94 opts.add("-Xpkginfo:always"); 95 files.add(javafile); 96 97 compile(opts, files); 98 } 99 test(OptKind ok, boolean sr, boolean cr, boolean rr)100 void test(OptKind ok, boolean sr, boolean cr, boolean rr) throws Exception { 101 count++; 102 System.err.println("Test " + count + ": ok:" + ok + " sr:" + sr + " cr:" + cr + " rr:" + rr); 103 104 StringBuilder sb = new StringBuilder(); 105 106 // create annotated package statement with all combinations of retention policy 107 if (sr) sb.append("@SR\n"); 108 if (cr) sb.append("@CR\n"); 109 if (rr) sb.append("@RR\n"); 110 sb.append("package p;\n"); 111 sb.append("\n"); 112 113 sb.append("import java.lang.annotation.*;\n"); 114 sb.append("@Retention(RetentionPolicy.SOURCE) @interface SR { }\n"); 115 sb.append("@Retention(RetentionPolicy.CLASS) @interface CR { }\n"); 116 sb.append("@Retention(RetentionPolicy.RUNTIME) @interface RR { }\n"); 117 118 // test specific tmp directory 119 File tmpDir = new File("tmp.test" + count); 120 File classesDir = new File(tmpDir, "classes"); 121 classesDir.mkdirs(); 122 File pkginfo_java = new File(new File(tmpDir, "src"), "package-info.java"); 123 writeFile(pkginfo_java, sb.toString()); 124 125 // build up list of options and files to be compiled 126 List<String> opts = new ArrayList<>(); 127 List<File> files = new ArrayList<>(); 128 129 opts.add("-d"); 130 opts.add(classesDir.getPath()); 131 if (ok.opt != null) 132 opts.add(ok.opt); 133 //opts.add("-verbose"); 134 files.add(pkginfo_java); 135 136 compile(opts, files); 137 138 File pkginfo_class = new File(new File(classesDir, "p"), "package-info.class"); 139 boolean exists = pkginfo_class.exists(); 140 141 boolean expected; 142 switch (ok) { 143 case ALWAYS: 144 expected = true; 145 break; 146 147 case LEGACY: 148 case NONE: 149 expected = (sr || cr || rr ); // any annotation 150 break; 151 152 case NONEMPTY: 153 expected = (cr || rr ); // any annotation in class file 154 break; 155 156 default: 157 throw new IllegalStateException(); 158 } 159 160 if (exists && !expected) 161 error("package-info.class found but not expected"); 162 if (!exists && expected) 163 error("package-info.class expected but not found"); 164 } 165 166 /** Compile files with options provided. */ compile(List<String> opts, List<File> files)167 void compile(List<String> opts, List<File> files) throws Exception { 168 System.err.println("javac: " + opts + " " + files); 169 List<String> args = new ArrayList<>(); 170 args.addAll(opts); 171 for (File f: files) 172 args.add(f.getPath()); 173 StringWriter sw = new StringWriter(); 174 PrintWriter pw = new PrintWriter(sw); 175 int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); 176 pw.flush(); 177 if (sw.getBuffer().length() > 0) 178 System.err.println(sw.toString()); 179 if (rc != 0) 180 throw new Exception("compilation failed: rc=" + rc); 181 } 182 183 /** Write a file with a given body. */ writeFile(File f, String body)184 void writeFile(File f, String body) throws Exception { 185 if (f.getParentFile() != null) 186 f.getParentFile().mkdirs(); 187 Writer out = new FileWriter(f); 188 try { 189 out.write(body); 190 } finally { 191 out.close(); 192 } 193 } 194 195 /** Report an error. */ error(String msg)196 void error(String msg) { 197 System.err.println("Error: " + msg); 198 errors++; 199 } 200 201 /** Test case counter. */ 202 int count; 203 204 /** Number of errors found. */ 205 int errors; 206 } 207