/* * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 8013357 * @summary javac should correctly enforce binary comparison rules. */ import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Symbol.*; import java.io.*; import java.lang.reflect.Array; import java.util.EnumSet; public class TestComparisons { private int errors = 0; private int testnum = 0; static final File testdir = new File("8013357"); private enum CompareType { OBJECT("Object"), NUMBER("Number"), STRING("String"), LONG("Long"), INTEGER("Integer"), SHORT("Short"), BOOLEAN("Boolean"), DOUBLE("Double"), FLOAT("Float"), CHAR("Character"), LONG_SUPER("List", true), INTEGER_SUPER("List", true), SHORT_SUPER("List", true), BOOLEAN_SUPER("List", true), DOUBLE_SUPER("List", true), FLOAT_SUPER("List", true), CHAR_SUPER("List", true), LONG_PRIM("long"), INTEGER_PRIM("int"), SHORT_PRIM("short"), BOOLEAN_PRIM("boolean"), DOUBLE_PRIM("double"), FLOAT_PRIM("float"), CHAR_PRIM("char"); public final boolean isList; public final String name; private CompareType(final String name, final boolean isList) { this.isList = isList; this.name = name; } private CompareType(final String name) { this(name, false); } } private static final boolean truthtab[][] = { // Object, comparable to everything but primitives. { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false }, // Number, any boxed form of a numeric primitive, and any // captures. { true, true, false, true, true, true, false, true, true, false, true, true, true, true, true, true, true, false, false, false, false, false, false, false }, // String, comparable only to Object and String. { true, false, true, false, false, false, false, false, false, false, true, true, true, true, true, true, true, false, false, false, false, false, false, false }, // Long, comparable to itself, Number, any numeric primitive, // and any captures. { true, true, false, true, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, false, true, true, true }, // Integer, comparable to itself, Number, any numeric // primitive, and any captures. { true, true, false, false, true, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, false, true, true, true }, // Short, comparable to itself, Number, any numeric primitive, // and any captures. { true, true, false, false, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, false, true, true, true }, // Boolean, comparable to itself, boolean, and any captures { true, false, false, false, false, false, true, false, false, false, true, true, true, true, true, true, true, false, false, false, true, false, false, false }, // Double, comparable to itself, Number, any numeric // primitive, and any captures. { true, true, false, false, false, false, false, true, false, false, true, true, true, true, true, true, true, true, true, true, false, true, true, true }, // Float, comparable to itself, Number, any numeric primitive, // and any captures. { true, true, false, false, false, false, false, false, true, false, true, true, true, true, true, true, true, true, true, true, false, true, true, true }, // Character, comparable to itself, any numeric primitive, and // any captures. { true, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, false, true, true, true }, // Long supertype wildcard, comparable to any reference type. { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false }, // Integer supertype wildcard, comparable to any reference type. { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false }, // Short supertype wildcard, comparable to any reference type. { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false }, // Boolean supertype wildcard, comparable to any reference type. { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false }, // Double supertype wildcard, comparable to any reference type. { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false }, // Float supertype wildcard, comparable to any reference type. { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false }, // Character supertype wildcard, comparable to any reference type. { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false }, // long, comparable to any numeric or boxed numeric type. { false, false, false, true, true, true, false, true, true, true, false, false, false, false, false, false, false, true, true, true, false, true, true, true }, // int, comparable to itself, any numeric type, or any boxed // numeric type. { false, false, false, true, true, true, false, true, true, true, false, false, false, false, false, false, false, true, true, true, false, true, true, true }, // short, comparable to itself, any numeric type, or any boxed // numeric type. { false, false, false, true, true, true, false, true, true, true, false, false, false, false, false, false, false, true, true, true, false, true, true, true }, // boolean, comparable only to itself and Boolean. { false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false }, // double, comparable to itself, any numeric type, or any // boxed numeric type. { false, false, false, true, true, true, false, true, true, true, false, false, false, false, false, false, false, true, true, true, false, true, true, true }, // float, comparable to itself, any numeric type, or any boxed // numeric type. { false, false, false, true, true, true, false, true, true, true, false, false, false, false, false, false, false, true, true, true, false, true, true, true }, // char, comparable to itself, any numeric type, or any boxed // numeric type. { false, false, false, true, true, true, false, true, true, true, false, false, false, false, false, false, false, true, true, true, false, true, true, true } }; private void assert_compile_fail(final File file, final String body) { final String filename = file.getPath(); final String[] args = { filename }; final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); final int rc = com.sun.tools.javac.Main.compile(args, pw); pw.close(); if (rc == 0) { System.err.println("Compilation of " + file.getName() + " didn't fail as expected.\nFile:\n" + body + "\nOutput:\n" + sw.toString()); errors++; } } private void assert_compile_succeed(final File file, final String body) { final String filename = file.getPath(); final String[] args = { filename }; final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); final int rc = com.sun.tools.javac.Main.compile(args, pw); pw.close(); if (rc != 0) { System.err.println("Compilation of " + file.getName() + " didn't succeed as expected.\nFile:\n" + body + "\nOutput:\n" + sw.toString()); errors++; } } private String makeBody(final int num, final CompareType left, final CompareType right) { return "import java.util.List;\n" + "public class Test" + num + " {\n" + " public boolean test(" + left.name + " left, " + right.name + " right) {\n" + " return left" + (left.isList ? ".get(0)" : "") + " == right" + (right.isList ? ".get(0)" : "") + ";\n" + " }\n" + "}\n"; } private File writeFile(final String filename, final String body) throws IOException { final File f = new File(testdir, filename); f.getParentFile().mkdirs(); final FileWriter out = new FileWriter(f); out.write(body); out.close(); return f; } private void test(final CompareType left, final CompareType right) throws IOException { final int num = testnum++; final String filename = "Test" + num + ".java"; final String body = makeBody(num, left, right); final File file = writeFile(filename, body); if (truthtab[left.ordinal()][right.ordinal()]) assert_compile_succeed(file, body); else assert_compile_fail(file, body); } void run() throws Exception { testdir.mkdir(); for(CompareType left : CompareType.values()) for(CompareType right : CompareType.values()) test(left, right); if (errors != 0) throw new Exception("ObjectZeroCompare test failed with " + errors + " errors."); } public static void main(String... args) throws Exception { new TestComparisons().run(); } }