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.Path;
  35 
  36 import toolbox.JavacTask;
  37 import toolbox.Task;
  38 
  39 public class AddExportsTest extends ModuleTestBase {
  40 
  41     public static void main(String... args) throws Exception {
  42         new AddExportsTest().runTests();
  43     }
  44 
  45     @Test
  46     public void testEmpty(Path base) throws Exception {
  47         Path src = base.resolve("src");
  48         tb.writeJavaFiles(src, "class Dummy { }");
  49         Path classes = base.resolve("classes");
  50         tb.createDirectories(classes);
  51         testEmpty(src, classes, "--add-exports", "");
  52         testEmpty(src, classes, "--add-exports=");
  53     }
  54 
  55     private void testEmpty(Path src, Path classes, String... options) throws Exception {
  56         String log = new JavacTask(tb, Task.Mode.CMDLINE)
  57                 .options(options)
  58                 .outdir(classes)
  59                 .files(findJavaFiles(src))
  60                 .run(Task.Expect.FAIL)
  61                 .writeAll()
  62                 .getOutput(Task.OutputKind.DIRECT);
  63 
  64         checkOutputContains(log,
  65             "javac: no value for --add-exports option");
  66     }
  67 
  68     @Test
  69     public void testEmptyItem(Path base) throws Exception {
  70         Path src = base.resolve("src");
  71         Path src_m1 = src.resolve("m1x");
  72         tb.writeJavaFiles(src_m1,
  73                           "module m1x { }",
  74                           "package p1; public class C1 { }");
  75         Path src_m2 = src.resolve("m2x");
  76         tb.writeJavaFiles(src_m2,
  77                           "module m2x { }",
  78                           "package p2; class C2 { p1.C1 c1; }");
  79         Path src_m3 = src.resolve("m3x");
  80         tb.writeJavaFiles(src_m3,
  81                           "module m3x { }",
  82                           "package p3; class C3 { p1.C1 c1; }");
  83         Path classes = base.resolve("classes");
  84         tb.createDirectories(classes);
  85 
  86         testEmptyItem(src, classes, "m1x/p1=,m2x,m3x");
  87         testEmptyItem(src, classes, "m1x/p1=m2x,,m3x");
  88         testEmptyItem(src, classes, "m1x/p1=m2x,m3x,");
  89     }
  90 
  91     void testEmptyItem(Path src, Path classes, String option) throws Exception {
  92         new JavacTask(tb)
  93                 .options("--module-source-path", src.toString(),
  94                          "--add-exports", option)
  95                 .outdir(classes)
  96                 .files(findJavaFiles(src))
  97                 .run()
  98                 .writeAll();
  99     }
 100 
 101     @Test
 102     public void testEmptyList(Path base) throws Exception {
 103         Path src = base.resolve("src");
 104         Path src_m1 = src.resolve("m1x");
 105         tb.writeJavaFiles(src_m1,
 106                           "module m1x { exports p1; }",
 107                           "package p1; public class C1 { }");
 108         Path classes = base.resolve("classes");
 109         tb.createDirectories(classes);
 110 
 111         testEmptyList(src, classes, "m1x/p1=");
 112         testEmptyList(src, classes, "m1x/p1=,");
 113     }
 114 
 115     void testEmptyList(Path src, Path classes, String option) throws Exception {
 116         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 117                 .options("--module-source-path", src.toString(),
 118                          "--add-exports", option)
 119                 .outdir(classes)
 120                 .files(findJavaFiles(src))
 121                 .run(Task.Expect.FAIL)
 122                 .writeAll()
 123                 .getOutput(Task.OutputKind.DIRECT);
 124 
 125         checkOutputContains(log,
 126             "javac: bad value for --add-exports option: '" + option + "'");
 127     }
 128 
 129     @Test
 130     public void testMissingSourceParts(Path base) throws Exception {
 131         Path src = base.resolve("src");
 132         Path src_m1 = src.resolve("m1x");
 133         tb.writeJavaFiles(src_m1,
 134                           "module m1x { exports p1; }",
 135                           "package p1; public class C1 { }");
 136         Path src_m2 = src.resolve("m2x");
 137         tb.writeJavaFiles(src_m2,
 138                           "module m2x { }",
 139                           "package p2; class C2 { p1.C1 c1; }");
 140         Path classes = base.resolve("classes");
 141         tb.createDirectories(classes);
 142 
 143         testMissingSourcePart(src, classes, "=m2x");
 144         testMissingSourcePart(src, classes, "/=m2x");
 145         testMissingSourcePart(src, classes, "m1x/=m2x");
 146         testMissingSourcePart(src, classes, "/p1=m2x");
 147         testMissingSourcePart(src, classes, "m1xp1=m2x");
 148     }
 149 
 150     private void testMissingSourcePart(Path src, Path classes, String option) throws Exception {
 151         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 152                 .options("--module-source-path", src.toString(),
 153                          "--add-exports", option)
 154                 .outdir(classes)
 155                 .files(findJavaFiles(src))
 156                 .run(Task.Expect.FAIL)
 157                 .writeAll()
 158                 .getOutput(Task.OutputKind.DIRECT);
 159 
 160         checkOutputContains(log,
 161             "javac: bad value for --add-exports option: '" + option + "'");
 162     }
 163 
 164     @Test
 165     public void testBadSourceParts(Path base) throws Exception {
 166         Path src = base.resolve("src");
 167         Path src_m1 = src.resolve("m1x");
 168         tb.writeJavaFiles(src_m1,
 169                           "module m1x { exports p1; }",
 170                           "package p1; public class C1 { }");
 171         Path src_m2 = src.resolve("m2x");
 172         tb.writeJavaFiles(src_m2,
 173                           "module m2x { }",
 174                           "package p2; class C2 { p1.C1 c1; }");
 175         Path classes = base.resolve("classes");
 176         tb.createDirectories(classes);
 177 
 178         testBadSourcePart(src, classes, "m!/p1=m2x", "m!");
 179         testBadSourcePart(src, classes, "m1x/p!=m2x", "p!");
 180     }
 181 
 182     private void testBadSourcePart(Path src, Path classes, String option, String badName)
 183                 throws Exception {
 184         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 185                 .options("-XDrawDiagnostics",
 186                          "--module-source-path", src.toString(),
 187                          "--add-exports", option)
 188                 .outdir(classes)
 189                 .files(findJavaFiles(src))
 190                 .run(Task.Expect.FAIL)
 191                 .writeAll()
 192                 .getOutput(Task.OutputKind.DIRECT);
 193 
 194         checkOutputContains(log,
 195             "- compiler.warn.bad.name.for.option: --add-exports, " + badName);
 196     }
 197 
 198     @Test
 199     public void testBadTarget(Path base) throws Exception {
 200         Path src = base.resolve("src");
 201         Path src_m1 = src.resolve("m1x");
 202         tb.writeJavaFiles(src_m1,
 203                           "module m1x { exports p1; }",
 204                           "package p1; public class C1 { }");
 205         Path classes = base.resolve("classes");
 206         tb.createDirectories(classes);
 207 
 208         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 209                 .options("-XDrawDiagnostics",
 210                          "--module-source-path", src.toString(),
 211                          "--add-exports", "m1x/p1=m!")
 212                 .outdir(classes)
 213                 .files(findJavaFiles(src))
 214                 .run()
 215                 .writeAll()
 216                 .getOutput(Task.OutputKind.DIRECT);
 217 
 218         checkOutputContains(log,
 219             "- compiler.warn.bad.name.for.option: --add-exports, m!");
 220     }
 221 
 222     @Test
 223     public void testSourceNotFound(Path base) throws Exception {
 224         Path src = base.resolve("src");
 225         Path src_m1 = src.resolve("m1x");
 226         tb.writeJavaFiles(src_m1,
 227                           "module m1x { }");
 228         Path classes = base.resolve("classes");
 229         tb.createDirectories(classes);
 230 
 231         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 232                 .options("-XDrawDiagnostics",
 233                          "--module-source-path", src.toString(),
 234                          "--add-exports", "DoesNotExist/p=m1x")
 235                 .outdir(classes)
 236                 .files(findJavaFiles(src))
 237                 .run()
 238                 .writeAll()
 239                 .getOutput(Task.OutputKind.DIRECT);
 240 
 241         checkOutputContains(log,
 242             "- compiler.warn.module.for.option.not.found: --add-exports, DoesNotExist");
 243     }
 244 
 245     @Test
 246     public void testTargetNotFound(Path base) throws Exception {
 247         Path src = base.resolve("src");
 248         Path src_m1 = src.resolve("m1x");
 249         tb.writeJavaFiles(src_m1,
 250                           "module m1x { }",
 251                           "package p1; class C1 { }");
 252         Path classes = base.resolve("classes");
 253         tb.createDirectories(classes);
 254 
 255         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 256                 .options("-XDrawDiagnostics",
 257                          "--module-source-path", src.toString(),
 258                          "--add-exports", "m1x/p1=DoesNotExist")
 259                 .outdir(classes)
 260                 .files(findJavaFiles(src))
 261                 .run()
 262                 .writeAll()
 263                 .getOutput(Task.OutputKind.DIRECT);
 264 
 265         checkOutputContains(log,
 266             "- compiler.warn.module.for.option.not.found: --add-exports, DoesNotExist");
 267     }
 268 
 269     @Test
 270     public void testDuplicate(Path base) throws Exception {
 271         Path src = base.resolve("src");
 272         Path src_m1 = src.resolve("m1x");
 273         tb.writeJavaFiles(src_m1,
 274                           "module m1x { }",
 275                           "package p1; public class C1 { }");
 276         Path src_m2 = src.resolve("m2x");
 277         tb.writeJavaFiles(src_m2,
 278                           "module m2x { }",
 279                           "package p2; class C2 { p1.C1 c1; }");
 280         Path classes = base.resolve("classes");
 281         tb.createDirectories(classes);
 282 
 283         new JavacTask(tb)
 284                 .options("--module-source-path", src.toString(),
 285                          "--add-exports", "m1x/p1=m2x,m2x")
 286                 .outdir(classes)
 287                 .files(findJavaFiles(src))
 288                 .run()
 289                 .writeAll();
 290     }
 291 
 292     @Test
 293     public void testRepeated_SameTarget(Path base) throws Exception {
 294         Path src = base.resolve("src");
 295         Path src_m1 = src.resolve("m1x");
 296         tb.writeJavaFiles(src_m1,
 297                           "module m1x { }",
 298                           "package p1; public class C1 { }");
 299         Path src_m2 = src.resolve("m2x");
 300         tb.writeJavaFiles(src_m2,
 301                           "module m2x { }",
 302                           "package p2; class C2 { p1.C1 c1; }");
 303         Path classes = base.resolve("classes");
 304         tb.createDirectories(classes);
 305 
 306         new JavacTask(tb)
 307                 .options("--module-source-path", src.toString(),
 308                          "--add-exports", "m1x/p1=m2x",
 309                          "--add-exports", "m1x/p1=m2x")
 310                 .outdir(classes)
 311                 .files(findJavaFiles(src))
 312                 .run()
 313                 .writeAll();
 314     }
 315 
 316     @Test
 317     public void testRepeated_DifferentTarget(Path base) throws Exception {
 318         Path src = base.resolve("src");
 319         Path src_m1 = src.resolve("m1x");
 320         tb.writeJavaFiles(src_m1,
 321                           "module m1x { }",
 322                           "package p1; public class C1 { }");
 323         Path src_m2 = src.resolve("m2x");
 324         tb.writeJavaFiles(src_m2,
 325                           "module m2x { }",
 326                           "package p2; class C2 { p1.C1 c1; }");
 327         Path src_m3 = src.resolve("m3x");
 328         tb.writeJavaFiles(src_m3,
 329                           "module m3x { }",
 330                           "package p3; class C3 { p1.C1 c1; }");
 331         Path classes = base.resolve("classes");
 332         tb.createDirectories(classes);
 333 
 334         new JavacTask(tb)
 335                 .options("--module-source-path", src.toString(),
 336                          "--add-exports", "m1x/p1=m2x",
 337                          "--add-exports", "m1x/p1=m3x")
 338                 .outdir(classes)
 339                 .files(findJavaFiles(src))
 340                 .run()
 341                 .writeAll();
 342     }
 343 }