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