7006109: Add test library to simplify the task of writing automated type-system tests
Summary: Types.java needs to be more stress-tested
Reviewed-by: jjg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/types/BoxingConversionTest.java Mon Dec 13 14:56:50 2010 +0000
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2010, 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 7006109
+ * @summary Add test library to simplify the task of writing automated type-system tests
+ * @author mcimadamore
+ * @library .
+ * @run main BoxingConversionTest
+ */
+
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Symbol.*;
+import java.lang.reflect.Array;
+import java.util.EnumSet;
+
+/**
+ * Check invariants in assignment/method conversion involving boxing conversions
+ */
+public class BoxingConversionTest extends TypeHarness {
+
+ Type[] types1;
+ Type[] types2;
+ Type[] types3;
+
+ enum Result {
+ OK_BOTH(true),
+ FAIL_BOTH(false),
+ OK_ASSIGN_ONLY(true);
+
+ boolean value;
+
+ Result(boolean value) {
+ this.value = value;
+ }
+ }
+
+ enum ConversionKind {
+ ASSIGNMENT_CONVERSION(EnumSet.of(Result.OK_BOTH, Result.OK_ASSIGN_ONLY)) {
+ @Override
+ void check(TypeHarness harness, Type from, Type to, Result expected) {
+ harness.assertAssignable(from, to, resSet.contains(expected));
+ }
+ },
+ METHOD_CONVERSION(EnumSet.of(Result.OK_BOTH)) {
+ @Override
+ void check(TypeHarness harness, Type from, Type to, Result expected) {
+ harness.assertConvertible(from, to, resSet.contains(expected));
+ }
+ };
+
+ EnumSet<Result> resSet;
+
+ private ConversionKind(EnumSet<Result> resSet) {
+ this.resSet = resSet;
+ }
+
+ abstract void check(TypeHarness harness, Type from, Type to, Result expected);
+ }
+
+ enum TestKind {
+ SIMPLE {
+ @Override
+ Type[] getFromTypes(BoxingConversionTest harness) {
+ return harness.types1;
+ }
+ @Override
+ Type[] getToTypes(BoxingConversionTest harness) {
+ return harness.types1;
+ }
+ @Override
+ Result[][] getResults(BoxingConversionTest harness) {
+ return harness.results1;
+ }
+ },
+ CONSTANT_TYPES {
+ @Override
+ Type[] getFromTypes(BoxingConversionTest harness) {
+ return harness.types2;
+ }
+ @Override
+ Type[] getToTypes(BoxingConversionTest harness) {
+ return harness.types3;
+ }
+ @Override
+ Result[][] getResults(BoxingConversionTest harness) {
+ return harness.results2;
+ }
+ };
+
+ abstract Type[] getFromTypes(BoxingConversionTest harness);
+ abstract Type[] getToTypes(BoxingConversionTest harness);
+ abstract Result[][] getResults(BoxingConversionTest harness);
+ }
+
+ static final Result T = Result.OK_BOTH;
+ static final Result F = Result.FAIL_BOTH;
+ static final Result A = Result.OK_ASSIGN_ONLY;
+ static final Result X = Result.FAIL_BOTH.FAIL_BOTH;
+
+ Result[][] results1 = {
+ //byte, short, int, long, float, double, char, bool, Byte, Short, Integer, Long, Float, Double, Character, Boolean
+ /*byte*/ { T , T , T , T , T , T , F , F , T , F , F , F , F , F , F , F },
+ /*short*/ { F , T , T , T , T , T , F , F , F , T , F , F , F , F , F , F },
+ /*int*/ { F , F , T , T , T , T , F , F , F , F , T , F , F , F , F , F },
+ /*long*/ { F , F , F , T , T , T , F , F , F , F , F , T , F , F , F , F },
+ /*float*/ { F , F , F , F , T , T , F , F , F , F , F , F , T , F , F , F },
+ /*double*/ { F , F , F , F , F , T , F , F , F , F , F , F , F , T , F , F },
+ /*char*/ { F , F , T , T , T , T , T , F , F , F , F , F , F , F , T , F },
+ /*bool*/ { F , F , F , F , F , F , F , T , F , F , F , F , F , F , F , T },
+ /*Byte*/ { T , T , T , T , T , T , F , F , T , F , F , F , F , F , F , F },
+ /*Short*/ { F , T , T , T , T , T , F , F , F , T , F , F , F , F , F , F },
+ /*Integer*/ { F , F , T , T , T , T , F , F , F , F , T , F , F , F , F , F },
+ /*Long*/ { F , F , F , T , T , T , F , F , F , F , F , T , F , F , F , F },
+ /*Float*/ { F , F , F , F , T , T , F , F , F , F , F , F , T , F , F , F },
+ /*Double*/ { F , F , F , F , F , T , F , F , F , F , F , F , F , T , F , F },
+ /*Character*/ { F , F , T , T , T , T , T , F , F , F , F , F , F , F , T , F },
+ /*Boolean*/ { F , F , F , F , F , F , F , T , F , F , F , F , F , F , F , T }};
+
+ Result[][] results2 = {
+ //Byte, Short, Integer, Long, Float, Double, Chararacter, Boolean
+ /*byte*/ { T , F , F , F , F , F , F , F },
+ /*short*/ { F , T , F , F , F , F , F , F },
+ /*short1*/ { A , T , F , F , F , F , A , F },
+ /*short2*/ { F , T , F , F , F , F , A , F },
+ /*int*/ { F , F , T , F , F , F , F , F },
+ /*int1*/ { A , A , T , F , F , F , A , F },
+ /*int2*/ { F , A , T , F , F , F , A , F },
+ /*int4*/ { F , F , T , F , F , F , F , F },
+ /*long*/ { F , F , F , T , F , F , F , F },
+ /*long1*/ { F , F , F , T , F , F , F , F },
+ /*long2*/ { F , F , F , T , F , F , F , F },
+ /*long4*/ { F , F , F , T , F , F , F , F },
+ /*long8*/ { F , F , F , T , F , F , F , F },
+ /*float*/ { F , F , F , F , T , F , F , F },
+ /*float1*/ { F , F , F , F , T , F , F , F },
+ /*float2*/ { F , F , F , F , T , F , F , F },
+ /*float4*/ { F , F , F , F , T , F , F , F },
+ /*double*/ { F , F , F , F , F , T , F , F },
+ /*double1*/ { F , F , F , F , F , T , F , F },
+ /*double2*/ { F , F , F , F , F , T , F , F },
+ /*double4*/ { F , F , F , F , F , T , F , F },
+ /*double8*/ { F , F , F , F , F , T , F , F },
+ /*char*/ { F , F , F , F , F , F , T , F },
+ /*char1*/ { A , A , F , F , F , F , T , F },
+ /*char2*/ { F , A , F , F , F , F , T , F },
+ /*bool*/ { F , F , F , F , F , F , F , T }};
+
+ BoxingConversionTest() {
+ Type[] primitiveTypes = new Type[] {
+ predef.byteType,
+ predef.shortType,
+ predef.intType,
+ predef.longType,
+ predef.floatType,
+ predef.doubleType,
+ predef.charType,
+ predef.booleanType };
+
+ Type[] boxedTypes = new Type[primitiveTypes.length];
+ for (int i = 0 ; i < primitiveTypes.length ; i++) {
+ boxedTypes[i] = box(primitiveTypes[i]);
+ }
+
+ types1 = join(Type.class, primitiveTypes, boxedTypes);
+
+ types2 = new Type[] {
+ predef.byteType,
+ predef.shortType,
+ fac.Constant((short)0x0001),
+ fac.Constant((short)0x0100),
+ predef.intType,
+ fac.Constant((int)0x0000_0001),
+ fac.Constant((int)0x0000_0100),
+ fac.Constant((int)0x0001_0000),
+ predef.longType,
+ fac.Constant((long)0x0000_0000_0000_0001L),
+ fac.Constant((long)0x0000_0000_0000_0100L),
+ fac.Constant((long)0x0000_0000_0001_0000L),
+ fac.Constant((long)0x0001_0000_0000_0000L),
+ predef.floatType,
+ fac.Constant((float)0x0000_0001),
+ fac.Constant((float)0x0000_0100),
+ fac.Constant((float)0x0001_0000),
+ predef.doubleType,
+ fac.Constant((double)0x0000_0000_0000_0001L),
+ fac.Constant((double)0x0000_0000_0000_0100L),
+ fac.Constant((double)0x0000_0000_0001_0000L),
+ fac.Constant((double)0x0001_0000_0000_0000L),
+ predef.charType,
+ fac.Constant((char)0x0001),
+ fac.Constant((char)0x0100),
+ predef.booleanType
+ };
+
+ types3 = boxedTypes;
+ }
+
+ void testConversion(ConversionKind convKind, TestKind testKind) {
+ Type[] rows = testKind.getFromTypes(this);
+ Type[] cols = testKind.getToTypes(this);
+ for (int i = 0; i < rows.length ; i++) {
+ for (int j = 0; j < cols.length ; j++) {
+ convKind.check(this, rows[i], cols[j], testKind.getResults(this)[i][j]);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ <T> T[] join(Class<T> type, T[]... args) {
+ int totalLength = 0;
+ for (T[] arr : args) {
+ totalLength += arr.length;
+ }
+ T[] new_arr = (T[])Array.newInstance(type, totalLength);
+ int idx = 0;
+ for (T[] arr : args) {
+ System.arraycopy(arr, 0, new_arr, idx, arr.length);
+ idx += arr.length;
+ }
+ return new_arr;
+ }
+
+ public static void main(String[] args) {
+ BoxingConversionTest harness = new BoxingConversionTest();
+ for (ConversionKind convKind : ConversionKind.values()) {
+ for (TestKind testKind : TestKind.values()) {
+ harness.testConversion(convKind, testKind);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/types/CastTest.java Mon Dec 13 14:56:50 2010 +0000
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2010, 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 7006109
+ * @summary Add test library to simplify the task of writing automated type-system tests
+ * @author mcimadamore
+ * @library .
+ * @run main CastTest
+ */
+
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Symbol.*;
+import java.lang.reflect.Array;
+
+import static com.sun.tools.javac.code.Flags.*;
+
+/**
+ * Check invariants in cast conversion involving primitive types and arrays
+ */
+public class CastTest extends TypeHarness {
+
+ Type[] allTypes;
+
+ static final boolean T = true;
+ static final boolean F = false;
+
+ boolean[][] cast_result = {
+ //byte, short, int, long, float, double, char, bool, C, +C, I, T, byte[], short[], int[], long[], float[], double[], char[], bool[], C[], +C[], I[], T[]
+ /*byte*/ { T , T , T , T , T , T , T , F , F, F , F, F, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*short*/ { T , T , T , T , T , T , T , F , F, F , F, F, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*int*/ { T , T , T , T , T , T , T , F , F, F , F, F, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*long*/ { T , T , T , T , T , T , T , F , F, F , F, F, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*float*/ { T , T , T , T , T , T , T , F , F, F , F, F, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*double*/ { T , T , T , T , T , T , T , F , F, F , F, F, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*char*/ { T , T , T , T , T , T , T , F , F, F , F, F, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*bool*/ { F , F , F , F , F , F , F , T , F, F , F, F, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*C*/ { F , F , F , F , F , F , F , F , T, F , T, T, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*+C*/ { F , F , F , F , F , F , F , F , F, T , F, T, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*I*/ { F , F , F , F , F , F , F , F , T, F , T, T, F , F , F , F , F , F , F , F , F , F , F , F },
+ /*T*/ { F , F , F , F , F , F , F , F , T, T , T, T, T , T , T , T , T , T , T , T , T , T , T , T },
+ /*byte[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, T , F , F , F , F , F , F , F , F , F , F , F },
+ /*short[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , T , F , F , F , F , F , F , F , F , F , F },
+ /*int[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , T , F , F , F , F , F , F , F , F , F },
+ /*long[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , T , F , F , F , F , F , F , F , F },
+ /*float[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , F , T , F , F , F , F , F , F , F },
+ /*double[]*/{ F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , F , F , T , F , F , F , F , F , F },
+ /*char[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , F , F , F , T , F , F , F , F , F },
+ /*bool[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , F , F , F , F , T , F , F , F , F },
+ /*C[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , F , F , F , F , F , T , F , T , T },
+ /*+C[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , F , F , F , F , F , F , T , F , T },
+ /*I[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , F , F , F , F , F , T , F , T , T },
+ /*T[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , F , F , F , F , F , T , T , T , T }};
+
+ CastTest() {
+ Type[] primitiveTypes = {
+ predef.byteType,
+ predef.shortType,
+ predef.intType,
+ predef.longType,
+ predef.floatType,
+ predef.doubleType,
+ predef.charType,
+ predef.booleanType };
+
+ Type[] referenceTypes = {
+ fac.Class(),
+ fac.Class(FINAL),
+ fac.Interface(),
+ fac.TypeVariable() };
+
+ Type[] arrayTypes = new Type[primitiveTypes.length + referenceTypes.length];
+ int idx = 0;
+ for (Type t : join(Type.class, primitiveTypes, referenceTypes)) {
+ arrayTypes[idx++] = fac.Array(t);
+ }
+
+ allTypes = join(Type.class, primitiveTypes, referenceTypes, arrayTypes);
+ }
+
+ void test() {
+ for (int i = 0; i < allTypes.length ; i++) {
+ for (int j = 0; j < allTypes.length ; j++) {
+ assertCastable(allTypes[i], allTypes[j], cast_result[i][j]);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ <T> T[] join(Class<T> type, T[]... args) {
+ int totalLength = 0;
+ for (T[] arr : args) {
+ totalLength += arr.length;
+ }
+ T[] new_arr = (T[])Array.newInstance(type, totalLength);
+ int idx = 0;
+ for (T[] arr : args) {
+ System.arraycopy(arr, 0, new_arr, idx, arr.length);
+ idx += arr.length;
+ }
+ return new_arr;
+ }
+
+ public static void main(String[] args) {
+ new CastTest().test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/types/PrimitiveConversionTest.java Mon Dec 13 14:56:50 2010 +0000
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2010, 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 7006109
+ * @summary Add test library to simplify the task of writing automated type-system tests
+ * @author mcimadamore
+ * @library .
+ * @run main PrimitiveConversionTest
+ */
+
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Symbol.*;
+import java.lang.reflect.Array;
+import java.util.EnumSet;
+
+/**
+ * Check invariants in assignment/method conversion involving primitive types and arrays
+ */
+public class PrimitiveConversionTest extends TypeHarness {
+
+ Type[] types1;
+ Type[] types2;
+ Type[] types3;
+
+ enum Result {
+ OK_BOTH(true),
+ FAIL_BOTH(false),
+ OK_ASSIGN_ONLY(true);
+
+ boolean value;
+
+ Result(boolean value) {
+ this.value = value;
+ }
+ }
+
+ enum ConversionKind {
+ ASSIGNMENT_CONVERSION(EnumSet.of(Result.OK_BOTH, Result.OK_ASSIGN_ONLY)) {
+ @Override
+ void check(TypeHarness harness, Type from, Type to, Result expected) {
+ harness.assertAssignable(from, to, resSet.contains(expected));
+ }
+ },
+ METHOD_CONVERSION(EnumSet.of(Result.OK_BOTH)) {
+ @Override
+ void check(TypeHarness harness, Type from, Type to, Result expected) {
+ harness.assertConvertible(from, to, resSet.contains(expected));
+ }
+ };
+
+ EnumSet<Result> resSet;
+
+ private ConversionKind(EnumSet<Result> resSet) {
+ this.resSet = resSet;
+ }
+
+ abstract void check(TypeHarness harness, Type from, Type to, Result expected);
+ }
+
+ enum TestKind {
+ SIMPLE {
+ @Override
+ Type[] getFromTypes(PrimitiveConversionTest harness) {
+ return harness.types1;
+ }
+ @Override
+ Type[] getToTypes(PrimitiveConversionTest harness) {
+ return harness.types1;
+ }
+ @Override
+ Result[][] getResults(PrimitiveConversionTest harness) {
+ return harness.results1;
+ }
+ },
+ CONSTANT_TYPES {
+ @Override
+ Type[] getFromTypes(PrimitiveConversionTest harness) {
+ return harness.types2;
+ }
+ @Override
+ Type[] getToTypes(PrimitiveConversionTest harness) {
+ return harness.types3;
+ }
+ @Override
+ Result[][] getResults(PrimitiveConversionTest harness) {
+ return harness.results2;
+ }
+ };
+
+ abstract Type[] getFromTypes(PrimitiveConversionTest harness);
+ abstract Type[] getToTypes(PrimitiveConversionTest harness);
+ abstract Result[][] getResults(PrimitiveConversionTest harness);
+ }
+
+ static final Result T = Result.OK_BOTH;
+ static final Result F = Result.FAIL_BOTH;
+ static final Result A = Result.OK_ASSIGN_ONLY;
+
+ Result[][] results1 = {
+ //byte, short, int, long, float, double, char, bool, C1, C2, C3, T , byte[], short[], int[], long[], float[], double[], char[], bool[], C1[], C2[], C3[], T[]
+ /*byte*/ { T , T , T , T , T , T , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*short*/ { F , T , T , T , T , T , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*int*/ { F , F , T , T , T , T , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*long*/ { F , F , F , T , T , T , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*float*/ { F , F , F , F , T , T , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*double*/ { F , F , F , F , F , T , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*char*/ { F , F , T , T , T , T , T , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*bool*/ { F , F , F , F , F , F , F , T , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*C1*/ { F , F , F , F , F , F , F , F , T , F , T , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*C2*/ { F , F , F , F , F , F , F , F , T , T , T , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*C3*/ { F , F , F , F , F , F , F , F , T , F , T , F , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*T*/ { F , F , F , F , F , F , F , F , F , F , F , T , F , F , F , F , F , F , F , F , F , F , F , F },
+ /*byte[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , T , F , F , F , F , F , F , F , F , F , F , F },
+ /*short[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , F , T , F , F , F , F , F , F , F , F , F , F },
+ /*int[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , F , F , T , F , F , F , F , F , F , F , F , F },
+ /*long[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , T , F , F , F , F , F , F , F , F },
+ /*float[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , T , F , F , F , F , F , F , F },
+ /*double[]*/{ F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , T , F , F , F , F , F , F },
+ /*char[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , T , F , F , F , F , F },
+ /*bool[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , T , F , F , F , F },
+ /*C1[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , T , F , T , F },
+ /*C2[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , T , T , T , F },
+ /*C3[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , T , F , T , F },
+ /*T[]*/ { F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , F , T }};
+
+ Result[][] results2 = {
+ //byte, short, int, long, float, double, char, bool
+ /*byte*/ { T , T , T , T , T , T , F , F },
+ /*short*/ { F , T , T , T , T , T , F , F },
+ /*short1*/ { A , T , T , T , T , T , A , F },
+ /*short2*/ { F , T , T , T , T , T , A , F },
+ /*int*/ { F , F , T , T , T , T , F , F },
+ /*int1*/ { A , A , T , T , T , T , A , F },
+ /*int2*/ { F , A , T , T , T , T , A , F },
+ /*int4*/ { F , F , T , T , T , T , F , F },
+ /*long*/ { F , F , F , T , T , T , F , F },
+ /*long1*/ { F , F , F , T , T , T , F , F },
+ /*long2*/ { F , F , F , T , T , T , F , F },
+ /*long4*/ { F , F , F , T , T , T , F , F },
+ /*long8*/ { F , F , F , T , T , T , F , F },
+ /*float*/ { F , F , F , F , T , T , F , F },
+ /*float1*/ { F , F , F , F , T , T , F , F },
+ /*float2*/ { F , F , F , F , T , T , F , F },
+ /*float4*/ { F , F , F , F , T , T , F , F },
+ /*double*/ { F , F , F , F , F , T , F , F },
+ /*double1*/ { F , F , F , F , F , T , F , F },
+ /*double2*/ { F , F , F , F , F , T , F , F },
+ /*double4*/ { F , F , F , F , F , T , F , F },
+ /*double8*/ { F , F , F , F , F , T , F , F },
+ /*char*/ { F , F , T , T , T , T , T , F },
+ /*char1*/ { A , A , T , T , T , T , T , F },
+ /*char2*/ { F , A , T , T , T , T , T , F },
+ /*bool*/ { F , F , F , F , F , F , F , T }};
+
+ PrimitiveConversionTest() {
+ Type[] primitiveTypes = new Type[] {
+ predef.byteType,
+ predef.shortType,
+ predef.intType,
+ predef.longType,
+ predef.floatType,
+ predef.doubleType,
+ predef.charType,
+ predef.booleanType };
+
+ ClassType c1 = fac.Class(fac.TypeVariable());
+ ClassType c2 = fac.Class();
+ c2.supertype_field = subst(c1,
+ Mapping(c1.getTypeArguments().head, predef.stringType));
+ Type c3 = erasure(c1);
+
+ Type[] referenceTypes = {
+ subst(c1,
+ Mapping(c1.getTypeArguments().head, predef.stringType)),
+ c2,
+ c3,
+ fac.TypeVariable() };
+
+ Type[] arrayTypes = new Type[primitiveTypes.length + referenceTypes.length];
+ int idx = 0;
+ for (Type t : join(Type.class, primitiveTypes, referenceTypes)) {
+ arrayTypes[idx++] = fac.Array(t);
+ }
+
+ types1 = join(Type.class, primitiveTypes, referenceTypes, arrayTypes);
+
+ types2 = new Type[] {
+ predef.byteType,
+ predef.shortType,
+ fac.Constant((short)0x0001),
+ fac.Constant((short)0x0100),
+ predef.intType,
+ fac.Constant((int)0x0000_0001),
+ fac.Constant((int)0x0000_0100),
+ fac.Constant((int)0x0001_0000),
+ predef.longType,
+ fac.Constant((long)0x0000_0000_0000_0001L),
+ fac.Constant((long)0x0000_0000_0000_0100L),
+ fac.Constant((long)0x0000_0000_0001_0000L),
+ fac.Constant((long)0x0001_0000_0000_0000L),
+ predef.floatType,
+ fac.Constant((float)0x0000_0001),
+ fac.Constant((float)0x0000_0100),
+ fac.Constant((float)0x0001_0000),
+ predef.doubleType,
+ fac.Constant((double)0x0000_0000_0000_0001L),
+ fac.Constant((double)0x0000_0000_0000_0100L),
+ fac.Constant((double)0x0000_0000_0001_0000L),
+ fac.Constant((double)0x0001_0000_0000_0000L),
+ predef.charType,
+ fac.Constant((char)0x0001),
+ fac.Constant((char)0x0100),
+ predef.booleanType
+ };
+
+ types3 = primitiveTypes;
+ }
+
+ void testConversion(ConversionKind convKind, TestKind testKind) {
+ Type[] rows = testKind.getFromTypes(this);
+ Type[] cols = testKind.getToTypes(this);
+ for (int i = 0; i < rows.length ; i++) {
+ for (int j = 0; j < cols.length ; j++) {
+ convKind.check(this, rows[i], cols[j], testKind.getResults(this)[i][j]);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ <T> T[] join(Class<T> type, T[]... args) {
+ int totalLength = 0;
+ for (T[] arr : args) {
+ totalLength += arr.length;
+ }
+ T[] new_arr = (T[])Array.newInstance(type, totalLength);
+ int idx = 0;
+ for (T[] arr : args) {
+ System.arraycopy(arr, 0, new_arr, idx, arr.length);
+ idx += arr.length;
+ }
+ return new_arr;
+ }
+
+ public static void main(String[] args) {
+ PrimitiveConversionTest harness = new PrimitiveConversionTest();
+ for (ConversionKind convKind : ConversionKind.values()) {
+ for (TestKind testKind : TestKind.values()) {
+ harness.testConversion(convKind, testKind);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/types/TypeHarness.java Mon Dec 13 14:56:50 2010 +0000
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+import com.sun.tools.javac.code.BoundKind;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+import com.sun.tools.javac.file.JavacFileManager;
+
+/**
+ * Test harness whose goal is to simplify the task of writing type-system
+ * regression test. It provides functionalities to build custom types as well
+ * as to access the underlying javac's symbol table in order to retrieve
+ * predefined types. Among the features supported by the harness are: type
+ * substitution, type containment, subtyping, cast-conversion, assigment
+ * conversion.
+ *
+ * This class is meant to be a common super class for all concrete type test
+ * classes. A subclass can access the type-factory and the test methods so as
+ * to write compact tests. An example is reported below:
+ *
+ * <pre>
+ * Type X = fac.TypeVariable();
+ * Type Y = fac.TypeVariable();
+ * Type A_X_Y = fac.Class(0, X, Y);
+ * Type A_Obj_Obj = fac.Class(0,
+ * predef.objectType,
+ * predef.objectType);
+ * checkSameType(A_Obj_Obj, subst(A_X_Y,
+ * Mapping(X, predef.objectType),
+ * Mapping(Y, predef.objectType)));
+ * </pre>
+ *
+ * The above code is used to create two class types, namely {@code A<X,Y>} and
+ * {@code A<Object,Object>} where both {@code X} and {@code Y} are type-variables.
+ * The code then verifies that {@code [X:=Object,Y:=Object]A<X,Y> == A<Object,Object>}.
+ *
+ * @author mcimadamore
+ */
+public class TypeHarness {
+
+ protected Types types;
+ protected Symtab predef;
+ protected Names names;
+ protected Factory fac;
+
+ protected TypeHarness() {
+ Context ctx = new Context();
+ JavacFileManager.preRegister(ctx);
+ types = Types.instance(ctx);
+ predef = Symtab.instance(ctx);
+ names = Names.instance(ctx);
+ fac = new Factory();
+ }
+
+ // <editor-fold defaultstate="collapsed" desc="type assertions">
+
+ /** assert that 's' is a subtype of 't' */
+ public void assertSubtype(Type s, Type t) {
+ assertSubtype(s, t, true);
+ }
+
+ /** assert that 's' is/is not a subtype of 't' */
+ public void assertSubtype(Type s, Type t, boolean expected) {
+ if (types.isSubtype(s, t) != expected) {
+ String msg = expected ?
+ " is not a subtype of " :
+ " is a subtype of ";
+ error(s + msg + t);
+ }
+ }
+
+ /** assert that 's' is the same type as 't' */
+ public void assertSameType(Type s, Type t) {
+ assertSameType(s, t, true);
+ }
+
+ /** assert that 's' is/is not the same type as 't' */
+ public void assertSameType(Type s, Type t, boolean expected) {
+ if (types.isSameType(s, t) != expected) {
+ String msg = expected ?
+ " is not the same type as " :
+ " is the same type as ";
+ error(s + msg + t);
+ }
+ }
+
+ /** assert that 's' is castable to 't' */
+ public void assertCastable(Type s, Type t) {
+ assertCastable(s, t, true);
+ }
+
+ /** assert that 's' is/is not castable to 't' */
+ public void assertCastable(Type s, Type t, boolean expected) {
+ if (types.isCastable(s, t) != expected) {
+ String msg = expected ?
+ " is not castable to " :
+ " is castable to ";
+ error(s + msg + t);
+ }
+ }
+
+ /** assert that 's' is convertible (method invocation conversion) to 't' */
+ public void assertConvertible(Type s, Type t) {
+ assertCastable(s, t, true);
+ }
+
+ /** assert that 's' is/is not convertible (method invocation conversion) to 't' */
+ public void assertConvertible(Type s, Type t, boolean expected) {
+ if (types.isConvertible(s, t) != expected) {
+ String msg = expected ?
+ " is not convertible to " :
+ " is convertible to ";
+ error(s + msg + t);
+ }
+ }
+
+ /** assert that 's' is assignable to 't' */
+ public void assertAssignable(Type s, Type t) {
+ assertCastable(s, t, true);
+ }
+
+ /** assert that 's' is/is not assignable to 't' */
+ public void assertAssignable(Type s, Type t, boolean expected) {
+ if (types.isAssignable(s, t) != expected) {
+ String msg = expected ?
+ " is not assignable to " :
+ " is assignable to ";
+ error(s + msg + t);
+ }
+ }
+ // </editor-fold>
+
+ private void error(String msg) {
+ throw new AssertionError("Unexpected result: " + msg);
+ }
+
+ // <editor-fold defaultstate="collapsed" desc="type functions">
+
+ /** compute the erasure of a type 't' */
+ public Type erasure(Type t) {
+ return types.erasure(t);
+ }
+
+ /** compute the capture of a type 't' */
+ public Type capture(Type t) {
+ return types.capture(t);
+ }
+
+ /** compute the boxed type associated with 't' */
+ public Type box(Type t) {
+ if (!t.isPrimitive()) {
+ throw new AssertionError("Cannot box non-primitive type: " + t);
+ }
+ return types.boxedClass(t).type;
+ }
+
+ /** compute the unboxed type associated with 't' */
+ public Type unbox(Type t) {
+ Type u = types.unboxedType(t);
+ if (t == null) {
+ throw new AssertionError("Cannot unbox reference type: " + t);
+ } else {
+ return u;
+ }
+ }
+
+ /** compute a type substitution on 't' given a list of type mappings */
+ public Type subst(Type t, Mapping... maps) {
+ ListBuffer<Type> from = ListBuffer.lb();
+ ListBuffer<Type> to = ListBuffer.lb();
+ for (Mapping tm : maps) {
+ from.append(tm.from);
+ to.append(tm.to);
+ }
+ return types.subst(t, from.toList(), to.toList());
+ }
+
+ /** create a fresh type mapping from a type to another */
+ public Mapping Mapping(Type from, Type to) {
+ return new Mapping(from, to);
+ }
+
+ public static class Mapping {
+ Type from;
+ Type to;
+ private Mapping(Type from, Type to) {
+ this.from = from;
+ this.to = to;
+ }
+ }
+ // </editor-fold>
+
+ // <editor-fold defaultstate="collapsed" desc="type factory">
+
+ /**
+ * This class is used to create Java types in a simple way. All main
+ * kinds of type are supported: primitive, reference, non-denotable. The
+ * factory also supports creation of constant types (used by the compiler
+ * to represent the type of a literal).
+ */
+ public class Factory {
+
+ private int synthNameCount = 0;
+
+ private Name syntheticName() {
+ return names.fromString("A$" + synthNameCount++);
+ }
+
+ public ClassType Class(long flags, Type... typeArgs) {
+ ClassSymbol csym = new ClassSymbol(flags, syntheticName(), predef.noSymbol);
+ csym.type = new ClassType(Type.noType, List.from(typeArgs), csym);
+ ((ClassType)csym.type).supertype_field = predef.objectType;
+ return (ClassType)csym.type;
+ }
+
+ public ClassType Class(Type... typeArgs) {
+ return Class(0, typeArgs);
+ }
+
+ public ClassType Interface(Type... typeArgs) {
+ return Class(Flags.INTERFACE, typeArgs);
+ }
+
+ public ClassType Interface(long flags, Type... typeArgs) {
+ return Class(Flags.INTERFACE | flags, typeArgs);
+ }
+
+ public Type Constant(byte b) {
+ return predef.byteType.constType(b);
+ }
+
+ public Type Constant(short s) {
+ return predef.shortType.constType(s);
+ }
+
+ public Type Constant(int i) {
+ return predef.intType.constType(i);
+ }
+
+ public Type Constant(long l) {
+ return predef.longType.constType(l);
+ }
+
+ public Type Constant(float f) {
+ return predef.floatType.constType(f);
+ }
+
+ public Type Constant(double d) {
+ return predef.doubleType.constType(d);
+ }
+
+ public Type Constant(char c) {
+ return predef.charType.constType(c + 0);
+ }
+
+ public ArrayType Array(Type elemType) {
+ return new ArrayType(elemType, predef.arrayClass);
+ }
+
+ public TypeVar TypeVariable() {
+ return TypeVariable(predef.objectType);
+ }
+
+ public TypeVar TypeVariable(Type bound) {
+ TypeSymbol tvsym = new TypeSymbol(0, syntheticName(), null, predef.noSymbol);
+ tvsym.type = new TypeVar(tvsym, bound, null);
+ return (TypeVar)tvsym.type;
+ }
+
+ public WildcardType Wildcard(BoundKind bk, Type bound) {
+ return new WildcardType(bound, bk, predef.boundClass);
+ }
+
+ public CapturedType CapturedVariable(Type upper, Type lower) {
+ return new CapturedType(syntheticName(), predef.noSymbol, upper, lower, null);
+ }
+
+ public ClassType Intersection(Type classBound, Type... intfBounds) {
+ ClassType ct = Class(Flags.COMPOUND);
+ ct.supertype_field = classBound;
+ ct.interfaces_field = List.from(intfBounds);
+ return ct;
+ }
+ }
+ // </editor-fold>
+}