test/jdk/java/lang/Integer/Unsigned.java
changeset 47216 71c04702a3d5
parent 26462 d6d34934be12
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/Integer/Unsigned.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4504839 4215269 6322074
+ * @summary Basic tests for unsigned operations.
+ * @author Joseph D. Darcy
+ */
+public class Unsigned {
+    public static void main(String... args) {
+        int errors = 0;
+
+        errors += testRoundtrip();
+        errors += testByteToUnsignedInt();
+        errors += testShortToUnsignedInt();
+        errors += testUnsignedCompare();
+        errors += testToUnsignedLong();
+        errors += testToStringUnsigned();
+        errors += testParseUnsignedInt();
+        errors += testDivideAndRemainder();
+
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors found in unsigned operations.");
+        }
+    }
+
+    private static int testRoundtrip() {
+        int errors = 0;
+
+        int[] data = {-1, 0, 1};
+
+        for(int datum : data) {
+            if (Integer.parseUnsignedInt(Integer.toBinaryString(datum), 2) != datum) {
+                errors++;
+                System.err.println("Bad binary roundtrip conversion of " + datum);
+            }
+
+            if (Integer.parseUnsignedInt(Integer.toOctalString(datum), 8) != datum) {
+                errors++;
+                System.err.println("Bad octal roundtrip conversion of " + datum);
+            }
+
+            if (Integer.parseUnsignedInt(Integer.toHexString(datum), 16) != datum) {
+                errors++;
+                System.err.println("Bad hex roundtrip conversion of " + datum);
+            }
+        }
+        return errors;
+    }
+
+    private static int testByteToUnsignedInt() {
+        int errors = 0;
+
+        for(int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+            byte datum = (byte) i;
+            int ui = Byte.toUnsignedInt(datum);
+
+            if ( (ui & (~0xff)) != 0 ||
+                 ((byte)ui != datum )) {
+                errors++;
+                System.err.printf("Bad conversion of byte %d to unsigned int %d%n",
+                                  datum, ui);
+            }
+        }
+        return errors;
+    }
+
+    private static int testShortToUnsignedInt() {
+        int errors = 0;
+
+        for(int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++) {
+            short datum = (short) i;
+            int ui = Short.toUnsignedInt(datum);
+
+            if ( (ui & (~0xffff)) != 0 ||
+                 ((short)ui != datum )) {
+                errors++;
+                System.err.printf("Bad conversion of short %d to unsigned int %d%n",
+                                  datum, ui);
+            }
+        }
+        return errors;
+    }
+
+    private static int testUnsignedCompare() {
+        int errors = 0;
+
+        int[] data = {
+            0,
+            1,
+            2,
+            3,
+            0x8000_0000,
+            0x8000_0001,
+            0x8000_0002,
+            0x8000_0003,
+            0xFFFF_FFFE,
+            0xFFFF_FFFF,
+        };
+
+        for(int i : data) {
+            for(int j : data) {
+                int libraryResult    = Integer.compareUnsigned(i, j);
+                int libraryResultRev = Integer.compareUnsigned(j, i);
+                int localResult      = compUnsigned(i, j);
+
+                if (i == j) {
+                    if (libraryResult != 0) {
+                        errors++;
+                        System.err.printf("Value 0x%x did not compare as " +
+                                          "an unsigned value equal to itself; got %d%n",
+                                          i, libraryResult);
+                    }
+                }
+
+                if (Integer.signum(libraryResult) != Integer.signum(localResult)) {
+                    errors++;
+                    System.err.printf("Unsigned compare of 0x%x to 0x%x%n:" +
+                                      "\texpected sign of %d, got %d%n",
+                                      i, j, localResult, libraryResult);
+                }
+
+                if (Integer.signum(libraryResult) !=
+                    -Integer.signum(libraryResultRev)) {
+                    errors++;
+                    System.err.printf("signum(compareUnsigned(x, y)) != -signum(compareUnsigned(y,x))" +
+                                      " for \t0x%x and 0x%x, computed %d and %d%n",
+                                      i, j, libraryResult, libraryResultRev);
+                }
+            }
+        }
+
+        return errors;
+    }
+
+    /**
+     * Straightforward compare unsigned algorithm.
+     */
+    private static int compUnsigned(int x, int y) {
+        int sign_x = x & Integer.MIN_VALUE;
+        int sign_y = y & Integer.MIN_VALUE;
+
+        int mant_x  = x & (~Integer.MIN_VALUE);
+        int mant_y  = y & (~Integer.MIN_VALUE);
+
+        if (sign_x == sign_y)
+            return Integer.compare(mant_x, mant_y);
+        else {
+            if (sign_x == 0)
+                return -1; // sign x is 0, sign y is 1 => (x < y)
+            else
+                return 1; //  sign x is 1, sign y is 0 => (x > y)
+        }
+    }
+
+    private static int testToUnsignedLong() {
+        int errors = 0;
+
+        int[] data = {
+            0,
+            1,
+            2,
+            3,
+            0x1234_5678,
+            0x8000_0000,
+            0x8000_0001,
+            0x8000_0002,
+            0x8000_0003,
+            0x8765_4321,
+            0xFFFF_FFFE,
+            0xFFFF_FFFF,
+        };
+
+        for(int datum : data) {
+            long result = Integer.toUnsignedLong(datum);
+
+            // High-order bits should be zero
+            if ((result & 0xffff_ffff_0000_0000L) != 0L) {
+                errors++;
+                System.err.printf("High bits set converting 0x%x to 0x%x%n",
+                                  datum, result);
+            }
+
+            // Lower-order bits should be equal to datum.
+            int lowOrder = (int)(result & 0x0000_0000_ffff_ffffL);
+            if (lowOrder != datum ) {
+                errors++;
+                System.err.printf("Low bits not preserved converting 0x%x to 0x%x%n",
+                                  datum, result);
+            }
+        }
+        return errors;
+    }
+
+    private static int testToStringUnsigned() {
+        int errors = 0;
+
+        int[] data = {
+            0,
+            1,
+            2,
+            3,
+            99999,
+            100000,
+            999999,
+            100000,
+            999999999,
+            1000000000,
+            0x1234_5678,
+            0x8000_0000,
+            0x8000_0001,
+            0x8000_0002,
+            0x8000_0003,
+            0x8765_4321,
+            0xFFFF_FFFE,
+            0xFFFF_FFFF,
+        };
+
+        for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+            for(int datum : data) {
+                String result1 = Integer.toUnsignedString(datum, radix);
+                String result2 = Long.toString(Integer.toUnsignedLong(datum), radix);
+
+                if (!result1.equals(result2)) {
+                    errors++;
+                    System.err.printf("Unexpected string difference converting 0x%x:" +
+                                      "\t%s %s%n",
+                                      datum, result1, result2);
+                }
+
+                if (radix == 10) {
+                    String result3 = Integer.toUnsignedString(datum);
+                    if (!result2.equals(result3)) {
+                        errors++;
+                        System.err.printf("Unexpected string difference converting 0x%x:" +
+                                          "\t%s %s%n",
+                                          datum, result3, result2);
+                    }
+                }
+
+                int parseResult = Integer.parseUnsignedInt(result1, radix);
+
+                if (parseResult != datum) {
+                    errors++;
+                        System.err.printf("Bad roundtrip conversion of %d in base %d" +
+                                          "\tconverting back ''%s'' resulted in %d%n",
+                                          datum, radix, result1,  parseResult);
+                }
+            }
+        }
+
+        return errors;
+    }
+
+    private static final long MAX_UNSIGNED_INT = Integer.toUnsignedLong(0xffff_ffff);
+
+    private static int testParseUnsignedInt() {
+        int errors = 0;
+
+        // Values include those between signed Integer.MAX_VALUE and
+        // unsignted int MAX_VALUE.
+        long[] inRange = {
+            0L,
+            1L,
+            10L,
+            2147483646L,   // MAX_VALUE - 1
+            2147483647L,   // MAX_VALUE
+            2147483648L,   // MAX_VALUE + 1
+
+            MAX_UNSIGNED_INT - 1L,
+            MAX_UNSIGNED_INT,
+        };
+
+        for(long value : inRange) {
+            for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+                String longString = Long.toString(value, radix);
+                int intResult = Integer.parseUnsignedInt(longString, radix);
+
+                if (Integer.toUnsignedLong(intResult) != value) {
+                    errors++;
+                    System.err.printf("Bad roundtrip conversion of %d in base %d" +
+                                      "\tconverting back ''%s'' resulted in %d%n",
+                                      value, radix, longString,  intResult);
+                }
+
+                // test offset based parse method
+                intResult = Integer.parseUnsignedInt("prefix" + longString + "suffix",
+                        "prefix".length(), "prefix".length() + longString.length(), radix);
+
+                if (Integer.toUnsignedLong(intResult) != value) {
+                    errors++;
+                    System.err.printf("Bad roundtrip conversion of %d in base %d" +
+                            "\tconverting back ''%s'' resulted in %d%n",
+                            value, radix, longString,  intResult);
+                }
+            }
+        }
+
+        String[] outOfRange = {
+            null,
+            "",
+            "-1",
+            Long.toString(MAX_UNSIGNED_INT + 1L),
+            Long.toString(Long.MAX_VALUE)
+        };
+
+        for(String s : outOfRange) {
+            try {
+                int result = Integer.parseUnsignedInt(s);
+                errors++; // Should not reach here
+                System.err.printf("Unexpected got %d from an unsigned conversion of %s",
+                                  result, s);
+            } catch(NumberFormatException nfe) {
+                ; // Correct result
+            }
+        }
+
+        return errors;
+    }
+
+    private static int testDivideAndRemainder() {
+        int errors = 0;
+
+        long[] inRange = {
+            0L,
+            1L,
+            2L,
+            2147483646L,   // MAX_VALUE - 1
+            2147483647L,   // MAX_VALUE
+            2147483648L,   // MAX_VALUE + 1
+
+            MAX_UNSIGNED_INT - 1L,
+            MAX_UNSIGNED_INT,
+        };
+
+        for(long dividend : inRange) {
+            for(long divisor : inRange) {
+                int quotient;
+                long longQuotient;
+
+                int remainder;
+                long longRemainder;
+
+                if (divisor == 0) {
+                    try {
+                        quotient = Integer.divideUnsigned((int) dividend, (int) divisor);
+                        errors++;
+                    } catch(ArithmeticException ea) {
+                        ; // Expected
+                    }
+
+                    try {
+                        remainder = Integer.remainderUnsigned((int) dividend, (int) divisor);
+                        errors++;
+                    } catch(ArithmeticException ea) {
+                        ; // Expected
+                    }
+                } else {
+                    quotient = Integer.divideUnsigned((int) dividend, (int) divisor);
+                    longQuotient = dividend / divisor;
+
+                    if (quotient != (int)longQuotient) {
+                        errors++;
+                        System.err.printf("Unexpected unsigned divide result %s on %s/%s%n",
+                                          Integer.toUnsignedString(quotient),
+                                          Integer.toUnsignedString((int) dividend),
+                                          Integer.toUnsignedString((int) divisor));
+                    }
+
+                    remainder = Integer.remainderUnsigned((int) dividend, (int) divisor);
+                    longRemainder = dividend % divisor;
+
+                    if (remainder != (int)longRemainder) {
+                        errors++;
+                        System.err.printf("Unexpected unsigned remainder result %s on %s%%%s%n",
+                                          Integer.toUnsignedString(remainder),
+                                          Integer.toUnsignedString((int) dividend),
+                                          Integer.toUnsignedString((int) divisor));
+                    }
+                }
+            }
+        }
+
+        return errors;
+    }
+}