ProvidesTest.java revision 3314:97ec97671022
112238SN/A/*
212238SN/A * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
312238SN/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
412238SN/A *
512238SN/A * This code is free software; you can redistribute it and/or modify it
612238SN/A * under the terms of the GNU General Public License version 2 only, as
712238SN/A * published by the Free Software Foundation.
812238SN/A *
912238SN/A * This code is distributed in the hope that it will be useful, but WITHOUT
1012238SN/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1112238SN/A * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1212238SN/A * version 2 for more details (a copy is included in the LICENSE file that
1312238SN/A * accompanied this code).
1412238SN/A *
1512238SN/A * You should have received a copy of the GNU General Public License version
1612238SN/A * 2 along with this work; if not, write to the Free Software Foundation,
1712238SN/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1812238SN/A *
1912238SN/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2012238SN/A * or visit www.oracle.com if you need additional information or have any
2112238SN/A * questions.
2212238SN/A */
2312238SN/A
2412238SN/A/**
2512238SN/A * @test
2612238SN/A * @summary simple tests of module provides
2712238SN/A * @library /tools/lib
2812238SN/A * @modules
2912238SN/A *      jdk.compiler/com.sun.tools.javac.api
3012238SN/A *      jdk.compiler/com.sun.tools.javac.main
3112238SN/A * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
3212238SN/A * @run main ProvidesTest
3312238SN/A */
3412238SN/A
3512238SN/Aimport java.nio.file.Files;
3612238SN/Aimport java.nio.file.Path;
3712238SN/Aimport java.util.Arrays;
3812238SN/Aimport java.util.List;
3912238SN/A
4012238SN/Aimport 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    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    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("-modulesourcepath", src.toString())
81                .outdir(modules)
82                .files(findJavaFiles(src))
83                .run(Task.Expect.SUCCESS)
84                .writeAll();
85
86    }
87
88    @Test
89    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    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    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                "module-info.java:1:37: compiler.err.service.implementation.doesnt.have.a.no.args.constructor: <any>",
147                "3 errors");
148        if (!output.containsAll(expected)) {
149            throw new Exception("Expected output not found");
150        }
151    }
152
153    @Test
154    void testProvidesFromAnotherModule(Path base) throws Exception {
155        Path modules = base.resolve("modules");
156        tb.writeJavaFiles(modules.resolve("M"),
157                "module M { exports p; }",
158                "package p; public class Service { }");
159        tb.writeJavaFiles(modules.resolve("L"),
160                "module L { requires M; provides p.Service with p.Service; }");
161
162        List<String> output = new JavacTask(tb)
163                .options("-XDrawDiagnostics",
164                        "-modulesourcepath", modules.toString())
165                .outdir(Files.createDirectories(base.resolve("classes")))
166                .files(findJavaFiles(modules))
167                .run(Task.Expect.FAIL)
168                .writeAll()
169                .getOutputLines(Task.OutputKind.DIRECT);
170        List<String> expected = Arrays.asList(
171                "module-info.java:1:24: compiler.err.service.implementation.not.in.right.module: M",
172                "1 error");
173        if (!output.containsAll(expected)) {
174            throw new Exception("Expected output not found");
175        }
176
177    }
178
179    @Test
180    void testServiceIsNotImplemented(Path base) throws Exception {
181        Path src = base.resolve("src");
182        tb.writeJavaFiles(src,
183                "module m { provides p.A with p.B; }",
184                "package p; public class A { }",
185                "package p; public class B { }");
186
187        List<String> output = new JavacTask(tb)
188                .options("-XDrawDiagnostics")
189                .outdir(Files.createDirectories(base.resolve("classes")))
190                .files(findJavaFiles(src))
191                .run(Task.Expect.FAIL)
192                .writeAll()
193                .getOutputLines(Task.OutputKind.DIRECT);
194
195        List<String> expected = Arrays.asList("module-info.java:1:31: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: p.B, p.A)",
196                "1 error");
197        if (!output.containsAll(expected)) {
198            throw new Exception("Expected output not found");
199        }
200    }
201
202    @Test
203    void testMissingImplementation(Path base) throws Exception {
204        Path src = base.resolve("src");
205        tb.writeJavaFiles(src,
206                "module m { provides p.C with p.Impl; }",
207                "package p; public class C { }");
208
209        List<String> output = new JavacTask(tb)
210                .options("-XDrawDiagnostics")
211                .outdir(Files.createDirectories(base.resolve("classes")))
212                .files(findJavaFiles(src))
213                .run(Task.Expect.FAIL)
214                .writeAll()
215                .getOutputLines(Task.OutputKind.DIRECT);
216
217        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)",
218                "1 error");
219        if (!output.containsAll(expected)) {
220            throw new Exception("Expected output not found");
221        }
222    }
223
224    @Test
225    void testSeveralImplementations(Path base) throws Exception {
226        Path src = base.resolve("src");
227        tb.writeJavaFiles(src,
228                "module m { provides p.C with p.Impl1; provides p.C with p.Impl2; }",
229                "package p; public class C { }",
230                "package p; public class Impl1 extends p.C { }",
231                "package p; public class Impl2 extends p.C { }");
232
233        new JavacTask(tb)
234                .outdir(Files.createDirectories(base.resolve("classes")))
235                .files(findJavaFiles(src))
236                .run(Task.Expect.SUCCESS)
237                .writeAll();
238    }
239
240    @Test
241    void testOneImplementationsForServices(Path base) throws Exception {
242        Path src = base.resolve("src");
243        tb.writeJavaFiles(src,
244                "module m { provides p.Service1 with p.Impl; provides p.Service2 with p.Impl; }",
245                "package p; public interface Service1 { }",
246                "package p; public abstract class Service2 { }",
247                "package p; public class Impl extends p.Service2 implements p.Service1 { }");
248
249        new JavacTask(tb)
250                .outdir(Files.createDirectories(base.resolve("classes")))
251                .files(findJavaFiles(src))
252                .run(Task.Expect.SUCCESS)
253                .writeAll();
254    }
255
256    @Test
257    void testAbstractImplementation(Path base) throws Exception {
258        Path src = base.resolve("src");
259        tb.writeJavaFiles(src,
260                "module m { provides p1.C1 with p2.C2; }",
261                "package p1; public class C1 { }",
262                "package p2; public abstract class C2 extends p1.C1 { }");
263
264        List<String> output = new JavacTask(tb)
265                .options("-XDrawDiagnostics")
266                .outdir(Files.createDirectories(base.resolve("classes")))
267                .files(findJavaFiles(src))
268                .run(Task.Expect.FAIL)
269                .writeAll()
270                .getOutputLines(Task.OutputKind.DIRECT);
271
272        List<String> expected = Arrays.asList(
273                "module-info.java:1:34: compiler.err.service.implementation.is.abstract: p2.C2");
274        if (!output.containsAll(expected)) {
275            throw new Exception("Expected output not found");
276        }
277    }
278
279    @Test
280    void testInterfaceImplementation(Path base) throws Exception {
281        Path src = base.resolve("src");
282        tb.writeJavaFiles(src,
283                "module m { provides p1.Service with p2.Impl; }",
284                "package p1; public interface Service { }",
285                "package p2; public interface Impl extends p1.Service { }");
286
287        List<String> output = new JavacTask(tb)
288                .options("-XDrawDiagnostics")
289                .outdir(Files.createDirectories(base.resolve("classes")))
290                .files(findJavaFiles(src))
291                .run(Task.Expect.FAIL)
292                .writeAll()
293                .getOutputLines(Task.OutputKind.DIRECT);
294
295        List<String> expected = Arrays.asList(
296                "module-info.java:1:39: compiler.err.service.implementation.is.abstract: p2.Impl");
297        if (!output.containsAll(expected)) {
298            throw new Exception("Expected output not found");
299        }
300    }
301
302    @Test
303    void testProtectedImplementation(Path base) throws Exception {
304        Path src = base.resolve("src");
305        tb.writeJavaFiles(src,
306                "module m { provides p1.C1 with p2.C2; }",
307                "package p1; public class C1 { }",
308                "package p2; class C2 extends p1.C1 { }");
309
310        List<String> output = new JavacTask(tb)
311                .options("-XDrawDiagnostics")
312                .outdir(Files.createDirectories(base.resolve("classes")))
313                .files(findJavaFiles(src))
314                .run(Task.Expect.FAIL)
315                .writeAll()
316                .getOutputLines(Task.OutputKind.DIRECT);
317
318        List<String> expected = Arrays.asList("module-info.java:1:34: compiler.err.not.def.public.cant.access: p2.C2, p2",
319                "1 error");
320        if (!output.containsAll(expected)) {
321            throw new Exception("Expected output not found");
322        }
323    }
324
325    @Test
326    void testNoNoArgConstructor(Path base) throws Exception {
327        Path src = base.resolve("src");
328        tb.writeJavaFiles(src,
329                "module m { uses p1.C1; provides p1.C1 with p2.C2; }",
330                "package p1; public class C1 { }",
331                "package p2; public class C2 extends p1.C1 { public C2(String str) { } }");
332
333        List<String> output = new JavacTask(tb)
334                .options("-XDrawDiagnostics")
335                .outdir(Files.createDirectories(base.resolve("classes")))
336                .files(findJavaFiles(src))
337                .run(Task.Expect.FAIL)
338                .writeAll()
339                .getOutputLines(Task.OutputKind.DIRECT);
340
341        List<String> expected = Arrays.asList(
342                "module-info.java:1:46: compiler.err.service.implementation.doesnt.have.a.no.args.constructor: p2.C2");
343        if (!output.containsAll(expected)) {
344            throw new Exception("Expected output not found");
345        }
346    }
347
348    @Test
349    void testPrivateNoArgConstructor(Path base) throws Exception {
350        Path src = base.resolve("src");
351        tb.writeJavaFiles(src,
352                "module m { uses p1.C1; provides p1.C1 with p2.C2; }",
353                "package p1; public class C1 { }",
354                "package p2; public class C2 extends p1.C1 { private C2() { } }");
355
356        List<String> output = new JavacTask(tb)
357                .options("-XDrawDiagnostics")
358                .outdir(Files.createDirectories(base.resolve("classes")))
359                .files(findJavaFiles(src))
360                .run(Task.Expect.FAIL)
361                .writeAll()
362                .getOutputLines(Task.OutputKind.DIRECT);
363
364        List<String> expected = Arrays.asList(
365                "module-info.java:1:46: compiler.err.service.implementation.no.args.constructor.not.public: p2.C2");
366        if (!output.containsAll(expected)) {
367            throw new Exception("Expected output not found");
368        }
369    }
370
371    @Test
372    void testServiceIndirectlyImplemented(Path base) throws Exception {
373        Path src = base.resolve("src");
374        tb.writeJavaFiles(src,
375                "module m { provides p1.C1 with p2.C3; }",
376                "package p1; public class C1 { }",
377                "package p2; public class C2 extends p1.C1 {  }",
378                "package p2; public class C3 extends p2.C2 {  }");
379
380        new JavacTask(tb)
381                .outdir(Files.createDirectories(base.resolve("classes")))
382                .files(findJavaFiles(src))
383                .run(Task.Expect.SUCCESS)
384                .writeAll();
385    }
386
387    @Test
388    void testServiceImplementationInnerClass(Path base) throws Exception {
389        Path src = base.resolve("src");
390        tb.writeJavaFiles(src,
391                "module m { provides p1.C1 with p2.C2.Inner; }",
392                "package p1; public class C1 { }",
393                "package p2; public class C2  { public class Inner extends p1.C1 { } }");
394
395        List<String> output = new JavacTask(tb)
396                .options("-XDrawDiagnostics")
397                .outdir(Files.createDirectories(base.resolve("classes")))
398                .files(findJavaFiles(src))
399                .run(Task.Expect.FAIL)
400                .writeAll()
401                .getOutputLines(Task.OutputKind.DIRECT);
402
403        List<String> expected = Arrays.asList(
404                "module-info.java:1:37: compiler.err.service.implementation.is.inner: p2.C2.Inner");
405        if (!output.containsAll(expected)) {
406            throw new Exception("Expected output not found");
407        }
408    }
409
410    @Test
411    void testServiceDefinitionInnerClass(Path base) throws Exception {
412        Path src = base.resolve("src");
413        tb.writeJavaFiles(src,
414                "module m { provides p1.C1.InnerDefinition with p2.C2; }",
415                "package p1; public class C1 { public class InnerDefinition { } }",
416                "package p2; public class C2 extends p1.C1.InnerDefinition { }");
417
418        List<String> output = new JavacTask(tb)
419                .options("-XDrawDiagnostics")
420                .outdir(Files.createDirectories(base.resolve("classes")))
421                .files(findJavaFiles(src))
422                .run(Task.Expect.FAIL)
423                .writeAll()
424                .getOutputLines(Task.OutputKind.DIRECT);
425
426        List<String> expected = Arrays.asList(
427                "module-info.java:1:26: compiler.err.service.definition.is.inner: p1.C1.InnerDefinition",
428                "module-info.java:1:12: compiler.warn.service.provided.but.not.exported.or.used: p1.C1.InnerDefinition",
429                "C2.java:1:20: compiler.err.encl.class.required: p1.C1.InnerDefinition",
430                "2 errors",
431                "1 warning");
432        if (!output.containsAll(expected)) {
433            throw new Exception("Expected output not found");
434        }
435    }
436}
437