ProvidesTest.java revision 3573:c4a18ee691c4
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 simple tests of module provides
27 * @library /tools/lib
28 * @modules
29 *      jdk.compiler/com.sun.tools.javac.api
30 *      jdk.compiler/com.sun.tools.javac.main
31 * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
32 * @run main ProvidesTest
33 */
34
35import java.nio.file.Files;
36import java.nio.file.Path;
37import java.util.Arrays;
38import java.util.List;
39
40import toolbox.JavacTask;
41import toolbox.Task;
42import toolbox.ToolBox;
43
44public class ProvidesTest extends ModuleTestBase {
45    public static void main(String... args) throws Exception {
46        ProvidesTest t = new ProvidesTest();
47        t.runTests();
48    }
49
50    @Test
51    public void testSimple(Path base) throws Exception {
52        Path src = base.resolve("src");
53        tb.writeJavaFiles(src,
54                "module m { provides p1.C1 with p2.C2; }",
55                "package p1; public class C1 { }",
56                "package p2; public class C2 extends p1.C1 { }");
57        Path classes = base.resolve("classes");
58        Files.createDirectories(classes);
59
60        new JavacTask(tb)
61                .outdir(classes)
62                .files(findJavaFiles(src))
63                .run(Task.Expect.SUCCESS)
64                .writeAll();
65    }
66
67    @Test
68    public void testMulti(Path base) throws Exception {
69        Path src = base.resolve("src");
70        tb.writeJavaFiles(src.resolve("m1"),
71                "module m1 { exports p1; }",
72                "package p1; public class C1 { }");
73        tb.writeJavaFiles(src.resolve("m2"),
74                "module m2 { requires m1; provides p1.C1 with p2.C2; }",
75                "package p2; public class C2 extends p1.C1 { }");
76        Path modules = base.resolve("modules");
77        Files.createDirectories(modules);
78
79        new JavacTask(tb)
80                .options("--module-source-path", src.toString())
81                .outdir(modules)
82                .files(findJavaFiles(src))
83                .run(Task.Expect.SUCCESS)
84                .writeAll();
85
86    }
87
88    @Test
89    public void testMissingWith(Path base) throws Exception {
90        Path src = base.resolve("src");
91        tb.writeJavaFiles(src,
92                "module m { provides p.C; }",
93                "package p; public class C { }");
94        Path classes = base.resolve("classes");
95        Files.createDirectories(classes);
96
97        String log = new JavacTask(tb)
98                .options("-XDrawDiagnostics")
99                .outdir(classes)
100                .files(findJavaFiles(src))
101                .run(Task.Expect.FAIL)
102                .writeAll()
103                .getOutput(Task.OutputKind.DIRECT);
104
105        if (!log.contains("module-info.java:1:24: compiler.err.expected: 'with'"))
106            throw new Exception("expected output not found");
107
108    }
109
110    @Test
111    public void testDuplicateProvides(Path base) throws Exception {
112        Path src = base.resolve("src");
113        tb.writeJavaFiles(src,
114                "module m { provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }",
115                "package p1; public class C1 { }",
116                "package p2; public class C2 extends p1.C1 { }");
117        Path classes = base.resolve("classes");
118        Files.createDirectories(classes);
119
120        new JavacTask(tb)
121                .options("-XDrawDiagnostic")
122                .outdir(classes)
123                .files(findJavaFiles(src))
124                .run(Task.Expect.FAIL)
125                .writeAll();
126    }
127
128    @Test
129    public void testMissingService(Path base) throws Exception {
130        Path src = base.resolve("src");
131        tb.writeJavaFiles(src,
132                "module m { provides p.Missing with p.C; }",
133                "package p; public class C extends p.Missing { }");
134
135        List<String> output = new JavacTask(tb)
136                .options("-XDrawDiagnostics")
137                .outdir(Files.createDirectories(base.resolve("classes")))
138                .files(findJavaFiles(src))
139                .run(Task.Expect.FAIL)
140                .writeAll()
141                .getOutputLines(Task.OutputKind.DIRECT);
142
143        List<String> expected = Arrays.asList(
144                "C.java:1:36: compiler.err.cant.resolve.location: kindname.class, Missing, , , (compiler.misc.location: kindname.package, p, null)",
145                "module-info.java:1:22: compiler.err.cant.resolve.location: kindname.class, Missing, , , (compiler.misc.location: kindname.package, p, null)",
146                "2 errors");
147        if (!output.containsAll(expected)) {
148            throw new Exception("Expected output not found");
149        }
150    }
151
152    @Test
153    public void testProvidesFromAnotherModule(Path base) throws Exception {
154        Path modules = base.resolve("modules");
155        tb.writeJavaFiles(modules.resolve("M"),
156                "module M { exports p; }",
157                "package p; public class Service { }");
158        tb.writeJavaFiles(modules.resolve("L"),
159                "module L { requires M; provides p.Service with p.Service; }");
160
161        List<String> output = new JavacTask(tb)
162                .options("-XDrawDiagnostics",
163                        "--module-source-path", modules.toString())
164                .outdir(Files.createDirectories(base.resolve("classes")))
165                .files(findJavaFiles(modules))
166                .run(Task.Expect.FAIL)
167                .writeAll()
168                .getOutputLines(Task.OutputKind.DIRECT);
169        List<String> expected = Arrays.asList(
170                "module-info.java:1:24: compiler.err.service.implementation.not.in.right.module: M",
171                "1 error");
172        if (!output.containsAll(expected)) {
173            throw new Exception("Expected output not found");
174        }
175
176    }
177
178    @Test
179    public void testServiceIsNotImplemented(Path base) throws Exception {
180        Path src = base.resolve("src");
181        tb.writeJavaFiles(src,
182                "module m { provides p.A with p.B; }",
183                "package p; public class A { }",
184                "package p; public class B { }");
185
186        List<String> output = new JavacTask(tb)
187                .options("-XDrawDiagnostics")
188                .outdir(Files.createDirectories(base.resolve("classes")))
189                .files(findJavaFiles(src))
190                .run(Task.Expect.FAIL)
191                .writeAll()
192                .getOutputLines(Task.OutputKind.DIRECT);
193
194        List<String> expected = Arrays.asList(
195                "module-info.java:1:31: compiler.err.service.implementation.must.be.subtype.of.service.interface",
196                "module-info.java:1:12: compiler.warn.service.provided.but.not.exported.or.used: p.A",
197                "1 error",
198                "1 warning");
199        if (!output.containsAll(expected)) {
200            throw new Exception("Expected output not found");
201        }
202    }
203
204    @Test
205    public void testMissingImplementation(Path base) throws Exception {
206        Path src = base.resolve("src");
207        tb.writeJavaFiles(src,
208                "module m { provides p.C with p.Impl; }",
209                "package p; public class C { }");
210
211        List<String> output = new JavacTask(tb)
212                .options("-XDrawDiagnostics")
213                .outdir(Files.createDirectories(base.resolve("classes")))
214                .files(findJavaFiles(src))
215                .run(Task.Expect.FAIL)
216                .writeAll()
217                .getOutputLines(Task.OutputKind.DIRECT);
218
219        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)",
220                "1 error");
221        if (!output.containsAll(expected)) {
222            throw new Exception("Expected output not found");
223        }
224    }
225
226    @Test
227    public void testSeveralImplementations(Path base) throws Exception {
228        Path src = base.resolve("src");
229        tb.writeJavaFiles(src,
230                "module m { provides p.C with p.Impl1; provides p.C with p.Impl2; }",
231                "package p; public class C { }",
232                "package p; public class Impl1 extends p.C { }",
233                "package p; public class Impl2 extends p.C { }");
234
235        new JavacTask(tb)
236                .outdir(Files.createDirectories(base.resolve("classes")))
237                .files(findJavaFiles(src))
238                .run(Task.Expect.SUCCESS)
239                .writeAll();
240    }
241
242    @Test
243    public void testOneImplementationsForServices(Path base) throws Exception {
244        Path src = base.resolve("src");
245        tb.writeJavaFiles(src,
246                "module m { provides p.Service1 with p.Impl; provides p.Service2 with p.Impl; }",
247                "package p; public interface Service1 { }",
248                "package p; public abstract class Service2 { }",
249                "package p; public class Impl extends p.Service2 implements p.Service1 { }");
250
251        new JavacTask(tb)
252                .outdir(Files.createDirectories(base.resolve("classes")))
253                .files(findJavaFiles(src))
254                .run(Task.Expect.SUCCESS)
255                .writeAll();
256    }
257
258    @Test
259    public void testAbstractImplementation(Path base) throws Exception {
260        Path src = base.resolve("src");
261        tb.writeJavaFiles(src,
262                "module m { provides p1.C1 with p2.C2; }",
263                "package p1; public class C1 { }",
264                "package p2; public abstract class C2 extends p1.C1 { }");
265
266        List<String> output = new JavacTask(tb)
267                .options("-XDrawDiagnostics")
268                .outdir(Files.createDirectories(base.resolve("classes")))
269                .files(findJavaFiles(src))
270                .run(Task.Expect.FAIL)
271                .writeAll()
272                .getOutputLines(Task.OutputKind.DIRECT);
273
274        List<String> expected = Arrays.asList(
275                "module-info.java:1:34: compiler.err.service.implementation.is.abstract: p2.C2");
276        if (!output.containsAll(expected)) {
277            throw new Exception("Expected output not found");
278        }
279    }
280
281    @Test
282    public void testInterfaceImplementation(Path base) throws Exception {
283        Path src = base.resolve("src");
284        tb.writeJavaFiles(src,
285                "module m { provides p1.Service with p2.Impl; }",
286                "package p1; public interface Service { }",
287                "package p2; public interface Impl extends p1.Service { }");
288
289        List<String> output = new JavacTask(tb)
290                .options("-XDrawDiagnostics")
291                .outdir(Files.createDirectories(base.resolve("classes")))
292                .files(findJavaFiles(src))
293                .run(Task.Expect.FAIL)
294                .writeAll()
295                .getOutputLines(Task.OutputKind.DIRECT);
296
297        List<String> expected = Arrays.asList(
298                "module-info.java:1:39: compiler.err.service.implementation.is.abstract: p2.Impl");
299        if (!output.containsAll(expected)) {
300            throw new Exception("Expected output not found");
301        }
302    }
303
304    @Test
305    public void testProtectedImplementation(Path base) throws Exception {
306        Path src = base.resolve("src");
307        tb.writeJavaFiles(src,
308                "module m { provides p1.C1 with p2.C2; }",
309                "package p1; public class C1 { }",
310                "package p2; class C2 extends p1.C1 { }");
311
312        List<String> output = new JavacTask(tb)
313                .options("-XDrawDiagnostics")
314                .outdir(Files.createDirectories(base.resolve("classes")))
315                .files(findJavaFiles(src))
316                .run(Task.Expect.FAIL)
317                .writeAll()
318                .getOutputLines(Task.OutputKind.DIRECT);
319
320        List<String> expected = Arrays.asList("module-info.java:1:34: compiler.err.not.def.public.cant.access: p2.C2, p2",
321                "1 error");
322        if (!output.containsAll(expected)) {
323            throw new Exception("Expected output not found");
324        }
325    }
326
327    @Test
328    public void testNoNoArgConstructor(Path base) throws Exception {
329        Path src = base.resolve("src");
330        tb.writeJavaFiles(src,
331                "module m { uses p1.C1; provides p1.C1 with p2.C2; }",
332                "package p1; public class C1 { }",
333                "package p2; public class C2 extends p1.C1 { public C2(String str) { } }");
334
335        List<String> output = new JavacTask(tb)
336                .options("-XDrawDiagnostics")
337                .outdir(Files.createDirectories(base.resolve("classes")))
338                .files(findJavaFiles(src))
339                .run(Task.Expect.FAIL)
340                .writeAll()
341                .getOutputLines(Task.OutputKind.DIRECT);
342
343        List<String> expected = Arrays.asList(
344                "module-info.java:1:46: compiler.err.service.implementation.doesnt.have.a.no.args.constructor: p2.C2");
345        if (!output.containsAll(expected)) {
346            throw new Exception("Expected output not found");
347        }
348    }
349
350    @Test
351    public void testPrivateNoArgConstructor(Path base) throws Exception {
352        Path src = base.resolve("src");
353        tb.writeJavaFiles(src,
354                "module m { uses p1.C1; provides p1.C1 with p2.C2; }",
355                "package p1; public class C1 { }",
356                "package p2; public class C2 extends p1.C1 { private C2() { } }");
357
358        List<String> output = new JavacTask(tb)
359                .options("-XDrawDiagnostics")
360                .outdir(Files.createDirectories(base.resolve("classes")))
361                .files(findJavaFiles(src))
362                .run(Task.Expect.FAIL)
363                .writeAll()
364                .getOutputLines(Task.OutputKind.DIRECT);
365
366        List<String> expected = Arrays.asList(
367                "module-info.java:1:46: compiler.err.service.implementation.no.args.constructor.not.public: p2.C2");
368        if (!output.containsAll(expected)) {
369            throw new Exception("Expected output not found");
370        }
371    }
372
373    @Test
374    public void testServiceIndirectlyImplemented(Path base) throws Exception {
375        Path src = base.resolve("src");
376        tb.writeJavaFiles(src,
377                "module m { provides p1.C1 with p2.C3; }",
378                "package p1; public class C1 { }",
379                "package p2; public class C2 extends p1.C1 {  }",
380                "package p2; public class C3 extends p2.C2 {  }");
381
382        new JavacTask(tb)
383                .outdir(Files.createDirectories(base.resolve("classes")))
384                .files(findJavaFiles(src))
385                .run(Task.Expect.SUCCESS)
386                .writeAll();
387    }
388
389    @Test
390    public void testServiceImplementationInnerClass(Path base) throws Exception {
391        Path src = base.resolve("src");
392        tb.writeJavaFiles(src,
393                "module m { provides p1.C1 with p2.C2.Inner; }",
394                "package p1; public class C1 { }",
395                "package p2; public class C2  { public class Inner extends p1.C1 { } }");
396
397        List<String> output = new JavacTask(tb)
398                .options("-XDrawDiagnostics")
399                .outdir(Files.createDirectories(base.resolve("classes")))
400                .files(findJavaFiles(src))
401                .run(Task.Expect.FAIL)
402                .writeAll()
403                .getOutputLines(Task.OutputKind.DIRECT);
404
405        List<String> expected = Arrays.asList(
406                "module-info.java:1:37: compiler.err.service.implementation.is.inner: p2.C2.Inner");
407        if (!output.containsAll(expected)) {
408            throw new Exception("Expected output not found");
409        }
410    }
411
412    @Test
413    public void testServiceDefinitionInnerClass(Path base) throws Exception {
414        Path src = base.resolve("src");
415        tb.writeJavaFiles(src,
416                "module m { provides p1.C1.InnerDefinition with p2.C2; }",
417                "package p1; public class C1 { public class InnerDefinition { } }",
418                "package p2; public class C2 extends p1.C1.InnerDefinition { }");
419
420        List<String> output = new JavacTask(tb)
421                .options("-XDrawDiagnostics")
422                .outdir(Files.createDirectories(base.resolve("classes")))
423                .files(findJavaFiles(src))
424                .run(Task.Expect.FAIL)
425                .writeAll()
426                .getOutputLines(Task.OutputKind.DIRECT);
427
428        List<String> expected = Arrays.asList(
429                "module-info.java:1:26: compiler.err.service.definition.is.inner: p1.C1.InnerDefinition",
430                "module-info.java:1:12: compiler.warn.service.provided.but.not.exported.or.used: p1.C1.InnerDefinition",
431                "C2.java:1:20: compiler.err.encl.class.required: p1.C1.InnerDefinition",
432                "2 errors",
433                "1 warning");
434        if (!output.containsAll(expected)) {
435            throw new Exception("Expected output not found");
436        }
437    }
438}
439