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 package runtime.valhalla.valuetypes;
  25 
  26 import java.lang.reflect.Array;
  27 import java.util.Arrays;
  28 import java.util.ArrayList;
  29 import java.util.List;
  30 
  31 import static jdk.test.lib.Asserts.*;
  32 
  33 /*
  34  * @test ValueTypeArray
  35  * @summary Plain array test for Inline Types
  36  * @library /test/lib
  37  * @compile -XDallowGenericsOverValues ValueTypeArray.java Point.java Long8Value.java Person.java
  38  * @run main/othervm -Xint  -XX:ValueArrayElemMaxFlatSize=-1 runtime.valhalla.valuetypes.ValueTypeArray
  39  * @run main/othervm -Xint  -XX:ValueArrayElemMaxFlatSize=0  runtime.valhalla.valuetypes.ValueTypeArray
  40  * @run main/othervm -Xcomp -XX:ValueArrayElemMaxFlatSize=-1 runtime.valhalla.valuetypes.ValueTypeArray
  41  * @run main/othervm -Xcomp -XX:ValueArrayElemMaxFlatSize=0  runtime.valhalla.valuetypes.ValueTypeArray
  42  */
  43 public class ValueTypeArray {
  44     public static void main(String[] args) {
  45         ValueTypeArray valueTypeArray = new ValueTypeArray();
  46         valueTypeArray.run();
  47     }
  48 
  49     public void run() {
  50         testClassForName();
  51         testSimplePointArray();
  52         testLong8Array();
  53         testMixedPersonArray();
  54         testMultiDimPointArray();
  55         testComposition();
  56 
  57         testSanityCheckcasts();
  58         testObjectArrayOfValues();
  59 
  60         testReflectArray();
  61         testUtilArrays();
  62     }
  63 
  64     void testClassForName() {
  65         String arrayClsName = "[Lruntime.valhalla.valuetypes.Point;";
  66         String qarrayClsName = "[Qruntime.valhalla.valuetypes.Point;";
  67         try {
  68             // L-type..
  69             Class<?> arrayCls = Class.forName(arrayClsName);
  70             assertTrue(arrayCls.isArray(), "Expected an array class");
  71 
  72             assertTrue(arrayCls.getComponentType() == Point.class.asIndirectType(),
  73                        "Expected component type of Point.class got: " + arrayCls.getComponentType());
  74 
  75             arrayClsName = "[" + arrayClsName;
  76             Class<?> mulArrayCls = Class.forName(arrayClsName);
  77             assertTrue(mulArrayCls.isArray());
  78             assertTrue(mulArrayCls.getComponentType() == arrayCls);
  79 
  80             // Q-type...
  81             arrayCls = Class.forName(qarrayClsName);
  82             assertTrue(arrayCls.isArray(), "Expected an array class");
  83 
  84             assertTrue(arrayCls.getComponentType() == Point.class,
  85                        arrayCls +
  86                        " Expected component type of Point.class got: " + arrayCls.getComponentType());
  87 
  88             qarrayClsName = "[" + qarrayClsName;
  89             mulArrayCls = Class.forName(qarrayClsName);
  90             assertTrue(mulArrayCls.isArray());
  91             assertTrue(mulArrayCls.getComponentType() == arrayCls);
  92         }
  93         catch (ClassNotFoundException cnfe) {
  94             fail("Class.forName(" + arrayClsName + ") failed", cnfe);
  95         }
  96     }
  97 
  98     void testSimplePointArray() {
  99         Point[] defaultPoint = new Point[1];
 100         Point p = defaultPoint[0];
 101         assertEquals(p.x, 0, "invalid default loaded from array");
 102         assertEquals(p.y, 0, "invalid default loaded from array");
 103         boolean gotNpe = false;
 104         try {
 105             defaultPoint[0] = (Point) getNull();
 106         } catch (NullPointerException npe) {
 107             gotNpe = true;
 108         }
 109         assertTrue(gotNpe, "Expected NullPointerException");
 110 
 111         Point[] points = createSimplePointArray();
 112         System.gc(); // check that VTs survive GC
 113         checkSimplePointArray(points);
 114 
 115         assertTrue(points instanceof Point[], "Instance of");
 116 
 117         testSimplePointArrayCopy();
 118     }
 119 
 120     void testSimplePointArrayCopy() {
 121         Point[] points = createSimplePointArray();
 122         Point[] pointsCopy = new Point[points.length];
 123         System.arraycopy(points, 0, pointsCopy, 0, points.length);
 124         checkSimplePointArray(pointsCopy);
 125 
 126         // Conjoint, overlap...left
 127         System.arraycopy(points, 0, points, 1, 2);
 128         checkArrayElementsEqual(points, new Point[] { pointsCopy[0], pointsCopy[0], pointsCopy[1], pointsCopy[3] });
 129 
 130         // Conjoint, overlap...right
 131         points = createSimplePointArray();
 132         System.arraycopy(points, 2, points, 1, 2);
 133         checkArrayElementsEqual(points, new Point[] { pointsCopy[0], pointsCopy[2], pointsCopy[3], pointsCopy[3] });
 134     }
 135 
 136     static Point[] createSimplePointArray() {
 137         Point[] ps = new Point[4];
 138         assertEquals(ps.length, 4, "Length");
 139         ps.toString();
 140         ps[0] = Point.createPoint(1, 2);
 141         ps[1] = Point.createPoint(3, 4);
 142         ps[2] = Point.createPoint(5, 6);
 143         ps[3] = Point.createPoint(7, 8);
 144         boolean sawOob = false;
 145         try {
 146             ps[ps.length] = Point.createPoint(0, 0);
 147         } catch (ArrayIndexOutOfBoundsException aioobe) { sawOob = true; }
 148         assertTrue(sawOob, "Didn't see AIOOBE");
 149         return ps;
 150     }
 151 
 152     static void checkSimplePointArray(Point[] points) {
 153         assertEquals(points[0].x, 1, "invalid 0 point x value");
 154         assertEquals(points[0].y, 2, "invalid 0 point y value");
 155         assertEquals(points[1].x, 3, "invalid 1 point x value");
 156         assertEquals(points[1].y, 4, "invalid 1 point y value");
 157         assertEquals(points[2].x, 5, "invalid 2 point x value");
 158         assertEquals(points[2].y, 6, "invalid 2 point y value");
 159         assertEquals(points[3].x, 7, "invalid 3 point x value");
 160         assertEquals(points[3].y, 8, "invalid 3 point y value");
 161     }
 162 
 163     void testLong8Array() {
 164         Long8Value[] values = new Long8Value[3];
 165         assertEquals(values.length, 3, "length");
 166         values.toString();
 167         Long8Value value = values[1];
 168         long zl = 0;
 169         Long8Value.check(value, zl, zl, zl, zl, zl, zl, zl, zl);
 170         values[1] = Long8Value.create(1, 2, 3, 4, 5, 6, 7, 8);
 171         value = values[1];
 172         Long8Value.check(value, 1, 2, 3, 4, 5, 6, 7, 8);
 173 
 174         Long8Value[] copy = new Long8Value[values.length];
 175         System.arraycopy(values, 0, copy, 0, values.length);
 176         value = copy[1];
 177         Long8Value.check(value, 1, 2, 3, 4, 5, 6, 7, 8);
 178     }
 179 
 180     void testMixedPersonArray() {
 181         Person[] people = new Person[3];
 182 
 183         people[0] = Person.create(1, "First", "Last");
 184         assertEquals(people[0].getId(), 1, "Invalid Id person");
 185         assertEquals(people[0].getFirstName(), "First", "Invalid First Name");
 186         assertEquals(people[0].getLastName(), "Last", "Invalid Last Name");
 187 
 188         people[1] = Person.create(2, "Jane", "Wayne");
 189         people[2] = Person.create(3, "Bob", "Dobalina");
 190 
 191         Person[] peopleCopy = new Person[people.length];
 192         System.arraycopy(people, 0, peopleCopy, 0, people.length);
 193         assertEquals(peopleCopy[2].getId(), 3, "Invalid Id");
 194         assertEquals(peopleCopy[2].getFirstName(), "Bob", "Invalid First Name");
 195         assertEquals(peopleCopy[2].getLastName(), "Dobalina", "Invalid Last Name");
 196     }
 197 
 198     void testMultiDimPointArray() {
 199         Point[][][] multiPoints = new Point[2][3][4];
 200         assertEquals(multiPoints.length, 2, "1st dim length");
 201         assertEquals(multiPoints[0].length, 3, "2st dim length");
 202         assertEquals(multiPoints[0][0].length, 4, "3rd dim length");
 203 
 204         Point defaultPoint = multiPoints[1][2][3];
 205         assertEquals(defaultPoint.x, 0, "invalid point x value");
 206         assertEquals(defaultPoint.y, 0, "invalid point x value");
 207     }
 208 
 209     void testReflectArray() {
 210         // Check the java.lang.reflect.Array.newInstance methods...
 211         Class<?> cls = (Class<?>) Point[].class;
 212         Point[][] array = (Point[][]) Array.newInstance(cls, 1);
 213         assertEquals(array.length, 1, "Incorrect length");
 214         assertTrue(array[0] == null, "Expected NULL");
 215 
 216         Point[][][] array3 = (Point[][][]) Array.newInstance(cls, 1, 2);
 217         assertEquals(array3.length, 1, "Incorrect length");
 218         assertEquals(array3[0].length, 2, "Incorrect length");
 219         assertTrue(array3[0][0] == null, "Expected NULL");
 220 
 221         // Now create ObjArrays of ValueArray...
 222         cls = (Class<?>) Point.class.asIndirectType();
 223         Point?[][] barray = (Point?[][]) Array.newInstance(cls, 1, 2);
 224         assertEquals(barray.length, 1, "Incorrect length");
 225         assertEquals(barray[0].length, 2, "Incorrect length");
 226         barray[0][1] = Point.createPoint(1, 2);
 227         Point? pb = barray[0][1];
 228         int x = pb.getX();
 229         assertEquals(x, 1, "Bad Point Value");
 230     }
 231 
 232     static final inline class MyInt implements Comparable<MyInt?> {
 233         final int value;
 234 
 235         private MyInt() { this(0); }
 236         private MyInt(int v) { value = v; }
 237         public int getValue() { return value; }
 238         public String toString() { return "MyInt: " + getValue(); }
 239         public int compareTo(MyInt? that) { return Integer.compare(this.getValue(), that.getValue()); }
 240         public boolean equals(Object o) {
 241             if (o instanceof MyInt) {
 242                 return this.getValue() == ((MyInt) o).getValue();
 243             }
 244             return false;
 245         }
 246 
 247         public static MyInt create(int v) {
 248             return new MyInt(v);
 249         }
 250 
 251         // Null-able fields here are a temp hack to avoid ClassCircularityError
 252         public static final MyInt? MIN = MyInt.create(Integer.MIN_VALUE);
 253         public static final MyInt? ZERO = MyInt.create(0);
 254         public static final MyInt? MAX = MyInt.create(Integer.MAX_VALUE);
 255     }
 256 
 257     static MyInt staticMyInt = MyInt.create(-1);
 258     static MyInt[] staticMyIntArray = new MyInt[] { staticMyInt };
 259     static MyInt[][] staticMyIntArrayArray = new MyInt[][] { staticMyIntArray, staticMyIntArray };
 260 
 261     static interface SomeSecondaryType {
 262         default String hi() { return "Hi"; }
 263     }
 264 
 265     static final inline class MyOtherInt implements SomeSecondaryType {
 266         final int value;
 267         private MyOtherInt() { value = 0; }
 268     }
 269 
 270     void testSanityCheckcasts() {
 271         MyInt[] myInts = new MyInt[1];
 272         assertTrue(myInts instanceof Object[]);
 273         assertTrue(myInts instanceof Comparable[]);
 274         assertTrue(myInts instanceof MyInt?[]);
 275 
 276         Class<?> cls = MyInt.class;
 277         assertTrue(cls.isInlineClass());
 278         Object arrObj = Array.newInstance(cls, 1);
 279         assertTrue(arrObj instanceof Object[], "Not Object array");
 280         assertTrue(arrObj instanceof Comparable[], "Not Comparable array");
 281         assertTrue(arrObj instanceof MyInt[], "Not MyInt array");
 282 
 283         Object[] arr = (Object[]) arrObj;
 284         assertTrue(arr instanceof Comparable[], "Not Comparable array");
 285         assertTrue(arr instanceof MyInt[], "Not MyInt array");
 286         Comparable[] comparables = (Comparable[])arr;
 287         MyInt[] myIntArr = (MyInt[]) arr;
 288 
 289         // multi-dim, check secondary array types are setup...
 290         MyOtherInt[][] matrix = new MyOtherInt[1][1];
 291         assertTrue(matrix[0] instanceof MyOtherInt[]);
 292         assertTrue(matrix[0] instanceof SomeSecondaryType[]);
 293         assertTrue(matrix[0] instanceof MyOtherInt?[]);
 294 
 295         // Box types vs Inline...
 296         MyInt?[] myValueRefs = new MyInt?[1];
 297         assertTrue(myValueRefs instanceof MyInt?[]);
 298         assertTrue(myValueRefs instanceof Object[]);
 299         assertTrue(myValueRefs instanceof Comparable[]);
 300         assertFalse(myValueRefs instanceof MyInt[]);
 301 
 302         MyInt?[][] myMdValueRefs = new MyInt?[1][1];
 303         assertTrue(myMdValueRefs[0] instanceof MyInt?[]);
 304         assertTrue(myMdValueRefs[0] instanceof Object[]);
 305         assertTrue(myMdValueRefs[0] instanceof Comparable[]);
 306         assertFalse(myMdValueRefs[0] instanceof MyInt[]);
 307 
 308         // Did we break checkcast...
 309         MyInt?[]     va1 = (MyInt?[])null;
 310         MyInt?[]     va2 = null;
 311         MyInt?[][]   va3 = (MyInt?[][])null;
 312         MyInt?[][][] va4 = (MyInt?[][][])null;
 313         MyInt[]      va5 = null;
 314         MyInt[]      va6 = (MyInt[])null;
 315         MyInt[][]    va7 = (MyInt[][])null;
 316         MyInt[][][]  va8 = (MyInt[][][])null;
 317     }
 318 
 319 
 320     void testUtilArrays() {
 321         // Sanity check j.u.Arrays
 322 
 323         // cast to q-type temp effect of avoiding circularity error (decl static MyInt?)
 324         MyInt[] myInts = new MyInt[] { (MyInt) MyInt.MAX, (MyInt) MyInt.MIN };
 325         // Sanity sort another copy
 326         MyInt[] copyMyInts = Arrays.copyOf(myInts, myInts.length + 1);
 327         checkArrayElementsEqual(copyMyInts, new MyInt[] { myInts[0], myInts[1], (MyInt) MyInt.ZERO});
 328 
 329         Arrays.sort(copyMyInts);
 330         checkArrayElementsEqual(copyMyInts, new MyInt[] { (MyInt) MyInt.MIN, (MyInt) MyInt.ZERO, (MyInt) MyInt.MAX });
 331 
 332         List myIntList = Arrays.asList(copyMyInts);
 333         checkArrayElementsEqual(copyMyInts, myIntList.toArray(new MyInt[copyMyInts.length]));
 334         // This next line needs testMixedLayoutArrays to work
 335         checkArrayElementsEqual(copyMyInts, myIntList.toArray());
 336 
 337         // Sanity check j.u.ArrayList
 338         ArrayList<MyInt> aList = new ArrayList<MyInt>(Arrays.asList(copyMyInts));
 339         assertTrue(aList.indexOf(MyInt.MIN) == 0, "Bad Index");
 340         assertTrue(aList.indexOf(MyInt.ZERO) == 1, "Bad Index");
 341         assertTrue(aList.indexOf(MyInt.MAX) == 2, "Bad Index");
 342 
 343         aList.remove(2);
 344         aList.add(MyInt.create(5));
 345     }
 346 
 347 
 348     void testObjectArrayOfValues() {
 349         testSanityObjectArrays();
 350         testMixedLayoutArrays();
 351     }
 352 
 353     void testSanityObjectArrays() {
 354         Object[] objects = new Object[2];
 355         assertTrue(objects[0] == null && objects[1] == null, "Not null ?");
 356 
 357         objects[0] = MyInt.create(1);
 358         objects[1] = Integer.valueOf(2);
 359         assertTrue(objects[0].equals(MyInt.create(1)), "Bad Value");
 360         assertTrue(objects[1].equals(Integer.valueOf(2)), "Bad Object");
 361 
 362         Comparable[] copyComparables = new Comparable[objects.length];
 363         System.arraycopy(objects, 0, copyComparables, 0, objects.length);
 364         checkArrayElementsEqual(objects, copyComparables);
 365 
 366         objects[0] = null;
 367         objects[1] = null;
 368         assertTrue(objects[0] == null && objects[1] == null, "Not null ?");
 369 
 370         Comparable[] comparables = new Comparable[2];
 371         assertTrue(comparables[0] == null && comparables[1] == null, "Not null ?");
 372         comparables[0] = MyInt.create(3);
 373         comparables[1] = Integer.valueOf(4);
 374         assertTrue(comparables[0].equals(MyInt.create(3)), "Bad Value");
 375         assertTrue(comparables[1].equals(Integer.valueOf(4)), "Bad Object");
 376 
 377         Object[] copyObjects = new Object[2];
 378         System.arraycopy(comparables, 0, copyObjects, 0, comparables.length);
 379         checkArrayElementsEqual(comparables, copyObjects);
 380 
 381         comparables[0] = null;
 382         comparables[1] = null;
 383         assertTrue(comparables[0] == null && comparables[1] == null, "Not null ?");
 384 
 385         MyInt?[] myIntRefArray = new MyInt?[1];
 386         assertTrue(myIntRefArray[0] == null, "Got: " + myIntRefArray[0]);
 387         myIntRefArray[0] = null;
 388 
 389         MyInt?[] srcNulls = new MyInt?[2];
 390         MyInt?[] dstNulls = new MyInt?[2];
 391         System.arraycopy(srcNulls, 0, dstNulls, 0, 2);
 392         checkArrayElementsEqual(srcNulls, dstNulls);
 393         srcNulls[1] = MyInt.create(1);
 394         System.arraycopy(srcNulls, 0, dstNulls, 0, 2);
 395         checkArrayElementsEqual(srcNulls, dstNulls);
 396     }
 397 
 398     void testMixedLayoutArrays() {
 399         Object[] objArray = new Object[3];
 400         Comparable[] compArray = new Comparable[3];
 401         MyInt[] valArray = new MyInt[] { (MyInt) MyInt.MIN, (MyInt) MyInt.ZERO, (MyInt) MyInt.MAX };
 402 
 403         arrayCopy(valArray, 0, objArray, 0, 3);
 404         checkArrayElementsEqual(valArray, objArray);
 405         arrayCopy(valArray, 0, objArray, 0, 3);
 406 
 407         objArray = new Object[3];
 408         System.arraycopy(valArray, 0, objArray, 0, 3);
 409         checkArrayElementsEqual(valArray, objArray);
 410 
 411         System.arraycopy(valArray, 0, compArray, 0, 3);
 412         checkArrayElementsEqual(valArray, compArray);
 413 
 414         valArray = new MyInt[] { (MyInt) MyInt.ZERO, (MyInt) MyInt.ZERO, (MyInt) MyInt.ZERO };
 415         System.arraycopy(compArray, 0, valArray, 0, 3);
 416         checkArrayElementsEqual(valArray, compArray);
 417 
 418         valArray = new MyInt[] { (MyInt) MyInt.ZERO, (MyInt) MyInt.ZERO, (MyInt) MyInt.ZERO };
 419         System.arraycopy(objArray, 0, valArray, 0, 3);
 420         checkArrayElementsEqual(valArray, objArray);
 421 
 422         // Sanity check dst == src
 423         System.arraycopy(valArray, 0, valArray, 0, 3);
 424         checkArrayElementsEqual(valArray, objArray);
 425 
 426         objArray[0] = "Not an inline object";
 427         try {
 428             System.arraycopy(objArray, 0, valArray, 0, 3);
 429             throw new RuntimeException("Expected ArrayStoreException");
 430         } catch (ArrayStoreException ase) {}
 431 
 432         MyInt?[] myIntRefArray = new MyInt?[3];
 433         System.arraycopy(valArray, 0, myIntRefArray, 0, 3);
 434         checkArrayElementsEqual(valArray, myIntRefArray);
 435 
 436         myIntRefArray[0] = null;
 437         try {
 438             System.arraycopy(myIntRefArray, 0, valArray, 0, 3);
 439             throw new RuntimeException("Expected NullPointerException");
 440         } catch (NullPointerException npe) {}
 441     }
 442 
 443     static final inline class MyPoint {
 444         final               MyInt x;
 445         final               MyInt y;
 446 
 447         private MyPoint() { this(0, 0); }
 448         private MyPoint(int x, int y) {
 449             this.x = new MyInt(x);
 450             this.y = new MyInt(y);
 451         }
 452         public boolean equals(Object that) {
 453             if (that instanceof MyPoint) {
 454                 MyPoint thatPoint = (MyPoint) that;
 455                 return x.equals(thatPoint.x) && java.util.Objects.equals(y, thatPoint.y);
 456             }
 457             return false;
 458         }
 459         static MyPoint create(int x) {
 460             return new MyPoint(x, x);
 461         }
 462         static MyPoint create(int x, int y) {
 463             return new MyPoint(x, y);
 464         }
 465         static final MyPoint? ORIGIN = create(0);
 466     }
 467 
 468     void testComposition() {
 469         // Test array operations with compostion of inline types, check element payload is correct...
 470         MyPoint a = MyPoint.create(1, 2);
 471         MyPoint b = MyPoint.create(7, 21);
 472         MyPoint c = MyPoint.create(Integer.MAX_VALUE, Integer.MIN_VALUE);
 473 
 474         MyPoint[] pts = new MyPoint[3];
 475         if (!pts[0].equals(MyPoint.ORIGIN)) {
 476             throw new RuntimeException("Equals failed: " + pts[0] + " vs " + MyPoint.ORIGIN);
 477         }
 478         pts = new MyPoint[] { a, b, c };
 479         checkArrayElementsEqual(pts, new Object[] { a, b, c});
 480         Object[] oarr = new Object[3];
 481 
 482         arrayCopy(pts, 0, oarr, 0, 3);
 483         checkArrayElementsEqual(pts, oarr);
 484 
 485         oarr = new Object[3];
 486         System.arraycopy(pts, 0, oarr, 0, 3);
 487         checkArrayElementsEqual(pts, oarr);
 488 
 489         System.arraycopy(oarr, 0, pts, 0, 3);
 490         checkArrayElementsEqual(pts, oarr);
 491 
 492         oarr = new Object[3];
 493         try {
 494             System.arraycopy(oarr, 0, pts, 0, 3);
 495             throw new RuntimeException("Expected NPE");
 496         }
 497         catch (NullPointerException npe) {}
 498 
 499         oarr = new Object[3];
 500         oarr[0] = new Object();
 501         try {
 502             System.arraycopy(oarr, 0, pts, 0, 3);
 503             throw new RuntimeException("Expected ASE");
 504         }
 505         catch (ArrayStoreException ase) {}
 506     }
 507 
 508     void checkArrayElementsEqual(MyInt[] arr1, Object[] arr2) {
 509         assertTrue(arr1.length == arr2.length, "Bad length");
 510         for (int i = 0; i < arr1.length; i++) {
 511             assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal");
 512         }
 513     }
 514 
 515     void checkArrayElementsEqual(MyPoint[] arr1, Object[] arr2) {
 516         assertTrue(arr1.length == arr2.length, "Bad length");
 517         for (int i = 0; i < arr1.length; i++) {
 518             assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal");
 519         }
 520     }
 521 
 522     void checkArrayElementsEqual(Object[] arr1, Object[] arr2) {
 523         assertTrue(arr1.length == arr2.length, "Bad length");
 524         for (int i = 0; i < arr1.length; i++) {
 525             assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal");
 526         }
 527     }
 528 
 529     void arrayCopy(MyInt[] src, int srcPos, Object[] dst, int dstPos, int length) {
 530         for (int i = 0; i < length ; i++) {
 531             dst[dstPos++] = src[srcPos++];
 532         }
 533     }
 534     void arrayCopy(MyPoint[] src, int srcPos, Object[] dst, int dstPos, int length) {
 535         for (int i = 0; i < length ; i++) {
 536             dst[dstPos++] = src[srcPos++];
 537         }
 538     }
 539 
 540     Object getNull() { return null; }
 541 
 542 }