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