1 /*
2  * Copyright (c) 2006, 2018, 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.math.BigDecimal;
24 
25 /*
26  * @test
27  * @bug 6362557 8200698
28  * @summary Some tests of add(BigDecimal, mc)
29  * @author Joseph D. Darcy
30  */
31 
32 import java.math.*;
33 import static java.math.BigDecimal.*;
34 import java.util.Set;
35 import java.util.EnumSet;
36 
37 import org.testng.Assert;
38 import org.testng.annotations.Test;
39 
40 // Android-changed: Replace error counting with asserts.
41 public class AddTests {
42 
43     private static Set<RoundingMode> nonExactRoundingModes =
44         EnumSet.complementOf(EnumSet.of(RoundingMode.UNNECESSARY));
45 
46     /**
47      * Test for some simple additions, particularly, it will test
48      * the overflow case.
49      */
simpleTests()50     private static int simpleTests() {
51         int failures = 0;
52 
53         BigDecimal[] bd1 = {
54             new BigDecimal(new BigInteger("7812404666936930160"), 11),
55             new BigDecimal(new BigInteger("7812404666936930160"), 12),
56             new BigDecimal(new BigInteger("7812404666936930160"), 13),
57         };
58         BigDecimal bd2 = new BigDecimal(new BigInteger("2790000"), 1);
59         BigDecimal[] expectedResult = {
60             new BigDecimal("78403046.66936930160"),
61             new BigDecimal("8091404.666936930160"),
62             new BigDecimal("1060240.4666936930160"),
63         };
64         for (int i = 0; i < bd1.length; i++) {
65             if (!bd1[i].add(bd2).equals(expectedResult[i]))
66                 failures++;
67         }
68         return failures;
69     }
70 
71     /**
72      * Test for extreme value of scale and rounding precision that
73      * could cause integer overflow in right-shift-into-sticky-bit
74      * computations.
75      */
76     @Test
extremaTests()77     public void extremaTests() {
78         addWithoutException(valueOf(1, -Integer.MAX_VALUE),
79                                         valueOf(2, Integer.MAX_VALUE), null);
80         addWithoutException(valueOf(1, -Integer.MAX_VALUE),
81                                         valueOf(-2, Integer.MAX_VALUE), null);
82     }
83 
84     /**
85      * Print sum of b1 and b2; correct result will not throw an
86      * exception.
87      */
addWithoutException(BigDecimal b1, BigDecimal b2, MathContext mc)88     private static void addWithoutException(BigDecimal b1, BigDecimal b2, MathContext mc) {
89         if (mc == null)
90             mc = new MathContext(2, RoundingMode.DOWN);
91 
92         try {
93             BigDecimal sum = b1.add(b2, mc);
94         } catch(ArithmeticException ae) {
95             Assert.fail("Unexpected ArithmeticException: " + ae.getMessage());
96         }
97     }
98 
99     /**
100      * Test combinations of operands that may meet the condensation
101      * criteria when rounded to different precisions.
102      */
103     @Test
roundingGradationTests()104     public void roundingGradationTests() {
105         roundAway(new BigDecimal("1234e100"),
106                               new BigDecimal(   "1234e97"));
107 
108         roundAway(new BigDecimal("1234e100"),
109                               new BigDecimal(    "1234e96"));
110 
111         roundAway(new BigDecimal("1234e100"),
112                               new BigDecimal(     "1234e95"));
113 
114         roundAway(new BigDecimal("1234e100"),
115                               new BigDecimal(      "1234e94"));
116 
117         roundAway(new BigDecimal("1234e100"),
118                               new BigDecimal(       "1234e93"));
119 
120         roundAway(new BigDecimal("1234e100"),
121                               new BigDecimal(        "1234e92"));
122 
123         roundAway(new BigDecimal("1234e100"),
124                               new BigDecimal("1234e50"));
125 
126 
127         roundAway(new BigDecimal("1000e100"),
128                               new BigDecimal(   "1234e97"));
129 
130         roundAway(new BigDecimal("1000e100"),
131                               new BigDecimal(    "1234e96"));
132 
133         roundAway(new BigDecimal("1000e100"),
134                               new BigDecimal(     "1234e95"));
135 
136         roundAway(new BigDecimal("1000e100"),
137                               new BigDecimal(      "1234e94"));
138 
139         roundAway(new BigDecimal("1000e100"),
140                               new BigDecimal(       "1234e93"));
141 
142         roundAway(new BigDecimal("1000e100"),
143                               new BigDecimal(        "1234e92"));
144 
145         roundAway(new BigDecimal("1000e100"),
146                               new BigDecimal("1234e50"));
147 
148 
149 
150         roundAway(new BigDecimal("1999e100"),
151                               new BigDecimal(   "1234e97"));
152 
153         roundAway(new BigDecimal("1999e100"),
154                               new BigDecimal(    "1234e96"));
155 
156         roundAway(new BigDecimal("1999e100"),
157                               new BigDecimal(     "1234e95"));
158 
159         roundAway(new BigDecimal("1999e100"),
160                               new BigDecimal(      "1234e94"));
161 
162         roundAway(new BigDecimal("1999e100"),
163                               new BigDecimal(       "1234e93"));
164 
165         roundAway(new BigDecimal("1999e100"),
166                               new BigDecimal(        "1234e92"));
167 
168         roundAway(new BigDecimal("1999e100"),
169                               new BigDecimal("1234e50"));
170 
171 
172 
173         roundAway(new BigDecimal("9999e100"),
174                               new BigDecimal(   "1234e97"));
175 
176         roundAway(new BigDecimal("9999e100"),
177                               new BigDecimal(    "1234e96"));
178 
179         roundAway(new BigDecimal("9999e100"),
180                               new BigDecimal(     "1234e95"));
181 
182         roundAway(new BigDecimal("9999e100"),
183                               new BigDecimal(      "1234e94"));
184 
185         roundAway(new BigDecimal("9999e100"),
186                               new BigDecimal(       "1234e93"));
187 
188         roundAway(new BigDecimal("9999e100"),
189                               new BigDecimal(        "1234e92"));
190 
191         roundAway(new BigDecimal("9999e100"),
192                               new BigDecimal("1234e50"));
193     }
194 
roundAway(BigDecimal b1, BigDecimal b2)195     private static void roundAway(BigDecimal b1, BigDecimal b2) {
196         b1.precision();
197         b2.precision();
198 
199         BigDecimal b1_negate = b1.negate();
200         BigDecimal b2_negate = b2.negate();
201 
202         b1_negate.precision();
203         b2_negate.precision();
204 
205         roundAway1(b1,        b2);
206         roundAway1(b1,        b2_negate);
207         roundAway1(b1_negate, b2);
208         roundAway1(b1_negate, b2_negate);
209     }
210 
roundAway1(BigDecimal b1, BigDecimal b2)211     private static void roundAway1(BigDecimal b1, BigDecimal b2) {
212         roundAway0(b1, b2);
213         roundAway0(b2, b1);
214     }
215 
216     /**
217      * Compare b1.add(b2, mc) with b1.add(b2).round(mc) for a variety
218      * of MathContexts.
219      */
roundAway0(BigDecimal b1, BigDecimal b2)220     private static void roundAway0(BigDecimal b1, BigDecimal b2) {
221         BigDecimal exactSum = b1.add(b2);
222 
223         for(int precision = 1 ; precision < exactSum.precision()+2; precision++) {
224             for(RoundingMode rm : nonExactRoundingModes) {
225                 MathContext mc = new MathContext(precision, rm);
226                 BigDecimal roundedExactSum = exactSum.round(mc);
227 
228                 try {
229                     BigDecimal sum = b1.add(b2, mc);
230 
231                     Assert.assertEquals(sum, roundedExactSum, "Exact sum " + exactSum +
232                                            "\trounded by " + mc +
233                                            "\texpected: " + roundedExactSum + " got: ");
234                 } catch (ArithmeticException ae) {
235                     Assert.fail("Unexpected ArithmeticException: " + ae.getMessage());
236                 }
237             }
238         }
239     }
240 
241     /**
242      * Verify calling the precision method should not change the
243      * computed result.
244      */
245     @Test
precisionConsistencyTest()246     public void precisionConsistencyTest() {
247         MathContext mc = new MathContext(1,RoundingMode.DOWN);
248         BigDecimal a = BigDecimal.valueOf(1999, -1); //value is equivalent to 19990
249 
250         BigDecimal sum1 = a.add(BigDecimal.ONE, mc);
251         a.precision();
252         BigDecimal sum2 = a.add(BigDecimal.ONE, mc);
253 
254         Assert.assertEquals(sum2, sum1, "Unequal sums after calling precision!" +
255             "Before:\t" + sum1.toString() +
256             "After:\t" + sum2.toString());
257     }
258 
259     @Test
arithmeticExceptionTest()260     public static void arithmeticExceptionTest() {
261         int failures = 0;
262         BigDecimal x;
263         try {
264             //
265             // The string representation "1e2147483647", which is equivalent
266             // to 10^Integer.MAX_VALUE, is used to create an augend with an
267             // unscaled value of 1 and a scale of -Integer.MAX_VALUE. The
268             // addend "1" has an unscaled value of 1 with a scale of 0. The
269             // addition is performed exactly and is specified to have a
270             // preferred scale of max(-Integer.MAX_VALUE, 0). As the scale
271             // of the result is 0, a value with Integer.MAX_VALUE + 1 digits
272             // would need to be created. Therefore the next statement is
273             // expected to overflow with an ArithmeticException.
274             //
275             x = new BigDecimal("1e2147483647").add(new BigDecimal(1));
276             failures++;
277             // Android-added: Add assert statement.
278             Assert.fail("ArithmeticException is expected.");
279         } catch (ArithmeticException ae) {
280         }
281         // Android-removed: Remove return the statement.
282         // return failures;
283     }
284 }
285