328 .files(findJavaFiles(cpSrc))
329 .run(Task.Expect.FAIL)
330 .writeAll()
331 .getOutputLines(Task.OutputKind.DIRECT);
332
333 if (!Objects.equals(actual, expected)) {
334 throw new IllegalStateException("incorrect errors; actual=" + actual + "; expected=" + expected);
335 }
336 }
337
338 @Test
339 public void testRuntime2Compile(Path base) throws Exception {
340 Path classpathSrc = base.resolve("classpath-src");
341 Path classpathOut = base.resolve("classpath-out");
342
343 tb.writeJavaFiles(classpathSrc,
344 generateCheckAccessibleClass("cp.CP"));
345
346 Files.createDirectories(classpathOut);
347
348 new JavacTask(tb)
349 .outdir(classpathOut)
350 .files(findJavaFiles(classpathSrc))
351 .run()
352 .writeAll()
353 .getOutput(Task.OutputKind.DIRECT);
354
355 Path automaticSrc = base.resolve("automatic-src");
356 Path automaticOut = base.resolve("automatic-out");
357
358 tb.writeJavaFiles(automaticSrc,
359 generateCheckAccessibleClass("automatic.Automatic"));
360
361 Files.createDirectories(automaticOut);
362
363 new JavacTask(tb)
364 .outdir(automaticOut)
365 .files(findJavaFiles(automaticSrc))
366 .run()
367 .writeAll()
368 .getOutput(Task.OutputKind.DIRECT);
369
370 Path modulePath = base.resolve("module-path");
371
372 Files.createDirectories(modulePath);
373
374 Path automaticJar = modulePath.resolve("automatic.jar");
375
376 new JarTask(tb, automaticJar)
377 .baseDir(automaticOut)
378 .files("automatic/Automatic.class")
379 .run();
380
381 Path moduleSrc = base.resolve("module-src");
382 Path m1 = moduleSrc.resolve("m1");
383
384 tb.writeJavaFiles(m1,
385 "module m1 { exports api; }",
386 "package api; public class Api { public void test() { } }");
387
388 new JavacTask(tb)
389 .options("--module-source-path", moduleSrc.toString())
390 .outdir(modulePath)
391 .files(findJavaFiles(moduleSrc))
392 .run()
393 .writeAll()
394 .getOutput(Task.OutputKind.DIRECT);
395
396 int index = 0;
397
398 for (String moduleInfo : MODULE_INFO_VARIANTS) {
399 for (String[] options : OPTIONS_VARIANTS) {
400 index++;
401
402 System.err.println("running check: " + moduleInfo + "; " + Arrays.asList(options));
403
404 Path m2Runtime = base.resolve(index + "-runtime").resolve("m2");
405 Path out = base.resolve(index + "-runtime").resolve("out").resolve("m2");
406
407 Files.createDirectories(out);
408
409 StringBuilder testClassNamed = new StringBuilder();
410
411 testClassNamed.append("package test;\n" +
412 "public class Test {\n" +
413 " public static void main(String... args) throws Exception {\n");
414
415 for (Entry<String, String> e : MODULES_TO_CHECK_TO_SAMPLE_CLASS.entrySet()) {
416 testClassNamed.append(" System.err.println(\"visible:" + e.getKey() + ":\" + java.lang.reflect.Layer.boot().findModule(\"" + e.getKey() + "\").isPresent());\n");
417 }
418
419 testClassNamed.append(" Class<?> cp = Class.forName(Test.class.getClassLoader().getUnnamedModule(), \"cp.CP\");\n");
420 testClassNamed.append(" cp.getDeclaredMethod(\"runMe\").invoke(null);\n");
421
422 testClassNamed.append(" Class<?> automatic = Class.forName(java.lang.reflect.Layer.boot().findModule(\"automatic\").get(), \"automatic.Automatic\");\n");
423 testClassNamed.append(" automatic.getDeclaredMethod(\"runMe\").invoke(null);\n");
424
425 testClassNamed.append(" }\n" +
426 "}");
427
428 tb.writeJavaFiles(m2Runtime, moduleInfo, testClassNamed.toString());
429
430 new JavacTask(tb)
431 .options("--module-path", modulePath.toString())
432 .outdir(out)
433 .files(findJavaFiles(m2Runtime))
434 .run()
435 .writeAll();
436
437 boolean success;
438 String output;
439
440 try {
441 output = new JavaTask(tb)
442 .vmOptions(augmentOptions(options,
443 Collections.emptyList(),
444 "--module-path", modulePath.toString() + File.pathSeparator + out.getParent().toString(),
445 "--class-path", classpathOut.toString(),
446 "--add-reads", "m2=ALL-UNNAMED,automatic",
447 "-m", "m2/test.Test"))
448 .run()
449 .writeAll()
450 .getOutput(Task.OutputKind.STDERR);
451
452 success = true;
453 } catch (Task.TaskError err) {
454 success = false;
455 output = "";
456 }
457
458 Path m2 = base.resolve(String.valueOf(index)).resolve("m2");
459
460 tb.writeJavaFiles(m2,
461 moduleInfo,
462 "package test;\n" +
463 "public class Test {}\n");
464
465 List<String> auxOptions = success ? Arrays.asList(
466 "--processor-path", System.getProperty("test.class.path"),
467 "-processor", CheckVisibleModule.class.getName(),
468 "-Aoutput=" + output,
469 "-XDaccessInternalAPI=true"
470 ) : Collections.emptyList();
471 new JavacTask(tb)
472 .options(augmentOptions(options,
473 auxOptions,
474 "--module-path", modulePath.toString(),
475 "--class-path", classpathOut.toString(),
476 "--should-stop:ifNoError=FLOW"))
477 .outdir(modulePath)
478 .files(findJavaFiles(m2))
479 .run(success ? Task.Expect.SUCCESS : Task.Expect.FAIL)
480 .writeAll();
481 }
482 }
483 }
484
485 private String generateCheckAccessibleClass(String fqn) {
486 String packageName = fqn.substring(0, fqn.lastIndexOf('.'));
487 String simpleName = fqn.substring(fqn.lastIndexOf('.') + 1);
488 StringBuilder checkClassesAccessible = new StringBuilder();
489 checkClassesAccessible.append("package " + packageName + ";" +
490 "public class " + simpleName + " {" +
493 checkClassesAccessible.append("try {");
494 checkClassesAccessible.append("Class.forName(\"" + e.getValue() + "\").newInstance();");
495 checkClassesAccessible.append("System.err.println(\"" + fqn + ":" + e.getKey() + ":true\");");
496 checkClassesAccessible.append("} catch (Exception ex) {");
497 checkClassesAccessible.append("System.err.println(\"" + fqn + ":" + e.getKey() + ":false\");");
498 checkClassesAccessible.append("}");
499 }
500
501 checkClassesAccessible.append(" }\n" +
502 "}");
503
504 return checkClassesAccessible.toString();
505 }
506
507 private static final Map<String, String> MODULES_TO_CHECK_TO_SAMPLE_CLASS = new LinkedHashMap<>();
508
509 static {
510 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("m1", "api.Api");
511 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("m2", "test.Test");
512 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("java.base", "java.lang.Object");
513 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("java.compiler", "javax.tools.ToolProvider");
514 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("jdk.compiler", "com.sun.tools.javac.Main");
515 };
516
517 @SupportedAnnotationTypes("*")
518 @SupportedOptions("output")
519 public static final class CheckVisibleModule extends AbstractProcessor {
520
521 @Override
522 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
523 String expected = processingEnv.getOptions().get("output");
524 Set<String> expectedElements = new HashSet<>(Arrays.asList(expected.split(System.getProperty("line.separator"))));
525 Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
526 Symtab syms = Symtab.instance(context);
527
528 for (Entry<String, String> e : MODULES_TO_CHECK_TO_SAMPLE_CLASS.entrySet()) {
529 String module = e.getKey();
530 ModuleElement mod = processingEnv.getElementUtils().getModuleElement(module);
531 String visible = "visible:" + module + ":" + (mod != null);
532
533 if (!expectedElements.contains(visible)) {
534 throw new AssertionError("actual: " + visible + "; expected: " + expected);
556
557 @Override
558 public SourceVersion getSupportedSourceVersion() {
559 return SourceVersion.latest();
560 }
561
562 }
563
564 public String[] augmentOptions(String[] options, List<String> auxOptions, String... baseOptions) {
565 List<String> all = new ArrayList<>();
566
567 all.addAll(Arrays.asList(options));
568 all.addAll(Arrays.asList(baseOptions));
569 all.addAll(auxOptions);
570
571 return all.toArray(new String[0]);
572 }
573
574 private static final String[] MODULE_INFO_VARIANTS = {
575 "module m2 { exports test; }",
576 "module m2 { requires m1; exports test; }",
577 "module m2 { requires jdk.compiler; exports test; }",
578 };
579
580 private static final String[][] OPTIONS_VARIANTS = {
581 {"--add-modules", "automatic"},
582 {"--add-modules", "m1,automatic"},
583 {"--add-modules", "jdk.compiler,automatic"},
584 {"--add-modules", "m1,jdk.compiler,automatic"},
585 {"--add-modules", "ALL-SYSTEM,automatic"},
586 {"--limit-modules", "java.base", "--add-modules", "automatic"},
587 {"--limit-modules", "java.base", "--add-modules", "ALL-SYSTEM,automatic"},
588 {"--limit-modules", "m2", "--add-modules", "automatic"},
589 {"--limit-modules", "jdk.compiler", "--add-modules", "automatic"},
590 };
591 }
|
328 .files(findJavaFiles(cpSrc))
329 .run(Task.Expect.FAIL)
330 .writeAll()
331 .getOutputLines(Task.OutputKind.DIRECT);
332
333 if (!Objects.equals(actual, expected)) {
334 throw new IllegalStateException("incorrect errors; actual=" + actual + "; expected=" + expected);
335 }
336 }
337
338 @Test
339 public void testRuntime2Compile(Path base) throws Exception {
340 Path classpathSrc = base.resolve("classpath-src");
341 Path classpathOut = base.resolve("classpath-out");
342
343 tb.writeJavaFiles(classpathSrc,
344 generateCheckAccessibleClass("cp.CP"));
345
346 Files.createDirectories(classpathOut);
347
348 System.err.println("Compiling classpath-src files:");
349 new JavacTask(tb)
350 .outdir(classpathOut)
351 .files(findJavaFiles(classpathSrc))
352 .run()
353 .writeAll()
354 .getOutput(Task.OutputKind.DIRECT);
355
356 Path automaticSrc = base.resolve("automatic-src");
357 Path automaticOut = base.resolve("automatic-out");
358
359 tb.writeJavaFiles(automaticSrc,
360 generateCheckAccessibleClass("automatic.Automatic"));
361
362 Files.createDirectories(automaticOut);
363
364 System.err.println("Compiling automatic-src files:");
365 new JavacTask(tb)
366 .outdir(automaticOut)
367 .files(findJavaFiles(automaticSrc))
368 .run()
369 .writeAll()
370 .getOutput(Task.OutputKind.DIRECT);
371
372 Path modulePath = base.resolve("module-path");
373
374 Files.createDirectories(modulePath);
375
376 Path automaticJar = modulePath.resolve("automatic.jar");
377
378 System.err.println("Creating automatic.jar:");
379 new JarTask(tb, automaticJar)
380 .baseDir(automaticOut)
381 .files("automatic/Automatic.class")
382 .run();
383
384 Path moduleSrc = base.resolve("module-src");
385 Path m1 = moduleSrc.resolve("m1");
386
387 tb.writeJavaFiles(m1,
388 "module m1 { exports api; }",
389 "package api; public class Api { public void test() { } }");
390
391 System.err.println("Compiling module-src files:");
392 new JavacTask(tb)
393 .options("--module-source-path", moduleSrc.toString())
394 .outdir(modulePath)
395 .files(findJavaFiles(moduleSrc))
396 .run()
397 .writeAll()
398 .getOutput(Task.OutputKind.DIRECT);
399
400 int index = 0;
401
402 for (String moduleInfo : MODULE_INFO_VARIANTS) {
403 for (String[] options : OPTIONS_VARIANTS) {
404 index++;
405
406 System.err.println("Running check: " + moduleInfo + "; " + Arrays.asList(options));
407
408 Path m2Runtime = base.resolve(index + "-runtime").resolve("m2");
409 Path out = base.resolve(index + "-runtime").resolve("out").resolve("m2");
410
411 Files.createDirectories(out);
412
413 StringBuilder testClassNamed = new StringBuilder();
414
415 testClassNamed.append("package test;\n" +
416 "public class Test {\n" +
417 " public static void main(String... args) throws Exception {\n");
418
419 for (Entry<String, String> e : MODULES_TO_CHECK_TO_SAMPLE_CLASS.entrySet()) {
420 testClassNamed.append(" System.err.println(\"visible:" + e.getKey() + ":\" + java.lang.reflect.Layer.boot().findModule(\"" + e.getKey() + "\").isPresent());\n");
421 }
422
423 testClassNamed.append(" Class<?> cp = Class.forName(Test.class.getClassLoader().getUnnamedModule(), \"cp.CP\");\n");
424 testClassNamed.append(" cp.getDeclaredMethod(\"runMe\").invoke(null);\n");
425
426 testClassNamed.append(" Class<?> automatic = Class.forName(java.lang.reflect.Layer.boot().findModule(\"automatic\").get(), \"automatic.Automatic\");\n");
427 testClassNamed.append(" automatic.getDeclaredMethod(\"runMe\").invoke(null);\n");
428
429 testClassNamed.append(" }\n" +
430 "}");
431
432 tb.writeJavaFiles(m2Runtime, moduleInfo, testClassNamed.toString());
433
434 System.err.println("Compiling " + m2Runtime + " files:");
435 new JavacTask(tb)
436 .options("--module-path", modulePath.toString())
437 .outdir(out)
438 .files(findJavaFiles(m2Runtime))
439 .run()
440 .writeAll();
441
442 boolean success;
443 String output;
444
445 try {
446 System.err.println("Running m2/test.Test:");
447 output = new JavaTask(tb)
448 .vmOptions(augmentOptions(options,
449 Collections.emptyList(),
450 "--module-path", modulePath.toString() + File.pathSeparator + out.getParent().toString(),
451 "--class-path", classpathOut.toString(),
452 "--add-reads", "m2=ALL-UNNAMED,automatic",
453 "-m", "m2/test.Test"))
454 .run()
455 .writeAll()
456 .getOutput(Task.OutputKind.STDERR);
457
458 success = true;
459 } catch (Task.TaskError err) {
460 success = false;
461 output = "";
462 }
463
464 Path m2 = base.resolve(String.valueOf(index)).resolve("m2");
465
466 tb.writeJavaFiles(m2,
467 moduleInfo,
468 "package test;\n" +
469 "public class Test {}\n");
470
471 List<String> auxOptions = success ? Arrays.asList(
472 "--processor-path", System.getProperty("test.class.path"),
473 "-processor", CheckVisibleModule.class.getName(),
474 "-Aoutput=" + output,
475 "-XDaccessInternalAPI=true"
476 ) : Collections.emptyList();
477
478 System.err.println("Compiling/processing m2 files:");
479 new JavacTask(tb)
480 .options(augmentOptions(options,
481 auxOptions,
482 "--module-path", modulePath.toString(),
483 "--class-path", classpathOut.toString(),
484 "--should-stop:ifNoError=FLOW"))
485 .outdir(modulePath)
486 .files(findJavaFiles(m2))
487 .run(success ? Task.Expect.SUCCESS : Task.Expect.FAIL)
488 .writeAll();
489 }
490 }
491 }
492
493 private String generateCheckAccessibleClass(String fqn) {
494 String packageName = fqn.substring(0, fqn.lastIndexOf('.'));
495 String simpleName = fqn.substring(fqn.lastIndexOf('.') + 1);
496 StringBuilder checkClassesAccessible = new StringBuilder();
497 checkClassesAccessible.append("package " + packageName + ";" +
498 "public class " + simpleName + " {" +
501 checkClassesAccessible.append("try {");
502 checkClassesAccessible.append("Class.forName(\"" + e.getValue() + "\").newInstance();");
503 checkClassesAccessible.append("System.err.println(\"" + fqn + ":" + e.getKey() + ":true\");");
504 checkClassesAccessible.append("} catch (Exception ex) {");
505 checkClassesAccessible.append("System.err.println(\"" + fqn + ":" + e.getKey() + ":false\");");
506 checkClassesAccessible.append("}");
507 }
508
509 checkClassesAccessible.append(" }\n" +
510 "}");
511
512 return checkClassesAccessible.toString();
513 }
514
515 private static final Map<String, String> MODULES_TO_CHECK_TO_SAMPLE_CLASS = new LinkedHashMap<>();
516
517 static {
518 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("m1", "api.Api");
519 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("m2", "test.Test");
520 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("java.base", "java.lang.Object");
521 };
522
523 @SupportedAnnotationTypes("*")
524 @SupportedOptions("output")
525 public static final class CheckVisibleModule extends AbstractProcessor {
526
527 @Override
528 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
529 String expected = processingEnv.getOptions().get("output");
530 Set<String> expectedElements = new HashSet<>(Arrays.asList(expected.split(System.getProperty("line.separator"))));
531 Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
532 Symtab syms = Symtab.instance(context);
533
534 for (Entry<String, String> e : MODULES_TO_CHECK_TO_SAMPLE_CLASS.entrySet()) {
535 String module = e.getKey();
536 ModuleElement mod = processingEnv.getElementUtils().getModuleElement(module);
537 String visible = "visible:" + module + ":" + (mod != null);
538
539 if (!expectedElements.contains(visible)) {
540 throw new AssertionError("actual: " + visible + "; expected: " + expected);
562
563 @Override
564 public SourceVersion getSupportedSourceVersion() {
565 return SourceVersion.latest();
566 }
567
568 }
569
570 public String[] augmentOptions(String[] options, List<String> auxOptions, String... baseOptions) {
571 List<String> all = new ArrayList<>();
572
573 all.addAll(Arrays.asList(options));
574 all.addAll(Arrays.asList(baseOptions));
575 all.addAll(auxOptions);
576
577 return all.toArray(new String[0]);
578 }
579
580 private static final String[] MODULE_INFO_VARIANTS = {
581 "module m2 { exports test; }",
582 "module m2 { requires m1; exports test; }"
583 };
584
585 private static final String[][] OPTIONS_VARIANTS = {
586 {"--add-modules", "automatic"},
587 {"--add-modules", "m1,automatic"},
588 {"--add-modules", "jdk.compiler,automatic"},
589 {"--add-modules", "m1,jdk.compiler,automatic"},
590 {"--add-modules", "ALL-SYSTEM,automatic"},
591 {"--limit-modules", "java.base", "--add-modules", "automatic"},
592 {"--limit-modules", "java.base", "--add-modules", "ALL-SYSTEM,automatic"},
593 {"--limit-modules", "m2", "--add-modules", "automatic"},
594 {"--limit-modules", "jdk.compiler", "--add-modules", "automatic"},
595 };
596 }
|