1 /* 2 * Copyright (c) 2012, 2019, 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.StrictMath; 24 25 import java.math.BigInteger; 26 27 import org.testng.annotations.Test; 28 29 import static org.testng.Assert.fail; 30 31 /** 32 * @test Test for StrictMath.*Exact integer and long methods. 33 * @bug 6708398 34 * @summary Basic tests for StrictMath exact arithmetic operations. 35 * 36 * @author Roger Riggs 37 */ 38 public class ExactArithTests { 39 40 /** 41 * Test StrictMath.addExact, multiplyExact, subtractExact, incrementExact, 42 * decrementExact, negateExact methods with {@code int} arguments. 43 */ 44 @Test testIntegerExact()45 public void testIntegerExact() { 46 testIntegerExact(0, 0); 47 testIntegerExact(1, 1); 48 testIntegerExact(1, -1); 49 testIntegerExact(-1, 1); 50 testIntegerExact(1000, 2000); 51 52 testIntegerExact(Integer.MIN_VALUE, Integer.MIN_VALUE); 53 testIntegerExact(Integer.MAX_VALUE, Integer.MAX_VALUE); 54 testIntegerExact(Integer.MIN_VALUE, 1); 55 testIntegerExact(Integer.MAX_VALUE, 1); 56 testIntegerExact(Integer.MIN_VALUE, 2); 57 testIntegerExact(Integer.MAX_VALUE, 2); 58 testIntegerExact(Integer.MIN_VALUE, -1); 59 testIntegerExact(Integer.MAX_VALUE, -1); 60 testIntegerExact(Integer.MIN_VALUE, -2); 61 testIntegerExact(Integer.MAX_VALUE, -2); 62 } 63 64 /** 65 * Test exact arithmetic by comparing with the same operations using long 66 * and checking that the result is the same as the integer truncation. 67 * Errors are reported with {@link fail}. 68 * 69 * @param x first parameter 70 * @param y second parameter 71 */ testIntegerExact(int x, int y)72 static void testIntegerExact(int x, int y) { 73 try { 74 // Test addExact 75 int sum = StrictMath.addExact(x, y); 76 long sum2 = (long) x + (long) y; 77 if ((int) sum2 != sum2) { 78 fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ") = " + sum + "; expected Arithmetic exception"); 79 } else if (sum != sum2) { 80 fail("FAIL: long StrictMath.addExact(" + x + " + " + y + ") = " + sum + "; expected: " + sum2); 81 } 82 } catch (ArithmeticException ex) { 83 long sum2 = (long) x + (long) y; 84 if ((int) sum2 == sum2) { 85 fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex); 86 } 87 } 88 89 try { 90 // Test subtractExact 91 int diff = StrictMath.subtractExact(x, y); 92 long diff2 = (long) x - (long) y; 93 if ((int) diff2 != diff2) { 94 fail("FAIL: int StrictMath.subtractExact(" + x + " - " + y + ") = " + diff + "; expected: " + diff2); 95 } 96 97 } catch (ArithmeticException ex) { 98 long diff2 = (long) x - (long) y; 99 if ((int) diff2 == diff2) { 100 fail("FAIL: int StrictMath.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex); 101 } 102 } 103 104 try { 105 // Test multiplyExact 106 int product = StrictMath.multiplyExact(x, y); 107 long m2 = (long) x * (long) y; 108 if ((int) m2 != m2) { 109 fail("FAIL: int StrictMath.multiplyExact(" + x + " * " + y + ") = " + product + "; expected: " + m2); 110 } 111 } catch (ArithmeticException ex) { 112 long m2 = (long) x * (long) y; 113 if ((int) m2 == m2) { 114 fail("FAIL: int StrictMath.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex); 115 } 116 } 117 118 try { 119 // Test incrementExact 120 int inc = StrictMath.incrementExact(x); 121 long inc2 = (long) x + 1L; 122 if ((int) inc2 != inc2) { 123 fail("FAIL: int StrictMath.incrementExact(" + x + ") = " + inc + "; expected Arithmetic exception"); 124 } else if (inc != inc2) { 125 fail("FAIL: long StrictMath.incrementExact(" + x + ") = " + inc + "; expected: " + inc2); 126 } 127 } catch (ArithmeticException ex) { 128 long inc2 = (long) x + 1L; 129 if ((int) inc2 == inc2) { 130 fail("FAIL: int StrictMath.incrementExact(" + x + ")" + "; Unexpected exception: " + ex); 131 } 132 } 133 134 try { 135 // Test decrementExact 136 int dec = StrictMath.decrementExact(x); 137 long dec2 = (long) x - 1L; 138 if ((int) dec2 != dec2) { 139 fail("FAIL: int StrictMath.decrementExact(" + x + ") = " + dec + "; expected Arithmetic exception"); 140 } else if (dec != dec2) { 141 fail("FAIL: long StrictMath.decrementExact(" + x + ") = " + dec + "; expected: " + dec2); 142 } 143 } catch (ArithmeticException ex) { 144 long dec2 = (long) x - 1L; 145 if ((int) dec2 == dec2) { 146 fail("FAIL: int StrictMath.decrementExact(" + x + ")" + "; Unexpected exception: " + ex); 147 } 148 } 149 150 try { 151 // Test negateExact 152 int neg = StrictMath.negateExact(x); 153 long neg2 = -((long)x); 154 if ((int) neg2 != neg2) { 155 fail("FAIL: int StrictMath.negateExact(" + x + ") = " + neg + "; expected Arithmetic exception"); 156 } else if (neg != neg2) { 157 fail("FAIL: long StrictMath.negateExact(" + x + ") = " + neg + "; expected: " + neg2); 158 } 159 } catch (ArithmeticException ex) { 160 long neg2 = -((long)x); 161 if ((int) neg2 == neg2) { 162 fail("FAIL: int StrictMath.negateExact(" + x + ")" + "; Unexpected exception: " + ex); 163 } 164 } 165 } 166 167 /** 168 * Test StrictMath.addExact, multiplyExact, subtractExact, incrementExact, 169 * decrementExact, negateExact, toIntExact methods with {@code long} arguments. 170 */ 171 @Test testLongExact()172 public void testLongExact() { 173 testLongExactTwice(0, 0); 174 testLongExactTwice(1, 1); 175 testLongExactTwice(1, -1); 176 testLongExactTwice(1000, 2000); 177 178 testLongExactTwice(Long.MIN_VALUE, Long.MIN_VALUE); 179 testLongExactTwice(Long.MAX_VALUE, Long.MAX_VALUE); 180 testLongExactTwice(Long.MIN_VALUE, 1); 181 testLongExactTwice(Long.MAX_VALUE, 1); 182 testLongExactTwice(Long.MIN_VALUE, 2); 183 testLongExactTwice(Long.MAX_VALUE, 2); 184 testLongExactTwice(Long.MIN_VALUE, -1); 185 testLongExactTwice(Long.MAX_VALUE, -1); 186 testLongExactTwice(Long.MIN_VALUE, -2); 187 testLongExactTwice(Long.MAX_VALUE, -2); 188 testLongExactTwice(Long.MIN_VALUE/2, 2); 189 testLongExactTwice(Long.MAX_VALUE, 2); 190 testLongExactTwice(Integer.MAX_VALUE, Integer.MAX_VALUE); 191 testLongExactTwice(Integer.MAX_VALUE, -Integer.MAX_VALUE); 192 testLongExactTwice(Integer.MAX_VALUE+1, Integer.MAX_VALUE+1); 193 testLongExactTwice(Integer.MAX_VALUE+1, -Integer.MAX_VALUE+1); 194 testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1); 195 testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1); 196 testLongExactTwice(Integer.MIN_VALUE/2, 2); 197 } 198 199 /** 200 * Test each of the exact operations with the arguments and 201 * with the arguments reversed. 202 * @param x 203 * @param y 204 */ testLongExactTwice(long x, long y)205 static void testLongExactTwice(long x, long y) { 206 testLongExact(x, y); 207 testLongExact(y, x); 208 } 209 210 211 /** 212 * Test long exact arithmetic by comparing with the same operations using BigInteger 213 * and checking that the result is the same as the long truncation. 214 * Errors are reported with {@link fail}. 215 * 216 * @param x first parameter 217 * @param y second parameter 218 */ testLongExact(long x, long y)219 static void testLongExact(long x, long y) { 220 BigInteger resultBig = null; 221 final BigInteger xBig = BigInteger.valueOf(x); 222 final BigInteger yBig = BigInteger.valueOf(y); 223 try { 224 // Test addExact 225 resultBig = xBig.add(yBig); 226 long sum = StrictMath.addExact(x, y); 227 checkResult("long StrictMath.addExact", x, y, sum, resultBig); 228 } catch (ArithmeticException ex) { 229 if (inLongRange(resultBig)) { 230 fail("FAIL: long StrictMath.addExact(" + x + " + " + y + "); Unexpected exception: " + ex); 231 } 232 } 233 234 try { 235 // Test subtractExact 236 resultBig = xBig.subtract(yBig); 237 long diff = StrictMath.subtractExact(x, y); 238 checkResult("long StrictMath.subtractExact", x, y, diff, resultBig); 239 } catch (ArithmeticException ex) { 240 if (inLongRange(resultBig)) { 241 fail("FAIL: long StrictMath.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex); 242 } 243 } 244 245 try { 246 // Test multiplyExact 247 resultBig = xBig.multiply(yBig); 248 long product = StrictMath.multiplyExact(x, y); 249 checkResult("long StrictMath.multiplyExact", x, y, product, resultBig); 250 } catch (ArithmeticException ex) { 251 if (inLongRange(resultBig)) { 252 fail("FAIL: long StrictMath.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex); 253 } 254 } 255 256 try { 257 // Test incrementExact 258 resultBig = xBig.add(BigInteger.ONE); 259 long inc = StrictMath.incrementExact(x); 260 checkResult("long Math.incrementExact", x, 1L, inc, resultBig); 261 } catch (ArithmeticException ex) { 262 if (inLongRange(resultBig)) { 263 fail("FAIL: long Math.incrementExact(" + x + "); Unexpected exception: " + ex); 264 } 265 } 266 267 try { 268 // Test decrementExact 269 resultBig = xBig.subtract(BigInteger.ONE); 270 long dec = StrictMath.decrementExact(x); 271 checkResult("long Math.decrementExact", x, 1L, dec, resultBig); 272 } catch (ArithmeticException ex) { 273 if (inLongRange(resultBig)) { 274 fail("FAIL: long Math.decrementExact(" + x + "); Unexpected exception: " + ex); 275 } 276 } 277 278 try { 279 // Test negateExact 280 resultBig = xBig.negate(); 281 long dec = StrictMath.negateExact(x); 282 checkResult("long Math.negateExact", x, 0L, dec, resultBig); 283 } catch (ArithmeticException ex) { 284 if (inLongRange(resultBig)) { 285 fail("FAIL: long Math.negateExact(" + x + "); Unexpected exception: " + ex); 286 } 287 } 288 289 try { 290 // Test toIntExact 291 int value = StrictMath.toIntExact(x); 292 if ((long)value != x) { 293 fail("FAIL: " + "long StrictMath.toIntExact" + "(" + x + ") = " + value + "; expected an arithmetic exception: "); 294 } 295 } catch (ArithmeticException ex) { 296 if (resultBig.bitLength() <= 32) { 297 fail("FAIL: long StrictMath.toIntExact(" + x + ")" + "; Unexpected exception: " + ex); 298 } 299 } 300 } 301 302 /** 303 * Compare the expected and actual results. 304 * @param message message for the error 305 * @param x first argument 306 * @param y second argument 307 * @param result actual result value 308 * @param expected expected result value 309 */ checkResult(String message, long x, long y, long result, BigInteger expected)310 static void checkResult(String message, long x, long y, long result, BigInteger expected) { 311 BigInteger resultBig = BigInteger.valueOf(result); 312 if (!inLongRange(expected)) { 313 fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result 314 + "; expected an arithmetic exception: "); 315 } else if (!resultBig.equals(expected)) { 316 fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected " 317 + expected); 318 } 319 } 320 321 /** 322 * Check if the value fits in 64 bits (a long). 323 * 324 * @return true if the value fits in 64 bits (including the sign). 325 */ inLongRange(BigInteger value)326 static boolean inLongRange(BigInteger value) { 327 return value.bitLength() <= 63; 328 } 329 330 // BEGIN Android-added: add multiplyExact(long, int) based on Math.ExactArithTests. 331 332 /** 333 * Test StrictMath.multiplyExact method with {@code long} and {@code int} arguments. 334 */ 335 @Test testLongIntExact()336 static void testLongIntExact() { 337 testLongIntExact(0, 0); 338 testLongIntExact(1, 1); 339 testLongIntExact(1, -1); 340 testLongIntExact(1000, 2000); 341 342 testLongIntExact(Long.MIN_VALUE, Integer.MIN_VALUE); 343 testLongIntExact(Long.MAX_VALUE, Integer.MAX_VALUE); 344 testLongIntExact(Long.MIN_VALUE, 1); 345 testLongIntExact(Long.MAX_VALUE, 1); 346 testLongIntExact(Long.MIN_VALUE, 2); 347 testLongIntExact(Long.MAX_VALUE, 2); 348 testLongIntExact(Long.MIN_VALUE, -1); 349 testLongIntExact(Long.MAX_VALUE, -1); 350 testLongIntExact(Long.MIN_VALUE, -2); 351 testLongIntExact(Long.MAX_VALUE, -2); 352 testLongIntExact(Long.MIN_VALUE / 2, 2); 353 testLongIntExact(Long.MAX_VALUE, 2); 354 testLongIntExact(Integer.MAX_VALUE, Integer.MAX_VALUE); 355 testLongIntExact(Integer.MAX_VALUE, -Integer.MAX_VALUE); 356 testLongIntExact((long) Integer.MAX_VALUE + 1L, Integer.MAX_VALUE); 357 testLongIntExact((long) Integer.MAX_VALUE + 1L, -Integer.MAX_VALUE + 1); 358 testLongIntExact((long) Integer.MIN_VALUE - 1L, Integer.MIN_VALUE); 359 testLongIntExact((long) Integer.MIN_VALUE - 1, Integer.MAX_VALUE); 360 testLongIntExact(Integer.MIN_VALUE / 2, 2); 361 } 362 363 /** 364 * Test long-int exact arithmetic by comparing with the same operations using BigInteger and 365 * checking that the result is the same as the long truncation. Errors are reported with {@link 366 * fail}. 367 * 368 * @param x first parameter 369 * @param y second parameter 370 */ testLongIntExact(long x, int y)371 static void testLongIntExact(long x, int y) { 372 BigInteger resultBig = null; 373 final BigInteger xBig = BigInteger.valueOf(x); 374 final BigInteger yBig = BigInteger.valueOf(y); 375 376 try { 377 // Test multiplyExact 378 resultBig = xBig.multiply(yBig); 379 long product = StrictMath.multiplyExact(x, y); 380 checkResult("long StrictMath.multiplyExact", x, y, product, resultBig); 381 } catch (ArithmeticException ex) { 382 if (inLongRange(resultBig)) { 383 fail("FAIL: long StrictMath.multiplyExact(" + x + " * " + y + ")" 384 + "; Unexpected exception: " + ex); 385 } 386 } 387 } 388 // END Android-added: add multiplyExact(long, int) based on Math.ExactArithTests. 389 }