1 /* 2 * Copyright 2001-2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 */ 23 24 /* 25 * @test 26 * @bug 4160406 4705734 4707389 4826774 4895911 27 * @summary Test for Double.parseDouble method and acceptance regex 28 */ 29 30 import java.util.regex.*; 31 32 public class ParseDouble { 33 34 private static void check(String val, double expected) { 35 double n = Double.parseDouble(val); 36 if (n != expected) 37 throw new RuntimeException("Double.parseDouble failed. String:" + 38 val + " Result:" + n); 39 } 40 41 private static void rudimentaryTest() { 42 check(new String(""+Double.MIN_VALUE), Double.MIN_VALUE); 43 check(new String(""+Double.MAX_VALUE), Double.MAX_VALUE); 44 45 check("10", (double) 10.0); 46 check("10.0", (double) 10.0); 47 check("10.01", (double) 10.01); 48 49 check("-10", (double) -10.0); 50 check("-10.00", (double) -10.0); 51 check("-10.01", (double) -10.01); 52 } 53 54 55 static String badStrings[] = { 56 "", 57 "+", 58 "-", 59 "+e", 60 "-e", 61 "+e170", 62 "-e170", 63 64 // Make sure intermediate white space is not deleted. 65 "1234 e10", 66 "-1234 e10", 67 68 // Control characters in the interior of a string are not legal 69 "1\u0007e1", 70 "1e\u00071", 71 72 // NaN and infinity can't have trailing type suffices or exponents 73 "NaNf", 74 "NaNF", 75 "NaNd", 76 "NaND", 77 "-NaNf", 78 "-NaNF", 79 "-NaNd", 80 "-NaND", 81 "+NaNf", 82 "+NaNF", 83 "+NaNd", 84 "+NaND", 85 "Infinityf", 86 "InfinityF", 87 "Infinityd", 88 "InfinityD", 89 "-Infinityf", 90 "-InfinityF", 91 "-Infinityd", 92 "-InfinityD", 93 "+Infinityf", 94 "+InfinityF", 95 "+Infinityd", 96 "+InfinityD", 97 98 "NaNe10", 99 "-NaNe10", 100 "+NaNe10", 101 "Infinitye10", 102 "-Infinitye10", 103 "+Infinitye10", 104 105 // Non-ASCII digits are not recognized 106 "\u0661e\u0661", // 1e1 in Arabic-Indic digits 107 "\u06F1e\u06F1", // 1e1 in Extended Arabic-Indic digits 108 "\u0967e\u0967", // 1e1 in Devanagari digits 109 110 // JCK test lex03592m3 111 ".", 112 113 // JCK test lex03592m4 114 "e42", 115 116 // JCK test lex03592m5 117 ".e42", 118 119 // JCK test lex03592m6 120 "d", 121 122 // JCK test lex03592m7 123 ".d", 124 125 // JCK test lex03592m8 126 "e42d", 127 128 // JCK test lex03592m9 129 ".e42d", 130 131 // JCK test lex03593m10 132 "1A01.01125e-10d", 133 134 // JCK test lex03593m11 135 "2;3.01125e-10d", 136 137 // JCK test lex03593m12 138 "1_34.01125e-10d", 139 140 // JCK test lex03593m14 141 "202..01125e-10d", 142 143 // JCK test lex03593m15 144 "202,01125e-10d", 145 146 // JCK test lex03593m16 147 "202.03b4e-10d", 148 149 // JCK test lex03593m18 150 "202.06_3e-10d", 151 152 // JCK test lex03593m20 153 "202.01125e-f0d", 154 155 // JCK test lex03593m21 156 "202.01125e_3d", 157 158 // JCK test lex03593m22 159 "202.01125e -5d", 160 161 // JCK test lex03593m24 162 "202.01125e-10r", 163 164 // JCK test lex03593m25 165 "202.01125e-10ff", 166 167 // JCK test lex03593m26 168 "1234L.01", 169 170 // JCK test lex03593m27 171 "12ee-2", 172 173 // JCK test lex03593m28 174 "12e-2.2.2", 175 176 // JCK test lex03593m29 177 "12.01e+", 178 179 // JCK test lex03593m30 180 "12.01E", 181 182 // Bad hexadecimal-style strings 183 184 // Two leading zeros 185 "00x1.0p1", 186 187 // Must have hex specifier 188 "1.0p1", 189 "00010p1", 190 "deadbeefp1", 191 192 // Need an explicit fully-formed exponent 193 "0x1.0p", 194 "0x1.0", 195 196 // Exponent must be in decimal 197 "0x1.0pa", 198 "0x1.0pf", 199 200 // Exponent separated by "p" 201 "0x1.0e22", 202 "0x1.0e22", 203 204 // Need a signifcand 205 "0xp22" 206 }; 207 208 static String goodStrings[] = { 209 "NaN", 210 "+NaN", 211 "-NaN", 212 "Infinity", 213 "+Infinity", 214 "-Infinity", 215 "1.1e-23f", 216 ".1e-23f", 217 "1e-23", 218 "1f", 219 "0", 220 "-0", 221 "+0", 222 "00", 223 "00", 224 "-00", 225 "+00", 226 "0000000000", 227 "-0000000000", 228 "+0000000000", 229 "1", 230 "2", 231 "1234", 232 "-1234", 233 "+1234", 234 "2147483647", // Integer.MAX_VALUE 235 "2147483648", 236 "-2147483648", // Integer.MIN_VALUE 237 "-2147483649", 238 239 "16777215", 240 "16777216", // 2^24 241 "16777217", 242 243 "-16777215", 244 "-16777216", // -2^24 245 "-16777217", 246 247 "9007199254740991", 248 "9007199254740992", // 2^53 249 "9007199254740993", 250 251 "-9007199254740991", 252 "-9007199254740992", // -2^53 253 "-9007199254740993", 254 255 "9223372036854775807", 256 "9223372036854775808", // Long.MAX_VALUE 257 "9223372036854775809", 258 259 "-9223372036854775808", 260 "-9223372036854775809", // Long.MIN_VALUE 261 "-9223372036854775810", 262 263 // Culled from JCK test lex03591m1 264 "54.07140d", 265 "7.01e-324d", 266 "2147483647.01d", 267 "1.2147483647f", 268 "000000000000000000000000001.F", 269 "1.00000000000000000000000000e-2F", 270 271 // Culled from JCK test lex03592m2 272 "2.", 273 ".0909", 274 "122112217090.0", 275 "7090e-5", 276 "2.E-20", 277 ".0909e42", 278 "122112217090.0E+100", 279 "7090f", 280 "2.F", 281 ".0909d", 282 "122112217090.0D", 283 "7090e-5f", 284 "2.E-20F", 285 ".0909e42d", 286 "122112217090.0E+100D", 287 288 // Culled from JCK test lex03594m31 -- unicode escapes 289 "\u0035\u0031\u0034\u0039\u0032\u0033\u0036\u0037\u0038\u0030.1102E-209D", 290 "1290873\u002E12301e100", 291 "1.1E-10\u0066", 292 293 // Culled from JCK test lex03595m1 294 "0.0E-10", 295 "1E10", 296 297 // Culled from JCK test lex03691m1 298 "0.f", 299 "1f", 300 "0.F", 301 "1F", 302 "0.12d", 303 "1e-0d", 304 "12.e+1D", 305 "0e-0D", 306 "12.e+01", 307 "1e-01", 308 309 // Good hex strings 310 // Vary capitalization of separators. 311 312 "0x1p1", 313 "0X1p1", 314 "0x1P1", 315 "0X1P1", 316 "0x1p1f", 317 "0X1p1f", 318 "0x1P1f", 319 "0X1P1f", 320 "0x1p1F", 321 "0X1p1F", 322 "0x1P1F", 323 "0X1P1F", 324 "0x1p1d", 325 "0X1p1d", 326 "0x1P1d", 327 "0X1P1d", 328 "0x1p1D", 329 "0X1p1D", 330 "0x1P1D", 331 "0X1P1D", 332 333 "-0x1p1", 334 "-0X1p1", 335 "-0x1P1", 336 "-0X1P1", 337 "-0x1p1f", 338 "-0X1p1f", 339 "-0x1P1f", 340 "-0X1P1f", 341 "-0x1p1F", 342 "-0X1p1F", 343 "-0x1P1F", 344 "-0X1P1F", 345 "-0x1p1d", 346 "-0X1p1d", 347 "-0x1P1d", 348 "-0X1P1d", 349 "-0x1p1D", 350 "-0X1p1D", 351 "-0x1P1D", 352 "-0X1P1D", 353 354 "0x1p-1", 355 "0X1p-1", 356 "0x1P-1", 357 "0X1P-1", 358 "0x1p-1f", 359 "0X1p-1f", 360 "0x1P-1f", 361 "0X1P-1f", 362 "0x1p-1F", 363 "0X1p-1F", 364 "0x1P-1F", 365 "0X1P-1F", 366 "0x1p-1d", 367 "0X1p-1d", 368 "0x1P-1d", 369 "0X1P-1d", 370 "0x1p-1D", 371 "0X1p-1D", 372 "0x1P-1D", 373 "0X1P-1D", 374 375 "-0x1p-1", 376 "-0X1p-1", 377 "-0x1P-1", 378 "-0X1P-1", 379 "-0x1p-1f", 380 "-0X1p-1f", 381 "-0x1P-1f", 382 "-0X1P-1f", 383 "-0x1p-1F", 384 "-0X1p-1F", 385 "-0x1P-1F", 386 "-0X1P-1F", 387 "-0x1p-1d", 388 "-0X1p-1d", 389 "-0x1P-1d", 390 "-0X1P-1d", 391 "-0x1p-1D", 392 "-0X1p-1D", 393 "-0x1P-1D", 394 "-0X1P-1D", 395 396 397 // Try different significand combinations 398 "0xap1", 399 "0xbp1", 400 "0xcp1", 401 "0xdp1", 402 "0xep1", 403 "0xfp1", 404 405 "0x1p1", 406 "0x.1p1", 407 "0x1.1p1", 408 409 "0x001p23", 410 "0x00.1p1", 411 "0x001.1p1", 412 413 "0x100p1", 414 "0x.100p1", 415 "0x1.100p1", 416 417 "0x00100p1", 418 "0x00.100p1", 419 "0x001.100p1" 420 }; 421 422 static String paddedBadStrings[]; 423 static String paddedGoodStrings[]; 424 static { 425 String pad = " \t\n\r\f\u0001\u000b\u001f"; 426 paddedBadStrings = new String[badStrings.length]; 427 for(int i = 0 ; i < badStrings.length; i++) 428 paddedBadStrings[i] = pad + badStrings[i] + pad; 429 430 paddedGoodStrings = new String[goodStrings.length]; 431 for(int i = 0 ; i < goodStrings.length; i++) 432 paddedGoodStrings[i] = pad + goodStrings[i] + pad; 433 434 } 435 436 437 /* 438 * Throws an exception if <code>Input</code> is 439 * <code>exceptionalInput</code> and {@link Double.parseDouble 440 * parseDouble} does <em>not</em> throw an exception or if 441 * <code>Input</code> is not <code>exceptionalInput</code> and 442 * <code>parseDouble</code> throws an exception. This method does 443 * not attempt to test whether the string is converted to the 444 * proper value; just whether the input is accepted appropriately 445 * or not. 446 */ 447 private static void testParsing(String [] input, 448 boolean exceptionalInput) { 449 for(int i = 0; i < input.length; i++) { 450 double d; 451 452 try { 453 d = Double.parseDouble(input[i]); 454 } 455 catch (NumberFormatException e) { 456 if (! exceptionalInput) { 457 throw new RuntimeException("Double.parseDouble rejected " + 458 "good string `" + input[i] + 459 "'."); 460 } 461 break; 462 } 463 if (exceptionalInput) { 464 throw new RuntimeException("Double.parseDouble accepted " + 465 "bad string `" + input[i] + 466 "'."); 467 } 468 } 469 } 470 471 /* 472 * Throws an exception if <code>Input</code> is 473 * <code>exceptionalInput</code> and the regular expression 474 * matches one of the strings or if <code>Input</code> is not 475 * <code>exceptionalInput</code> and the regular expression fails 476 * to match an input string. 477 */ 478 private static void testRegex(String [] input, boolean exceptionalInput) { 479 /* 480 * The regex below is taken from the JavaDoc for 481 * Double.valueOf. 482 */ 483 484 final String Digits = "(\\p{Digit}+)"; 485 final String HexDigits = "(\\p{XDigit}+)"; 486 // an exponent is 'e' or 'E' followed by an optionally 487 // signed decimal integer. 488 final String Exp = "[eE][+-]?"+Digits; 489 final String fpRegex = 490 ("[\\x00-\\x20]*"+ // Optional leading "whitespace" 491 "[+-]?(" + // Optional sign character 492 "NaN|" + // "NaN" string 493 "Infinity|" + // "Infinity" string 494 495 // A floating-point string representing a finite positive 496 // number without a leading sign has at most five basic pieces: 497 // Digits . Digits ExponentPart FloatTypeSuffix 498 // 499 // Since this method allows integer-only strings as input 500 // in addition to strings of floating-point literals, the 501 // two sub-patterns below are simplifications of the grammar 502 // productions from the Java Language Specification, 2nd 503 // edition, section 3.10.2. 504 505 506 // A decimal floating-point string representing a finite positive 507 // number without a leading sign has at most five basic pieces: 508 // Digits . Digits ExponentPart FloatTypeSuffix 509 // 510 // Since this method allows integer-only strings as input 511 // in addition to strings of floating-point literals, the 512 // two sub-patterns below are simplifications of the grammar 513 // productions from the Java Language Specification, 2nd 514 // edition, section 3.10.2. 515 516 // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt 517 "(((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ 518 519 // . Digits ExponentPart_opt FloatTypeSuffix_opt 520 "(\\.("+Digits+")("+Exp+")?))|"+ 521 522 // Hexadecimal strings 523 "((" + 524 // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt 525 "(0[xX]" + HexDigits + "(\\.)?)|" + 526 527 // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt 528 "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + 529 530 ")[pP][+-]?" + Digits + "))" + 531 "[fFdD]?))" + 532 "[\\x00-\\x20]*");// Optional trailing "whitespace" 533 Pattern fpPattern = Pattern.compile(fpRegex); 534 535 for(int i = 0; i < input.length; i++) { 536 Matcher m = fpPattern.matcher(input[i]); 537 if (m.matches() != ! exceptionalInput) { 538 throw new RuntimeException("Regular expression " + 539 (exceptionalInput? 540 "accepted bad": 541 "rejected good") + 542 " string `" + 543 input[i] + "'."); 544 } 545 } 546 547 } 548 549 public static void main(String[] args) throws Exception { 550 rudimentaryTest(); 551 552 testParsing(goodStrings, false); 553 testParsing(paddedGoodStrings, false); 554 testParsing(badStrings, true); 555 testParsing(paddedBadStrings, true); 556 557 testRegex(goodStrings, false); 558 testRegex(paddedGoodStrings, false); 559 testRegex(badStrings, true); 560 testRegex(paddedBadStrings, true); 561 } 562 }