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 optionsvalidation; 25 26 import java.math.BigInteger; 27 import java.util.ArrayList; 28 import java.util.List; 29 import jdk.test.lib.Platform; 30 31 public class IntJVMOption extends JVMOption { 32 33 enum IntType { 34 35 INTX, 36 UINTX, 37 UINT64_T 38 } 39 40 private static final BigInteger MIN_LONG; 41 private static final BigInteger MAX_LONG; 42 private static final BigInteger MAX_UNSIGNED_LONG; 43 private static final BigInteger MAX_UNSIGNED_LONG_64; 44 private static final BigInteger MINUS_ONE = new BigInteger("-1"); 45 private static final BigInteger MAX_4_BYTE_INT_PLUS_ONE = new BigInteger("2147483648"); 46 private static final BigInteger MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE = new BigInteger("4294967296"); 47 48 /** 49 * Mininum option value 50 */ 51 private BigInteger min; 52 /** 53 * Maximum option value 54 */ 55 private BigInteger max; 56 57 /** 58 * Is this value is signed or unsigned 59 */ 60 private boolean unsigned; 61 62 /** 63 * Is this value is 64 bit unsigned 64 */ 65 private boolean uint64 = false; 66 67 static { 68 if (Platform.is32bit()) { 69 MIN_LONG = new BigInteger(String.valueOf(Integer.MIN_VALUE)); 70 MAX_LONG = new BigInteger(String.valueOf(Integer.MAX_VALUE)); 71 MAX_UNSIGNED_LONG = MAX_LONG.multiply(new BigInteger("2")).add(BigInteger.ONE); 72 } else { 73 MIN_LONG = new BigInteger(String.valueOf(Long.MIN_VALUE)); 74 MAX_LONG = new BigInteger(String.valueOf(Long.MAX_VALUE)); 75 MAX_UNSIGNED_LONG = MAX_LONG.multiply(new BigInteger("2")).add(BigInteger.ONE); 76 } 77 78 MAX_UNSIGNED_LONG_64 = (new BigInteger(String.valueOf(Long.MAX_VALUE))) 79 .multiply(new BigInteger("2")).add(BigInteger.ONE); 80 } 81 82 /** 83 * Default constructor. Init min and max with minimum int and maximum int. 84 */ 85 private IntJVMOption() { 86 min = MIN_LONG; 87 max = MAX_LONG; 88 unsigned = false; 89 uint64 = false; 90 } 91 92 /** 93 * Initialize new integer option with given type. Type can be: INTX - 94 * integer signed option UINTX - unsigned integer option UINT64_T - unsigned 95 * 64 bit integer option 96 * 97 * @param name 98 * @param type 99 */ 100 IntJVMOption(String name, IntType type) { 101 this(); 102 this.name = name; 103 104 switch (type) { 105 case UINT64_T: 106 uint64 = true; 107 case UINTX: 108 unsigned = true; 109 break; 110 } 111 112 if (unsigned) { 113 min = BigInteger.ZERO; 114 max = MAX_UNSIGNED_LONG; 115 } 116 117 if (uint64) { 118 max = MAX_UNSIGNED_LONG_64; 119 } 120 } 121 122 /** 123 * Initialize integer option with passed name, min and max values. Min and 124 * max are string because they can be very big, bigger than long. 125 * 126 * @param name Name of the option 127 * @param min Minimum value of the option 128 * @param max Maximum value of the option 129 */ 130 public IntJVMOption(String name, String min, String max) { 131 this(); 132 this.name = name; 133 this.min = new BigInteger(min); 134 this.max = new BigInteger(max); 135 } 136 137 /** 138 * Set new minimum option value 139 * 140 * @param min New minimum value 141 */ 142 @Override 143 void setMin(String min) { 144 this.min = new BigInteger(min); 145 } 146 147 /** 148 * Get string with minimum value of the option 149 * 150 * @return String with minimum value of the option 151 */ 152 @Override 153 String getMin() { 154 return min.toString(); 155 } 156 157 /** 158 * Set new maximum option value 159 * 160 * @param max New maximum value 161 */ 162 @Override 163 void setMax(String max) { 164 this.max = new BigInteger(max); 165 } 166 167 /** 168 * Get string with maximum value of the option 169 * 170 * @return String with maximum value of the option 171 */ 172 @Override 173 String getMax() { 174 return max.toString(); 175 } 176 177 /** 178 * Return list of strings with valid option values which used for testing 179 * using jcmd, attach and etc. 180 * 181 * @return List of strings which contain valid values for option 182 */ 183 @Override 184 protected List<String> getValidValues() { 185 List<String> validValues = new ArrayList<>(); 186 187 validValues.add(min.toString()); 188 validValues.add(max.toString()); 189 190 if ((min.compareTo(MINUS_ONE) == -1) && (max.compareTo(MINUS_ONE) == 1)) { 191 /* 192 * Add -1 as valid value if min is less than -1 and max is greater than -1 193 */ 194 validValues.add("-1"); 195 } 196 197 if ((min.compareTo(BigInteger.ZERO) == -1) && (max.compareTo(BigInteger.ZERO) == 1)) { 198 /* 199 * Add 0 as valid value if min is less than 0 and max is greater than 0 200 */ 201 validValues.add("0"); 202 } 203 if ((min.compareTo(BigInteger.ONE) == -1) && (max.compareTo(BigInteger.ONE) == 1)) { 204 /* 205 * Add 1 as valid value if min is less than 1 and max is greater than 1 206 */ 207 validValues.add("1"); 208 } 209 210 if (max.compareTo(MAX_4_BYTE_INT_PLUS_ONE) == 1) { 211 /* 212 * Check for overflow when flag is assigned to the 213 * 4 byte int variable 214 */ 215 validValues.add(MAX_4_BYTE_INT_PLUS_ONE.toString()); 216 } 217 218 if (max.compareTo(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE) == 1) { 219 /* 220 * Check for overflow when flag is assigned to the 221 * 4 byte unsigned int variable 222 */ 223 validValues.add(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE.toString()); 224 } 225 226 return validValues; 227 } 228 229 /** 230 * Return list of strings with invalid option values which used for testing 231 * using jcmd, attach and etc. 232 * 233 * @return List of strings which contain invalid values for option 234 */ 235 @Override 236 protected List<String> getInvalidValues() { 237 List<String> invalidValues = new ArrayList<>(); 238 239 if (min.compareTo(MIN_LONG) != 0) { 240 invalidValues.add(min.subtract(BigInteger.ONE).toString()); 241 } 242 243 if (!unsigned && (max.compareTo(MAX_LONG) != 0)) { 244 invalidValues.add(max.add(BigInteger.ONE).toString()); 245 } 246 247 if (unsigned 248 && ((!uint64 && (max.compareTo(MAX_UNSIGNED_LONG) != 0)) 249 || (uint64 && (max.compareTo(MAX_UNSIGNED_LONG_64) != 0)))) { 250 invalidValues.add(max.add(BigInteger.ONE).toString()); 251 } 252 253 return invalidValues; 254 } 255 256 /** 257 * Return expected error message for option with value "value" when it used 258 * on command line with passed value 259 * 260 * @param value Option value 261 * @return Expected error message 262 */ 263 @Override 264 protected String getErrorMessageCommandLine(String value) { 265 String errorMsg; 266 267 if (withRange) { 268 /* Option have defined range in VM */ 269 if (unsigned && ((new BigInteger(value)).compareTo(BigInteger.ZERO) < 0)) { 270 /* 271 * Special case for unsigned options with lower range equal to 0. If 272 * passed value is negative then error will be catched earlier for 273 * such options. Thus use different error message. 274 */ 275 errorMsg = String.format("Improperly specified VM option '%s=%s'", name, value); 276 } else { 277 errorMsg = String.format("%s=%s is outside the allowed range [ %s ... %s ]", 278 name, value, min.toString(), max.toString()); 279 } 280 } else { 281 errorMsg = ""; 282 } 283 284 return errorMsg; 285 } 286 }