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  }