1 /*
   2  * Copyright (c) 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 package runtime.valhalla.valuetypes;
  26 
  27 import java.lang.reflect.*;
  28 import static jdk.test.lib.Asserts.*;
  29 
  30 /*
  31  * @test VarArgsArray
  32  * @summary Test if JVM API using varargs work with inline type arrays
  33  * @library /test/lib
  34  * @compile VarArgsArray.java NewInstanceFromConstructor.java IntValue.java
  35  * @run main/othervm -Xint runtime.valhalla.valuetypes.VarArgsArray
  36  * @run main/othervm -Xcomp runtime.valhalla.valuetypes.VarArgsArray
  37  */
  38 public class VarArgsArray {
  39 
  40     static final int TOKEN_VALUE = 4711;
  41 
  42     int methodACnt = 0;
  43     int methodBCnt = 0;
  44     int methodCCnt = 0;
  45 
  46     public VarArgsArray() {
  47     }
  48 
  49     public void test() throws Throwable {
  50         // test publicly accessable API in the VM...given an inline type array
  51         testJvmInvokeMethod();
  52         testJvmNewInstanceFromConstructor();
  53     }
  54 
  55     public void testJvmInvokeMethod() throws Throwable {
  56         MyInt[] array0 = new MyInt[0];
  57         MyInt[] array1 = new MyInt[] { new MyInt(TOKEN_VALUE) };
  58         MyInt[] array2 = new MyInt[] { new MyInt(TOKEN_VALUE), new MyInt(TOKEN_VALUE) };
  59 
  60         Method methodARef = getClass().getDeclaredMethod("methodA", MyInt.class);
  61         Method methodBRef = getClass().getDeclaredMethod("methodB", MyInt.class, MyInt.class);
  62         Method methodCRef = getClass().getDeclaredMethod("methodC", MyInt.class, String.class);
  63 
  64         // Positive tests...
  65         methodARef.invoke(this, (Object[])array1);
  66         assertWithMsg(methodACnt == 1, "methodA did not invoke");
  67 
  68         methodARef.invoke(this, array1[0]);
  69         assertWithMsg(methodACnt == 2, "methodA did not invoke");
  70 
  71         methodBRef.invoke(this, (Object[]) array2);
  72         assertWithMsg(methodBCnt == 1, "methodB did not invoke");
  73 
  74         methodBRef.invoke(this, array2[0], array2[1]);
  75         assertWithMsg(methodBCnt == 2, "methodB did not invoke");
  76 
  77         // Negative tests...
  78         int argExCnt = 0;
  79         try {
  80             methodARef.invoke(this, (Object[]) array0);
  81             throw new RuntimeException("Expected fail");
  82         } catch (IllegalArgumentException argEx) { argExCnt++; }
  83         try {
  84             methodARef.invoke(this, (Object[]) array2);
  85             throw new RuntimeException("Expected fail");
  86         } catch (IllegalArgumentException argEx) { argExCnt++; }
  87         try {
  88             methodCRef.invoke(this, (Object[]) array2);
  89             throw new RuntimeException("Expected fail");
  90         } catch (IllegalArgumentException argEx) { argExCnt++; }
  91         assertWithMsg(argExCnt == 3, "Did not see the correct number of exceptions");
  92         assertWithMsg(methodACnt == 2, "methodA bad invoke count");
  93         assertWithMsg(methodBCnt == 2, "methodB bad invoke count");
  94         assertWithMsg(methodCCnt == 0, "methodC bad invoke count");
  95     }
  96 
  97     public void testJvmNewInstanceFromConstructor() throws Throwable {
  98         // Inner classes use outer in param list, so these won't exercise inline type array
  99         Class tc = NewInstanceFromConstructor.class;
 100         Class pt = IntValue.class;
 101         Constructor consARef = tc.getConstructor(pt);
 102         Constructor consBRef = tc.getConstructor(pt, pt);
 103         Constructor consCRef = tc.getConstructor(pt, String.class);
 104         IntValue[] array0 = new IntValue[0];
 105         IntValue[] array1 = new IntValue[] { new IntValue(TOKEN_VALUE) };
 106         IntValue[] array2 = new IntValue[] { new IntValue(TOKEN_VALUE),
 107                                              new IntValue(TOKEN_VALUE) };
 108 
 109         // Positive tests...
 110         consARef.newInstance((Object[])array1);
 111         consARef.newInstance(array1[0]);
 112         NewInstanceFromConstructor test = (NewInstanceFromConstructor)
 113             consBRef.newInstance((Object[])array2);
 114         assertWithMsg(test.getValue() == (2 * TOKEN_VALUE), "Param corrrupt");
 115         consBRef.newInstance(array2[0], array2[1]);
 116         assertWithMsg(NewInstanceFromConstructor.getConsCalls() == 4, "Constructor did not invoke");
 117 
 118         // Negative tests...
 119         int argExCnt = 0;
 120         try {
 121             consARef.newInstance((Object[])array0);
 122             throw new RuntimeException("Expected fail");
 123         } catch (IllegalArgumentException argEx) { argExCnt++; }
 124         try {
 125             consARef.newInstance((Object[])array2);
 126             throw new RuntimeException("Expected fail");
 127         } catch (IllegalArgumentException argEx) { argExCnt++; }
 128         try {
 129             consCRef.newInstance((Object[])array2);
 130             throw new RuntimeException("Expected fail");
 131         } catch (IllegalArgumentException argEx) { argExCnt++; }
 132         assertWithMsg(argExCnt == 3, "Did not see the correct number of exceptions");
 133         assertWithMsg(NewInstanceFromConstructor.getConsCalls() == 4, "Constructor should have been invoked");
 134     }
 135 
 136     public void methodA(MyInt a) {
 137         assertWithMsg(a.value == TOKEN_VALUE, "Bad arg");
 138         methodACnt++;
 139     }
 140 
 141     public void methodB(MyInt a, MyInt b) {
 142         assertWithMsg(a.value == TOKEN_VALUE, "Bad arg");
 143         assertWithMsg(b.value == TOKEN_VALUE, "Bad arg");
 144         methodBCnt++;
 145     }
 146 
 147     public void methodC(MyInt a, String b) {
 148         assertWithMsg(a.value == TOKEN_VALUE, "Bad arg");
 149         methodCCnt++;
 150     }
 151 
 152     static void assertWithMsg(boolean expr, String msg) throws RuntimeException {
 153         assertTrue(expr, msg);
 154     }
 155 
 156     public static void main(String[] args) throws Throwable {
 157         new VarArgsArray().test();
 158     }
 159 
 160     inline class MyInt {
 161         int value;
 162         public MyInt() { this(0); }
 163         public MyInt(int v) { this.value = v; }
 164     }
 165 
 166 
 167 }