1 /*
2  * Copyright (c) 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.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     // BEGIN Android-removed: main(), error counter, replace fail() with testng.Assert.fail().
41     /**
42      * The count of test errors.
43      *
44     private static int errors = 0;
45 
46     /**
47      * @param args the command line arguments
48      *
49     public static void main(String[] args) {
50         testIntegerExact();
51         testLongExact();
52 
53         if (errors > 0) {
54             throw new RuntimeException(errors + " errors found in ExactArithTests.");
55         }
56     }
57 
58     static void fail(String message) {
59         errors++;
60         System.err.println(message);
61     }
62     */
63     // END Android-removed: main(), error counter.
64 
65     /**
66      * Test StrictMath.addExact, multiplyExact, subtractExact, toIntValue methods
67      * with {@code int} arguments.
68      */
69     // Android-added: @Test annotation.
70     @Test
testIntegerExact()71     static void testIntegerExact() {
72         testIntegerExact(0, 0);
73         testIntegerExact(1, 1);
74         testIntegerExact(1, -1);
75         testIntegerExact(-1, 1);
76         testIntegerExact(1000, 2000);
77 
78         testIntegerExact(Integer.MIN_VALUE, Integer.MIN_VALUE);
79         testIntegerExact(Integer.MAX_VALUE, Integer.MAX_VALUE);
80         testIntegerExact(Integer.MIN_VALUE, 1);
81         testIntegerExact(Integer.MAX_VALUE, 1);
82         testIntegerExact(Integer.MIN_VALUE, 2);
83         testIntegerExact(Integer.MAX_VALUE, 2);
84         testIntegerExact(Integer.MIN_VALUE, -1);
85         testIntegerExact(Integer.MAX_VALUE, -1);
86         testIntegerExact(Integer.MIN_VALUE, -2);
87         testIntegerExact(Integer.MAX_VALUE, -2);
88 
89     }
90 
91     /**
92      * Test exact arithmetic by comparing with the same operations using long
93      * and checking that the result is the same as the integer truncation.
94      * Errors are reported with {@link fail}.
95      *
96      * @param x first parameter
97      * @param y second parameter
98      */
testIntegerExact(int x, int y)99     static void testIntegerExact(int x, int y) {
100         try {
101             // Test addExact
102             int sum = StrictMath.addExact(x, y);
103             long sum2 = (long) x + (long) y;
104             if ((int) sum2 != sum2) {
105                 fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ") = " + sum + "; expected Arithmetic exception");
106             } else if (sum != sum2) {
107                 fail("FAIL: long StrictMath.addExact(" + x + " + " + y + ") = " + sum + "; expected: " + sum2);
108             }
109         } catch (ArithmeticException ex) {
110             long sum2 = (long) x + (long) y;
111             if ((int) sum2 == sum2) {
112                 fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
113 
114             }
115         }
116 
117         try {
118             // Test subtractExact
119             int diff = StrictMath.subtractExact(x, y);
120             long diff2 = (long) x - (long) y;
121             if ((int) diff2 != diff2) {
122                 fail("FAIL: int StrictMath.subtractExact(" + x + " - " + y + ") = " + diff + "; expected: " + diff2);
123             }
124 
125         } catch (ArithmeticException ex) {
126             long diff2 = (long) x - (long) y;
127             if ((int) diff2 == diff2) {
128                 fail("FAIL: int StrictMath.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex);
129             }
130         }
131 
132         try {
133             // Test multiplyExact
134             int product = StrictMath.multiplyExact(x, y);
135             long m2 = (long) x * (long) y;
136             if ((int) m2 != m2) {
137                 fail("FAIL: int StrictMath.multiplyExact(" + x + " * " + y + ") = " + product + "; expected: " + m2);
138             }
139         } catch (ArithmeticException ex) {
140             long m2 = (long) x * (long) y;
141             if ((int) m2 == m2) {
142                 fail("FAIL: int StrictMath.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
143             }
144         }
145 
146     }
147 
148     /**
149      * Test StrictMath.addExact, multiplyExact, subtractExact, toIntExact methods
150      * with {@code long} arguments.
151      */
152     // Android-added: @Test annotation.
153     @Test
testLongExact()154     static void testLongExact() {
155         testLongExactTwice(0, 0);
156         testLongExactTwice(1, 1);
157         testLongExactTwice(1, -1);
158         testLongExactTwice(1000, 2000);
159 
160         testLongExactTwice(Long.MIN_VALUE, Long.MIN_VALUE);
161         testLongExactTwice(Long.MAX_VALUE, Long.MAX_VALUE);
162         testLongExactTwice(Long.MIN_VALUE, 1);
163         testLongExactTwice(Long.MAX_VALUE, 1);
164         testLongExactTwice(Long.MIN_VALUE, 2);
165         testLongExactTwice(Long.MAX_VALUE, 2);
166         testLongExactTwice(Long.MIN_VALUE, -1);
167         testLongExactTwice(Long.MAX_VALUE, -1);
168         testLongExactTwice(Long.MIN_VALUE, -2);
169         testLongExactTwice(Long.MAX_VALUE, -2);
170         testLongExactTwice(Long.MIN_VALUE/2, 2);
171         testLongExactTwice(Long.MAX_VALUE, 2);
172         testLongExactTwice(Integer.MAX_VALUE, Integer.MAX_VALUE);
173         testLongExactTwice(Integer.MAX_VALUE, -Integer.MAX_VALUE);
174         testLongExactTwice(Integer.MAX_VALUE+1, Integer.MAX_VALUE+1);
175         testLongExactTwice(Integer.MAX_VALUE+1, -Integer.MAX_VALUE+1);
176         testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1);
177         testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1);
178         testLongExactTwice(Integer.MIN_VALUE/2, 2);
179 
180     }
181 
182     /**
183      * Test each of the exact operations with the arguments and
184      * with the arguments reversed.
185      * @param x
186      * @param y
187      */
testLongExactTwice(long x, long y)188     static void testLongExactTwice(long x, long y) {
189         testLongExact(x, y);
190         testLongExact(y, x);
191     }
192 
193 
194     /**
195      * Test long exact arithmetic by comparing with the same operations using BigInteger
196      * and checking that the result is the same as the long truncation.
197      * Errors are reported with {@link fail}.
198      *
199      * @param x first parameter
200      * @param y second parameter
201      */
testLongExact(long x, long y)202     static void testLongExact(long x, long y) {
203         BigInteger resultBig = null;
204         final BigInteger xBig = BigInteger.valueOf(x);
205         final BigInteger yBig = BigInteger.valueOf(y);
206         try {
207             // Test addExact
208             resultBig = xBig.add(yBig);
209             long sum = StrictMath.addExact(x, y);
210             checkResult("long StrictMath.addExact", x, y, sum, resultBig);
211         } catch (ArithmeticException ex) {
212             if (inLongRange(resultBig)) {
213                 fail("FAIL: long StrictMath.addExact(" + x + " + " + y + "); Unexpected exception: " + ex);
214             }
215         }
216 
217         try {
218             // Test subtractExact
219             resultBig = xBig.subtract(yBig);
220             long diff = StrictMath.subtractExact(x, y);
221             checkResult("long StrictMath.subtractExact", x, y, diff, resultBig);
222         } catch (ArithmeticException ex) {
223             if (inLongRange(resultBig)) {
224                 fail("FAIL: long StrictMath.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex);
225             }
226         }
227 
228         try {
229             // Test multiplyExact
230             resultBig = xBig.multiply(yBig);
231             long product = StrictMath.multiplyExact(x, y);
232             checkResult("long StrictMath.multiplyExact", x, y, product, resultBig);
233         } catch (ArithmeticException ex) {
234             if (inLongRange(resultBig)) {
235                 fail("FAIL: long StrictMath.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
236             }
237         }
238 
239         try {
240             // Test toIntExact
241             int value = StrictMath.toIntExact(x);
242             if ((long)value != x) {
243                 fail("FAIL: " + "long StrictMath.toIntExact" + "(" + x + ") = " + value + "; expected an arithmetic exception: ");
244             }
245         } catch (ArithmeticException ex) {
246             if (resultBig.bitLength() <= 32) {
247                 fail("FAIL: long StrictMath.toIntExact(" + x + ")" + "; Unexpected exception: " + ex);
248             }
249         }
250 
251     }
252 
253     /**
254      * Compare the expected and actual results.
255      * @param message message for the error
256      * @param x first argument
257      * @param y second argument
258      * @param result actual result value
259      * @param expected expected result value
260      */
checkResult(String message, long x, long y, long result, BigInteger expected)261     static void checkResult(String message, long x, long y, long result, BigInteger expected) {
262         BigInteger resultBig = BigInteger.valueOf(result);
263         if (!inLongRange(expected)) {
264             fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected an arithmetic exception: ");
265         } else if (!resultBig.equals(expected)) {
266             fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected " + expected);
267         }
268     }
269 
270     /**
271      * Check if the value fits in 64 bits (a long).
272      * @param value
273      * @return true if the value fits in 64 bits (including the sign).
274      */
inLongRange(BigInteger value)275     static boolean inLongRange(BigInteger value) {
276         return value.bitLength() <= 63;
277     }
278 
279     // BEGIN Android-added: add multiplyExact(long, int) based on Math.ExactArithTests.
280     /**
281      * Test StrictMath.multiplyExact method with {@code long} and {@code int}
282      * arguments.
283      */
284     @Test
testLongIntExact()285     static void testLongIntExact() {
286         testLongIntExact(0, 0);
287         testLongIntExact(1, 1);
288         testLongIntExact(1, -1);
289         testLongIntExact(1000, 2000);
290 
291         testLongIntExact(Long.MIN_VALUE, Integer.MIN_VALUE);
292         testLongIntExact(Long.MAX_VALUE, Integer.MAX_VALUE);
293         testLongIntExact(Long.MIN_VALUE, 1);
294         testLongIntExact(Long.MAX_VALUE, 1);
295         testLongIntExact(Long.MIN_VALUE, 2);
296         testLongIntExact(Long.MAX_VALUE, 2);
297         testLongIntExact(Long.MIN_VALUE, -1);
298         testLongIntExact(Long.MAX_VALUE, -1);
299         testLongIntExact(Long.MIN_VALUE, -2);
300         testLongIntExact(Long.MAX_VALUE, -2);
301         testLongIntExact(Long.MIN_VALUE/2, 2);
302         testLongIntExact(Long.MAX_VALUE, 2);
303         testLongIntExact(Integer.MAX_VALUE, Integer.MAX_VALUE);
304         testLongIntExact(Integer.MAX_VALUE, -Integer.MAX_VALUE);
305         testLongIntExact((long)Integer.MAX_VALUE+1L, Integer.MAX_VALUE);
306         testLongIntExact((long)Integer.MAX_VALUE+1L, -Integer.MAX_VALUE+1);
307         testLongIntExact((long)Integer.MIN_VALUE-1L, Integer.MIN_VALUE);
308         testLongIntExact((long)Integer.MIN_VALUE-1, Integer.MAX_VALUE);
309         testLongIntExact(Integer.MIN_VALUE/2, 2);
310     }
311 
312     /**
313      * Test long-int exact arithmetic by comparing with the same operations using BigInteger
314      * and checking that the result is the same as the long truncation.
315      * Errors are reported with {@link fail}.
316      *
317      * @param x first parameter
318      * @param y second parameter
319      */
testLongIntExact(long x, int y)320     static void testLongIntExact(long x, int y) {
321         BigInteger resultBig = null;
322         final BigInteger xBig = BigInteger.valueOf(x);
323         final BigInteger yBig = BigInteger.valueOf(y);
324 
325         try {
326             // Test multiplyExact
327             resultBig = xBig.multiply(yBig);
328             long product = StrictMath.multiplyExact(x, y);
329             checkResult("long StrictMath.multiplyExact", x, y, product, resultBig);
330         } catch (ArithmeticException ex) {
331             if (inLongRange(resultBig)) {
332                 fail("FAIL: long StrictMath.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
333             }
334         }
335     }
336     // END Android-added: add multiplyExact(long, int) based on Math.ExactArithTests.
337 }