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 8155026 27 * @summary Test automatic modules 28 * @library /tools/lib 29 * @modules 30 * java.desktop 31 * jdk.compiler/com.sun.tools.javac.api 32 * jdk.compiler/com.sun.tools.javac.main 33 * @build toolbox.ToolBox toolbox.JavacTask toolbox.JarTask ModuleTestBase 34 * @run main AutomaticModules 35 */ 36 37 import java.nio.file.Files; 38 import java.nio.file.Path; 39 import java.util.Arrays; 40 import java.util.List; 41 42 import toolbox.JarTask; 43 import toolbox.JavacTask; 44 import toolbox.Task; 45 46 public class AutomaticModules extends ModuleTestBase { 47 48 public static void main(String... args) throws Exception { 49 AutomaticModules t = new AutomaticModules(); 50 t.runTests(); 51 } 52 53 @Test 54 public void testSimple(Path base) throws Exception { 55 Path legacySrc = base.resolve("legacy-src"); 56 tb.writeJavaFiles(legacySrc, 57 "package api; import java.awt.event.ActionListener; public abstract class Api implements ActionListener {}"); 58 Path legacyClasses = base.resolve("legacy-classes"); 59 Files.createDirectories(legacyClasses); 60 61 String log = new JavacTask(tb) 62 .options() 63 .outdir(legacyClasses) 64 .files(findJavaFiles(legacySrc)) 65 .run() 66 .writeAll() 67 .getOutput(Task.OutputKind.DIRECT); 68 69 if (!log.isEmpty()) { 70 throw new Exception("unexpected output: " + log); 71 } 72 73 Path modulePath = base.resolve("module-path"); 74 75 Files.createDirectories(modulePath); 76 77 Path jar = modulePath.resolve("test-api-1.0.jar"); 78 79 new JarTask(tb, jar) 80 .baseDir(legacyClasses) 81 .files("api/Api.class") 82 .run(); 83 84 Path moduleSrc = base.resolve("module-src"); 85 Path m1 = moduleSrc.resolve("m1"); 86 87 Path classes = base.resolve("classes"); 88 89 Files.createDirectories(classes); 90 91 tb.writeJavaFiles(m1, 92 "module m1 { requires test.api; requires java.desktop; }", 93 "package impl; public class Impl { public void e(api.Api api) { api.actionPerformed(null); } }"); 94 95 new JavacTask(tb) 96 .options("--module-source-path", moduleSrc.toString(), "--module-path", modulePath.toString()) 97 .outdir(classes) 98 .files(findJavaFiles(moduleSrc)) 99 .run() 100 .writeAll(); 101 } 102 103 @Test 104 public void testUnnamedModule(Path base) throws Exception { 105 Path legacySrc = base.resolve("legacy-src"); 106 tb.writeJavaFiles(legacySrc, 107 "package api; public abstract class Api { public void run(CharSequence str) { } private void run(base.Base base) { } }", 108 "package base; public interface Base { public void run(); }"); 109 Path legacyClasses = base.resolve("legacy-classes"); 110 Files.createDirectories(legacyClasses); 111 112 String log = new JavacTask(tb) 113 .options() 114 .outdir(legacyClasses) 115 .files(findJavaFiles(legacySrc)) 116 .run() 117 .writeAll() 118 .getOutput(Task.OutputKind.DIRECT); 119 120 if (!log.isEmpty()) { 121 throw new Exception("unexpected output: " + log); 122 } 123 124 Path modulePath = base.resolve("module-path"); 125 126 Files.createDirectories(modulePath); 127 128 Path apiJar = modulePath.resolve("test-api-1.0.jar"); 129 130 new JarTask(tb, apiJar) 131 .baseDir(legacyClasses) 132 .files("api/Api.class") 133 .run(); 134 135 Path baseJar = base.resolve("base.jar"); 136 137 new JarTask(tb, baseJar) 138 .baseDir(legacyClasses) 139 .files("base/Base.class") 140 .run(); 141 142 Path moduleSrc = base.resolve("module-src"); 143 Path m1 = moduleSrc.resolve("m1"); 144 145 Path classes = base.resolve("classes"); 146 147 Files.createDirectories(classes); 148 149 tb.writeJavaFiles(m1, 150 "module m1 { requires test.api; }", 151 "package impl; public class Impl { public void e(api.Api api) { api.run(\"\"); } }"); 152 153 new JavacTask(tb) 154 .options("--module-source-path", moduleSrc.toString(), "--module-path", modulePath.toString(), "--class-path", baseJar.toString()) 155 .outdir(classes) 156 .files(findJavaFiles(moduleSrc)) 157 .run() 158 .writeAll(); 159 } 160 161 @Test 162 public void testModuleInfoFromClassFileDependsOnAutomatic(Path base) throws Exception { 163 Path automaticSrc = base.resolve("automaticSrc"); 164 tb.writeJavaFiles(automaticSrc, "package api; public class Api {}"); 165 Path automaticClasses = base.resolve("automaticClasses"); 166 tb.createDirectories(automaticClasses); 167 168 String automaticLog = new JavacTask(tb) 169 .outdir(automaticClasses) 170 .files(findJavaFiles(automaticSrc)) 171 .run() 172 .writeAll() 173 .getOutput(Task.OutputKind.DIRECT); 174 175 if (!automaticLog.isEmpty()) 176 throw new Exception("expected output not found: " + automaticLog); 177 178 Path modulePath = base.resolve("module-path"); 179 180 Files.createDirectories(modulePath); 181 182 Path automaticJar = modulePath.resolve("automatic-1.0.jar"); 183 184 new JarTask(tb, automaticJar) 185 .baseDir(automaticClasses) 186 .files("api/Api.class") 187 .run(); 188 189 Path depSrc = base.resolve("depSrc"); 190 Path depClasses = base.resolve("depClasses"); 191 192 Files.createDirectories(depSrc); 193 Files.createDirectories(depClasses); 194 195 tb.writeJavaFiles(depSrc, 196 "module m1 { requires public automatic; }", 197 "package dep; public class Dep { api.Api api; }"); 198 199 new JavacTask(tb) 200 .options("--module-path", modulePath.toString()) 201 .outdir(depClasses) 202 .files(findJavaFiles(depSrc)) 203 .run() 204 .writeAll(); 205 206 Path moduleJar = modulePath.resolve("m1.jar"); 207 208 new JarTask(tb, moduleJar) 209 .baseDir(depClasses) 210 .files("module-info.class", "dep/Dep.class") 211 .run(); 212 213 Path testSrc = base.resolve("testSrc"); 214 Path testClasses = base.resolve("testClasses"); 215 216 Files.createDirectories(testSrc); 217 Files.createDirectories(testClasses); 218 219 tb.writeJavaFiles(testSrc, 220 "module m2 { requires automatic; }", 221 "package test; public class Test { }"); 222 223 new JavacTask(tb) 224 .options("--module-path", modulePath.toString()) 225 .outdir(testClasses) 226 .files(findJavaFiles(testSrc)) 227 .run() 228 .writeAll(); 229 } 230 231 @Test 232 public void testAutomaticAndNamedModules(Path base) throws Exception { 233 Path modulePath = base.resolve("module-path"); 234 235 Files.createDirectories(modulePath); 236 237 for (char c : new char[] {'A', 'B'}) { 238 Path automaticSrc = base.resolve("automaticSrc" + c); 239 tb.writeJavaFiles(automaticSrc, "package api" + c + "; public class Api {}"); 240 Path automaticClasses = base.resolve("automaticClasses" + c); 241 tb.createDirectories(automaticClasses); 242 243 String automaticLog = new JavacTask(tb) 244 .outdir(automaticClasses) 245 .files(findJavaFiles(automaticSrc)) 246 .run() 247 .writeAll() 248 .getOutput(Task.OutputKind.DIRECT); 249 250 if (!automaticLog.isEmpty()) 251 throw new Exception("expected output not found: " + automaticLog); 252 253 Path automaticJar = modulePath.resolve("automatic" + c + "-1.0.jar"); 254 255 new JarTask(tb, automaticJar) 256 .baseDir(automaticClasses) 257 .files("api" + c + "/Api.class") 258 .run(); 259 } 260 261 Path moduleSrc = base.resolve("module-src"); 262 263 tb.writeJavaFiles(moduleSrc.resolve("m1"), 264 "module m1 { requires automaticA; }", 265 "package impl; public class Impl { apiA.Api a; apiB.Api b; m2.M2 m;}"); 266 267 tb.writeJavaFiles(moduleSrc.resolve("m2"), 268 "module m2 { exports m2; }", 269 "package m2; public class M2 { }"); 270 271 Path classes = base.resolve("classes"); 272 273 Files.createDirectories(classes); 274 275 List<String> log = new JavacTask(tb) 276 .options("--module-source-path", moduleSrc.toString(), 277 "--module-path", modulePath.toString(), 278 "--add-modules", "automaticB", 279 "-XDrawDiagnostics") 280 .outdir(classes) 281 .files(findJavaFiles(moduleSrc)) 282 .run(Task.Expect.FAIL) 283 .writeAll() 284 .getOutputLines(Task.OutputKind.DIRECT); 285 286 List<String> expected = Arrays.asList("Impl.java:1:61: compiler.err.not.def.access.package.cant.access: m2.M2, m2", 287 "1 error"); 288 289 if (!expected.equals(log)) { 290 throw new Exception("expected output not found: " + log); 291 } 292 293 log = new JavacTask(tb) 294 .options("--module-source-path", moduleSrc.toString(), 295 "--module-path", modulePath.toString(), 296 "-XDrawDiagnostics") 297 .outdir(classes) 298 .files(findJavaFiles(moduleSrc)) 299 .run(Task.Expect.FAIL) 300 .writeAll() 301 .getOutputLines(Task.OutputKind.DIRECT); 302 303 expected = Arrays.asList("Impl.java:1:51: compiler.err.doesnt.exist: apiB", 304 "Impl.java:1:61: compiler.err.not.def.access.package.cant.access: m2.M2, m2", 305 "2 errors"); 306 307 if (!expected.equals(log)) { 308 throw new Exception("expected output not found: " + log); 309 } 310 } 311 }