1 /* 2 * Copyright (c) 2009, 2012, 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 test.java.lang.Integer; 24 25 import org.testng.annotations.Test; 26 import org.testng.Assert; 27 28 /* 29 * @test 30 * @bug 4504839 4215269 6322074 31 * @summary Basic tests for unsigned operations. 32 * @author Joseph D. Darcy 33 */ 34 public class Unsigned { main(String... args)35 public static void main(String... args) { 36 int errors = 0; 37 38 errors += testRoundtrip(); 39 errors += testByteToUnsignedInt(); 40 errors += testShortToUnsignedInt(); 41 errors += testUnsignedCompare(); 42 errors += testToUnsignedLong(); 43 errors += testToStringUnsigned(); 44 errors += testParseUnsignedInt(); 45 errors += testDivideAndRemainder(); 46 47 if (errors > 0) { 48 throw new RuntimeException(errors + " errors found in unsigned operations."); 49 } 50 } 51 testRoundtrip()52 private static int testRoundtrip() { 53 int errors = 0; 54 55 int[] data = {-1, 0, 1}; 56 57 for(int datum : data) { 58 if (Integer.parseUnsignedInt(Integer.toBinaryString(datum), 2) != datum) { 59 errors++; 60 System.err.println("Bad binary roundtrip conversion of " + datum); 61 } 62 63 if (Integer.parseUnsignedInt(Integer.toOctalString(datum), 8) != datum) { 64 errors++; 65 System.err.println("Bad octal roundtrip conversion of " + datum); 66 } 67 68 if (Integer.parseUnsignedInt(Integer.toHexString(datum), 16) != datum) { 69 errors++; 70 System.err.println("Bad hex roundtrip conversion of " + datum); 71 } 72 } 73 return errors; 74 } 75 testByteToUnsignedInt()76 private static int testByteToUnsignedInt() { 77 int errors = 0; 78 79 for(int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { 80 byte datum = (byte) i; 81 int ui = Byte.toUnsignedInt(datum); 82 83 if ( (ui & (~0xff)) != 0 || 84 ((byte)ui != datum )) { 85 errors++; 86 System.err.printf("Bad conversion of byte %d to unsigned int %d%n", 87 datum, ui); 88 } 89 } 90 return errors; 91 } 92 testShortToUnsignedInt()93 private static int testShortToUnsignedInt() { 94 int errors = 0; 95 96 for(int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++) { 97 short datum = (short) i; 98 int ui = Short.toUnsignedInt(datum); 99 100 if ( (ui & (~0xffff)) != 0 || 101 ((short)ui != datum )) { 102 errors++; 103 System.err.printf("Bad conversion of short %d to unsigned int %d%n", 104 datum, ui); 105 } 106 } 107 return errors; 108 } 109 testUnsignedCompare()110 private static int testUnsignedCompare() { 111 int errors = 0; 112 113 int[] data = { 114 0, 115 1, 116 2, 117 3, 118 0x8000_0000, 119 0x8000_0001, 120 0x8000_0002, 121 0x8000_0003, 122 0xFFFF_FFFE, 123 0xFFFF_FFFF, 124 }; 125 126 for(int i : data) { 127 for(int j : data) { 128 int libraryResult = Integer.compareUnsigned(i, j); 129 int libraryResultRev = Integer.compareUnsigned(j, i); 130 int localResult = compUnsigned(i, j); 131 132 if (i == j) { 133 if (libraryResult != 0) { 134 errors++; 135 System.err.printf("Value 0x%x did not compare as " + 136 "an unsigned value equal to itself; got %d%n", 137 i, libraryResult); 138 } 139 } 140 141 if (Integer.signum(libraryResult) != Integer.signum(localResult)) { 142 errors++; 143 System.err.printf("Unsigned compare of 0x%x to 0x%x%n:" + 144 "\texpected sign of %d, got %d%n", 145 i, j, localResult, libraryResult); 146 } 147 148 if (Integer.signum(libraryResult) != 149 -Integer.signum(libraryResultRev)) { 150 errors++; 151 System.err.printf("signum(compareUnsigned(x, y)) != -signum(compareUnsigned(y,x))" + 152 " for \t0x%x and 0x%x, computed %d and %d%n", 153 i, j, libraryResult, libraryResultRev); 154 } 155 } 156 } 157 158 return errors; 159 } 160 161 /** 162 * Straightforward compare unsigned algorithm. 163 */ compUnsigned(int x, int y)164 private static int compUnsigned(int x, int y) { 165 int sign_x = x & Integer.MIN_VALUE; 166 int sign_y = y & Integer.MIN_VALUE; 167 168 int mant_x = x & (~Integer.MIN_VALUE); 169 int mant_y = y & (~Integer.MIN_VALUE); 170 171 if (sign_x == sign_y) 172 return Integer.compare(mant_x, mant_y); 173 else { 174 if (sign_x == 0) 175 return -1; // sign x is 0, sign y is 1 => (x < y) 176 else 177 return 1; // sign x is 1, sign y is 0 => (x > y) 178 } 179 } 180 testToUnsignedLong()181 private static int testToUnsignedLong() { 182 int errors = 0; 183 184 int[] data = { 185 0, 186 1, 187 2, 188 3, 189 0x1234_5678, 190 0x8000_0000, 191 0x8000_0001, 192 0x8000_0002, 193 0x8000_0003, 194 0x8765_4321, 195 0xFFFF_FFFE, 196 0xFFFF_FFFF, 197 }; 198 199 for(int datum : data) { 200 long result = Integer.toUnsignedLong(datum); 201 202 // High-order bits should be zero 203 if ((result & 0xffff_ffff_0000_0000L) != 0L) { 204 errors++; 205 System.err.printf("High bits set converting 0x%x to 0x%x%n", 206 datum, result); 207 } 208 209 // Lower-order bits should be equal to datum. 210 int lowOrder = (int)(result & 0x0000_0000_ffff_ffffL); 211 if (lowOrder != datum ) { 212 errors++; 213 System.err.printf("Low bits not preserved converting 0x%x to 0x%x%n", 214 datum, result); 215 } 216 } 217 return errors; 218 } 219 testToStringUnsigned()220 private static int testToStringUnsigned() { 221 int errors = 0; 222 223 int[] data = { 224 0, 225 1, 226 2, 227 3, 228 99999, 229 100000, 230 999999, 231 100000, 232 999999999, 233 1000000000, 234 0x1234_5678, 235 0x8000_0000, 236 0x8000_0001, 237 0x8000_0002, 238 0x8000_0003, 239 0x8765_4321, 240 0xFFFF_FFFE, 241 0xFFFF_FFFF, 242 }; 243 244 for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { 245 for(int datum : data) { 246 String result1 = Integer.toUnsignedString(datum, radix); 247 String result2 = Long.toString(Integer.toUnsignedLong(datum), radix); 248 249 if (!result1.equals(result2)) { 250 errors++; 251 System.err.printf("Unexpected string difference converting 0x%x:" + 252 "\t%s %s%n", 253 datum, result1, result2); 254 } 255 256 if (radix == 10) { 257 String result3 = Integer.toUnsignedString(datum); 258 if (!result2.equals(result3)) { 259 errors++; 260 System.err.printf("Unexpected string difference converting 0x%x:" + 261 "\t%s %s%n", 262 datum, result3, result2); 263 } 264 } 265 266 int parseResult = Integer.parseUnsignedInt(result1, radix); 267 268 if (parseResult != datum) { 269 errors++; 270 System.err.printf("Bad roundtrip conversion of %d in base %d" + 271 "\tconverting back ''%s'' resulted in %d%n", 272 datum, radix, result1, parseResult); 273 } 274 } 275 } 276 277 return errors; 278 } 279 280 private static final long MAX_UNSIGNED_INT = Integer.toUnsignedLong(0xffff_ffff); 281 testParseUnsignedInt()282 private static int testParseUnsignedInt() { 283 int errors = 0; 284 285 // Values include those between signed Integer.MAX_VALUE and 286 // unsignted int MAX_VALUE. 287 long[] inRange = { 288 0L, 289 1L, 290 10L, 291 2147483646L, // MAX_VALUE - 1 292 2147483647L, // MAX_VALUE 293 2147483648L, // MAX_VALUE + 1 294 295 MAX_UNSIGNED_INT - 1L, 296 MAX_UNSIGNED_INT, 297 }; 298 299 for(long value : inRange) { 300 for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { 301 String longString = Long.toString(value, radix); 302 int intResult = Integer.parseUnsignedInt(longString, radix); 303 304 if (Integer.toUnsignedLong(intResult) != value) { 305 errors++; 306 System.err.printf("Bad roundtrip conversion of %d in base %d" + 307 "\tconverting back ''%s'' resulted in %d%n", 308 value, radix, longString, intResult); 309 } 310 311 // test offset based parse method 312 intResult = Integer.parseUnsignedInt("prefix" + longString + "suffix", 313 "prefix".length(), "prefix".length() + longString.length(), radix); 314 315 if (Integer.toUnsignedLong(intResult) != value) { 316 errors++; 317 System.err.printf("Bad roundtrip conversion of %d in base %d" + 318 "\tconverting back ''%s'' resulted in %d%n", 319 value, radix, longString, intResult); 320 } 321 } 322 } 323 324 String[] outOfRange = { 325 null, 326 "", 327 "-1", 328 Long.toString(MAX_UNSIGNED_INT + 1L), 329 Long.toString(Long.MAX_VALUE) 330 }; 331 332 for(String s : outOfRange) { 333 try { 334 int result = Integer.parseUnsignedInt(s); 335 errors++; // Should not reach here 336 System.err.printf("Unexpected got %d from an unsigned conversion of %s", 337 result, s); 338 } catch(NumberFormatException nfe) { 339 ; // Correct result 340 } 341 } 342 343 return errors; 344 } 345 testDivideAndRemainder()346 private static int testDivideAndRemainder() { 347 int errors = 0; 348 349 long[] inRange = { 350 0L, 351 1L, 352 2L, 353 2147483646L, // MAX_VALUE - 1 354 2147483647L, // MAX_VALUE 355 2147483648L, // MAX_VALUE + 1 356 357 MAX_UNSIGNED_INT - 1L, 358 MAX_UNSIGNED_INT, 359 }; 360 361 for(long dividend : inRange) { 362 for(long divisor : inRange) { 363 int quotient; 364 long longQuotient; 365 366 int remainder; 367 long longRemainder; 368 369 if (divisor == 0) { 370 try { 371 quotient = Integer.divideUnsigned((int) dividend, (int) divisor); 372 errors++; 373 } catch(ArithmeticException ea) { 374 ; // Expected 375 } 376 377 try { 378 remainder = Integer.remainderUnsigned((int) dividend, (int) divisor); 379 errors++; 380 } catch(ArithmeticException ea) { 381 ; // Expected 382 } 383 } else { 384 quotient = Integer.divideUnsigned((int) dividend, (int) divisor); 385 longQuotient = dividend / divisor; 386 387 if (quotient != (int)longQuotient) { 388 errors++; 389 System.err.printf("Unexpected unsigned divide result %s on %s/%s%n", 390 Integer.toUnsignedString(quotient), 391 Integer.toUnsignedString((int) dividend), 392 Integer.toUnsignedString((int) divisor)); 393 } 394 395 remainder = Integer.remainderUnsigned((int) dividend, (int) divisor); 396 longRemainder = dividend % divisor; 397 398 if (remainder != (int)longRemainder) { 399 errors++; 400 System.err.printf("Unexpected unsigned remainder result %s on %s%%%s%n", 401 Integer.toUnsignedString(remainder), 402 Integer.toUnsignedString((int) dividend), 403 Integer.toUnsignedString((int) divisor)); 404 } 405 } 406 } 407 } 408 409 return errors; 410 } 411 } 412