1 /* 2 * Copyright (c) 2018, 2021, 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 * @summary Basic test for Array::get, Array::set, Arrays::setAll on primitive class array 27 * @run testng/othervm -XX:FlatArrayElementMaxSize=-1 ValueArray 28 * @run testng/othervm -XX:FlatArrayElementMaxSize=0 ValueArray 29 */ 30 31 import java.lang.reflect.Array; 32 import java.util.Arrays; 33 34 import org.testng.annotations.DataProvider; 35 import org.testng.annotations.Test; 36 import static org.testng.Assert.*; 37 38 public class ValueArray { 39 @DataProvider(name="elementTypes") 40 static Object[][] elementTypes() { 41 return new Object[][]{ 42 new Object[] { Point.class.asValueType(), Point.default }, 43 new Object[] { Point.ref.class, null }, 44 new Object[] { ValueOptional.class, null }, 45 }; 46 } 47 48 /* 49 * Test an array created from the given element type via Array::newInstance 50 */ 51 @Test(dataProvider="elementTypes") 52 public void testElementType(Class<?> elementType, Object defaultValue) { 53 assertTrue(elementType.isValue()); 54 assertTrue(elementType.isPrimaryType() || defaultValue != null); 55 56 Object[] array = (Object[])Array.newInstance(elementType, 1); 57 Class<?> arrayType = array.getClass(); 58 assertTrue(arrayType.componentType() == elementType); 59 // Array is a reference type 60 assertTrue(arrayType.isArray()); 61 assertTrue(arrayType.isPrimaryType()); 62 assertEquals(arrayType.asPrimaryType(), arrayType); 63 assertTrue(array[0] == defaultValue); 64 65 // check the element type of multi-dimensional array 66 Object[][] multiArray = (Object[][])Array.newInstance(elementType, 1, 2, 3); 67 Class<?> c = multiArray.getClass(); 68 while (c.getComponentType() != null) { 69 c = c.getComponentType(); 70 } 71 assertTrue(c == elementType); 72 } 73 74 @DataProvider(name="arrayTypes") 75 static Object[][] arrayTypes() { 76 return new Object[][] { 77 new Object[] { Object[].class, 78 new Object[] { new Object(), new Object()}}, 79 new Object[] { Point[].class, 80 new Point[] { Point.makePoint(1, 2), 81 Point.makePoint(10, 20), 82 Point.makePoint(100, 200)}}, 83 new Object[] { Point[][].class, 84 new Point[][] { new Point[] { Point.makePoint(1, 2), 85 Point.makePoint(10, 20)}}}, 86 new Object[] { Point.ref[].class, 87 new Point.ref[] { Point.makePoint(11, 22), 88 Point.makePoint(110, 220), 89 null }}, 90 new Object[] { NonFlattenValue[].class, 91 new NonFlattenValue[] { NonFlattenValue.make(1, 2), 92 NonFlattenValue.make(10, 20), 93 NonFlattenValue.make(100, 200)}}, 94 new Object[] { Point[].class, new Point[0] }, 95 new Object[] { Point.ref[].class, new Point.ref[0] }, 96 new Object[] { ValueOptional[].class, new ValueOptional[0] }, 97 }; 98 } 99 100 /* 101 * Test the following properties of an array of value class: 102 * - class name 103 * - array element can be null or not 104 * - array covariance if the element type is a primitive value type 105 */ 106 @Test(dataProvider="arrayTypes") 107 public void testArrays(Class<?> arrayClass, Object[] array) { 108 testClassName(arrayClass); 109 testArrayElements(arrayClass, array); 110 Class<?> componentType = arrayClass.componentType(); 111 if (componentType.isPrimitiveClass()) { 112 Object[] qArray = (Object[]) Array.newInstance(componentType.asValueType(), 0); 113 Object[] lArray = (Object[]) Array.newInstance(componentType.asPrimaryType(), 0); 114 testArrayCovariance(componentType, qArray, lArray); 115 } 116 } 117 118 /** 119 * Verify the array class's name of the form "[QPoint;" or "[LPoint;" 120 */ 121 static void testClassName(Class<?> arrayClass) { 122 // test class names 123 String arrayClassName = arrayClass.getName(); 124 StringBuilder sb = new StringBuilder(); 125 Class<?> c = arrayClass; 126 while (c.isArray()) { 127 sb.append("["); 128 c = c.getComponentType(); 129 } 130 sb.append(c.isPrimitiveValueType() ? "Q" : "L").append(c.getName()).append(";"); 131 assertEquals(sb.toString(), arrayClassName); 132 } 133 134 /** 135 * Setting the elements of an array. 136 * NPE will be thrown if null is set on an element in an array of primitive value type 137 */ 138 static void testArrayElements(Class<?> arrayClass, Object[] array) { 139 Class<?> componentType = arrayClass.getComponentType(); 140 assertTrue(arrayClass.isArray()); 141 assertTrue(array.getClass() == arrayClass); 142 Object[] newArray = (Object[]) Array.newInstance(componentType, array.length); 143 assertTrue(newArray.getClass() == arrayClass); 144 assertTrue(newArray.getClass().getComponentType() == componentType); 145 146 // set elements 147 for (int i = 0; i < array.length; i++) { 148 Array.set(newArray, i, array[i]); 149 } 150 for (int i = 0; i < array.length; i++) { 151 Object o = Array.get(newArray, i); 152 assertEquals(o, array[i]); 153 } 154 Arrays.setAll(newArray, i -> array[i]); 155 156 // test nullable 157 if (!componentType.isPrimitiveValueType()) { 158 for (int i = 0; i < newArray.length; i++) { 159 Array.set(newArray, i, null); 160 } 161 } else { 162 for (int i = 0; i < newArray.length; i++) { 163 try { 164 Array.set(newArray, i, null); 165 fail("expect NPE but not thrown"); 166 } catch (NullPointerException e) { 167 } 168 } 169 } 170 } 171 172 /** 173 * Point[] is a subtype of Point.ref[], which is a subtype of Object[]. 174 */ 175 static void testArrayCovariance(Class<?> componentType, Object[] qArray, Object[] lArray) { 176 assertTrue(componentType.isPrimitiveClass()); 177 178 // Class.instanceOf (self) 179 assertTrue(qArray.getClass().isInstance(qArray)); 180 assertTrue(lArray.getClass().isInstance(lArray)); 181 182 // Class.isAssignableFrom (self) 183 assertTrue(qArray.getClass().isAssignableFrom(qArray.getClass())); 184 assertTrue(lArray.getClass().isAssignableFrom(lArray.getClass())); 185 186 // V.val[] is a subtype of V.ref[] 187 assertFalse(qArray.getClass().isInstance(lArray)); 188 assertTrue(lArray.getClass().isInstance(qArray)); 189 190 // V.val[] is a subtype of V.ref[] 191 assertTrue(lArray.getClass().isAssignableFrom(qArray.getClass())); 192 assertFalse(qArray.getClass().isAssignableFrom(lArray.getClass())); 193 194 // Class.cast (self) 195 qArray.getClass().cast(qArray); 196 lArray.getClass().cast(lArray); 197 198 // Class.cast 199 lArray.getClass().cast(qArray); 200 try { 201 qArray.getClass().cast(lArray); 202 fail("cast of Point.ref[] to Point[] should not succeed"); 203 } catch (ClassCastException cce) { 204 } 205 } 206 207 @Test 208 public static void testIntArray() { 209 int[] array = new int[] { 1, 2, 3}; 210 for (int i=0; i < array.length; i++) { 211 Array.set(array, i, Integer.valueOf(i*10)); 212 } 213 214 for (int i=0; i < array.length; i++) { 215 Integer o = (Integer) Array.get(array, i); 216 assertTrue(o.intValue() == i*10); 217 } 218 Arrays.setAll(array, i -> array[i]); 219 } 220 221 @Test 222 public static void testNonArrayObject() { 223 Object o = new Object(); 224 try { 225 Array.get(o, 0); 226 fail("IAE not thrown"); 227 } catch (IllegalArgumentException e) {} 228 229 try { 230 Array.set(o, 0, o); 231 fail("IAE not thrown"); 232 } catch (IllegalArgumentException e) {} 233 234 } 235 236 @Test 237 static void testInstanceOf() { 238 Point[] qArray = new Point[0]; 239 Point.ref[] lArray = new Point.ref[0]; 240 ValueOptional[] vArray = new ValueOptional[0]; 241 242 // language instanceof 243 assertTrue(qArray instanceof Point[]); 244 assertTrue(lArray instanceof Point.ref[]); 245 assertTrue(vArray instanceof ValueOptional[]); 246 } 247 }