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