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