1 /*
2  * Copyright (c) 1999, 2017, 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  * @library /test/lib
28  * @build jdk.test.lib.RandomFactory
29  * @run main StringConstructor
30  * @bug 4103117 4331084 4488017 4490929 6255285 6268365 8074460 8078672
31  * @summary Tests the BigDecimal string constructor (use -Dseed=X to set PRNG seed).
32  * @key randomness
33  */
34 
35 import java.math.*;
36 import java.util.Random;
37 
38 import org.testng.Assert;
39 import org.testng.annotations.Test;
40 
41 // Android-changed: Replace error counting with asserts.
42 public class StringConstructor {
43 
44     @Test
testBadStrings()45     public void testBadStrings() {
46         constructWithError("");
47         constructWithError("+");
48         constructWithError("-");
49         constructWithError("+e");
50         constructWithError("-e");
51         constructWithError("e+");
52         constructWithError("1.-0");
53         constructWithError(".-123");
54         constructWithError("-");
55         constructWithError("--1.1");
56         constructWithError("-+1.1");
57         constructWithError("+-1.1");
58         constructWithError("1-.1");
59         constructWithError("1+.1");
60         constructWithError("1.111+1");
61         constructWithError("1.111-1");
62         constructWithError("11.e+");
63         constructWithError("11.e-");
64         constructWithError("11.e+-");
65         constructWithError("11.e-+");
66         constructWithError("11.e-+1");
67         constructWithError("11.e+-1");
68 
69         // Range checks
70         constructWithError("1e" + Integer.MIN_VALUE);
71         constructWithError("10e" + Integer.MIN_VALUE);
72         constructWithError("0.01e" + Integer.MIN_VALUE);
73         constructWithError("1e" + ((long) Integer.MIN_VALUE - 1));
74         constructWithError("1e" + ((long) Integer.MAX_VALUE + 1));
75     }
76 
77     @Test
testRoundtrip()78     public void testRoundtrip() {
79         // Roundtrip tests
80         Random random = new Random();
81         for (int i=0; i<100; i++) {
82             int size = random.nextInt(100) + 1;
83             BigInteger bi = new BigInteger(size, random);
84             if (random.nextBoolean())
85                 bi = bi.negate();
86             int decimalLength = bi.toString().length();
87             int scale = random.nextInt(decimalLength);
88             BigDecimal bd = new BigDecimal(bi, scale);
89             String bdString = bd.toString();
90             BigDecimal bdDoppel = new BigDecimal(bdString);
91             Assert.assertEquals(bd, bdDoppel, "bd string: scale: " + bd.scale() +
92                                    "\t" + bdString + "\nbd doppel: scale: " + bdDoppel.scale() +
93                                    "\t" + bdDoppel.toString());
94         }
95     }
96 
97     /*
98      * Verify precision is set properly if the significand has
99      * non-ASCII leading zeros.
100      */
101     @Test
nonAsciiZeroTest()102     public void nonAsciiZeroTest() {
103         String[] values = {
104             "00004e5",
105             "\u0660\u0660\u0660\u06604e5",
106         };
107 
108         BigDecimal expected = new BigDecimal("4e5");
109 
110         for(String s : values) {
111             BigDecimal tmp = new BigDecimal(s);
112             Assert.assertFalse(! expected.equals(tmp) || tmp.precision() != 1,
113                 "Bad conversion of " + s + "got " +
114                                    tmp + "precision = " + tmp.precision());
115         }
116 
117     }
118 
119     @Test
testLeadingExponentZeroTest()120     public void testLeadingExponentZeroTest() {
121         BigDecimal twelve = new BigDecimal("12");
122         BigDecimal onePointTwo = new BigDecimal("1.2");
123 
124         String start = "1.2e0";
125         String end = "1";
126         String middle = "";
127 
128         // Test with more excess zeros than the largest number of
129         // decimal digits needed to represent a long
130         int limit  = ((int)Math.log10(Long.MAX_VALUE)) + 6;
131         for(int i = 0; i < limit; i++, middle += "0") {
132             String t1 = start + middle;
133             String t2 = t1 + end;
134 
135             testString(t1, onePointTwo);
136             testString(t2, twelve);
137         }
138     }
139 
testString(String s, BigDecimal expected)140     private static void testString(String s, BigDecimal expected) {
141         testString0(s, expected);
142         testString0(switchZero(s), expected);
143     }
144 
testString0(String s, BigDecimal expected)145     private static void testString0(String s, BigDecimal expected) {
146         Assert.assertEquals(new BigDecimal(s), expected, s + " is not equal to " + expected);
147     }
148 
switchZero(String s)149     private static String switchZero(String s) {
150         return s.replace('0', '\u0660'); // Arabic-Indic zero
151     }
152 
constructWithError(String badString)153     private static void constructWithError(String badString) {
154         try {
155             BigDecimal d = new BigDecimal(badString);
156             Assert.fail(badString + " accepted");
157         } catch(NumberFormatException e) {
158             // expected
159         }
160     }
161 }
162