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