1 /* 2 * Copyright (c) 2015, 2018, 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 8207032 27 * @summary Test the --add-exports option 28 * @library /tools/lib 29 * @modules jdk.compiler/com.sun.tools.javac.api 30 * jdk.compiler/com.sun.tools.javac.main 31 * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase 32 * @run main AddExportsTest 33 */ 34 35 import java.nio.file.Path; 36 37 import toolbox.JavacTask; 38 import toolbox.Task; 39 import toolbox.Task.Expect; 40 import toolbox.Task.OutputKind; 41 42 public class AddExportsTest extends ModuleTestBase { 43 main(String... args)44 public static void main(String... args) throws Exception { 45 new AddExportsTest().runTests(); 46 } 47 48 @Test testEmpty(Path base)49 public void testEmpty(Path base) throws Exception { 50 Path src = base.resolve("src"); 51 tb.writeJavaFiles(src, "class Dummy { }"); 52 Path classes = base.resolve("classes"); 53 tb.createDirectories(classes); 54 testEmpty(src, classes, "--add-exports", ""); 55 testEmpty(src, classes, "--add-exports="); 56 } 57 testEmpty(Path src, Path classes, String... options)58 private void testEmpty(Path src, Path classes, String... options) throws Exception { 59 String log = new JavacTask(tb, Task.Mode.CMDLINE) 60 .options(options) 61 .outdir(classes) 62 .files(findJavaFiles(src)) 63 .run(Task.Expect.FAIL) 64 .writeAll() 65 .getOutput(Task.OutputKind.DIRECT); 66 67 checkOutputContains(log, 68 "error: no value for --add-exports option"); 69 } 70 71 @Test testEmptyItem(Path base)72 public void testEmptyItem(Path base) throws Exception { 73 Path src = base.resolve("src"); 74 Path src_m1 = src.resolve("m1x"); 75 tb.writeJavaFiles(src_m1, 76 "module m1x { }", 77 "package p1; public class C1 { }"); 78 Path src_m2 = src.resolve("m2x"); 79 tb.writeJavaFiles(src_m2, 80 "module m2x { requires m1x; }", 81 "package p2; class C2 { p1.C1 c1; }"); 82 Path src_m3 = src.resolve("m3x"); 83 tb.writeJavaFiles(src_m3, 84 "module m3x { requires m1x; }", 85 "package p3; class C3 { p1.C1 c1; }"); 86 Path classes = base.resolve("classes"); 87 tb.createDirectories(classes); 88 89 testEmptyItem(src, classes, "m1x/p1=,m2x,m3x"); 90 testEmptyItem(src, classes, "m1x/p1=m2x,,m3x"); 91 testEmptyItem(src, classes, "m1x/p1=m2x,m3x,"); 92 } 93 testEmptyItem(Path src, Path classes, String option)94 void testEmptyItem(Path src, Path classes, String option) throws Exception { 95 new JavacTask(tb) 96 .options("--module-source-path", src.toString(), 97 "--add-exports", option) 98 .outdir(classes) 99 .files(findJavaFiles(src)) 100 .run() 101 .writeAll(); 102 } 103 104 @Test testEmptyList(Path base)105 public void testEmptyList(Path base) throws Exception { 106 Path src = base.resolve("src"); 107 Path src_m1 = src.resolve("m1x"); 108 tb.writeJavaFiles(src_m1, 109 "module m1x { exports p1; }", 110 "package p1; public class C1 { }"); 111 Path classes = base.resolve("classes"); 112 tb.createDirectories(classes); 113 114 testEmptyList(src, classes, "m1x/p1="); 115 testEmptyList(src, classes, "m1x/p1=,"); 116 } 117 testEmptyList(Path src, Path classes, String option)118 void testEmptyList(Path src, Path classes, String option) throws Exception { 119 String log = new JavacTask(tb, Task.Mode.CMDLINE) 120 .options("--module-source-path", src.toString(), 121 "--add-exports", option) 122 .outdir(classes) 123 .files(findJavaFiles(src)) 124 .run(Task.Expect.FAIL) 125 .writeAll() 126 .getOutput(Task.OutputKind.DIRECT); 127 128 checkOutputContains(log, 129 "error: bad value for --add-exports option: '" + option + "'"); 130 } 131 132 @Test testMissingSourceParts(Path base)133 public void testMissingSourceParts(Path base) throws Exception { 134 Path src = base.resolve("src"); 135 Path src_m1 = src.resolve("m1x"); 136 tb.writeJavaFiles(src_m1, 137 "module m1x { exports p1; }", 138 "package p1; public class C1 { }"); 139 Path src_m2 = src.resolve("m2x"); 140 tb.writeJavaFiles(src_m2, 141 "module m2x { }", 142 "package p2; class C2 { p1.C1 c1; }"); 143 Path classes = base.resolve("classes"); 144 tb.createDirectories(classes); 145 146 testMissingSourcePart(src, classes, "=m2x"); 147 testMissingSourcePart(src, classes, "/=m2x"); 148 testMissingSourcePart(src, classes, "m1x/=m2x"); 149 testMissingSourcePart(src, classes, "/p1=m2x"); 150 testMissingSourcePart(src, classes, "m1xp1=m2x"); 151 } 152 testMissingSourcePart(Path src, Path classes, String option)153 private void testMissingSourcePart(Path src, Path classes, String option) throws Exception { 154 String log = new JavacTask(tb, Task.Mode.CMDLINE) 155 .options("--module-source-path", src.toString(), 156 "--add-exports", option) 157 .outdir(classes) 158 .files(findJavaFiles(src)) 159 .run(Task.Expect.FAIL) 160 .writeAll() 161 .getOutput(Task.OutputKind.DIRECT); 162 163 checkOutputContains(log, 164 "error: bad value for --add-exports option: '" + option + "'"); 165 } 166 167 @Test testBadSourceParts(Path base)168 public void testBadSourceParts(Path base) throws Exception { 169 Path src = base.resolve("src"); 170 Path src_m1 = src.resolve("m1x"); 171 tb.writeJavaFiles(src_m1, 172 "module m1x { exports p1; }", 173 "package p1; public class C1 { }"); 174 Path src_m2 = src.resolve("m2x"); 175 tb.writeJavaFiles(src_m2, 176 "module m2x { }", 177 "package p2; class C2 { p1.C1 c1; }"); 178 Path classes = base.resolve("classes"); 179 tb.createDirectories(classes); 180 181 testBadSourcePart(src, classes, "m!/p1=m2x", "m!"); 182 testBadSourcePart(src, classes, "m1x/p!=m2x", "p!"); 183 } 184 testBadSourcePart(Path src, Path classes, String option, String badName)185 private void testBadSourcePart(Path src, Path classes, String option, String badName) 186 throws Exception { 187 String log = new JavacTask(tb, Task.Mode.CMDLINE) 188 .options("-XDrawDiagnostics", 189 "--module-source-path", src.toString(), 190 "--add-exports", option) 191 .outdir(classes) 192 .files(findJavaFiles(src)) 193 .run(Task.Expect.FAIL) 194 .writeAll() 195 .getOutput(Task.OutputKind.DIRECT); 196 197 checkOutputContains(log, 198 "- compiler.warn.bad.name.for.option: --add-exports, " + badName); 199 } 200 201 @Test testBadTarget(Path base)202 public void testBadTarget(Path base) throws Exception { 203 Path src = base.resolve("src"); 204 Path src_m1 = src.resolve("m1x"); 205 tb.writeJavaFiles(src_m1, 206 "module m1x { exports p1; }", 207 "package p1; public class C1 { }"); 208 Path classes = base.resolve("classes"); 209 tb.createDirectories(classes); 210 211 String log = new JavacTask(tb, Task.Mode.CMDLINE) 212 .options("-XDrawDiagnostics", 213 "--module-source-path", src.toString(), 214 "--add-exports", "m1x/p1=m!") 215 .outdir(classes) 216 .files(findJavaFiles(src)) 217 .run() 218 .writeAll() 219 .getOutput(Task.OutputKind.DIRECT); 220 221 checkOutputContains(log, 222 "- compiler.warn.bad.name.for.option: --add-exports, m!"); 223 } 224 225 @Test testSourceNotFound(Path base)226 public void testSourceNotFound(Path base) throws Exception { 227 Path src = base.resolve("src"); 228 Path src_m1 = src.resolve("m1x"); 229 tb.writeJavaFiles(src_m1, 230 "module m1x { }"); 231 Path classes = base.resolve("classes"); 232 tb.createDirectories(classes); 233 234 String log = new JavacTask(tb, Task.Mode.CMDLINE) 235 .options("-XDrawDiagnostics", 236 "--module-source-path", src.toString(), 237 "--add-exports", "DoesNotExist/p=m1x") 238 .outdir(classes) 239 .files(findJavaFiles(src)) 240 .run() 241 .writeAll() 242 .getOutput(Task.OutputKind.DIRECT); 243 244 checkOutputContains(log, 245 "- compiler.warn.module.for.option.not.found: --add-exports, DoesNotExist"); 246 } 247 248 @Test testTargetNotFound(Path base)249 public void testTargetNotFound(Path base) throws Exception { 250 Path src = base.resolve("src"); 251 Path src_m1 = src.resolve("m1x"); 252 tb.writeJavaFiles(src_m1, 253 "module m1x { }", 254 "package p1; class C1 { }"); 255 Path classes = base.resolve("classes"); 256 tb.createDirectories(classes); 257 258 String log = new JavacTask(tb, Task.Mode.CMDLINE) 259 .options("-XDrawDiagnostics", 260 "--module-source-path", src.toString(), 261 "--add-exports", "m1x/p1=DoesNotExist") 262 .outdir(classes) 263 .files(findJavaFiles(src)) 264 .run() 265 .writeAll() 266 .getOutput(Task.OutputKind.DIRECT); 267 268 checkOutputContains(log, 269 "- compiler.warn.module.for.option.not.found: --add-exports, DoesNotExist"); 270 } 271 272 @Test testDuplicate(Path base)273 public void testDuplicate(Path base) throws Exception { 274 Path src = base.resolve("src"); 275 Path src_m1 = src.resolve("m1x"); 276 tb.writeJavaFiles(src_m1, 277 "module m1x { }", 278 "package p1; public class C1 { }"); 279 Path src_m2 = src.resolve("m2x"); 280 tb.writeJavaFiles(src_m2, 281 "module m2x { requires m1x; }", 282 "package p2; class C2 { p1.C1 c1; }"); 283 Path classes = base.resolve("classes"); 284 tb.createDirectories(classes); 285 286 new JavacTask(tb) 287 .options("--module-source-path", src.toString(), 288 "--add-exports", "m1x/p1=m2x,m2x") 289 .outdir(classes) 290 .files(findJavaFiles(src)) 291 .run() 292 .writeAll(); 293 } 294 295 @Test testRepeated_SameTarget(Path base)296 public void testRepeated_SameTarget(Path base) throws Exception { 297 Path src = base.resolve("src"); 298 Path src_m1 = src.resolve("m1x"); 299 tb.writeJavaFiles(src_m1, 300 "module m1x { }", 301 "package p1; public class C1 { }"); 302 Path src_m2 = src.resolve("m2x"); 303 tb.writeJavaFiles(src_m2, 304 "module m2x { requires m1x; }", 305 "package p2; class C2 { p1.C1 c1; }"); 306 Path classes = base.resolve("classes"); 307 tb.createDirectories(classes); 308 309 new JavacTask(tb) 310 .options("--module-source-path", src.toString(), 311 "--add-exports", "m1x/p1=m2x", 312 "--add-exports", "m1x/p1=m2x") 313 .outdir(classes) 314 .files(findJavaFiles(src)) 315 .run() 316 .writeAll(); 317 } 318 319 @Test testRepeated_DifferentTarget(Path base)320 public void testRepeated_DifferentTarget(Path base) throws Exception { 321 Path src = base.resolve("src"); 322 Path src_m1 = src.resolve("m1x"); 323 tb.writeJavaFiles(src_m1, 324 "module m1x { }", 325 "package p1; public class C1 { }"); 326 Path src_m2 = src.resolve("m2x"); 327 tb.writeJavaFiles(src_m2, 328 "module m2x { requires m1x; }", 329 "package p2; class C2 { p1.C1 c1; }"); 330 Path src_m3 = src.resolve("m3x"); 331 tb.writeJavaFiles(src_m3, 332 "module m3x { requires m1x; }", 333 "package p3; class C3 { p1.C1 c1; }"); 334 Path classes = base.resolve("classes"); 335 tb.createDirectories(classes); 336 337 new JavacTask(tb) 338 .options("--module-source-path", src.toString(), 339 "--add-exports", "m1x/p1=m2x", 340 "--add-exports", "m1x/p1=m3x") 341 .outdir(classes) 342 .files(findJavaFiles(src)) 343 .run() 344 .writeAll(); 345 } 346 347 @Test testNoReads(Path base)348 public void testNoReads(Path base) throws Exception { 349 Path src = base.resolve("src"); 350 Path src_m1 = src.resolve("m1x"); 351 tb.writeJavaFiles(src_m1, 352 "module m1x { }", 353 "package p1; public class C1 { }"); 354 Path src_m2 = src.resolve("m2x"); 355 tb.writeJavaFiles(src_m2, 356 "module m2x { }", 357 "package p2; class C2 { p1.C1 c1; }"); 358 Path classes = base.resolve("classes"); 359 tb.createDirectories(classes); 360 361 String log; 362 363 log = new JavacTask(tb) 364 .options("--module-source-path", src.toString(), 365 "-XDrawDiagnostics") 366 .outdir(classes) 367 .files(findJavaFiles(src)) 368 .run(Expect.FAIL) 369 .writeAll() 370 .getOutput(OutputKind.DIRECT); 371 372 checkOutputContains(log, 373 "C2.java:1:24: compiler.err.package.not.visible: p1, (compiler.misc.not.def.access.does.not.read: m2x, p1, m1x)"); 374 375 log = new JavacTask(tb) 376 .options("--module-source-path", src.toString(), 377 "-XDrawDiagnostics", 378 "--add-exports", "m1x/p1=m2x") 379 .outdir(classes) 380 .files(findJavaFiles(src)) 381 .run(Expect.FAIL) 382 .writeAll() 383 .getOutput(OutputKind.DIRECT); 384 385 checkOutputContains(log, 386 "C2.java:1:24: compiler.err.package.not.visible: p1, (compiler.misc.not.def.access.does.not.read: m2x, p1, m1x)"); 387 388 Path mp = base.resolve("mp"); 389 tb.createDirectories(mp); 390 391 new JavacTask(tb) 392 .options("--module-source-path", src.toString(), 393 "-XDrawDiagnostics", 394 "--add-exports", "m1x/p1=m2x", 395 "--add-reads", "m2x=m1x") 396 .outdir(mp) 397 .files(findJavaFiles(src)) 398 .run(Expect.SUCCESS) 399 .writeAll(); 400 401 log = new JavacTask(tb) 402 .options("-XDrawDiagnostics", 403 "--add-exports", "m1x/p1=m2x", 404 "--add-reads", "m2x=m1x", 405 "--module-path", mp.toString()) 406 .outdir(classes) 407 .files(findJavaFiles(src_m2)) 408 .run(Expect.FAIL) 409 .writeAll() 410 .getOutput(OutputKind.DIRECT); 411 412 checkOutputContains(log, 413 "C2.java:1:24: compiler.err.package.not.visible: p1, (compiler.misc.not.def.access.does.not.read: m2x, p1, m1x)"); 414 checkOutputContains(log, 415 "- compiler.warn.module.for.option.not.found: --add-reads, m1x"); 416 checkOutputContains(log, 417 "- compiler.warn.module.for.option.not.found: --add-exports, m1x"); 418 419 new JavacTask(tb) 420 .options("-XDrawDiagnostics", 421 "--add-exports", "m1x/p1=m2x", 422 "--add-reads", "m2x=m1x", 423 "--module-path", mp.toString(), 424 "--add-modules", "m1x") 425 .outdir(classes) 426 .files(findJavaFiles(src_m2)) 427 .run(Expect.SUCCESS) 428 .writeAll() 429 .getOutput(OutputKind.DIRECT); 430 } 431 } 432