1 /*
2  * Copyright 2002-2008 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.springframework.util;
18 
19 import java.math.BigDecimal;
20 import java.math.BigInteger;
21 import java.text.NumberFormat;
22 import java.util.Locale;
23 
24 import junit.framework.TestCase;
25 
26 import org.springframework.core.JdkVersion;
27 
28 /**
29  * @author Rob Harrop
30  * @author Juergen Hoeller
31  */
32 public class NumberUtilsTests extends TestCase {
33 
testParseNumber()34 	public void testParseNumber() {
35 		String aByte = "" + Byte.MAX_VALUE;
36 		String aShort = "" + Short.MAX_VALUE;
37 		String anInteger = "" + Integer.MAX_VALUE;
38 		String aLong = "" + Long.MAX_VALUE;
39 		String aFloat = "" + Float.MAX_VALUE;
40 		String aDouble = "" + Double.MAX_VALUE;
41 
42 		assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class));
43 		assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class));
44 		assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class));
45 		assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class));
46 		assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class));
47 		assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
48 	}
49 
testParseNumberUsingNumberFormat()50 	public void testParseNumberUsingNumberFormat() {
51 		NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
52 		String aByte = "" + Byte.MAX_VALUE;
53 		String aShort = "" + Short.MAX_VALUE;
54 		String anInteger = "" + Integer.MAX_VALUE;
55 		String aLong = "" + Long.MAX_VALUE;
56 		String aFloat = "" + Float.MAX_VALUE;
57 		String aDouble = "" + Double.MAX_VALUE;
58 
59 		assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class, nf));
60 		assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class, nf));
61 		assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class, nf));
62 		assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
63 		assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class, nf));
64 		assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
65 	}
66 
testParseWithTrim()67 	public void testParseWithTrim() {
68 		String aByte = " " + Byte.MAX_VALUE + " ";
69 		String aShort = " " + Short.MAX_VALUE + " ";
70 		String anInteger = " " + Integer.MAX_VALUE + " ";
71 		String aLong = " " + Long.MAX_VALUE + " ";
72 		String aFloat = " " + Float.MAX_VALUE + " ";
73 		String aDouble = " " + Double.MAX_VALUE + " ";
74 
75 		assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class));
76 		assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class));
77 		assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class));
78 		assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class));
79 		assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class));
80 		assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
81 	}
82 
testParseWithTrimUsingNumberFormat()83 	public void testParseWithTrimUsingNumberFormat() {
84 		NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
85 		String aByte = " " + Byte.MAX_VALUE + " ";
86 		String aShort = " " + Short.MAX_VALUE + " ";
87 		String anInteger = " " + Integer.MAX_VALUE + " ";
88 		String aLong = " " + Long.MAX_VALUE + " ";
89 		String aFloat = " " + Float.MAX_VALUE + " ";
90 		String aDouble = " " + Double.MAX_VALUE + " ";
91 
92 		assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class, nf));
93 		assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class, nf));
94 		assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class, nf));
95 		assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
96 		assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class, nf));
97 		assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
98 	}
99 
testParseAsHex()100 	public void testParseAsHex() {
101 		String aByte = "0x" + Integer.toHexString(new Byte(Byte.MAX_VALUE).intValue());
102 		String aShort = "0x" + Integer.toHexString(new Short(Short.MAX_VALUE).intValue());
103 		String anInteger = "0x" + Integer.toHexString(Integer.MAX_VALUE);
104 		String aLong = "0x" + Long.toHexString(Long.MAX_VALUE);
105 		String aReallyBigInt = "FEBD4E677898DFEBFFEE44";
106 
107 		assertByteEquals(aByte);
108 		assertShortEquals(aShort);
109 		assertIntegerEquals(anInteger);
110 		assertLongEquals(aLong);
111 		assertEquals("BigInteger did not parse",
112 				new BigInteger(aReallyBigInt, 16), NumberUtils.parseNumber("0x" + aReallyBigInt, BigInteger.class));
113 	}
114 
testParseNegativeHex()115 	public void testParseNegativeHex() {
116 		String aByte = "-0x80";
117 		String aShort = "-0x8000";
118 		String anInteger = "-0x80000000";
119 		String aLong = "-0x8000000000000000";
120 		String aReallyBigInt = "FEBD4E677898DFEBFFEE44";
121 
122 		assertNegativeByteEquals(aByte);
123 		assertNegativeShortEquals(aShort);
124 		assertNegativeIntegerEquals(anInteger);
125 		assertNegativeLongEquals(aLong);
126 		assertEquals("BigInteger did not parse",
127 				new BigInteger(aReallyBigInt, 16).negate(), NumberUtils.parseNumber("-0x" + aReallyBigInt, BigInteger.class));
128 	}
129 
testDoubleToBigInteger()130 	public void testDoubleToBigInteger() {
131 		Double decimal = new Double(3.14d);
132 		assertEquals(new BigInteger("3"), NumberUtils.convertNumberToTargetClass(decimal, BigInteger.class));
133 	}
134 
testBigDecimalToBigInteger()135 	public void testBigDecimalToBigInteger() {
136 		String number = "987459837583750387355346";
137 		BigDecimal decimal = new BigDecimal(number);
138 		assertEquals(new BigInteger(number), NumberUtils.convertNumberToTargetClass(decimal, BigInteger.class));
139 	}
140 
testNonExactBigDecimalToBigInteger()141 	public void testNonExactBigDecimalToBigInteger() {
142 		BigDecimal decimal = new BigDecimal("987459837583750387355346.14");
143 		assertEquals(new BigInteger("987459837583750387355346"), NumberUtils.convertNumberToTargetClass(decimal, BigInteger.class));
144 	}
145 
testParseBigDecimalNumber1()146 	public void testParseBigDecimalNumber1() {
147 		String bigDecimalAsString = "0.10";
148 		Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class);
149 		assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
150 	}
151 
testParseBigDecimalNumber2()152 	public void testParseBigDecimalNumber2() {
153 		String bigDecimalAsString = "0.001";
154 		Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class);
155 		assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
156 	}
157 
testParseBigDecimalNumber3()158 	public void testParseBigDecimalNumber3() {
159 		String bigDecimalAsString = "3.14159265358979323846";
160 		Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class);
161 		assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
162 	}
163 
testParseLocalizedBigDecimalNumber1()164 	public void testParseLocalizedBigDecimalNumber1() {
165 		if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
166 			return;
167 		}
168 		String bigDecimalAsString = "0.10";
169 		NumberFormat numberFormat = NumberFormat.getInstance(Locale.ENGLISH);
170 		Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class, numberFormat);
171 		assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
172 	}
173 
testParseLocalizedBigDecimalNumber2()174 	public void testParseLocalizedBigDecimalNumber2() {
175 		if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
176 			return;
177 		}
178 		String bigDecimalAsString = "0.001";
179 		NumberFormat numberFormat = NumberFormat.getInstance(Locale.ENGLISH);
180 		Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class, numberFormat);
181 		assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
182 	}
183 
testParseLocalizedBigDecimalNumber3()184 	public void testParseLocalizedBigDecimalNumber3() {
185 		if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
186 			return;
187 		}
188 		String bigDecimalAsString = "3.14159265358979323846";
189 		NumberFormat numberFormat = NumberFormat.getInstance(Locale.ENGLISH);
190 		Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class, numberFormat);
191 		assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
192 	}
193 
testParseOverflow()194 	public void testParseOverflow() {
195 		String aLong = "" + Long.MAX_VALUE;
196 		String aDouble = "" + Double.MAX_VALUE;
197 
198 		try {
199 			NumberUtils.parseNumber(aLong, Byte.class);
200 			fail("Should have thrown IllegalArgumentException");
201 		}
202 		catch (IllegalArgumentException expected) {
203 		}
204 
205 		try {
206 			NumberUtils.parseNumber(aLong, Short.class);
207 			fail("Should have thrown IllegalArgumentException");
208 		}
209 		catch (IllegalArgumentException expected) {
210 		}
211 
212 		try {
213 			NumberUtils.parseNumber(aLong, Integer.class);
214 			fail("Should have thrown IllegalArgumentException");
215 		}
216 		catch (IllegalArgumentException expected) {
217 		}
218 
219 		assertEquals(new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class));
220 
221 		assertEquals(new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
222 	}
223 
testParseNegativeOverflow()224 	public void testParseNegativeOverflow() {
225 		String aLong = "" + Long.MIN_VALUE;
226 		String aDouble = "" + Double.MIN_VALUE;
227 
228 		try {
229 			NumberUtils.parseNumber(aLong, Byte.class);
230 			fail("Should have thrown IllegalArgumentException");
231 		}
232 		catch (IllegalArgumentException expected) {
233 		}
234 
235 		try {
236 			NumberUtils.parseNumber(aLong, Short.class);
237 			fail("Should have thrown IllegalArgumentException");
238 		}
239 		catch (IllegalArgumentException expected) {
240 		}
241 
242 		try {
243 			NumberUtils.parseNumber(aLong, Integer.class);
244 			fail("Should have thrown IllegalArgumentException");
245 		}
246 		catch (IllegalArgumentException expected) {
247 		}
248 
249 		assertEquals(new Long(Long.MIN_VALUE), NumberUtils.parseNumber(aLong, Long.class));
250 
251 		assertEquals(new Double(Double.MIN_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
252 	}
253 
testParseOverflowUsingNumberFormat()254 	public void testParseOverflowUsingNumberFormat() {
255 		NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
256 		String aLong = "" + Long.MAX_VALUE;
257 		String aDouble = "" + Double.MAX_VALUE;
258 
259 		try {
260 			NumberUtils.parseNumber(aLong, Byte.class, nf);
261 			fail("Should have thrown IllegalArgumentException");
262 		}
263 		catch (IllegalArgumentException expected) {
264 		}
265 
266 		try {
267 			NumberUtils.parseNumber(aLong, Short.class, nf);
268 			fail("Should have thrown IllegalArgumentException");
269 		}
270 		catch (IllegalArgumentException expected) {
271 		}
272 
273 		try {
274 			NumberUtils.parseNumber(aLong, Integer.class, nf);
275 			fail("Should have thrown IllegalArgumentException");
276 		}
277 		catch (IllegalArgumentException expected) {
278 		}
279 
280 		assertEquals(new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
281 
282 		assertEquals(new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
283 	}
284 
testParseNegativeOverflowUsingNumberFormat()285 	public void testParseNegativeOverflowUsingNumberFormat() {
286 		NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
287 		String aLong = "" + Long.MIN_VALUE;
288 		String aDouble = "" + Double.MIN_VALUE;
289 
290 		try {
291 			NumberUtils.parseNumber(aLong, Byte.class, nf);
292 			fail("Should have thrown IllegalArgumentException");
293 		}
294 		catch (IllegalArgumentException expected) {
295 		}
296 
297 		try {
298 			NumberUtils.parseNumber(aLong, Short.class, nf);
299 			fail("Should have thrown IllegalArgumentException");
300 		}
301 		catch (IllegalArgumentException expected) {
302 		}
303 
304 		try {
305 			NumberUtils.parseNumber(aLong, Integer.class, nf);
306 			fail("Should have thrown IllegalArgumentException");
307 		}
308 		catch (IllegalArgumentException expected) {
309 		}
310 
311 		assertEquals(new Long(Long.MIN_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
312 
313 		assertEquals(new Double(Double.MIN_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
314 	}
315 
assertLongEquals(String aLong)316 	private void assertLongEquals(String aLong) {
317 		assertEquals("Long did not parse", Long.MAX_VALUE, NumberUtils.parseNumber(aLong, Long.class).longValue());
318 	}
319 
assertIntegerEquals(String anInteger)320 	private void assertIntegerEquals(String anInteger) {
321 		assertEquals("Integer did not parse", Integer.MAX_VALUE, NumberUtils.parseNumber(anInteger, Integer.class).intValue());
322 	}
323 
assertShortEquals(String aShort)324 	private void assertShortEquals(String aShort) {
325 		assertEquals("Short did not parse", Short.MAX_VALUE, NumberUtils.parseNumber(aShort, Short.class).shortValue());
326 	}
327 
assertByteEquals(String aByte)328 	private void assertByteEquals(String aByte) {
329 		assertEquals("Byte did not parse", Byte.MAX_VALUE, NumberUtils.parseNumber(aByte, Byte.class).byteValue());
330 	}
331 
assertNegativeLongEquals(String aLong)332 	private void assertNegativeLongEquals(String aLong) {
333 		assertEquals("Long did not parse", Long.MIN_VALUE, NumberUtils.parseNumber(aLong, Long.class).longValue());
334 	}
335 
assertNegativeIntegerEquals(String anInteger)336 	private void assertNegativeIntegerEquals(String anInteger) {
337 		assertEquals("Integer did not parse", Integer.MIN_VALUE, NumberUtils.parseNumber(anInteger, Integer.class).intValue());
338 	}
339 
assertNegativeShortEquals(String aShort)340 	private void assertNegativeShortEquals(String aShort) {
341 		assertEquals("Short did not parse", Short.MIN_VALUE, NumberUtils.parseNumber(aShort, Short.class).shortValue());
342 	}
343 
assertNegativeByteEquals(String aByte)344 	private void assertNegativeByteEquals(String aByte) {
345 		assertEquals("Byte did not parse", Byte.MIN_VALUE, NumberUtils.parseNumber(aByte, Byte.class).byteValue());
346 	}
347 
348 }
349