ProvidesTest.java revision 3993:ce416299fd2d
1/* 2 * Copyright (c) 2015, 2017, 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 * @summary simple tests of module provides 27 * @bug 8168854 8172807 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 ModuleTestBase 33 * @run main ProvidesTest 34 */ 35 36import java.nio.file.Files; 37import java.nio.file.Path; 38import java.util.Arrays; 39import java.util.List; 40 41import toolbox.JavacTask; 42import toolbox.Task; 43import toolbox.Task.Expect; 44 45public class ProvidesTest extends ModuleTestBase { 46 public static void main(String... args) throws Exception { 47 ProvidesTest t = new ProvidesTest(); 48 t.runTests(); 49 } 50 51 @Test 52 public void testSimple(Path base) throws Exception { 53 Path src = base.resolve("src"); 54 tb.writeJavaFiles(src, 55 "module m { provides p1.C1 with p2.C2; }", 56 "package p1; public class C1 { }", 57 "package p2; public class C2 extends p1.C1 { }"); 58 Path classes = base.resolve("classes"); 59 Files.createDirectories(classes); 60 61 new JavacTask(tb) 62 .outdir(classes) 63 .files(findJavaFiles(src)) 64 .run(Task.Expect.SUCCESS) 65 .writeAll(); 66 } 67 68 @Test 69 public void testMulti(Path base) throws Exception { 70 Path src = base.resolve("src"); 71 tb.writeJavaFiles(src.resolve("m1x"), 72 "module m1x { exports p1; }", 73 "package p1; public class C1 { }"); 74 tb.writeJavaFiles(src.resolve("m2x"), 75 "module m2x { requires m1x; provides p1.C1 with p2.C2; }", 76 "package p2; public class C2 extends p1.C1 { }"); 77 Path modules = base.resolve("modules"); 78 Files.createDirectories(modules); 79 80 new JavacTask(tb) 81 .options("--module-source-path", src.toString()) 82 .outdir(modules) 83 .files(findJavaFiles(src)) 84 .run(Task.Expect.SUCCESS) 85 .writeAll(); 86 87 } 88 89 @Test 90 public void testMissingWith(Path base) throws Exception { 91 Path src = base.resolve("src"); 92 tb.writeJavaFiles(src, 93 "module m { provides p.C; }", 94 "package p; public class C { }"); 95 Path classes = base.resolve("classes"); 96 Files.createDirectories(classes); 97 98 String log = new JavacTask(tb) 99 .options("-XDrawDiagnostics") 100 .outdir(classes) 101 .files(findJavaFiles(src)) 102 .run(Task.Expect.FAIL) 103 .writeAll() 104 .getOutput(Task.OutputKind.DIRECT); 105 106 if (!log.contains("module-info.java:1:24: compiler.err.expected: 'with'")) 107 throw new Exception("expected output not found"); 108 109 } 110 111 @Test 112 public void testDuplicateImplementations1(Path base) throws Exception { 113 Path src = base.resolve("src"); 114 tb.writeJavaFiles(src, 115 "module m { exports p1; exports p2; provides p1.C1 with p2.C2, p2.C2; }", 116 "package p1; public class C1 { }", 117 "package p2; public class C2 extends p1.C1 { }"); 118 Path classes = base.resolve("classes"); 119 Files.createDirectories(classes); 120 121 List<String> output = new JavacTask(tb) 122 .options("-XDrawDiagnostics") 123 .outdir(classes) 124 .files(findJavaFiles(src)) 125 .run(Task.Expect.FAIL) 126 .writeAll() 127 .getOutputLines(Task.OutputKind.DIRECT); 128 129 List<String> expected = Arrays.asList( 130 "module-info.java:1:65: compiler.err.duplicate.provides: p1.C1, p2.C2", 131 "1 error"); 132 if (!output.containsAll(expected)) { 133 throw new Exception("Expected output not found"); 134 } 135 } 136 137 @Test 138 public void testDuplicateImplementations2(Path base) throws Exception { 139 Path src = base.resolve("src"); 140 tb.writeJavaFiles(src, 141 "module m { exports p1; provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }", 142 "package p1; public class C1 { }", 143 "package p2; public class C2 extends p1.C1 { }"); 144 Path classes = base.resolve("classes"); 145 Files.createDirectories(classes); 146 147 List<String> output = new JavacTask(tb) 148 .options("-XDrawDiagnostics") 149 .outdir(classes) 150 .files(findJavaFiles(src)) 151 .run(Task.Expect.FAIL) 152 .writeAll() 153 .getOutputLines(Task.OutputKind.DIRECT); 154 155 List<String> expected = Arrays.asList( 156 "module-info.java:1:62: compiler.err.repeated.provides.for.service: p1.C1", 157 "module-info.java:1:73: compiler.err.duplicate.provides: p1.C1, p2.C2", 158 "2 errors"); 159 if (!output.containsAll(expected)) { 160 throw new Exception("Expected output not found"); 161 } 162 } 163 164 @Test 165 public void testMissingService(Path base) throws Exception { 166 Path src = base.resolve("src"); 167 tb.writeJavaFiles(src, 168 "module m { provides p.Missing with p.C; }", 169 "package p; public class C extends p.Missing { }"); 170 171 List<String> output = new JavacTask(tb) 172 .options("-XDrawDiagnostics") 173 .outdir(Files.createDirectories(base.resolve("classes"))) 174 .files(findJavaFiles(src)) 175 .run(Task.Expect.FAIL) 176 .writeAll() 177 .getOutputLines(Task.OutputKind.DIRECT); 178 179 List<String> expected = Arrays.asList( 180 "C.java:1:36: compiler.err.cant.resolve.location: kindname.class, Missing, , , (compiler.misc.location: kindname.package, p, null)", 181 "module-info.java:1:22: compiler.err.cant.resolve.location: kindname.class, Missing, , , (compiler.misc.location: kindname.package, p, null)", 182 "2 errors"); 183 if (!output.containsAll(expected)) { 184 throw new Exception("Expected output not found"); 185 } 186 } 187 188 @Test 189 public void testProvidesFromAnotherModule(Path base) throws Exception { 190 Path modules = base.resolve("modules"); 191 tb.writeJavaFiles(modules.resolve("M"), 192 "module M { exports p; }", 193 "package p; public class Service { }"); 194 tb.writeJavaFiles(modules.resolve("L"), 195 "module L { requires M; provides p.Service with p.Service; }"); 196 197 List<String> output = new JavacTask(tb) 198 .options("-XDrawDiagnostics", 199 "--module-source-path", modules.toString()) 200 .outdir(Files.createDirectories(base.resolve("classes"))) 201 .files(findJavaFiles(modules)) 202 .run(Task.Expect.FAIL) 203 .writeAll() 204 .getOutputLines(Task.OutputKind.DIRECT); 205 List<String> expected = Arrays.asList( 206 "module-info.java:1:24: compiler.err.service.implementation.not.in.right.module: M", 207 "1 error"); 208 if (!output.containsAll(expected)) { 209 throw new Exception("Expected output not found"); 210 } 211 212 } 213 214 @Test 215 public void testServiceIsNotImplemented(Path base) throws Exception { 216 Path src = base.resolve("src"); 217 tb.writeJavaFiles(src, 218 "module m { provides p.A with p.B; }", 219 "package p; public class A { }", 220 "package p; public class B { }"); 221 222 List<String> output = new JavacTask(tb) 223 .options("-XDrawDiagnostics") 224 .outdir(Files.createDirectories(base.resolve("classes"))) 225 .files(findJavaFiles(src)) 226 .run(Task.Expect.FAIL) 227 .writeAll() 228 .getOutputLines(Task.OutputKind.DIRECT); 229 230 List<String> expected = Arrays.asList( 231 "module-info.java:1:31: compiler.err.service.implementation.must.be.subtype.of.service.interface", 232 "module-info.java:1:12: compiler.warn.service.provided.but.not.exported.or.used: p.A", 233 "1 error", 234 "1 warning"); 235 if (!output.containsAll(expected)) { 236 throw new Exception("Expected output not found"); 237 } 238 } 239 240 @Test 241 public void testMissingImplementation(Path base) throws Exception { 242 Path src = base.resolve("src"); 243 tb.writeJavaFiles(src, 244 "module m { provides p.C with p.Impl; }", 245 "package p; public class C { }"); 246 247 List<String> output = new JavacTask(tb) 248 .options("-XDrawDiagnostics") 249 .outdir(Files.createDirectories(base.resolve("classes"))) 250 .files(findJavaFiles(src)) 251 .run(Task.Expect.FAIL) 252 .writeAll() 253 .getOutputLines(Task.OutputKind.DIRECT); 254 255 List<String> expected = Arrays.asList("module-info.java:1:31: compiler.err.cant.resolve.location: kindname.class, Impl, , , (compiler.misc.location: kindname.package, p, null)", 256 "1 error"); 257 if (!output.containsAll(expected)) { 258 throw new Exception("Expected output not found"); 259 } 260 } 261 262 @Test 263 public void testSeveralImplementations(Path base) throws Exception { 264 Path src = base.resolve("src"); 265 tb.writeJavaFiles(src, 266 "module m { provides p.C with p.Impl1, p.Impl2; }", 267 "package p; public class C { }", 268 "package p; public class Impl1 extends p.C { }", 269 "package p; public class Impl2 extends p.C { }"); 270 271 new JavacTask(tb) 272 .outdir(Files.createDirectories(base.resolve("classes"))) 273 .files(findJavaFiles(src)) 274 .run(Task.Expect.SUCCESS) 275 .writeAll(); 276 } 277 278 @Test 279 public void testRepeatedProvides(Path base) throws Exception { 280 Path src = base.resolve("src"); 281 tb.writeJavaFiles(src, 282 "module m { exports p; provides p.C with p.Impl1; provides p.C with p.Impl2; }", 283 "package p; public class C { }", 284 "package p; public class Impl1 extends p.C { }", 285 "package p; public class Impl2 extends p.C { }"); 286 287 List<String> output = new JavacTask(tb) 288 .options("-XDrawDiagnostics") 289 .outdir(Files.createDirectories(base.resolve("classes"))) 290 .files(findJavaFiles(src)) 291 .run(Task.Expect.FAIL) 292 .writeAll() 293 .getOutputLines(Task.OutputKind.DIRECT); 294 295 List<String> expected = Arrays.asList("module-info.java:1:60: compiler.err.repeated.provides.for.service: p.C", 296 "1 error"); 297 if (!output.containsAll(expected)) { 298 throw new Exception("Expected output not found"); 299 } 300 } 301 302 @Test 303 public void testOneImplementationsForServices(Path base) throws Exception { 304 Path src = base.resolve("src"); 305 tb.writeJavaFiles(src, 306 "module m { provides p.Service1 with p.Impl; provides p.Service2 with p.Impl; }", 307 "package p; public interface Service1 { }", 308 "package p; public abstract class Service2 { }", 309 "package p; public class Impl extends p.Service2 implements p.Service1 { }"); 310 311 new JavacTask(tb) 312 .outdir(Files.createDirectories(base.resolve("classes"))) 313 .files(findJavaFiles(src)) 314 .run(Task.Expect.SUCCESS) 315 .writeAll(); 316 } 317 318 @Test 319 public void testAbstractImplementation(Path base) throws Exception { 320 Path src = base.resolve("src"); 321 tb.writeJavaFiles(src, 322 "module m { provides p1.C1 with p2.C2; }", 323 "package p1; public class C1 { }", 324 "package p2; public abstract class C2 extends p1.C1 { }"); 325 326 List<String> output = new JavacTask(tb) 327 .options("-XDrawDiagnostics") 328 .outdir(Files.createDirectories(base.resolve("classes"))) 329 .files(findJavaFiles(src)) 330 .run(Task.Expect.FAIL) 331 .writeAll() 332 .getOutputLines(Task.OutputKind.DIRECT); 333 334 List<String> expected = Arrays.asList( 335 "module-info.java:1:34: compiler.err.service.implementation.is.abstract: p2.C2"); 336 if (!output.containsAll(expected)) { 337 throw new Exception("Expected output not found"); 338 } 339 } 340 341 @Test 342 public void testInterfaceImplementation(Path base) throws Exception { 343 Path src = base.resolve("src"); 344 tb.writeJavaFiles(src, 345 "module m { provides p1.Service with p2.Impl; }", 346 "package p1; public interface Service { }", 347 "package p2; public interface Impl extends p1.Service { }"); 348 349 List<String> output = new JavacTask(tb) 350 .options("-XDrawDiagnostics") 351 .outdir(Files.createDirectories(base.resolve("classes"))) 352 .files(findJavaFiles(src)) 353 .run(Task.Expect.FAIL) 354 .writeAll() 355 .getOutputLines(Task.OutputKind.DIRECT); 356 357 List<String> expected = Arrays.asList( 358 "module-info.java:1:39: compiler.err.service.implementation.is.abstract: p2.Impl"); 359 if (!output.containsAll(expected)) { 360 throw new Exception("Expected output not found"); 361 } 362 } 363 364 @Test 365 public void testProtectedImplementation(Path base) throws Exception { 366 Path src = base.resolve("src"); 367 tb.writeJavaFiles(src, 368 "module m { provides p1.C1 with p2.C2; }", 369 "package p1; public class C1 { }", 370 "package p2; class C2 extends p1.C1 { }"); 371 372 List<String> output = new JavacTask(tb) 373 .options("-XDrawDiagnostics") 374 .outdir(Files.createDirectories(base.resolve("classes"))) 375 .files(findJavaFiles(src)) 376 .run(Task.Expect.FAIL) 377 .writeAll() 378 .getOutputLines(Task.OutputKind.DIRECT); 379 380 List<String> expected = Arrays.asList("module-info.java:1:34: compiler.err.not.def.public: p2.C2, p2", 381 "1 error"); 382 if (!output.containsAll(expected)) { 383 throw new Exception("Expected output not found"); 384 } 385 } 386 387 @Test 388 public void testNoNoArgConstructor(Path base) throws Exception { 389 Path src = base.resolve("src"); 390 tb.writeJavaFiles(src, 391 "module m { uses p1.C1; provides p1.C1 with p2.C2; }", 392 "package p1; public class C1 { }", 393 "package p2; public class C2 extends p1.C1 { public C2(String str) { } }"); 394 395 List<String> output = new JavacTask(tb) 396 .options("-XDrawDiagnostics") 397 .outdir(Files.createDirectories(base.resolve("classes"))) 398 .files(findJavaFiles(src)) 399 .run(Task.Expect.FAIL) 400 .writeAll() 401 .getOutputLines(Task.OutputKind.DIRECT); 402 403 List<String> expected = Arrays.asList( 404 "module-info.java:1:46: compiler.err.service.implementation.doesnt.have.a.no.args.constructor: p2.C2"); 405 if (!output.containsAll(expected)) { 406 throw new Exception("Expected output not found"); 407 } 408 } 409 410 @Test 411 public void testPrivateNoArgConstructor(Path base) throws Exception { 412 Path src = base.resolve("src"); 413 tb.writeJavaFiles(src, 414 "module m { uses p1.C1; provides p1.C1 with p2.C2; }", 415 "package p1; public class C1 { }", 416 "package p2; public class C2 extends p1.C1 { private C2() { } }"); 417 418 List<String> output = new JavacTask(tb) 419 .options("-XDrawDiagnostics") 420 .outdir(Files.createDirectories(base.resolve("classes"))) 421 .files(findJavaFiles(src)) 422 .run(Task.Expect.FAIL) 423 .writeAll() 424 .getOutputLines(Task.OutputKind.DIRECT); 425 426 List<String> expected = Arrays.asList( 427 "module-info.java:1:46: compiler.err.service.implementation.no.args.constructor.not.public: p2.C2"); 428 if (!output.containsAll(expected)) { 429 throw new Exception("Expected output not found"); 430 } 431 } 432 433 @Test 434 public void testServiceIndirectlyImplemented(Path base) throws Exception { 435 Path src = base.resolve("src"); 436 tb.writeJavaFiles(src, 437 "module m { provides p1.C1 with p2.C3; }", 438 "package p1; public class C1 { }", 439 "package p2; public class C2 extends p1.C1 { }", 440 "package p2; public class C3 extends p2.C2 { }"); 441 442 new JavacTask(tb) 443 .outdir(Files.createDirectories(base.resolve("classes"))) 444 .files(findJavaFiles(src)) 445 .run(Task.Expect.SUCCESS) 446 .writeAll(); 447 } 448 449 @Test 450 public void testServiceImplementationInnerClass(Path base) throws Exception { 451 Path src = base.resolve("src"); 452 tb.writeJavaFiles(src, 453 "module m { provides p1.C1 with p2.C2.Inner; }", 454 "package p1; public class C1 { }", 455 "package p2; public class C2 { public class Inner extends p1.C1 { } }"); 456 457 List<String> output = new JavacTask(tb) 458 .options("-XDrawDiagnostics") 459 .outdir(Files.createDirectories(base.resolve("classes"))) 460 .files(findJavaFiles(src)) 461 .run(Task.Expect.FAIL) 462 .writeAll() 463 .getOutputLines(Task.OutputKind.DIRECT); 464 465 List<String> expected = Arrays.asList( 466 "module-info.java:1:37: compiler.err.service.implementation.is.inner: p2.C2.Inner"); 467 if (!output.containsAll(expected)) { 468 throw new Exception("Expected output not found"); 469 } 470 } 471 472 @Test 473 public void testServiceDefinitionInnerClass(Path base) throws Exception { 474 Path src = base.resolve("src"); 475 tb.writeJavaFiles(src, 476 "module m { provides p1.C1.InnerDefinition with p2.C2; }", 477 "package p1; public class C1 { public class InnerDefinition { } }", 478 "package p2; public class C2 extends p1.C1.InnerDefinition { public C2() { new p1.C1().super(); } }"); 479 480 new JavacTask(tb) 481 .options("-XDrawDiagnostics") 482 .outdir(Files.createDirectories(base.resolve("classes"))) 483 .files(findJavaFiles(src)) 484 .run(Expect.SUCCESS) 485 .writeAll(); 486 } 487 488 @Test 489 public void testFactory(Path base) throws Exception { 490 Path src = base.resolve("src"); 491 tb.writeJavaFiles(src, 492 "module m { exports p1; provides p1.C1 with p2.C2; }", 493 "package p1; public interface C1 { }", 494 "package p2; public class C2 { public static p1.C1 provider() { return null; } }"); 495 496 new JavacTask(tb) 497 .options("-XDrawDiagnostics") 498 .outdir(Files.createDirectories(base.resolve("classes"))) 499 .files(findJavaFiles(src)) 500 .run() 501 .writeAll() 502 .getOutput(Task.OutputKind.DIRECT); 503 504 List<String> output; 505 List<String> expected; 506 507 tb.writeJavaFiles(src, 508 "package p2; public class C2 { public p1.C1 provider() { return null; } }"); 509 510 output = new JavacTask(tb) 511 .options("-XDrawDiagnostics") 512 .outdir(Files.createDirectories(base.resolve("classes"))) 513 .files(findJavaFiles(src)) 514 .run(Task.Expect.FAIL) 515 .writeAll() 516 .getOutputLines(Task.OutputKind.DIRECT); 517 518 expected = Arrays.asList("module-info.java:1:46: compiler.err.service.implementation.must.be.subtype.of.service.interface", 519 "1 error"); 520 521 if (!expected.equals(output)) { 522 throw new Exception("Expected output not found. Output: " + output); 523 } 524 525 tb.writeJavaFiles(src, 526 "package p2; public class C2 { static p1.C1 provider() { return null; } }"); 527 528 output = new JavacTask(tb) 529 .options("-XDrawDiagnostics") 530 .outdir(Files.createDirectories(base.resolve("classes"))) 531 .files(findJavaFiles(src)) 532 .run(Task.Expect.FAIL) 533 .writeAll() 534 .getOutputLines(Task.OutputKind.DIRECT); 535 536 expected = Arrays.asList("module-info.java:1:46: compiler.err.service.implementation.must.be.subtype.of.service.interface", 537 "1 error"); 538 539 if (!expected.equals(output)) { 540 throw new Exception("Expected output not found. Output: " + output); 541 } 542 543 tb.writeJavaFiles(src, 544 "package p2; public class C2 { public static Object provider() { return null; } }"); 545 546 output = new JavacTask(tb) 547 .options("-XDrawDiagnostics") 548 .outdir(Files.createDirectories(base.resolve("classes"))) 549 .files(findJavaFiles(src)) 550 .run(Task.Expect.FAIL) 551 .writeAll() 552 .getOutputLines(Task.OutputKind.DIRECT); 553 554 expected = Arrays.asList("module-info.java:1:46: compiler.err.service.implementation.provider.return.must.be.subtype.of.service.interface", 555 "1 error"); 556 557 if (!expected.equals(output)) { 558 throw new Exception("Expected output not found. Output: " + output); 559 } 560 561 tb.writeJavaFiles(src, 562 "package p2; public class C2 { public static p1.C1 provider = new p1.C1() {}; }"); 563 564 output = new JavacTask(tb) 565 .options("-XDrawDiagnostics") 566 .outdir(Files.createDirectories(base.resolve("classes"))) 567 .files(findJavaFiles(src)) 568 .run(Task.Expect.FAIL) 569 .writeAll() 570 .getOutputLines(Task.OutputKind.DIRECT); 571 572 expected = Arrays.asList("module-info.java:1:46: compiler.err.service.implementation.must.be.subtype.of.service.interface", 573 "1 error"); 574 575 if (!expected.equals(output)) { 576 throw new Exception("Expected output not found. Output: " + output); 577 } 578 } 579} 580