gitee.com/quant1x/pkg@v0.2.8/fastjson/fastfloat/parse_test.go (about) 1 package fastfloat 2 3 import ( 4 "math" 5 "math/rand" 6 "strconv" 7 "testing" 8 ) 9 10 func TestParseUint64BestEffort(t *testing.T) { 11 f := func(s string, expectedNum uint64) { 12 t.Helper() 13 14 num := ParseUint64BestEffort(s) 15 if num != expectedNum { 16 t.Fatalf("unexpected number parsed from %q; got %v; want %v", s, num, expectedNum) 17 } 18 } 19 20 // Invalid first char 21 f("", 0) 22 f(" ", 0) 23 f("foo", 0) 24 f("-", 0) 25 f("-foo", 0) 26 f("-123", 0) 27 28 // Invalid suffix 29 f("1foo", 0) 30 f("13223 ", 0) 31 f("1-2", 0) 32 33 // Int 34 f("1", 1) 35 f("123", 123) 36 f("1234567890", 1234567890) 37 f("9223372036854775807", 9223372036854775807) 38 f("18446744073709551615", 18446744073709551615) 39 40 // Too big int 41 f("18446744073709551616", 0) 42 } 43 44 func TestParseUint64Failure(t *testing.T) { 45 f := func(s string) { 46 t.Helper() 47 48 num, err := ParseUint64(s) 49 if err == nil { 50 t.Fatalf("expecting non-nil error") 51 } 52 if num != 0 { 53 t.Fatalf("unexpected number returned from ParseUint64(%q); got %v; want %v", s, num, 0) 54 } 55 } 56 57 // Invalid first char 58 f("") 59 f(" ") 60 f("foo") 61 f("-") 62 f("-foo") 63 f("-123") 64 65 // Invalid suffix 66 f("1foo") 67 f("13223 ") 68 f("1-2") 69 70 // Too big int 71 f("18446744073709551616") 72 } 73 74 func TestParseUint64Success(t *testing.T) { 75 f := func(s string, expectedNum uint64) { 76 t.Helper() 77 78 num, err := ParseUint64(s) 79 if err != nil { 80 t.Fatalf("unexpected error in ParseUint64(%q): %s", s, err) 81 } 82 if num != expectedNum { 83 t.Fatalf("unexpected number parsed from %q; got %v; want %v", s, num, expectedNum) 84 } 85 } 86 87 f("0", 0) 88 f("1", 1) 89 f("123", 123) 90 f("1234567890", 1234567890) 91 f("9223372036854775807", 9223372036854775807) 92 f("18446744073709551615", 18446744073709551615) 93 } 94 95 func TestParseInt64BestEffort(t *testing.T) { 96 f := func(s string, expectedNum int64) { 97 t.Helper() 98 99 num := ParseInt64BestEffort(s) 100 if num != expectedNum { 101 t.Fatalf("unexpected number parsed from %q; got %v; want %v", s, num, expectedNum) 102 } 103 } 104 105 // Invalid first char 106 f("", 0) 107 f(" ", 0) 108 f("foo", 0) 109 f("-", 0) 110 f("-foo", 0) 111 112 // Invalid suffix 113 f("1foo", 0) 114 f("13223 ", 0) 115 f("1-2", 0) 116 117 // Int 118 f("0", 0) 119 f("-0", 0) 120 f("1", 1) 121 f("123", 123) 122 f("-123", -123) 123 f("1234567890", 1234567890) 124 f("9223372036854775807", 9223372036854775807) 125 f("-9223372036854775807", -9223372036854775807) 126 127 // Too big int 128 f("9223372036854775808", 0) 129 f("18446744073709551615", 0) 130 } 131 132 func TestParseInt64Failure(t *testing.T) { 133 f := func(s string) { 134 t.Helper() 135 136 num, err := ParseInt64(s) 137 if err == nil { 138 t.Fatalf("expecting non-nil error") 139 } 140 if num != 0 { 141 t.Fatalf("unexpected number returned from ParseInt64(%q); got %v; want %v", s, num, 0) 142 } 143 } 144 145 // Invalid first char 146 f("") 147 f(" ") 148 f("foo") 149 f("-") 150 f("-foo") 151 152 // Invalid suffix 153 f("1foo") 154 f("-13223 ") 155 f("1-2") 156 157 // Too big int 158 f("9223372036854775808") 159 f("18446744073709551615") 160 f("-18446744073709551615") 161 } 162 163 func TestParseInt64Success(t *testing.T) { 164 f := func(s string, expectedNum int64) { 165 t.Helper() 166 167 num, err := ParseInt64(s) 168 if err != nil { 169 t.Fatalf("unexpected error returned from ParseInt64(%q): %s", s, err) 170 } 171 if num != expectedNum { 172 t.Fatalf("unexpected number parsed from %q; got %v; want %v", s, num, expectedNum) 173 } 174 } 175 176 // Int 177 f("0", 0) 178 f("-0", 0) 179 f("1", 1) 180 f("123", 123) 181 f("-123", -123) 182 f("1234567890", 1234567890) 183 f("9223372036854775807", 9223372036854775807) 184 f("-9223372036854775807", -9223372036854775807) 185 } 186 187 func TestParseBestEffort(t *testing.T) { 188 f := func(s string, expectedNum float64) { 189 t.Helper() 190 191 num := ParseBestEffort(s) 192 if math.IsNaN(expectedNum) { 193 if !math.IsNaN(num) { 194 t.Fatalf("unexpected number parsed from %q; got %v; want %v", s, num, expectedNum) 195 } 196 } else if num != expectedNum { 197 t.Fatalf("unexpected number parsed from %q; got %v; want %v", s, num, expectedNum) 198 } 199 } 200 201 // Invalid first char 202 f("", 0) 203 f(" ", 0) 204 f("foo", 0) 205 f(" bar ", 0) 206 f("-", 0) 207 f("--", 0) 208 f("-.", 0) 209 f(".", 0) 210 f("-.e", 0) 211 f("+112", 0) 212 f("++", 0) 213 f("e123", 0) 214 f("E123", 0) 215 f("-e12", 0) 216 f(".", 0) 217 f("..34", 0) 218 f("-.e3", 0) 219 f(".e+3", 0) 220 221 // Invalid suffix 222 f("1foo", 0) 223 f("1 foo", 0) 224 f("12.34.56", 0) 225 f("13e34.56", 0) 226 f("12.34e56e4", 0) 227 f("123..45", 0) 228 f("123ee34", 0) 229 f("123e", 0) 230 f("123e+", 0) 231 f("123E-", 0) 232 f("123E+.", 0) 233 f("-123e-23foo", 0) 234 f("12345678901234567890foobar", 0) 235 f("0.12345678901234567890foobar", 0) 236 f("-0.12345678901234567890foobar", 0) 237 f("1e-400.5", 0) 238 239 // Integer 240 f("0", 0) 241 f("-0", 0) 242 f("0123", 123) 243 f("-00123", -123) 244 f("1", 1) 245 f("-1", -1) 246 f("1234567890123456", 1234567890123456) 247 f("12345678901234567", 12345678901234567) 248 f("123456789012345678", 123456789012345678) 249 f("1234567890123456789", 1234567890123456789) 250 f("12345678901234567890", 12345678901234567890) 251 f("-12345678901234567890", -12345678901234567890) 252 f("9223372036854775807", 9223372036854775807) 253 f("18446744073709551615", 18446744073709551615) 254 f("-18446744073709551615", -18446744073709551615) 255 256 // Fractional part 257 f("0.0", 0) 258 f("0.000", 0) 259 f("0.1", 0.1) 260 f("0.3", 0.3) 261 f("-0.1", -0.1) 262 f("-0.123", -0.123) 263 f("1.66", 1.66) 264 f("12.", 12) 265 f(".12", 0.12) 266 f("-.12", -0.12) 267 f("12345.12345678901", 12345.12345678901) 268 f("12345.123456789012", 12345.123456789012) 269 f("12345.1234567890123", 12345.1234567890123) 270 f("12345.12345678901234", 12345.12345678901234) 271 f("12345.123456789012345", 12345.123456789012345) 272 f("12345.1234567890123456", 12345.1234567890123456) 273 f("12345.12345678901234567", 12345.12345678901234567) 274 f("12345.123456789012345678", 12345.123456789012345678) 275 f("12345.1234567890123456789", 12345.1234567890123456789) 276 f("12345.12345678901234567890", 12345.12345678901234567890) 277 f("-12345.12345678901234567890", -12345.12345678901234567890) 278 f("18446744073709551615.18446744073709551615", 18446744073709551615.18446744073709551615) 279 f("-18446744073709551615.18446744073709551615", -18446744073709551615.18446744073709551615) 280 281 // Exponent part 282 f("0e0", 0) 283 f("123e+001", 123e1) 284 f("0e12", 0) 285 f("-0E123", 0) 286 f("-0E-123", 0) 287 f("-0E+123", 0) 288 f("123e12", 123e12) 289 f("-123E-12", -123e-12) 290 f("-123e-400", 0) 291 f("123e456", math.Inf(1)) // too big exponent 292 f("-123e456", math.Inf(-1)) // too big exponent 293 f("1e4", 1e4) 294 f("-1E-10", -1e-10) 295 296 // Fractional + exponent part 297 f("0.123e4", 0.123e4) 298 f("-123.456E-10", -123.456e-10) 299 f("1.e4", 1.e4) 300 f("-1.E-10", -1.e-10) 301 302 // inf and nan 303 f("12345678909123456789012e45678", math.Inf(1)) 304 f("-12345678909123456789012e45678", math.Inf(-1)) 305 f("0.12345678909123456789012e45678", math.Inf(1)) 306 f("-0.12345678909123456789012e45678", math.Inf(-1)) 307 f("1.1e2345678909123456789012", math.Inf(1)) 308 f("-1.1e2345678909123456789012", math.Inf(-1)) 309 f("inf", math.Inf(1)) 310 f("-Inf", math.Inf(-1)) 311 f("+iNf", math.Inf(1)) 312 f("INF", math.Inf(1)) 313 f("infinity", math.Inf(1)) 314 f("-Infinity", math.Inf(-1)) 315 f("+iNfINIty", math.Inf(1)) 316 f("INFINITY", math.Inf(1)) 317 f("nan", math.NaN()) 318 f("-nan", math.NaN()) 319 f("naN", math.NaN()) 320 f("NaN", math.NaN()) 321 } 322 323 func TestParseFailure(t *testing.T) { 324 f := func(s string) { 325 t.Helper() 326 327 num, err := Parse(s) 328 if err == nil { 329 t.Fatalf("expecting non-nil error") 330 } 331 if num != 0 { 332 t.Fatalf("unexpected number returned from ParseInt64(%q); got %v; want %v", s, num, 0) 333 } 334 } 335 336 // Invalid first char 337 f("") 338 f(" ") 339 f("foo") 340 f(" bar ") 341 f("-") 342 f("--") 343 f(".") 344 f("-.") 345 f("-.e") 346 f("+112") 347 f("++") 348 f("e123") 349 f("E123") 350 f("-e12") 351 f(".") 352 f("..34") 353 f("-.e3") 354 f(".e+3") 355 356 // Invalid suffix 357 f("1foo") 358 f("1 foo") 359 f("12.34.56") 360 f("13e34.56") 361 f("12.34e56e4") 362 f("123..45") 363 f("123ee34") 364 f("123e") 365 f("123e+") 366 f("123E-") 367 f("123E+.") 368 f("-123e-23foo") 369 f("12345678901234567890foobar") 370 f("0.12345678901234567890foobar") 371 f("-0.12345678901234567890foobar") 372 f("1e-400.5") 373 } 374 375 func TestParseSuccess(t *testing.T) { 376 f := func(s string, expectedNum float64) { 377 t.Helper() 378 379 num, err := Parse(s) 380 if err != nil { 381 t.Fatalf("unexpected error in Parse(%q): %s", s, err) 382 } 383 if math.IsNaN(expectedNum) { 384 if !math.IsNaN(num) { 385 t.Fatalf("unexpected number parsed from %q; got %v; want %v", s, num, expectedNum) 386 } 387 } else if num != expectedNum { 388 t.Fatalf("unexpected number parsed from %q; got %v; want %v", s, num, expectedNum) 389 } 390 } 391 392 // Integer 393 f("0", 0) 394 f("-0", 0) 395 f("0123", 123) 396 f("-00123", -123) 397 f("1", 1) 398 f("-1", -1) 399 f("1234567890123456", 1234567890123456) 400 f("12345678901234567", 12345678901234567) 401 f("123456789012345678", 123456789012345678) 402 f("1234567890123456789", 1234567890123456789) 403 f("12345678901234567890", 12345678901234567890) 404 f("-12345678901234567890", -12345678901234567890) 405 f("9223372036854775807", 9223372036854775807) 406 f("18446744073709551615", 18446744073709551615) 407 f("-18446744073709551615", -18446744073709551615) 408 409 // Fractional part 410 f("0.0", 0) 411 f("0.000", 0) 412 f("0.1", 0.1) 413 f("0.3", 0.3) 414 f("-0.1", -0.1) 415 f("-0.123", -0.123) 416 f("1.66", 1.66) 417 f("12.", 12) 418 f(".12", 0.12) 419 f("-.12", -0.12) 420 f("12345.12345678901", 12345.12345678901) 421 f("12345.123456789012", 12345.123456789012) 422 f("12345.1234567890123", 12345.1234567890123) 423 f("12345.12345678901234", 12345.12345678901234) 424 f("12345.123456789012345", 12345.123456789012345) 425 f("12345.1234567890123456", 12345.1234567890123456) 426 f("12345.12345678901234567", 12345.12345678901234567) 427 f("12345.123456789012345678", 12345.123456789012345678) 428 f("12345.1234567890123456789", 12345.1234567890123456789) 429 f("12345.12345678901234567890", 12345.12345678901234567890) 430 f("-12345.12345678901234567890", -12345.12345678901234567890) 431 f("18446744073709551615.18446744073709551615", 18446744073709551615.18446744073709551615) 432 f("-18446744073709551615.18446744073709551615", -18446744073709551615.18446744073709551615) 433 434 // Exponent part 435 f("0e0", 0) 436 f("123e+001", 123e1) 437 f("0e12", 0) 438 f("-0E123", 0) 439 f("-0E-123", 0) 440 f("-0E+123", 0) 441 f("123e12", 123e12) 442 f("-123E-12", -123e-12) 443 f("-123e-400", 0) 444 f("123e456", math.Inf(1)) // too big exponent 445 f("-123e456", math.Inf(-1)) // too big exponent 446 f("1e4", 1e4) 447 f("-1E-10", -1e-10) 448 449 // Fractional + exponent part 450 f("0.123e4", 0.123e4) 451 f("-123.456E-10", -123.456e-10) 452 f("1.e4", 1.e4) 453 f("-1.E-10", -1.e-10) 454 f(".1e3", 100) 455 f("-.12e3", -120) 456 457 // inf and nan 458 f("12345678909123456789012e45678", math.Inf(1)) 459 f("-12345678909123456789012e45678", math.Inf(-1)) 460 f("0.12345678909123456789012e45678", math.Inf(1)) 461 f("-0.12345678909123456789012e45678", math.Inf(-1)) 462 f("inf", math.Inf(1)) 463 f("-Inf", math.Inf(-1)) 464 f("+iNf", math.Inf(1)) 465 f("INF", math.Inf(1)) 466 f("infinity", math.Inf(1)) 467 f("-Infinity", math.Inf(-1)) 468 f("+iNfINIty", math.Inf(1)) 469 f("INFINITY", math.Inf(1)) 470 f("nan", math.NaN()) 471 f("-nan", math.NaN()) 472 f("naN", math.NaN()) 473 f("NaN", math.NaN()) 474 } 475 476 func TestParseBestEffortFuzz(t *testing.T) { 477 r := rand.New(rand.NewSource(0)) 478 for i := 0; i < 100000; i++ { 479 f := r.Float64() 480 s := strconv.FormatFloat(f, 'g', -1, 64) 481 numExpected, err := strconv.ParseFloat(s, 64) 482 if err != nil { 483 t.Fatalf("unexpected error when parsing %q: %s", s, err) 484 } 485 num := ParseBestEffort(s) 486 if num != numExpected { 487 t.Fatalf("unexpected number parsed from %q; got %g; want %g", s, num, numExpected) 488 } 489 } 490 } 491 492 func TestParseFuzz(t *testing.T) { 493 r := rand.New(rand.NewSource(0)) 494 for i := 0; i < 100000; i++ { 495 f := r.Float64() 496 s := strconv.FormatFloat(f, 'g', -1, 64) 497 numExpected, err := strconv.ParseFloat(s, 64) 498 if err != nil { 499 t.Fatalf("unexpected error when parsing %q: %s", s, err) 500 } 501 num, err := Parse(s) 502 if err != nil { 503 t.Fatalf("unexpected error in Parse(%q): %s", s, err) 504 } 505 if num != numExpected { 506 t.Fatalf("unexpected number parsed from %q; got %g; want %g", s, num, numExpected) 507 } 508 } 509 }