TestComparisons.java revision 3504:30bfbfa94fad
1/*
2 * Copyright (c) 2013, 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 * @bug 8013357
27 * @summary javac should correctly enforce binary comparison rules.
28 * @modules jdk.compiler
29 */
30
31import java.io.*;
32
33public class TestComparisons {
34
35    private int errors = 0;
36    private int testnum = 0;
37
38    static final File testdir = new File("8013357");
39
40    private enum CompareType {
41        BYTE_PRIM("byte"),
42        SHORT_PRIM("short"),
43        CHAR_PRIM("char"),
44        INTEGER_PRIM("int"),
45        LONG_PRIM("long"),
46        FLOAT_PRIM("float"),
47        DOUBLE_PRIM("double"),
48        BOOLEAN_PRIM("boolean"),
49
50        BYTE("Byte"),
51        SHORT("Short"),
52        CHAR("Character"),
53        INTEGER("Integer"),
54        LONG("Long"),
55        FLOAT("Float"),
56        DOUBLE("Double"),
57        BOOLEAN("Boolean"),
58
59        BYTE_SUPER("List<? super Byte>", true),
60        SHORT_SUPER("List<? super Short>", true),
61        CHAR_SUPER("List<? super Character>", true),
62        INTEGER_SUPER("List<? super Integer>", true),
63        LONG_SUPER("List<? super Long>", true),
64        FLOAT_SUPER("List<? super Float>", true),
65        DOUBLE_SUPER("List<? super Double>", true),
66        BOOLEAN_SUPER("List<? super Boolean>", true),
67
68        OBJECT("Object"),
69        NUMBER("Number"),
70        STRING("String");
71
72        public final boolean isList;
73        public final String name;
74
75        private CompareType(final String name, final boolean isList) {
76            this.isList = isList;
77            this.name = name;
78        }
79
80        private CompareType(final String name) {
81            this(name, false);
82        }
83    }
84
85    // The integers here refer to which subsection of JLS 15.21 is in
86    // effect.  0 means no comparison is allowed.
87    private static final int truthtab[][] = {
88        // byte, comparable to itself, any numeric type, or any boxed
89        // numeric type.
90        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
91          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
92          0, 0, 0, 0, 0, 0, 0, 0, // Captures
93          0, 0, 0                 // Reference types
94        },
95        // short, comparable to itself, any numeric type, or any boxed
96        // numeric type.
97        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
98          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
99          0, 0, 0, 0, 0, 0, 0, 0, // Captures
100          0, 0, 0                 // Reference types
101        },
102        // char, comparable to itself, any numeric type, or any boxed
103        // numeric type.
104        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
105          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
106          0, 0, 0, 0, 0, 0, 0, 0, // Captures
107          0, 0, 0                 // Reference types
108        },
109        // int, comparable to itself, any numeric type, or any boxed
110        // numeric type.
111        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
112          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
113          0, 0, 0, 0, 0, 0, 0, 0, // Captures
114          0, 0, 0                 // Reference types
115        },
116        // long, comparable to itself, any numeric type, or any boxed
117        // numeric type.
118        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
119          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
120          0, 0, 0, 0, 0, 0, 0, 0, // Captures
121          0, 0, 0                 // Reference types
122        },
123        // float, comparable to itself, any numeric type, or any boxed
124        // numeric type.
125        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
126          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
127          0, 0, 0, 0, 0, 0, 0, 0, // Captures
128          0, 0, 0                 // Reference types
129        },
130        // double, comparable to itself, any numeric type, or any boxed
131        // numeric type.
132        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
133          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
134          0, 0, 0, 0, 0, 0, 0, 0, // Captures
135          0, 0, 0                 // Reference types
136        },
137        // boolean, comparable only to itself and Boolean.
138        { 0, 0, 0, 0, 0, 0, 0, 2, // Primitives
139          0, 0, 0, 0, 0, 0, 0, 2, // Boxed primitives
140          0, 0, 0, 0, 0, 0, 0, 0, // Captures
141          0, 0, 0                 // Reference types
142        },
143        // Byte, comparable to itself, Number, Object, any numeric primitive,
144        // and any captures.
145        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
146          3, 0, 0, 0, 0, 0, 0, 0, // Boxed primitives
147          3, 3, 3, 3, 3, 3, 3, 3, // Captures
148          3, 3, 0                 // Reference types
149        },
150        // Short, comparable to itself, Number, Object, any numeric primitive,
151        // and any captures.
152        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
153          0, 3, 0, 0, 0, 0, 0, 0, // Boxed primitives
154          3, 3, 3, 3, 3, 3, 3, 3, // Captures
155          3, 3, 0                 // Reference types
156        },
157        // Character, comparable to itself, Object, any numeric primitive,
158        // and any captures.
159        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
160          0, 0, 3, 0, 0, 0, 0, 0, // Boxed primitives
161          3, 3, 3, 3, 3, 3, 3, 3, // Captures
162          3, 0, 0                 // Reference types
163        },
164        // Int, comparable to itself, Number, Object, any numeric primitive,
165        // and any captures.
166        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
167          0, 0, 0, 3, 0, 0, 0, 0, // Boxed primitives
168          3, 3, 3, 3, 3, 3, 3, 3, // Captures
169          3, 3, 0                 // Reference types
170        },
171        // Long, comparable to itself, Number, Object, any numeric primitive,
172        // and any captures.
173        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
174          0, 0, 0, 0, 3, 0, 0, 0, // Boxed primitives
175          3, 3, 3, 3, 3, 3, 3, 3, // Captures
176          3, 3, 0                 // Reference types
177        },
178        // Float, comparable to itself, Number, Object, any numeric primitive,
179        // and any captures.
180        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
181          0, 0, 0, 0, 0, 3, 0, 0, // Boxed primitives
182          3, 3, 3, 3, 3, 3, 3, 3, // Captures
183          3, 3, 0                 // Reference types
184        },
185        // Double, comparable to itself, Number, Object, any numeric primitive,
186        // and any captures.
187        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
188          0, 0, 0, 0, 0, 0, 3, 0, // Boxed primitives
189          3, 3, 3, 3, 3, 3, 3, 3, // Captures
190          3, 3, 0                 // Reference types
191        },
192        // Boolean, to itself, any capture, Object, and boolean.
193        { 0, 0, 0, 0, 0, 0, 0, 2, // Primitives
194          0, 0, 0, 0, 0, 0, 0, 2, // Boxed primitives
195          3, 3, 3, 3, 3, 3, 3, 3, // Captures
196          3, 0, 0                 // Reference types
197        },
198        // Byte supertype wildcard, comparable to any reference type.
199        // and any captures.
200        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
201          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
202          3, 3, 3, 3, 3, 3, 3, 3, // Captures
203          3, 3, 3                 // Reference types
204        },
205        // Short supertype wildcard, comparable to any reference type.
206        // and any captures.
207        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
208          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
209          3, 3, 3, 3, 3, 3, 3, 3, // Captures
210          3, 3, 3                 // Reference types
211        },
212        // Character supertype wildcard, comparable to any reference type.
213        // and any captures.
214        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
215          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
216          3, 3, 3, 3, 3, 3, 3, 3, // Captures
217          3, 3, 3                 // Reference types
218        },
219        // Integer supertype wildcard, comparable to any reference type.
220        // and any captures.
221        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
222          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
223          3, 3, 3, 3, 3, 3, 3, 3, // Captures
224          3, 3, 3                 // Reference types
225        },
226        // Long supertype wildcard, comparable to any reference type.
227        // and any captures.
228        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
229          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
230          3, 3, 3, 3, 3, 3, 3, 3, // Captures
231          3, 3, 3                 // Reference types
232        },
233        // Float supertype wildcard, comparable to any reference type.
234        // and any captures.
235        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
236          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
237          3, 3, 3, 3, 3, 3, 3, 3, // Captures
238          3, 3, 3                 // Reference types
239        },
240        // Double supertype wildcard, comparable to any reference type.
241        // and any captures.
242        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
243          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
244          3, 3, 3, 3, 3, 3, 3, 3, // Captures
245          3, 3, 3                 // Reference types
246        },
247        // Boolean supertype wildcard, comparable to any reference type.
248        // and any captures.
249        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
250          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
251          3, 3, 3, 3, 3, 3, 3, 3, // Captures
252          3, 3, 3                 // Reference types
253        },
254        // Object, comparable to any reference type.
255        // and any captures.
256        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
257          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
258          3, 3, 3, 3, 3, 3, 3, 3, // Captures
259          3, 3, 3                 // Reference types
260        },
261        // Number, comparable to Object, any of its subclasses.
262        // and any captures.
263        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
264          3, 3, 0, 3, 3, 3, 3, 0, // Boxed primitives
265          3, 3, 3, 3, 3, 3, 3, 3, // Captures
266          3, 3, 0                 // Reference types
267        },
268        // String supertype wildcard, comparable to any reference type.
269        // and any captures.
270        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
271          0, 0, 0, 0, 0, 0, 0, 0, // Boxed primitives
272          3, 3, 3, 3, 3, 3, 3, 3, // Captures
273          3, 0, 3                 // Reference types
274        }
275    };
276
277    private void assert_compile_fail(final File file, final String body) {
278        final String filename = file.getPath();
279        final String[] args = { filename };
280        final StringWriter sw = new StringWriter();
281        final PrintWriter pw = new PrintWriter(sw);
282        final int rc = com.sun.tools.javac.Main.compile(args, pw);
283        pw.close();
284        if (rc == 0) {
285            System.err.println("Compilation of " + file.getName() +
286                               " didn't fail as expected.\nFile:\n" +
287                               body + "\nOutput:\n" + sw.toString());
288            errors++;
289        }
290    }
291
292    private void assert_compile_succeed(final File file, final String body) {
293        final String filename = file.getPath();
294        final String[] args = { filename };
295        final StringWriter sw = new StringWriter();
296        final PrintWriter pw = new PrintWriter(sw);
297        final int rc = com.sun.tools.javac.Main.compile(args, pw);
298        pw.close();
299        if (rc != 0) {
300            System.err.println("Compilation of " + file.getName() +
301                               " didn't succeed as expected.\nFile:\n" +
302                               body + "\nOutput:\n" +
303                               sw.toString());
304            errors++;
305        }
306    }
307
308    private String makeBody(final int num,
309                            final CompareType left,
310                            final CompareType right) {
311        return "import java.util.List;\n" +
312            "public class Test" + num + " {\n" +
313            "    public boolean test(" + left.name +
314            " left, " + right.name + " right) {\n" +
315            "        return left" + (left.isList ? ".get(0)" : "") +
316            " == right" + (right.isList ? ".get(0)" : "") + ";\n" +
317            "    }\n" +
318            "}\n";
319    }
320
321    private File writeFile(final String filename,
322                           final String body)
323        throws IOException {
324        final File f = new File(testdir, filename);
325        f.getParentFile().mkdirs();
326        final FileWriter out = new FileWriter(f);
327        out.write(body);
328        out.close();
329        return f;
330    }
331
332    private void test(final CompareType left, final CompareType right)
333        throws IOException {
334        final int num = testnum++;
335        final String filename = "Test" + num + ".java";
336        final String body = makeBody(num, left, right);
337        final File file = writeFile(filename, body);
338        if (truthtab[left.ordinal()][right.ordinal()] != 0)
339            assert_compile_succeed(file, body);
340        else
341            assert_compile_fail(file, body);
342    }
343
344    void run() throws Exception {
345        testdir.mkdir();
346
347        for(CompareType left : CompareType.values())
348            for(CompareType right : CompareType.values())
349                test(left, right);
350
351        if (errors != 0)
352            throw new Exception("ObjectZeroCompare test failed with " +
353                                errors + " errors.");
354    }
355
356    public static void main(String... args) throws Exception {
357        new TestComparisons().run();
358    }
359}
360