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.reflect.Field;
27import java.lang.reflect.Method;
28import java.lang.reflect.Modifier;
29import java.util.HashMap;
30
31abstract class TestInstanceCloneUtils {
32    static class Base implements Cloneable {
33        void initialize(Class c, int i) {
34            for (Field f : c.getDeclaredFields()) {
35                setVal(f, i);
36                i++;
37            }
38            if (c != Base.class) {
39                initialize(c.getSuperclass(), i);
40            }
41        }
42
43        Base(boolean initialize) {
44            if (initialize) {
45                initialize(getClass(), 0);
46            }
47        }
48
49        void setVal(Field f, int i) {
50            try {
51                if (f.getType() == int.class) {
52                    f.setInt(this, i);
53                    return;
54                } else if (f.getType() == short.class) {
55                    f.setShort(this, (short)i);
56                    return;
57                } else if (f.getType() == byte.class) {
58                    f.setByte(this, (byte)i);
59                    return;
60                } else if (f.getType() == long.class) {
61                    f.setLong(this, i);
62                    return;
63                }
64            } catch(IllegalAccessException iae) {
65                throw new RuntimeException("Getting fields failed");
66            }
67            throw new RuntimeException("unexpected field type");
68        }
69
70        int getVal(Field f) {
71            try {
72                if (f.getType() == int.class) {
73                    return f.getInt(this);
74                } else if (f.getType() == short.class) {
75                    return (int)f.getShort(this);
76                } else if (f.getType() == byte.class) {
77                    return (int)f.getByte(this);
78                } else if (f.getType() == long.class) {
79                    return (int)f.getLong(this);
80                }
81            } catch(IllegalAccessException iae) {
82                throw new RuntimeException("Setting fields failed");
83            }
84            throw new RuntimeException("unexpected field type");
85        }
86
87        boolean fields_equal(Class c, Base o) {
88            for (Field f : c.getDeclaredFields()) {
89                if (getVal(f) != o.getVal(f)) {
90                    return false;
91                }
92            }
93            if (c != Base.class) {
94                return fields_equal(c.getSuperclass(), o);
95            }
96            return true;
97        }
98
99        public boolean equals(Object obj) {
100            return fields_equal(getClass(), (Base)obj);
101        }
102
103        String print_fields(Class c, String s) {
104            for (Field f : c.getDeclaredFields()) {
105                if (s != "") {
106                    s += "\n";
107                }
108                s = s + f + " = " + getVal(f);
109            }
110            if (c != Base.class) {
111                return print_fields(c.getSuperclass(), s);
112            }
113            return s;
114        }
115
116        public String toString() {
117            return print_fields(getClass(), "");
118        }
119
120        int fields_sum(Class c, int s) {
121            for (Field f : c.getDeclaredFields()) {
122                s += getVal(f);
123            }
124            if (c != Base.class) {
125                return fields_sum(c.getSuperclass(), s);
126            }
127            return s;
128        }
129
130        public int sum() {
131            return fields_sum(getClass(), 0);
132        }
133
134    }
135
136    static class A extends Base {
137        int i1;
138        int i2;
139        int i3;
140        int i4;
141        int i5;
142
143        A(boolean initialize) {
144            super(initialize);
145        }
146
147        public Object clone() throws CloneNotSupportedException {
148            return super.clone();
149        }
150    }
151
152    static class B extends A {
153        int i6;
154
155        B(boolean initialize) {
156            super(initialize);
157        }
158    }
159
160    static final class D extends Base {
161        byte  i1;
162        short i2;
163        long  i3;
164        int   i4;
165        int   i5;
166
167        D(boolean initialize) {
168            super(initialize);
169        }
170
171        public Object clone() throws CloneNotSupportedException {
172            return super.clone();
173        }
174    }
175
176    static final class E extends Base {
177        int i1;
178        int i2;
179        int i3;
180        int i4;
181        int i5;
182        int i6;
183        int i7;
184        int i8;
185        int i9;
186
187        E(boolean initialize) {
188            super(initialize);
189        }
190
191        public Object clone() throws CloneNotSupportedException {
192            return super.clone();
193        }
194    }
195
196    static final class F extends Base {
197        F(boolean initialize) {
198            super(initialize);
199        }
200
201        public Object clone() throws CloneNotSupportedException {
202            return super.clone();
203        }
204    }
205
206    static class G extends Base {
207        int i1;
208        int i2;
209        int i3;
210
211        G(boolean initialize) {
212            super(initialize);
213        }
214
215        public Object myclone() throws CloneNotSupportedException {
216            return clone();
217        }
218    }
219
220    static class H extends G {
221        int i4;
222        int i5;
223
224        H(boolean initialize) {
225            super(initialize);
226        }
227
228        public Object clone() throws CloneNotSupportedException {
229            return super.clone();
230        }
231    }
232
233    static class J extends Base  {
234        int i1;
235        int i2;
236        int i3;
237
238        J(boolean initialize) {
239            super(initialize);
240        }
241
242        public Object myclone() throws CloneNotSupportedException {
243            return clone();
244        }
245    }
246
247    static class K extends J {
248        int i4;
249        int i5;
250
251        K(boolean initialize) {
252            super(initialize);
253        }
254
255    }
256
257    static final A a = new A(true);
258    static final B b = new B(true);
259    static final D d = new D(true);
260    static final E e = new E(true);
261    static final F f = new F(true);
262    static final G g = new G(true);
263    static final H h = new H(true);
264    static final J j = new J(true);
265    static final K k = new K(true);
266
267    final HashMap<String,Method> tests = new HashMap<>();
268    {
269        for (Method m : this.getClass().getDeclaredMethods()) {
270            if (m.getName().matches("m[0-9]+")) {
271                assert(Modifier.isStatic(m.getModifiers())) : m;
272                tests.put(m.getName(), m);
273            }
274        }
275    }
276
277    boolean success = true;
278
279    void doTest(Base src, String name) throws Exception {
280        Method m = tests.get(name);
281
282        for (int i = 0; i < 20000; i++) {
283            boolean failure = false;
284            Base res = null;
285            int s = 0;
286            Class retType = m.getReturnType();
287            if (retType.isPrimitive()) {
288                if (!retType.equals(Void.TYPE)) {
289                    s = (int)m.invoke(null, src);
290                    failure = (s != src.sum());
291                } else {
292                    m.invoke(null, src);
293                }
294            } else {
295                res = (Base)m.invoke(null, src);
296                failure = !res.equals(src);
297            }
298            if (failure) {
299                System.out.println("Test " + name + " failed");
300                System.out.println("source: ");
301                System.out.println(src);
302                System.out.println("result: ");
303                if (m.getReturnType().isPrimitive()) {
304                    System.out.println(s);
305                } else {
306                    System.out.println(res);
307                }
308                success = false;
309                break;
310            }
311        }
312    }
313
314}
315