1/*
2 * Copyright (c) 2015, 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
24package compiler.arraycopy;
25
26import java.lang.annotation.Retention;
27import java.lang.annotation.RetentionPolicy;
28import java.lang.reflect.Method;
29import java.lang.reflect.Modifier;
30import java.util.HashMap;
31
32abstract class TestArrayCopyUtils {
33    public enum ArraySrc {
34        SMALL,
35        LARGE,
36        ZERO
37    }
38
39    public enum ArrayDst {
40        NONE,
41        NEW,
42        SRC
43    }
44
45    static class A {
46    }
47
48    static class B extends A {
49    }
50
51    static final A[] small_a_src = new A[5];
52    static final A[] large_a_src = new A[10];
53    static final A[] zero_a_src = new A[0];
54    static final int[] small_int_src = new int[5];
55    static final int[] large_int_src = new int[10];
56    static final int[] zero_int_src = new int[0];
57    static final Object[] small_object_src = new Object[5];
58    static Object src;
59
60    @Retention(RetentionPolicy.RUNTIME)
61    @interface Args {
62        ArraySrc src();
63        ArrayDst dst() default ArrayDst.NONE;
64        int[] extra_args() default {};
65    }
66
67    final HashMap<String,Method> tests = new HashMap<>();
68    {
69        for (Method m : this.getClass().getDeclaredMethods()) {
70            if (m.getName().matches("m[0-9]+(_check)?")) {
71                assert(Modifier.isStatic(m.getModifiers())) : m;
72                tests.put(m.getName(), m);
73            }
74        }
75    }
76
77    boolean success = true;
78
79    void doTest(String name) throws Exception {
80        Method m = tests.get(name);
81        Method m_check = tests.get(name + "_check");
82        Class[] paramTypes = m.getParameterTypes();
83        Object[] params = new Object[paramTypes.length];
84        Class retType = m.getReturnType();
85        boolean isIntArray = (retType.isPrimitive() && !retType.equals(Void.TYPE)) ||
86            (retType.equals(Void.TYPE) && paramTypes[0].getComponentType().isPrimitive()) ||
87            (retType.isArray() && retType.getComponentType().isPrimitive());
88
89        Args args = m.getAnnotation(Args.class);
90
91        Object src = null;
92        switch(args.src()) {
93        case SMALL: {
94            if (isIntArray) {
95                src = small_int_src;
96            } else {
97                src = small_a_src;
98            }
99            break;
100        }
101        case LARGE: {
102            if (isIntArray) {
103                src = large_int_src;
104            } else {
105                src = large_a_src;
106            }
107            break;
108        }
109        case ZERO: {
110            if (isIntArray) {
111                src = zero_int_src;
112            } else {
113                src = zero_a_src;
114            }
115            break;
116        }
117        }
118
119        for (int i = 0; i < 20000; i++) {
120            boolean failure = false;
121
122            int p = 0;
123
124            if (params.length > 0) {
125                if (isIntArray) {
126                    params[0] = ((int[])src).clone();
127                } else {
128                    params[0] = ((A[])src).clone();
129                }
130                p++;
131            }
132
133            if (params.length > 1) {
134                switch(args.dst()) {
135                case NEW: {
136                    if (isIntArray) {
137                        params[1] = new int[((int[])params[0]).length];
138                    } else {
139                        params[1] = new A[((A[])params[0]).length];
140                    }
141                    p++;
142                    break;
143                }
144                case SRC: {
145                    params[1] = params[0];
146                    p++;
147                    break;
148                }
149                case NONE: break;
150                }
151            }
152
153            for (int j = 0; j < args.extra_args().length; j++) {
154                params[p+j] = args.extra_args()[j];
155            }
156
157            Object res = m.invoke(null, params);
158
159            if (retType.isPrimitive() && !retType.equals(Void.TYPE)) {
160                int s = (int)res;
161                int sum = 0;
162                int[] int_res = (int[])src;
163                for (int j = 0; j < int_res.length; j++) {
164                    sum += int_res[j];
165                }
166                failure = (s != sum);
167                if (failure) {
168                    System.out.println("Test " + name + " failed: result = " + s + " != " + sum);
169                }
170            } else {
171                Object dest = null;
172                if (!retType.equals(Void.TYPE)) {
173                    dest = res;
174                } else {
175                    dest = params[1];
176                }
177
178                if (m_check != null) {
179                    failure = (boolean)m_check.invoke(null,  new Object[] { src, dest });
180                } else {
181                    if (isIntArray) {
182                        int[] int_res = (int[])src;
183                        int[] int_dest = (int[])dest;
184                        for (int j = 0; j < int_res.length; j++) {
185                            if (int_res[j] != int_dest[j]) {
186                                System.out.println("Test " + name + " failed for " + j + " src[" + j +"]=" + int_res[j] + ", dest[" + j + "]=" + int_dest[j]);
187                                failure = true;
188                            }
189                        }
190                    } else {
191                        Object[] object_res = (Object[])src;
192                        Object[] object_dest = (Object[])dest;
193                        for (int j = 0; j < object_res.length; j++) {
194                            if (object_res[j] != object_dest[j]) {
195                                System.out.println("Test " + name + " failed for " + j + " src[" + j +"]=" + object_res[j] + ", dest[" + j + "]=" + object_dest[j]);
196                                failure = true;
197                            }
198                        }
199                    }
200                }
201            }
202
203            if (failure) {
204                success = false;
205                break;
206            }
207        }
208    }
209
210    TestArrayCopyUtils() {
211        for (int i = 0; i < small_a_src.length; i++) {
212            small_a_src[i] = new A();
213        }
214
215        for (int i = 0; i < small_int_src.length; i++) {
216            small_int_src[i] = i;
217        }
218
219        for (int i = 0; i < large_int_src.length; i++) {
220            large_int_src[i] = i;
221        }
222
223        for (int i = 0; i < 5; i++) {
224            small_object_src[i] = new Object();
225        }
226    }
227}
228