1 /* 2 * Copyright (c) 2007, 2018, 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 package nsk.share.jdi; 24 25 import java.lang.reflect.*; 26 import nsk.share.*; 27 import nsk.share.jpda.ConversionUtils; 28 import com.sun.jdi.*; 29 30 /* 31 * Class contains several common methods used by tests checking that values are 32 * correctly converted as a result of JDI interface work (e.g. when method 33 * 'ObjectReference.setValue(Field, Value)' is called) 34 */ 35 public class ValueConversionDebugger extends TestDebuggerType2 { 36 37 protected static enum ValueType { 38 BYTE, 39 CHAR, 40 SHORT, 41 INT, 42 LONG, 43 FLOAT, 44 DOUBLE 45 } 46 47 /* 48 * short aliases for ValueType members 49 */ 50 protected static ValueType BYTE = ValueType.BYTE; 51 protected static ValueType CHAR = ValueType.CHAR; 52 protected static ValueType SHORT = ValueType.SHORT; 53 protected static ValueType INT = ValueType.INT; 54 protected static ValueType LONG = ValueType.LONG; 55 protected static ValueType FLOAT = ValueType.FLOAT; 56 protected static ValueType DOUBLE = ValueType.DOUBLE; 57 58 /* 59 * Is information lost when given PrimitiveValue converted to the 60 * primitive type representing by the destType 61 */ informationLoss(PrimitiveValue value, Class destType)62 public static boolean informationLoss(PrimitiveValue value, Class destType) { 63 /* 64 * Use reflection here to avoid large nested switches 65 * (construct method name, method is located in the nsk.share.jpda.ConversionUtils) 66 */ 67 String methodNameToCall = "informationLoss"; 68 69 Object param = null; 70 71 if (value instanceof ByteValue) { 72 methodNameToCall += "ByteTo"; 73 param = new Byte(value.byteValue()); 74 } else if (value instanceof ShortValue) { 75 methodNameToCall += "ShortTo"; 76 param = new Short(value.shortValue()); 77 } else if (value instanceof CharValue) { 78 methodNameToCall += "CharTo"; 79 param = new Character(value.charValue()); 80 } else if (value instanceof IntegerValue) { 81 methodNameToCall += "IntTo"; 82 param = new Integer(value.intValue()); 83 } else if (value instanceof LongValue) { 84 methodNameToCall += "LongTo"; 85 param = new Long(value.longValue()); 86 } else if (value instanceof FloatValue) { 87 methodNameToCall += "FloatTo"; 88 param = new Float(value.floatValue()); 89 } else if (value instanceof DoubleValue) { 90 methodNameToCall += "DoubleTo"; 91 param = new Double(value.doubleValue()); 92 } else 93 throw new IllegalArgumentException("Illegal PrimitiveValue: " + value); 94 95 if (!destType.isPrimitive()) 96 throw new IllegalArgumentException("Illegal destType: " + destType + ", should be primitive type"); 97 98 if (destType == Byte.TYPE) { 99 methodNameToCall += "Byte"; 100 } else if (destType == Short.TYPE) { 101 methodNameToCall += "Short"; 102 } else if (destType == Character.TYPE) { 103 methodNameToCall += "Char"; 104 } else if (destType == Integer.TYPE) { 105 methodNameToCall += "Int"; 106 } else if (destType == Long.TYPE) { 107 methodNameToCall += "Long"; 108 } else if (destType == Float.TYPE) { 109 methodNameToCall += "Float"; 110 } else if (destType == Double.TYPE) { 111 methodNameToCall += "Double"; 112 } else 113 throw new IllegalArgumentException("Illegal destType: " + destType + ", should be primitive type"); 114 115 java.lang.reflect.Method method; 116 try { 117 method = ConversionUtils.class.getMethod(methodNameToCall, param.getClass()); 118 } catch (NoSuchMethodException e) { 119 throw new Failure("Unexpected exception: " + e, e); 120 } 121 122 try { 123 return (Boolean)method.invoke(null, new Object[]{param}); 124 } catch (IllegalAccessException e) { 125 throw new Failure("Unexpected exception: " + e, e); 126 } catch (InvocationTargetException e) { 127 throw new Failure("Unexpected exception: " + e, e); 128 } 129 } 130 131 /* 132 * Is given PrimitiveValue can be converted to the primitive type represented by the 133 * destType without information loss 134 */ isValidConversion(PrimitiveValue value, Class destType)135 public static boolean isValidConversion(PrimitiveValue value, Class destType) { 136 return !informationLoss(value, destType); 137 } 138 139 /* 140 * Method is used in subclasses for creation of tested values 141 * (reflection is used to simplify coding) 142 */ createValue(Object arr, int arrayIndex)143 protected PrimitiveValue createValue(Object arr, int arrayIndex) { 144 PrimitiveValue value; 145 146 if (arr instanceof byte[]) { 147 value = debuggee.VM().mirrorOf(Array.getByte(arr,arrayIndex)); 148 } else if (arr instanceof char[]) { 149 value = debuggee.VM().mirrorOf(Array.getChar(arr,arrayIndex)); 150 } else if (arr instanceof double[]) { 151 value = debuggee.VM().mirrorOf(Array.getDouble(arr,arrayIndex)); 152 } else if (arr instanceof float[]) { 153 value = debuggee.VM().mirrorOf(Array.getFloat(arr,arrayIndex)); 154 } else if (arr instanceof int[]) { 155 value = debuggee.VM().mirrorOf(Array.getInt(arr,arrayIndex)); 156 } else if (arr instanceof long[]) { 157 value = debuggee.VM().mirrorOf(Array.getLong(arr,arrayIndex)); 158 } else if (arr instanceof short[]) { 159 value = debuggee.VM().mirrorOf(Array.getShort(arr,arrayIndex)); 160 } else { 161 setSuccess(false); 162 throw new TestBug("Unexpected object was passed in the 'createValue': " + arr); 163 } 164 165 return value; 166 } 167 168 /* 169 * used by subclasses for debug output 170 * (modified in the method 'isValidConversion') 171 */ 172 protected String lastConversion; 173 174 /* 175 * Is given PrimitiveValue can be converted to the primitive type represented by the given type 176 * without information loss 177 */ isValidConversion(ValueType type, PrimitiveValue value)178 protected boolean isValidConversion(ValueType type, PrimitiveValue value) { 179 com.sun.jdi.Type fromType = value.type(); 180 181 boolean ret = false; 182 lastConversion = " conversion from " 183 + value + "(" + fromType + ")" + " to "; 184 switch (type) { 185 case BYTE: 186 byte b = value.byteValue(); 187 ret = isValidConversion(value, Byte.TYPE); 188 lastConversion += b + "(byte)"; 189 break; 190 case CHAR: 191 char c = value.charValue(); 192 ret = isValidConversion(value, Character.TYPE); 193 lastConversion += Integer.toHexString(c) + "(char)"; 194 break; 195 case DOUBLE: 196 double d = value.doubleValue(); 197 ret = isValidConversion(value, Double.TYPE); 198 lastConversion += d + "(double)"; 199 break; 200 case FLOAT: 201 float f = value.floatValue(); 202 ret = isValidConversion(value, Float.TYPE); 203 lastConversion += f + "(float)"; 204 break; 205 case INT: 206 int i = value.intValue(); 207 ret = isValidConversion(value, Integer.TYPE); 208 lastConversion += i + "(int)"; 209 break; 210 case LONG: 211 long j = value.longValue(); 212 ret = isValidConversion(value, Long.TYPE); 213 lastConversion += j + "(long)"; 214 break; 215 case SHORT: 216 short s = value.shortValue(); 217 ret = isValidConversion(value, Short.TYPE); 218 lastConversion += s + "(short)"; 219 break; 220 default: 221 throw new IllegalArgumentException("Invalid type: " + type); 222 } 223 return ret; 224 } 225 226 /* 227 * Used in subclasses to check that given PrimitiveValue was correctly converted as a result 228 * of JDI interface work (retValue - conversion result) 229 * ( 230 * example: 231 * test assigns DoubleValue = 1.5 (value) to the byte Field (retValue - ByteValue = 1), 232 * in this case we should check that value.byteValue() == retValue.byteValue() 233 * ) 234 */ checkValueConversion(PrimitiveValue value, PrimitiveValue retValue)235 protected void checkValueConversion(PrimitiveValue value, PrimitiveValue retValue) { 236 boolean res; 237 238 if (retValue instanceof ByteValue) { 239 res = value.byteValue() != retValue.byteValue(); 240 } else if (retValue instanceof ShortValue) { 241 res = value.shortValue() != retValue.shortValue(); 242 } else if (retValue instanceof CharValue) { 243 res = value.charValue() != retValue.charValue(); 244 } else if (retValue instanceof IntegerValue) { 245 res = value.intValue() != retValue.intValue(); 246 } else if (retValue instanceof LongValue) { 247 res = value.longValue() != retValue.longValue(); 248 } else if (retValue instanceof FloatValue) { 249 res = value.floatValue() != retValue.floatValue(); 250 } else if (retValue instanceof DoubleValue) { 251 res = value.doubleValue() != retValue.doubleValue(); 252 } else { 253 throw new TestBug("Invalid value type in the 'checkValueConversion': " + retValue.type().name()); 254 } 255 256 if (res) { 257 setSuccess(false); 258 complain("Conversion error"); 259 complain("From type: " + value.type().name() + ", to type: " + retValue.type().name()); 260 complain(retValue + " != " + value); 261 display(""); 262 } 263 } 264 } 265