1 /*
   2  * Copyright (c) 2018, 2019, 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 inline class array
  27  * @compile -XDallowWithFieldOperator Point.java NonFlattenValue.java
  28  * @compile -XDallowWithFieldOperator ValueArray.java
  29  * @run testng/othervm -XX:+EnableValhalla -XX:ValueArrayElemMaxFlatSize=-1 ValueArray
  30  * @run testng/othervm -XX:+EnableValhalla -XX:ValueArrayElemMaxFlatSize=0  ValueArray
  31  */
  32 
  33 import java.lang.reflect.Array;
  34 import java.util.Arrays;
  35 
  36 import org.testng.annotations.BeforeTest;
  37 import org.testng.annotations.DataProvider;
  38 import org.testng.annotations.Test;
  39 import static org.testng.Assert.*;
  40 
  41 public class ValueArray {
  42     private static Class<?> nullablePointArrayClass() {
  43         Object a = new Point?[0];
  44         return a.getClass();
  45     }
  46 
  47     @DataProvider(name="arrayTypes")
  48     static Object[][] arrayTypes() {
  49         return new Object[][] {
  50             new Object[] { Object[].class,
  51                            new Object[] { new Object(), new Object()}},
  52             new Object[] { Point[].class,
  53                            new Point[] { Point.makePoint(1, 2),
  54                                          Point.makePoint(10, 20),
  55                                          Point.makePoint(100, 200)}},
  56             new Object[] { Point[][].class,
  57                            new Point[][] { new Point[] { Point.makePoint(1, 2),
  58                                                          Point.makePoint(10, 20)}}},
  59             new Object[] { nullablePointArrayClass(),
  60                            new Point?[] { Point.makePoint(11, 22),
  61                                           Point.makePoint(110, 220),
  62                                           null}},
  63             new Object[] { NonFlattenValue[].class,
  64                            new NonFlattenValue[] { NonFlattenValue.make(1, 2),
  65                                                    NonFlattenValue.make(10, 20),
  66                                                    NonFlattenValue.make(100, 200)}},
  67         };
  68     }
  69 
  70 
  71     @Test(dataProvider="arrayTypes")
  72     public static void test(Class<?> c, Object[] elements) {
  73         ValueArray test = new ValueArray(c, elements.length);
  74         test.run(elements);
  75         Class<?> compType = c.getComponentType();
  76         if (compType.isValue()) {
  77             test.testSetNullElement(compType == compType.asBoxType());
  78         }
  79      }
  80 
  81     @Test
  82     public static void testPointArray() {
  83         PointArray array = PointArray.makeArray(Point.makePoint(1, 2), Point.makePoint(10, 20));
  84         ValueArray test = new ValueArray(array.points);
  85         test.run(Point.makePoint(3, 4), Point.makePoint(30, 40));
  86     }
  87 
  88     @Test
  89     public static void testNullablePointArray() {
  90         Point ?[]array = new Point ?[3];
  91         array[0] = Point.makePoint(1, 2);
  92         array[1] = null;
  93         array[2] = Point.makePoint(3, 4);
  94 
  95         ValueArray test = new ValueArray(array);
  96         test.run(null, Point.makePoint(3, 4), null);
  97     }
  98 
  99     @Test
 100     public static void testIntArray() {
 101         int[] array = new int[] { 1, 2, 3};
 102         for (int i=0; i < array.length; i++) {
 103             Array.set(array, i, Integer.valueOf(i*10));
 104         }
 105 
 106         for (int i=0; i < array.length; i++) {
 107             Integer o = (Integer) Array.get(array, i);
 108             assertTrue(o.intValue() == i*10);
 109         }
 110         Arrays.setAll(array, i -> array[i]);
 111     }
 112 
 113     @Test
 114     public static void testNonArrayObject() {
 115         Object o = new Object();
 116         try {
 117             Array.get(o, 0);
 118             throw new AssertionError("IAE not thrown");
 119         } catch (IllegalArgumentException e) {}
 120 
 121         try {
 122             Array.set(o, 0, o);
 123             throw new AssertionError("IAE not thrown");
 124         } catch (IllegalArgumentException e) {}
 125 
 126     }
 127 
 128     @Test()
 129     static void testArrayCovariance() {
 130         Point[] lArray = new Point[0];
 131         Point?[] qArray = new Point?[0];
 132 
 133         // language instanceof
 134         assertTrue(lArray instanceof Point[]);
 135         assertTrue(qArray instanceof Point?[]);
 136 
 137         // Class.instanceOf (self)
 138         assertTrue(lArray.getClass().isInstance(lArray));
 139         assertTrue(qArray.getClass().isInstance(qArray));
 140 
 141         // Class.instanceof inline vs indirect
 142         assertFalse(lArray.getClass().isInstance(qArray));
 143         assertTrue(qArray.getClass().isInstance(lArray));
 144 
 145         // Class.isAssignableFrom (self)
 146         assertTrue(lArray.getClass().isAssignableFrom(lArray.getClass()));
 147         assertTrue(qArray.getClass().isAssignableFrom(qArray.getClass()));
 148 
 149         // Class.isAssignableFrom inline vs indirect
 150         assertTrue(qArray.getClass().isAssignableFrom(lArray.getClass()));
 151         assertFalse(lArray.getClass().isAssignableFrom(qArray.getClass()));
 152 
 153         // Class.cast (self)
 154         lArray.getClass().cast(lArray);
 155         qArray.getClass().cast(qArray);
 156 
 157         // Class.cast inline vs indirect
 158         qArray.getClass().cast(lArray);
 159         try {
 160             lArray.getClass().cast(qArray);
 161             fail("cast of Point? to Point should not succeed");
 162         } catch (ClassCastException cce) {
 163             // expected
 164         }
 165     }
 166 
 167     private final Object[] array;
 168 
 169     ValueArray(Class<?> arrayClass, int len) {
 170         this((Object[])Array.newInstance(arrayClass.getComponentType(), len));
 171         assertTrue(array.getClass() == arrayClass);
 172     }
 173 
 174     ValueArray(Object[] array) {
 175         this.array = array;
 176     }
 177 
 178     void run(Object... elements) {
 179         for (int i=0; i < elements.length; i++) {
 180             Array.set(array, i, elements[i]);
 181         }
 182 
 183         for (int i=0; i < elements.length; i++) {
 184             Object o = Array.get(array, i);
 185             assertEquals(o, elements[i]);
 186         }
 187 
 188         Arrays.setAll(array, i -> elements[i]);
 189     }
 190 
 191     void testSetNullElement(boolean nullable) {
 192         assert(array.getClass().getComponentType().isValue());
 193         for (int i=0; i < array.length; i++) {
 194             try {
 195                 Array.set(array, i, null);
 196                 if (!nullable)
 197                     throw new AssertionError("NPE not thrown");
 198             } catch (NullPointerException e) {
 199                 assertFalse(nullable);
 200             }
 201         }
 202     }
 203 
 204   static inline class PointArray {
 205         public Point[] points;
 206         PointArray() {
 207             points = new Point[0];
 208         }
 209         public static PointArray makeArray(Point... points) {
 210             PointArray a = PointArray.default;
 211             Point[] array = new Point[points.length];
 212             for (int i=0; i < points.length; i++) {
 213                 array[i] = points[i];
 214             }
 215             a = __WithField(a.points, array);
 216             return a;
 217         }
 218     }
 219 }