|
1 /* |
|
2 * Copyright (c) 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 Check convenient errors are produced for inaccessible classes. |
|
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.JarTask toolbox.JavacTask ModuleTestBase |
|
31 * @run main ConvenientAccessErrorsTest |
|
32 */ |
|
33 |
|
34 import java.nio.file.Files; |
|
35 import java.nio.file.Path; |
|
36 import java.util.Arrays; |
|
37 import java.util.List; |
|
38 |
|
39 import toolbox.JarTask; |
|
40 import toolbox.JavacTask; |
|
41 import toolbox.Task; |
|
42 |
|
43 public class ConvenientAccessErrorsTest extends ModuleTestBase { |
|
44 |
|
45 public static void main(String... args) throws Exception { |
|
46 new ConvenientAccessErrorsTest().runTests(); |
|
47 } |
|
48 |
|
49 @Test |
|
50 public void testNoDep(Path base) throws Exception { |
|
51 Path src = base.resolve("src"); |
|
52 Path src_m1 = src.resolve("m1x"); |
|
53 tb.writeJavaFiles(src_m1, |
|
54 "module m1x { exports api; }", |
|
55 "package api; public class Api { public void call() { } }"); |
|
56 Path src_m2 = src.resolve("m2x"); |
|
57 tb.writeJavaFiles(src_m2, |
|
58 "module m2x { }", |
|
59 "package test; public class Test { api.Api api; }"); |
|
60 Path classes = base.resolve("classes"); |
|
61 tb.createDirectories(classes); |
|
62 |
|
63 List<String> log = new JavacTask(tb) |
|
64 .options("-XDrawDiagnostics", |
|
65 "--module-source-path", src.toString()) |
|
66 .outdir(classes) |
|
67 .files(findJavaFiles(src)) |
|
68 .run(Task.Expect.FAIL) |
|
69 .writeAll() |
|
70 .getOutputLines(Task.OutputKind.DIRECT); |
|
71 |
|
72 List<String> expected = Arrays.asList( |
|
73 "Test.java:1:35: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.does.not.read: m2x, api, m1x)", |
|
74 "1 error"); |
|
75 |
|
76 if (!expected.equals(log)) |
|
77 throw new Exception("expected output not found; actual: " + log); |
|
78 } |
|
79 |
|
80 @Test |
|
81 public void testNotExported(Path base) throws Exception { |
|
82 Path src = base.resolve("src"); |
|
83 Path src_m1 = src.resolve("m1x"); |
|
84 tb.writeJavaFiles(src_m1, |
|
85 "module m1x { exports api; }", |
|
86 "package api; public class Api { }", |
|
87 "package impl; public class Impl { }"); |
|
88 Path src_m2 = src.resolve("m2x"); |
|
89 tb.writeJavaFiles(src_m2, |
|
90 "module m2x { requires m1x; }", |
|
91 "package test; public class Test { impl.Impl api; }"); |
|
92 Path src_m3 = src.resolve("m3x"); |
|
93 tb.writeJavaFiles(src_m3, |
|
94 "module m3x { requires m1x; }"); |
|
95 Path classes = base.resolve("classes"); |
|
96 tb.createDirectories(classes); |
|
97 |
|
98 List<String> log = new JavacTask(tb) |
|
99 .options("-XDrawDiagnostics", |
|
100 "--module-source-path", src.toString()) |
|
101 .outdir(classes) |
|
102 .files(findJavaFiles(src)) |
|
103 .run(Task.Expect.FAIL) |
|
104 .writeAll() |
|
105 .getOutputLines(Task.OutputKind.DIRECT); |
|
106 |
|
107 List<String> expected = Arrays.asList( |
|
108 "Test.java:1:35: compiler.err.package.not.visible: impl, (compiler.misc.not.def.access.not.exported: impl, m1x)", |
|
109 "1 error"); |
|
110 |
|
111 if (!expected.equals(log)) |
|
112 throw new Exception("expected output not found; actual: " + log); |
|
113 |
|
114 tb.writeJavaFiles(src_m1, |
|
115 "module m1x { exports api; exports impl to m3x;}"); |
|
116 |
|
117 log = new JavacTask(tb) |
|
118 .options("-XDrawDiagnostics", |
|
119 "--module-source-path", src.toString()) |
|
120 .outdir(classes) |
|
121 .files(findJavaFiles(src)) |
|
122 .run(Task.Expect.FAIL) |
|
123 .writeAll() |
|
124 .getOutputLines(Task.OutputKind.DIRECT); |
|
125 |
|
126 expected = Arrays.asList( |
|
127 "Test.java:1:35: compiler.err.package.not.visible: impl, (compiler.misc.not.def.access.not.exported.to.module: impl, m1x, m2x)", |
|
128 "1 error"); |
|
129 |
|
130 if (!expected.equals(log)) |
|
131 throw new Exception("expected output not found; actual: " + log); |
|
132 } |
|
133 |
|
134 @Test |
|
135 public void testInaccessibleInExported(Path base) throws Exception { |
|
136 Path src = base.resolve("src"); |
|
137 Path src_m1 = src.resolve("m1x"); |
|
138 tb.writeJavaFiles(src_m1, |
|
139 "module m1x { exports api; }", |
|
140 "package api; class Api { }"); |
|
141 Path src_m2 = src.resolve("m2x"); |
|
142 tb.writeJavaFiles(src_m2, |
|
143 "module m2x { requires m1x; }", |
|
144 "package test; public class Test { api.Api api; }"); |
|
145 Path classes = base.resolve("classes"); |
|
146 tb.createDirectories(classes); |
|
147 |
|
148 List<String> log = new JavacTask(tb) |
|
149 .options("-XDrawDiagnostics", |
|
150 "--module-source-path", src.toString()) |
|
151 .outdir(classes) |
|
152 .files(findJavaFiles(src)) |
|
153 .run(Task.Expect.FAIL) |
|
154 .writeAll() |
|
155 .getOutputLines(Task.OutputKind.DIRECT); |
|
156 |
|
157 List<String> expected = Arrays.asList( |
|
158 "Test.java:1:38: compiler.err.not.def.public.cant.access: api.Api, api", |
|
159 "1 error"); |
|
160 |
|
161 if (!expected.equals(log)) |
|
162 throw new Exception("expected output not found; actual: " + log); |
|
163 } |
|
164 |
|
165 // @Test |
|
166 public void testInaccessibleUnnamedModule(Path base) throws Exception { |
|
167 Path jar = prepareTestJar(base, "package api; class Api { public static class Foo {} }"); |
|
168 |
|
169 Path moduleSrc = base.resolve("module-src"); |
|
170 Path m1x = moduleSrc.resolve("m1x"); |
|
171 |
|
172 Path classes = base.resolve("classes"); |
|
173 |
|
174 Files.createDirectories(classes); |
|
175 |
|
176 tb.writeJavaFiles(m1x, |
|
177 "module m1x { }", |
|
178 "package test; public class Test { api.Api api; api.Api.Foo api; }"); |
|
179 |
|
180 List<String> log = new JavacTask(tb) |
|
181 .options("-classpath", jar.toString(), |
|
182 "-XDrawDiagnostics") |
|
183 .outdir(classes) |
|
184 .files(findJavaFiles(moduleSrc)) |
|
185 .run(Task.Expect.FAIL) |
|
186 .writeAll() |
|
187 .getOutputLines(Task.OutputKind.DIRECT); |
|
188 |
|
189 List<String> expected = Arrays.asList( |
|
190 "Test.java:1:38: compiler.err.not.def.access.package.cant.access: api.Api, api, (compiler.misc.not.def.access.does.not.read.unnamed: api, m1x)", |
|
191 "Test.java:1:51: compiler.err.not.def.access.package.cant.access: api.Api, api, (compiler.misc.not.def.access.does.not.read.unnamed: api, m1x)", |
|
192 "2 errors"); |
|
193 |
|
194 if (!expected.equals(log)) |
|
195 throw new Exception("expected output not found; actual: " + log); |
|
196 } |
|
197 |
|
198 @Test |
|
199 public void testIndirectReferenceToUnnamedModule(Path base) throws Exception { |
|
200 Path jar = prepareTestJar(base, "package api; public class Api { public void test() {} }"); |
|
201 |
|
202 Path moduleSrc = base.resolve("module-src"); |
|
203 Path m1x = moduleSrc.resolve("m1x"); |
|
204 Path auxiliary = moduleSrc.resolve("auxiliary"); |
|
205 |
|
206 Path classes = base.resolve("classes"); |
|
207 |
|
208 Files.createDirectories(classes); |
|
209 |
|
210 tb.writeJavaFiles(m1x, |
|
211 "module m1x { requires auxiliary; }", |
|
212 "package test; public class Test { { auxiliary.Auxiliary.get().test(); } }"); |
|
213 |
|
214 tb.writeJavaFiles(auxiliary, |
|
215 "module auxiliary { exports auxiliary; }", |
|
216 "package auxiliary; public class Auxiliary { public static api.Api get() { return null; } }"); |
|
217 |
|
218 List<String> log = new JavacTask(tb) |
|
219 .options("-classpath", jar.toString(), |
|
220 "-XDrawDiagnostics", |
|
221 "--add-reads", "auxiliary=ALL-UNNAMED", |
|
222 "--module-source-path", moduleSrc.toString()) |
|
223 .outdir(classes) |
|
224 .files(findJavaFiles(moduleSrc)) |
|
225 .run(Task.Expect.FAIL) |
|
226 .writeAll() |
|
227 .getOutputLines(Task.OutputKind.DIRECT); |
|
228 |
|
229 List<String> expected = Arrays.asList( |
|
230 "Test.java:1:62: compiler.err.not.def.access.class.intf.cant.access.reason: test(), api.Api, api, (compiler.misc.not.def.access.does.not.read.unnamed: api, m1x)", |
|
231 "1 error"); |
|
232 |
|
233 if (!expected.equals(log)) |
|
234 throw new Exception("expected output not found; actual: " + log); |
|
235 } |
|
236 |
|
237 private Path prepareTestJar(Path base, String code) throws Exception { |
|
238 Path legacySrc = base.resolve("legacy-src"); |
|
239 tb.writeJavaFiles(legacySrc, code); |
|
240 Path legacyClasses = base.resolve("legacy-classes"); |
|
241 Files.createDirectories(legacyClasses); |
|
242 |
|
243 String log = new JavacTask(tb) |
|
244 .options() |
|
245 .outdir(legacyClasses) |
|
246 .files(findJavaFiles(legacySrc)) |
|
247 .run() |
|
248 .writeAll() |
|
249 .getOutput(Task.OutputKind.DIRECT); |
|
250 |
|
251 if (!log.isEmpty()) { |
|
252 throw new Exception("unexpected output: " + log); |
|
253 } |
|
254 |
|
255 Path lib = base.resolve("lib"); |
|
256 |
|
257 Files.createDirectories(lib); |
|
258 |
|
259 Path jar = lib.resolve("test-api-1.0.jar"); |
|
260 |
|
261 new JarTask(tb, jar) |
|
262 .baseDir(legacyClasses) |
|
263 .files("api/Api.class") |
|
264 .run(); |
|
265 |
|
266 return jar; |
|
267 } |
|
268 |
|
269 @Test |
|
270 public void testUnnamedModuleAccess(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 { exports api to m2x; }", |
|
275 "package api; class Api { }", |
|
276 "package impl; class Impl { }"); |
|
277 Path src_m2 = src.resolve("m2x"); |
|
278 tb.writeJavaFiles(src_m2, |
|
279 "module m2x { requires m1x; }"); |
|
280 Path modulepath = base.resolve("modulepath"); |
|
281 tb.createDirectories(modulepath); |
|
282 |
|
283 new JavacTask(tb) |
|
284 .options("--module-source-path", src.toString()) |
|
285 .outdir(modulepath) |
|
286 .files(findJavaFiles(src)) |
|
287 .run() |
|
288 .writeAll(); |
|
289 |
|
290 Path unnamedSrc = base.resolve("unnamedSrc"); |
|
291 tb.writeJavaFiles(unnamedSrc, |
|
292 "public class Test { api.Api api; impl.Impl impl; }"); |
|
293 Path unnamedClasses = base.resolve("unnamed-classes"); |
|
294 Files.createDirectories(unnamedClasses); |
|
295 |
|
296 List<String> log = new JavacTask(tb) |
|
297 .options("--module-path", modulepath.toString(), |
|
298 "-XDrawDiagnostics") |
|
299 .outdir(unnamedClasses) |
|
300 .files(findJavaFiles(unnamedSrc)) |
|
301 .run(Task.Expect.FAIL) |
|
302 .writeAll() |
|
303 .getOutputLines(Task.OutputKind.DIRECT); |
|
304 |
|
305 List<String> expected = Arrays.asList( |
|
306 "Test.java:1:21: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.does.not.read.from.unnamed: api, m1x)", |
|
307 "Test.java:1:34: compiler.err.package.not.visible: impl, (compiler.misc.not.def.access.does.not.read.from.unnamed: impl, m1x)", |
|
308 "2 errors" |
|
309 ); |
|
310 |
|
311 if (!expected.equals(log)) { |
|
312 throw new Exception("unexpected output: " + log); |
|
313 } |
|
314 |
|
315 log = new JavacTask(tb) |
|
316 .options("--module-path", modulepath.toString(), |
|
317 "--add-modules", "m1x", |
|
318 "-XDrawDiagnostics") |
|
319 .outdir(unnamedClasses) |
|
320 .files(findJavaFiles(unnamedSrc)) |
|
321 .run(Task.Expect.FAIL) |
|
322 .writeAll() |
|
323 .getOutputLines(Task.OutputKind.DIRECT); |
|
324 |
|
325 expected = Arrays.asList( |
|
326 "Test.java:1:21: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.not.exported.to.module.from.unnamed: api, m1x)", |
|
327 "Test.java:1:34: compiler.err.package.not.visible: impl, (compiler.misc.not.def.access.not.exported.from.unnamed: impl, m1x)", |
|
328 "2 errors" |
|
329 ); |
|
330 |
|
331 if (!expected.equals(log)) { |
|
332 throw new Exception("unexpected output: " + log); |
|
333 } |
|
334 } |
|
335 |
|
336 @Test |
|
337 public void testInImport(Path base) throws Exception { |
|
338 Path src = base.resolve("src"); |
|
339 Path src_m1 = src.resolve("m1x"); |
|
340 tb.writeJavaFiles(src_m1, |
|
341 "module m1x { }", |
|
342 "package api; public class Api { public String test() { return null; } }"); |
|
343 Path src_m2 = src.resolve("m2x"); |
|
344 tb.writeJavaFiles(src_m2, |
|
345 "module m2x { requires m1x; }", |
|
346 "package test; import api.Api; public class Test { Api api; { api.test().length(); } }"); |
|
347 Path classes = base.resolve("classes"); |
|
348 tb.createDirectories(classes); |
|
349 |
|
350 List<String> log = new JavacTask(tb) |
|
351 .options("-XDrawDiagnostics", |
|
352 "--module-source-path", src.toString()) |
|
353 .outdir(classes) |
|
354 .files(findJavaFiles(src)) |
|
355 .run(Task.Expect.FAIL) |
|
356 .writeAll() |
|
357 .getOutputLines(Task.OutputKind.DIRECT); |
|
358 |
|
359 List<String> expected = Arrays.asList( |
|
360 "Test.java:1:22: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.not.exported: api, m1x)", |
|
361 "1 error"); |
|
362 |
|
363 if (!expected.equals(log)) |
|
364 throw new Exception("expected output not found; actual: " + log); |
|
365 } |
|
366 |
|
367 @Test |
|
368 public void testInImportOnDemand(Path base) throws Exception { |
|
369 Path src = base.resolve("src"); |
|
370 Path src_m1 = src.resolve("m1x"); |
|
371 tb.writeJavaFiles(src_m1, |
|
372 "module m1x { }", |
|
373 "package api; public class Api { public String test() { return null; } }"); |
|
374 Path src_m2 = src.resolve("m2x"); |
|
375 tb.writeJavaFiles(src_m2, |
|
376 "module m2x { requires m1x; }", |
|
377 "package test; import api.*; public class Test { Api api; { api.test().length(); } }"); |
|
378 Path classes = base.resolve("classes"); |
|
379 tb.createDirectories(classes); |
|
380 |
|
381 List<String> log = new JavacTask(tb) |
|
382 .options("-XDrawDiagnostics", |
|
383 "--module-source-path", src.toString()) |
|
384 .outdir(classes) |
|
385 .files(findJavaFiles(src)) |
|
386 .run(Task.Expect.FAIL) |
|
387 .writeAll() |
|
388 .getOutputLines(Task.OutputKind.DIRECT); |
|
389 |
|
390 List<String> expected = Arrays.asList( |
|
391 "Test.java:1:22: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.not.exported: api, m1x)", |
|
392 "Test.java:1:49: compiler.err.not.def.access.package.cant.access: api.Api, api, (compiler.misc.not.def.access.not.exported: api, m1x)", |
|
393 "2 errors"); |
|
394 |
|
395 if (!expected.equals(log)) |
|
396 throw new Exception("expected output not found; actual: " + log); |
|
397 } |
|
398 |
|
399 @Test |
|
400 public void testUnusedImportOnDemand1(Path base) throws Exception { |
|
401 Path src = base.resolve("src"); |
|
402 tb.writeJavaFiles(src, |
|
403 "package test; import javax.annotation.*; public class Test { }"); |
|
404 Path classes = base.resolve("classes"); |
|
405 tb.createDirectories(classes); |
|
406 |
|
407 List<String> log = new JavacTask(tb) |
|
408 .options("-XDrawDiagnostics", |
|
409 "--add-modules", "java.compiler") |
|
410 .outdir(classes) |
|
411 .files(findJavaFiles(src)) |
|
412 .run() |
|
413 .writeAll() |
|
414 .getOutputLines(Task.OutputKind.DIRECT); |
|
415 |
|
416 List<String> expected = Arrays.asList(""); |
|
417 |
|
418 if (!expected.equals(log)) |
|
419 throw new Exception("expected output not found; actual: " + log); |
|
420 } |
|
421 |
|
422 @Test |
|
423 public void testUnusedImportOnDemand2(Path base) throws Exception { |
|
424 Path src = base.resolve("src"); |
|
425 Path src_m1 = src.resolve("m1x"); |
|
426 tb.writeJavaFiles(src_m1, |
|
427 "module m1x { }", |
|
428 "package api; public class Api { }"); |
|
429 Path src_m2 = src.resolve("m2x"); |
|
430 tb.writeJavaFiles(src_m2, |
|
431 "module m2x { requires m1x; }", |
|
432 "package test; import api.*; public class Test { }"); |
|
433 Path classes = base.resolve("classes"); |
|
434 tb.createDirectories(classes); |
|
435 |
|
436 List<String> log = new JavacTask(tb) |
|
437 .options("-XDrawDiagnostics", |
|
438 "--module-source-path", src.toString()) |
|
439 .outdir(classes) |
|
440 .files(findJavaFiles(src)) |
|
441 .run(Task.Expect.FAIL) |
|
442 .writeAll() |
|
443 .getOutputLines(Task.OutputKind.DIRECT); |
|
444 |
|
445 List<String> expected = Arrays.asList( |
|
446 "Test.java:1:22: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.not.exported: api, m1x)", |
|
447 "1 error"); |
|
448 |
|
449 if (!expected.equals(log)) |
|
450 throw new Exception("expected output not found; actual: " + log); |
|
451 } |
|
452 |
|
453 @Test |
|
454 public void testClassPackageConflict(Path base) throws Exception { |
|
455 Path libSrc = base.resolve("libSrc"); |
|
456 tb.writeJavaFiles(libSrc, |
|
457 "package test.desktop; public class Any { }"); |
|
458 Path libClasses = base.resolve("libClasses"); |
|
459 tb.createDirectories(libClasses); |
|
460 |
|
461 new JavacTask(tb) |
|
462 .outdir(libClasses) |
|
463 .files(findJavaFiles(libSrc)) |
|
464 .run() |
|
465 .writeAll() |
|
466 .getOutputLines(Task.OutputKind.DIRECT); |
|
467 |
|
468 Path src = base.resolve("src"); |
|
469 tb.writeJavaFiles(src, |
|
470 "package test; public class desktop { public static class Action { } }", |
|
471 "package use; import test.desktop.*; public class Use { test.desktop.Action a; }"); |
|
472 Path classes = base.resolve("classes"); |
|
473 tb.createDirectories(classes); |
|
474 |
|
475 new JavacTask(tb) |
|
476 .options("-XDrawDiagnostics") |
|
477 .classpath(libClasses) |
|
478 .outdir(classes) |
|
479 .files(findJavaFiles(src)) |
|
480 .run() |
|
481 .writeAll(); |
|
482 } |
|
483 |
|
484 @Test |
|
485 public void testClassPackageConflictInUnnamed(Path base) throws Exception { |
|
486 Path libSrc = base.resolve("libSrc"); |
|
487 tb.writeJavaFiles(libSrc, |
|
488 "package desktop; public class Any { }"); |
|
489 Path libClasses = base.resolve("libClasses"); |
|
490 tb.createDirectories(libClasses); |
|
491 |
|
492 new JavacTask(tb) |
|
493 .outdir(libClasses) |
|
494 .files(findJavaFiles(libSrc)) |
|
495 .run() |
|
496 .writeAll() |
|
497 .getOutputLines(Task.OutputKind.DIRECT); |
|
498 |
|
499 Path src = base.resolve("src"); |
|
500 tb.writeJavaFiles(src, |
|
501 "public class desktop { public static class Action { } }", |
|
502 "import desktop.*; public class Use { desktop.Action a; }"); |
|
503 Path classes = base.resolve("classes"); |
|
504 tb.createDirectories(classes); |
|
505 |
|
506 new JavacTask(tb) |
|
507 .options("-XDrawDiagnostics") |
|
508 .classpath(libClasses) |
|
509 .outdir(classes) |
|
510 .files(findJavaFiles(src)) |
|
511 .run() |
|
512 .writeAll(); |
|
513 } |
|
514 |
|
515 } |