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  * @summary Test the --add-exports option
  27  * @library /tools/lib
  28  * @modules jdk.compiler/com.sun.tools.javac.api
  29  *          jdk.compiler/com.sun.tools.javac.main
  30  * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
  31  * @run main AddExportsTest
  32  */
  33 
  34 import java.nio.file.Files;
  35 import java.nio.file.Path;
  36 import java.util.Set;
  37 
  38 import toolbox.JavacTask;
  39 import toolbox.Task;
  40 import toolbox.ToolBox;
  41 
  42 public class AddExportsTest extends ModuleTestBase {
  43 
  44     public static void main(String... args) throws Exception {
  45         new AddExportsTest().runTests();
  46     }
  47 
  48     @Test
  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 
  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             "javac: no value for --add-exports option");
  69     }
  70 
  71     @Test
  72     public void testEmptyItem(Path base) throws Exception {
  73         Path src = base.resolve("src");
  74         Path src_m1 = src.resolve("m1");
  75         tb.writeJavaFiles(src_m1,
  76                           "module m1 { }",
  77                           "package p1; public class C1 { }");
  78         Path src_m2 = src.resolve("m2");
  79         tb.writeJavaFiles(src_m2,
  80                           "module m2 { }",
  81                           "package p2; class C2 { p1.C1 c1; }");
  82         Path src_m3 = src.resolve("m3");
  83         tb.writeJavaFiles(src_m3,
  84                           "module m3 { }",
  85                           "package p3; class C3 { p1.C1 c1; }");
  86         Path classes = base.resolve("classes");
  87         tb.createDirectories(classes);
  88 
  89         testEmptyItem(src, classes, "m1/p1=,m2,m3");
  90         testEmptyItem(src, classes, "m1/p1=m2,,m3");
  91         testEmptyItem(src, classes, "m1/p1=m2,m3,");
  92     }
  93 
  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
 105     public void testEmptyList(Path base) throws Exception {
 106         Path src = base.resolve("src");
 107         Path src_m1 = src.resolve("m1");
 108         tb.writeJavaFiles(src_m1,
 109                           "module m1 { exports p1; }",
 110                           "package p1; public class C1 { }");
 111         Path classes = base.resolve("classes");
 112         tb.createDirectories(classes);
 113 
 114         testEmptyList(src, classes, "m1/p1=");
 115         testEmptyList(src, classes, "m1/p1=,");
 116     }
 117 
 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             "javac: bad value for --add-exports option: '" + option + "'");
 130     }
 131 
 132     @Test
 133     public void testMissingSourceParts(Path base) throws Exception {
 134         Path src = base.resolve("src");
 135         Path src_m1 = src.resolve("m1");
 136         tb.writeJavaFiles(src_m1,
 137                           "module m1 { exports p1; }",
 138                           "package p1; public class C1 { }");
 139         Path src_m2 = src.resolve("m2");
 140         tb.writeJavaFiles(src_m2,
 141                           "module m2 { }",
 142                           "package p2; class C2 { p1.C1 c1; }");
 143         Path classes = base.resolve("classes");
 144         tb.createDirectories(classes);
 145 
 146         testMissingSourcePart(src, classes, "=m2");
 147         testMissingSourcePart(src, classes, "/=m2");
 148         testMissingSourcePart(src, classes, "m1/=m2");
 149         testMissingSourcePart(src, classes, "/p1=m2");
 150         testMissingSourcePart(src, classes, "m1p1=m2");
 151     }
 152 
 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             "javac: bad value for --add-exports option: '" + option + "'");
 165     }
 166 
 167     @Test
 168     public void testBadSourceParts(Path base) throws Exception {
 169         Path src = base.resolve("src");
 170         Path src_m1 = src.resolve("m1");
 171         tb.writeJavaFiles(src_m1,
 172                           "module m1 { exports p1; }",
 173                           "package p1; public class C1 { }");
 174         Path src_m2 = src.resolve("m2");
 175         tb.writeJavaFiles(src_m2,
 176                           "module m2 { }",
 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=m2", "m!");
 182         testBadSourcePart(src, classes, "m1/p!=m2", "p!");
 183     }
 184 
 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
 202     public void testBadTarget(Path base) throws Exception {
 203         Path src = base.resolve("src");
 204         Path src_m1 = src.resolve("m1");
 205         tb.writeJavaFiles(src_m1,
 206                           "module m1 { 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", "m1/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
 226     public void testSourceNotFound(Path base) throws Exception {
 227         Path src = base.resolve("src");
 228         Path src_m1 = src.resolve("m1");
 229         tb.writeJavaFiles(src_m1,
 230                           "module m1 { }");
 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=m1")
 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
 249     public void testTargetNotFound(Path base) throws Exception {
 250         Path src = base.resolve("src");
 251         Path src_m1 = src.resolve("m1");
 252         tb.writeJavaFiles(src_m1,
 253                           "module m1 { }",
 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", "m1/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
 273     public void testDuplicate(Path base) throws Exception {
 274         Path src = base.resolve("src");
 275         Path src_m1 = src.resolve("m1");
 276         tb.writeJavaFiles(src_m1,
 277                           "module m1 { }",
 278                           "package p1; public class C1 { }");
 279         Path src_m2 = src.resolve("m2");
 280         tb.writeJavaFiles(src_m2,
 281                           "module m2 { }",
 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", "m1/p1=m2,m2")
 289                 .outdir(classes)
 290                 .files(findJavaFiles(src))
 291                 .run()
 292                 .writeAll();
 293     }
 294 
 295     @Test
 296     public void testRepeated_SameTarget(Path base) throws Exception {
 297         Path src = base.resolve("src");
 298         Path src_m1 = src.resolve("m1");
 299         tb.writeJavaFiles(src_m1,
 300                           "module m1 { }",
 301                           "package p1; public class C1 { }");
 302         Path src_m2 = src.resolve("m2");
 303         tb.writeJavaFiles(src_m2,
 304                           "module m2 { }",
 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", "m1/p1=m2",
 312                          "--add-exports", "m1/p1=m2")
 313                 .outdir(classes)
 314                 .files(findJavaFiles(src))
 315                 .run()
 316                 .writeAll();
 317     }
 318 
 319     @Test
 320     public void testRepeated_DifferentTarget(Path base) throws Exception {
 321         Path src = base.resolve("src");
 322         Path src_m1 = src.resolve("m1");
 323         tb.writeJavaFiles(src_m1,
 324                           "module m1 { }",
 325                           "package p1; public class C1 { }");
 326         Path src_m2 = src.resolve("m2");
 327         tb.writeJavaFiles(src_m2,
 328                           "module m2 { }",
 329                           "package p2; class C2 { p1.C1 c1; }");
 330         Path src_m3 = src.resolve("m3");
 331         tb.writeJavaFiles(src_m3,
 332                           "module m3 { }",
 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", "m1/p1=m2",
 340                          "--add-exports", "m1/p1=m3")
 341                 .outdir(classes)
 342                 .files(findJavaFiles(src))
 343                 .run()
 344                 .writeAll();
 345     }
 346 }