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