1 /* 2 * Copyright (c) 2015, 2016, 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 8158123 27 * @summary tests for module declarations 28 * @library /tools/lib 29 * @modules 30 * jdk.compiler/com.sun.tools.javac.api 31 * jdk.compiler/com.sun.tools.javac.main 32 * jdk.jdeps/com.sun.tools.javap 33 * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase 34 * @run main ModuleInfoTest 35 */ 36 37 import java.nio.file.Files; 38 import java.nio.file.Path; 39 import java.util.Arrays; 40 41 import toolbox.JavacTask; 42 import toolbox.Task; 43 import toolbox.ToolBox; 44 45 public class ModuleInfoTest extends ModuleTestBase { 46 47 public static void main(String... args) throws Exception { 48 ModuleInfoTest t = new ModuleInfoTest(); 49 t.runTests(); 50 } 51 52 /** 53 * Check error message if module declaration not in module-info.java. 54 */ 55 @Test 56 public void testModuleDeclNotInModuleJava(Path base) throws Exception { 57 Path src = base.resolve("src"); 58 tb.writeFile(src.resolve("M.java"), "module M { }"); 59 String log = new JavacTask(tb) 60 .options("-XDrawDiagnostics") 61 .files(findJavaFiles(src)) 62 .run(Task.Expect.FAIL) 63 .writeAll() 64 .getOutput(Task.OutputKind.DIRECT); 65 66 if (!log.contains("M.java:1:1: compiler.err.module.decl.sb.in.module-info.java")) 67 throw new Exception("expected output not found"); 68 } 69 70 /** 71 * Verify that a package private class can be put in module-info.java. 72 */ 73 @Test 74 public void testNotModuleDeclInModuleJava_1(Path base) throws Exception { 75 Path src = base.resolve("src"); 76 tb.writeFile(src.resolve("module-info.java"), "class C { }"); 77 new JavacTask(tb) 78 .options("-XDrawDiagnostics") 79 .files(findJavaFiles(src)) 80 .run() 81 .writeAll(); 82 } 83 84 /** 85 * Verify that a public class cannot be put in module-info.java. 86 */ 87 @Test 88 public void testNotModuleDeclInModuleJava_2(Path base) throws Exception { 89 Path src = base.resolve("src"); 90 tb.writeFile(src.resolve("module-info.java"), "public class C { }"); 91 String log = new JavacTask(tb) 92 .options("-XDrawDiagnostics") 93 .files(findJavaFiles(src)) 94 .run(Task.Expect.FAIL) 95 .writeAll() 96 .getOutput(Task.OutputKind.DIRECT); 97 98 if (!log.contains("module-info.java:1:8: compiler.err.class.public.should.be.in.file: C")) 99 throw new Exception("expected output not found"); 100 } 101 102 /** 103 * Verify that only one module decl can be put in module-info.java. 104 */ 105 @Test 106 public void testSingleModuleDecl(Path base) throws Exception { 107 Path src = base.resolve("src"); 108 tb.writeJavaFiles(src, "module M1 { } /*...*/ module M2 { }"); 109 String log = new JavacTask(tb) 110 .options("-XDrawDiagnostics") 111 .files(findJavaFiles(src)) 112 .run(Task.Expect.FAIL) 113 .writeAll() 114 .getOutput(Task.OutputKind.DIRECT); 115 116 if (!log.contains("module-info.java:1:14: compiler.err.expected: token.end-of-input")) 117 throw new Exception("expected output not found"); 118 } 119 120 /** 121 * Verify that missing requires are reported. 122 */ 123 @Test 124 public void testRequiresNotFound(Path base) throws Exception { 125 Path src = base.resolve("src"); 126 tb.writeJavaFiles(src, "module M1 { requires M2; }"); 127 String log = new JavacTask(tb) 128 .options("-XDrawDiagnostics") 129 .files(findJavaFiles(src)) 130 .run(Task.Expect.FAIL) 131 .writeAll() 132 .getOutput(Task.OutputKind.DIRECT); 133 134 if (!log.contains("module-info.java:1:22: compiler.err.module.not.found: M2")) 135 throw new Exception("expected output not found"); 136 } 137 138 /** 139 * Verify that missing exports are reported. 140 */ 141 @Test 142 public void testExportsNotFound(Path base) throws Exception { 143 Path src = base.resolve("src"); 144 tb.writeJavaFiles(src, "module M1 { exports p to M2; }"); 145 String log = new JavacTask(tb) 146 .options("-XDrawDiagnostics") 147 .files(findJavaFiles(src)) 148 .run(Task.Expect.FAIL) 149 .writeAll() 150 .getOutput(Task.OutputKind.DIRECT); 151 152 if (!log.contains("module-info.java:1:26: compiler.err.module.not.found: M2")) 153 throw new Exception("expected output not found"); 154 } 155 156 /** 157 * Verify that a simple loop is detected. 158 */ 159 @Test 160 public void testRequiresSelf(Path base) throws Exception { 161 Path src = base.resolve("src"); 162 tb.writeJavaFiles(src, "module M { requires M; }"); 163 String log = new JavacTask(tb) 164 .options("-XDrawDiagnostics") 165 .files(findJavaFiles(src)) 166 .run(Task.Expect.FAIL) 167 .writeAll() 168 .getOutput(Task.OutputKind.DIRECT); 169 170 if (!log.contains("module-info.java:1:21: compiler.err.cyclic.requires: M")) 171 throw new Exception("expected output not found"); 172 } 173 174 /** 175 * Verify that a multi-module loop is detected. 176 */ 177 @Test 178 public void testRequiresLoop(Path base) throws Exception { 179 Path src = base.resolve("src"); 180 Path src_m1 = src.resolve("m1"); 181 tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }"); 182 Path src_m2 = src.resolve("m2"); 183 tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires m3; }"); 184 Path src_m3 = src.resolve("m3"); 185 tb.writeFile(src_m3.resolve("module-info.java"), "module m3 { requires m1; }"); 186 187 Path classes = base.resolve("classes"); 188 Files.createDirectories(classes); 189 190 String log = new JavacTask(tb) 191 .options("-XDrawDiagnostics", "--module-source-path", src.toString()) 192 .outdir(classes) 193 .files(findJavaFiles(src)) 194 .run(Task.Expect.FAIL) 195 .writeAll() 196 .getOutput(Task.OutputKind.DIRECT); 197 198 if (!log.contains("module-info.java:1:22: compiler.err.cyclic.requires: m3")) 199 throw new Exception("expected output not found"); 200 } 201 202 /** 203 * Verify that a multi-module loop is detected. 204 */ 205 @Test 206 public void testRequiresPublicLoop(Path base) throws Exception { 207 Path src = base.resolve("src"); 208 Path src_m1 = src.resolve("m1"); 209 tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }"); 210 Path src_m2 = src.resolve("m2"); 211 tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires public m3; }"); 212 Path src_m3 = src.resolve("m3"); 213 tb.writeFile(src_m3.resolve("module-info.java"), "module m3 { requires m1; }"); 214 215 Path classes = base.resolve("classes"); 216 Files.createDirectories(classes); 217 218 String log = new JavacTask(tb) 219 .options("-XDrawDiagnostics", "--module-source-path", src.toString()) 220 .outdir(classes) 221 .files(findJavaFiles(src)) 222 .run(Task.Expect.FAIL) 223 .writeAll() 224 .getOutput(Task.OutputKind.DIRECT); 225 226 if (!log.contains("module-info.java:1:29: compiler.err.cyclic.requires: m3")) 227 throw new Exception("expected output not found"); 228 } 229 230 /** 231 * Verify that duplicate requires are detected. 232 */ 233 @Test 234 public void testDuplicateRequires(Path base) throws Exception { 235 Path src = base.resolve("src"); 236 Path src_m1 = src.resolve("m1"); 237 tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }"); 238 Path src_m2 = src.resolve("m2"); 239 tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires m1; requires m1; }"); 240 241 Path classes = base.resolve("classes"); 242 Files.createDirectories(classes); 243 244 String log = new JavacTask(tb) 245 .options("-XDrawDiagnostics", "--module-source-path", src.toString()) 246 .outdir(classes) 247 .files(findJavaFiles(src)) 248 .run(Task.Expect.FAIL) 249 .writeAll() 250 .getOutput(Task.OutputKind.DIRECT); 251 252 if (!log.contains("module-info.java:1:35: compiler.err.duplicate.requires: m1")) 253 throw new Exception("expected output not found"); 254 } 255 256 /** 257 * Verify that duplicate exported packages are detected. 258 */ 259 @Test 260 public void testDuplicateExports_packages(Path base) throws Exception { 261 Path src = base.resolve("src"); 262 tb.writeJavaFiles(src, "module m1 { exports p; exports p; }"); 263 264 Path classes = base.resolve("classes"); 265 Files.createDirectories(classes); 266 267 String log = new JavacTask(tb) 268 .options("-XDrawDiagnostics") 269 .outdir(classes) 270 .files(findJavaFiles(src)) 271 .run(Task.Expect.FAIL) 272 .writeAll() 273 .getOutput(Task.OutputKind.DIRECT); 274 275 if (!log.contains("module-info.java:1:32: compiler.err.duplicate.exports: p")) 276 throw new Exception("expected output not found"); 277 } 278 279 /** 280 * Verify that duplicate exported packages are detected. 281 */ 282 @Test 283 public void testDuplicateExports_packages2(Path base) throws Exception { 284 Path src = base.resolve("src"); 285 tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p; exports p to m2; }"); 286 tb.writeJavaFiles(src.resolve("m2"), "module m2 { }"); 287 288 Path classes = base.resolve("classes"); 289 Files.createDirectories(classes); 290 291 String log = new JavacTask(tb) 292 .options("-XDrawDiagnostics", "--module-source-path", src.toString()) 293 .outdir(classes) 294 .files(findJavaFiles(src)) 295 .run(Task.Expect.FAIL) 296 .writeAll() 297 .getOutput(Task.OutputKind.DIRECT); 298 299 if (!log.contains("module-info.java:1:32: compiler.err.duplicate.exports: p")) 300 throw new Exception("expected output not found"); 301 } 302 303 /** 304 * Verify that duplicate exported packages are detected. 305 */ 306 @Test 307 public void testDuplicateExports_modules(Path base) throws Exception { 308 Path src = base.resolve("src"); 309 Path src_m1 = src.resolve("m1"); 310 tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }"); 311 Path src_m2 = src.resolve("m2"); 312 tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { exports p to m1, m1; }"); 313 314 Path classes = base.resolve("classes"); 315 Files.createDirectories(classes); 316 317 String log = new JavacTask(tb) 318 .options("-XDrawDiagnostics", "--module-source-path", src.toString()) 319 .outdir(classes) 320 .files(findJavaFiles(src)) 321 .run(Task.Expect.FAIL) 322 .writeAll() 323 .getOutput(Task.OutputKind.DIRECT); 324 325 if (!log.contains("module-info.java:1:30: compiler.err.duplicate.exports: m1")) 326 throw new Exception("expected output not found"); 327 } 328 329 /** 330 * Verify that annotations are not permitted at 331 * any of the module names or the package names. 332 */ 333 @Test 334 public void testAnnotations(Path base) throws Exception { 335 Path src = base.resolve("src"); 336 Path src_m1 = src.resolve("m1.sub"); 337 Path classes = base.resolve("classes"); 338 Files.createDirectories(classes); 339 340 String code = "module @m1.@sub { " + 341 "requires @p1.@p2; " + 342 "exports @p1.@p2; " + 343 "exports @p1.@p2 to @m2.@sub; " + 344 "exports @p1.@p2 to @m2.@sub, @m3.@sub; " + 345 "uses @p1.@Interface; " + 346 "provides @p1.@Interface with @p2.@Concrete; " + 347 "}"; 348 String[] splittedCode = code.split("@"); 349 int length = splittedCode.length; 350 String anno = "@Anno "; 351 352 for (int i = 1; i < length; i++) { 353 String preAnno = String.join("", Arrays.copyOfRange(splittedCode, 0, i)); 354 String postAnno = String.join("", Arrays.copyOfRange(splittedCode, i, length)); 355 String moduleInfo = preAnno + anno + postAnno; 356 tb.writeFile(src_m1.resolve("module-info.java"), moduleInfo); 357 358 String log = new JavacTask(tb) 359 .options("-XDrawDiagnostics", "--module-source-path", src.toString()) 360 .outdir(classes) 361 .files(findJavaFiles(src)) 362 .run(Task.Expect.FAIL) 363 .writeAll() 364 .getOutput(Task.OutputKind.DIRECT); 365 366 if (!log.matches("(?s)^module\\-info\\.java:\\d+:\\d+: compiler\\.err\\.expected: token\\.identifier.*")) 367 throw new Exception("expected output not found"); 368 } 369 } 370 }