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 
  24 package compiler.arraycopy;
  25 
  26 import java.lang.reflect.Field;
  27 import java.lang.reflect.Method;
  28 import java.lang.reflect.Modifier;
  29 import java.util.HashMap;
  30 
  31 abstract 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 }