...

Source file src/google.golang.org/protobuf/internal/encoding/json/decode_test.go

Documentation: google.golang.org/protobuf/internal/encoding/json

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package json_test
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  	"strings"
    11  	"testing"
    12  	"unicode/utf8"
    13  
    14  	"github.com/google/go-cmp/cmp"
    15  
    16  	"google.golang.org/protobuf/internal/encoding/json"
    17  )
    18  
    19  type R struct {
    20  	// E is expected error substring from calling Decoder.Read if set.
    21  	E string
    22  	// V is one of the checker implementations that validates the token value.
    23  	V checker
    24  	// P is expected Token.Pos() if set > 0.
    25  	P int
    26  	// RS is expected result from Token.RawString() if not empty.
    27  	RS string
    28  }
    29  
    30  // checker defines API for Token validation.
    31  type checker interface {
    32  	// check checks and expects for token API call to return and compare
    33  	// against implementation-stored value. Returns empty string if success,
    34  	// else returns error message describing the error.
    35  	check(json.Token) string
    36  }
    37  
    38  // checkers that checks the token kind only.
    39  var (
    40  	EOF         = kindOnly{json.EOF}
    41  	Null        = kindOnly{json.Null}
    42  	ObjectOpen  = kindOnly{json.ObjectOpen}
    43  	ObjectClose = kindOnly{json.ObjectClose}
    44  	ArrayOpen   = kindOnly{json.ArrayOpen}
    45  	ArrayClose  = kindOnly{json.ArrayClose}
    46  )
    47  
    48  type kindOnly struct {
    49  	want json.Kind
    50  }
    51  
    52  func (x kindOnly) check(tok json.Token) string {
    53  	if got := tok.Kind(); got != x.want {
    54  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, x.want)
    55  	}
    56  	return ""
    57  }
    58  
    59  type Name struct {
    60  	val string
    61  }
    62  
    63  func (x Name) check(tok json.Token) string {
    64  	if got := tok.Kind(); got != json.Name {
    65  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Name)
    66  	}
    67  
    68  	if got := tok.Name(); got != x.val {
    69  		return fmt.Sprintf("Token.Name(): got %v, want %v", got, x.val)
    70  	}
    71  	return ""
    72  }
    73  
    74  type Bool struct {
    75  	val bool
    76  }
    77  
    78  func (x Bool) check(tok json.Token) string {
    79  	if got := tok.Kind(); got != json.Bool {
    80  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Bool)
    81  	}
    82  
    83  	if got := tok.Bool(); got != x.val {
    84  		return fmt.Sprintf("Token.Bool(): got %v, want %v", got, x.val)
    85  	}
    86  	return ""
    87  }
    88  
    89  type Str struct {
    90  	val string
    91  }
    92  
    93  func (x Str) check(tok json.Token) string {
    94  	if got := tok.Kind(); got != json.String {
    95  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.String)
    96  	}
    97  
    98  	if got := tok.ParsedString(); got != x.val {
    99  		return fmt.Sprintf("Token.ParsedString(): got %v, want %v", got, x.val)
   100  	}
   101  	return ""
   102  }
   103  
   104  type F64 struct {
   105  	val float64
   106  }
   107  
   108  func (x F64) check(tok json.Token) string {
   109  	if got := tok.Kind(); got != json.Number {
   110  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   111  	}
   112  
   113  	got, ok := tok.Float(64)
   114  	if !ok {
   115  		return fmt.Sprintf("Token.Float(64): returned not ok")
   116  	}
   117  	if got != x.val {
   118  		return fmt.Sprintf("Token.Float(64): got %v, want %v", got, x.val)
   119  	}
   120  	return ""
   121  }
   122  
   123  type F32 struct {
   124  	val float32
   125  }
   126  
   127  func (x F32) check(tok json.Token) string {
   128  	if got := tok.Kind(); got != json.Number {
   129  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   130  	}
   131  
   132  	got, ok := tok.Float(32)
   133  	if !ok {
   134  		return fmt.Sprintf("Token.Float(32): returned not ok")
   135  	}
   136  	if float32(got) != x.val {
   137  		return fmt.Sprintf("Token.Float(32): got %v, want %v", got, x.val)
   138  	}
   139  	return ""
   140  }
   141  
   142  // NotF64 is a checker to validate a Number token where Token.Float(64) returns not ok.
   143  var NotF64 = xf64{}
   144  
   145  type xf64 struct{}
   146  
   147  func (x xf64) check(tok json.Token) string {
   148  	if got := tok.Kind(); got != json.Number {
   149  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   150  	}
   151  
   152  	_, ok := tok.Float(64)
   153  	if ok {
   154  		return fmt.Sprintf("Token.Float(64): returned ok")
   155  	}
   156  	return ""
   157  }
   158  
   159  // NotF32 is a checker to validate a Number token where Token.Float(32) returns not ok.
   160  var NotF32 = xf32{}
   161  
   162  type xf32 struct{}
   163  
   164  func (x xf32) check(tok json.Token) string {
   165  	if got := tok.Kind(); got != json.Number {
   166  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   167  	}
   168  
   169  	_, ok := tok.Float(32)
   170  	if ok {
   171  		return fmt.Sprintf("Token.Float(32): returned ok")
   172  	}
   173  	return ""
   174  }
   175  
   176  type I64 struct {
   177  	val int64
   178  }
   179  
   180  func (x I64) check(tok json.Token) string {
   181  	if got := tok.Kind(); got != json.Number {
   182  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   183  	}
   184  
   185  	got, ok := tok.Int(64)
   186  	if !ok {
   187  		return fmt.Sprintf("Token.Int(64): returned not ok")
   188  	}
   189  	if got != x.val {
   190  		return fmt.Sprintf("Token.Int(64): got %v, want %v", got, x.val)
   191  	}
   192  	return ""
   193  }
   194  
   195  type I32 struct {
   196  	val int32
   197  }
   198  
   199  func (x I32) check(tok json.Token) string {
   200  	if got := tok.Kind(); got != json.Number {
   201  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   202  	}
   203  
   204  	got, ok := tok.Int(32)
   205  	if !ok {
   206  		return fmt.Sprintf("Token.Int(32): returned not ok")
   207  	}
   208  	if int32(got) != x.val {
   209  		return fmt.Sprintf("Token.Int(32): got %v, want %v", got, x.val)
   210  	}
   211  	return ""
   212  }
   213  
   214  // NotI64 is a checker to validate a Number token where Token.Int(64) returns not ok.
   215  var NotI64 = xi64{}
   216  
   217  type xi64 struct{}
   218  
   219  func (x xi64) check(tok json.Token) string {
   220  	if got := tok.Kind(); got != json.Number {
   221  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   222  	}
   223  
   224  	_, ok := tok.Int(64)
   225  	if ok {
   226  		return fmt.Sprintf("Token.Int(64): returned ok")
   227  	}
   228  	return ""
   229  }
   230  
   231  // NotI32 is a checker to validate a Number token where Token.Int(32) returns not ok.
   232  var NotI32 = xi32{}
   233  
   234  type xi32 struct{}
   235  
   236  func (x xi32) check(tok json.Token) string {
   237  	if got := tok.Kind(); got != json.Number {
   238  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   239  	}
   240  
   241  	_, ok := tok.Int(32)
   242  	if ok {
   243  		return fmt.Sprintf("Token.Int(32): returned ok")
   244  	}
   245  	return ""
   246  }
   247  
   248  type Ui64 struct {
   249  	val uint64
   250  }
   251  
   252  func (x Ui64) check(tok json.Token) string {
   253  	if got := tok.Kind(); got != json.Number {
   254  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   255  	}
   256  
   257  	got, ok := tok.Uint(64)
   258  	if !ok {
   259  		return fmt.Sprintf("Token.Uint(64): returned not ok")
   260  	}
   261  	if got != x.val {
   262  		return fmt.Sprintf("Token.Uint(64): got %v, want %v", got, x.val)
   263  	}
   264  	return ""
   265  }
   266  
   267  type Ui32 struct {
   268  	val uint32
   269  }
   270  
   271  func (x Ui32) check(tok json.Token) string {
   272  	if got := tok.Kind(); got != json.Number {
   273  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   274  	}
   275  
   276  	got, ok := tok.Uint(32)
   277  	if !ok {
   278  		return fmt.Sprintf("Token.Uint(32): returned not ok")
   279  	}
   280  	if uint32(got) != x.val {
   281  		return fmt.Sprintf("Token.Uint(32): got %v, want %v", got, x.val)
   282  	}
   283  	return ""
   284  }
   285  
   286  // NotUi64 is a checker to validate a Number token where Token.Uint(64) returns not ok.
   287  var NotUi64 = xui64{}
   288  
   289  type xui64 struct{}
   290  
   291  func (x xui64) check(tok json.Token) string {
   292  	if got := tok.Kind(); got != json.Number {
   293  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   294  	}
   295  
   296  	_, ok := tok.Uint(64)
   297  	if ok {
   298  		return fmt.Sprintf("Token.Uint(64): returned ok")
   299  	}
   300  	return ""
   301  }
   302  
   303  // NotI32 is a checker to validate a Number token where Token.Uint(32) returns not ok.
   304  var NotUi32 = xui32{}
   305  
   306  type xui32 struct{}
   307  
   308  func (x xui32) check(tok json.Token) string {
   309  	if got := tok.Kind(); got != json.Number {
   310  		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
   311  	}
   312  
   313  	_, ok := tok.Uint(32)
   314  	if ok {
   315  		return fmt.Sprintf("Token.Uint(32): returned ok")
   316  	}
   317  	return ""
   318  }
   319  
   320  var errEOF = json.ErrUnexpectedEOF.Error()
   321  
   322  func TestDecoder(t *testing.T) {
   323  	const space = " \n\r\t"
   324  
   325  	tests := []struct {
   326  		in string
   327  		// want is a list of expected values returned from calling
   328  		// Decoder.Read. An item makes the test code invoke
   329  		// Decoder.Read and compare against R.E for error returned or use R.V to
   330  		// validate the returned Token object.
   331  		want []R
   332  	}{
   333  		{
   334  			in:   ``,
   335  			want: []R{{V: EOF}},
   336  		},
   337  		{
   338  			in:   space,
   339  			want: []R{{V: EOF}},
   340  		},
   341  		{
   342  			// Calling Read after EOF will keep returning EOF for
   343  			// succeeding Read calls.
   344  			in: space,
   345  			want: []R{
   346  				{V: EOF},
   347  				{V: EOF},
   348  				{V: EOF},
   349  			},
   350  		},
   351  
   352  		// JSON literals.
   353  		{
   354  			in: space + `null` + space,
   355  			want: []R{
   356  				{V: Null, P: len(space), RS: `null`},
   357  				{V: EOF},
   358  			},
   359  		},
   360  		{
   361  			in: space + `true` + space,
   362  			want: []R{
   363  				{V: Bool{true}},
   364  				{V: EOF},
   365  			},
   366  		},
   367  		{
   368  			in: space + `false` + space,
   369  			want: []R{
   370  				{V: Bool{false}},
   371  				{V: EOF},
   372  			},
   373  		},
   374  		{
   375  			// Error returned will produce the same error again.
   376  			in: space + `foo` + space,
   377  			want: []R{
   378  				{E: `invalid value foo`},
   379  				{E: `invalid value foo`},
   380  			},
   381  		},
   382  
   383  		// JSON strings.
   384  		{
   385  			in: space + `""` + space,
   386  			want: []R{
   387  				{V: Str{}},
   388  				{V: EOF},
   389  			},
   390  		},
   391  		{
   392  			in: space + `"hello"` + space,
   393  			want: []R{
   394  				{V: Str{"hello"}, RS: `"hello"`},
   395  				{V: EOF},
   396  			},
   397  		},
   398  		{
   399  			in:   `"hello`,
   400  			want: []R{{E: errEOF}},
   401  		},
   402  		{
   403  			in:   "\"\x00\"",
   404  			want: []R{{E: `invalid character '\x00' in string`}},
   405  		},
   406  		{
   407  			in: "\"\u0031\u0032\"",
   408  			want: []R{
   409  				{V: Str{"12"}, RS: "\"\u0031\u0032\""},
   410  				{V: EOF},
   411  			},
   412  		},
   413  		{
   414  			// Invalid UTF-8 error is returned in ReadString instead of Read.
   415  			in:   "\"\xff\"",
   416  			want: []R{{E: `syntax error (line 1:1): invalid UTF-8 in string`}},
   417  		},
   418  		{
   419  			in: `"` + string(utf8.RuneError) + `"`,
   420  			want: []R{
   421  				{V: Str{string(utf8.RuneError)}},
   422  				{V: EOF},
   423  			},
   424  		},
   425  		{
   426  			in: `"\uFFFD"`,
   427  			want: []R{
   428  				{V: Str{string(utf8.RuneError)}},
   429  				{V: EOF},
   430  			},
   431  		},
   432  		{
   433  			in:   `"\x"`,
   434  			want: []R{{E: `invalid escape code "\\x" in string`}},
   435  		},
   436  		{
   437  			in:   `"\uXXXX"`,
   438  			want: []R{{E: `invalid escape code "\\uXXXX" in string`}},
   439  		},
   440  		{
   441  			in:   `"\uDEAD"`, // unmatched surrogate pair
   442  			want: []R{{E: errEOF}},
   443  		},
   444  		{
   445  			in:   `"\uDEAD\uBEEF"`, // invalid surrogate half
   446  			want: []R{{E: `invalid escape code "\\uBEEF" in string`}},
   447  		},
   448  		{
   449  			in: `"\uD800\udead"`, // valid surrogate pair
   450  			want: []R{
   451  				{V: Str{`𐊭`}},
   452  				{V: EOF},
   453  			},
   454  		},
   455  		{
   456  			in: `"\u0000\"\\\/\b\f\n\r\t"`,
   457  			want: []R{
   458  				{V: Str{"\u0000\"\\/\b\f\n\r\t"}},
   459  				{V: EOF},
   460  			},
   461  		},
   462  
   463  		// Invalid JSON numbers.
   464  		{
   465  			in:   `-`,
   466  			want: []R{{E: `invalid value -`}},
   467  		},
   468  		{
   469  			in:   `+0`,
   470  			want: []R{{E: `invalid value +0`}},
   471  		},
   472  		{
   473  			in:   `-+`,
   474  			want: []R{{E: `invalid value -+`}},
   475  		},
   476  		{
   477  			in:   `0.`,
   478  			want: []R{{E: `invalid value 0.`}},
   479  		},
   480  		{
   481  			in:   `.1`,
   482  			want: []R{{E: `invalid value .1`}},
   483  		},
   484  		{
   485  			in:   `1.0.1`,
   486  			want: []R{{E: `invalid value 1.0.1`}},
   487  		},
   488  		{
   489  			in:   `1..1`,
   490  			want: []R{{E: `invalid value 1..1`}},
   491  		},
   492  		{
   493  			in:   `-1-2`,
   494  			want: []R{{E: `invalid value -1-2`}},
   495  		},
   496  		{
   497  			in:   `01`,
   498  			want: []R{{E: `invalid value 01`}},
   499  		},
   500  		{
   501  			in:   `1e`,
   502  			want: []R{{E: `invalid value 1e`}},
   503  		},
   504  		{
   505  			in:   `1e1.2`,
   506  			want: []R{{E: `invalid value 1e1.2`}},
   507  		},
   508  		{
   509  			in:   `1Ee`,
   510  			want: []R{{E: `invalid value 1Ee`}},
   511  		},
   512  		{
   513  			in:   `1.e1`,
   514  			want: []R{{E: `invalid value 1.e1`}},
   515  		},
   516  		{
   517  			in:   `1.e+`,
   518  			want: []R{{E: `invalid value 1.e+`}},
   519  		},
   520  		{
   521  			in:   `1e+-2`,
   522  			want: []R{{E: `invalid value 1e+-2`}},
   523  		},
   524  		{
   525  			in:   `1e--2`,
   526  			want: []R{{E: `invalid value 1e--2`}},
   527  		},
   528  		{
   529  			in:   `1.0true`,
   530  			want: []R{{E: `invalid value 1.0true`}},
   531  		},
   532  
   533  		// JSON numbers as floating point.
   534  		{
   535  			in: space + `0.0` + space,
   536  			want: []R{
   537  				{V: F32{0}, P: len(space), RS: `0.0`},
   538  				{V: EOF},
   539  			},
   540  		},
   541  		{
   542  			in: space + `0` + space,
   543  			want: []R{
   544  				{V: F32{0}},
   545  				{V: EOF},
   546  			},
   547  		},
   548  		{
   549  			in: space + `-0` + space,
   550  			want: []R{
   551  				{V: F32{float32(math.Copysign(0, -1))}},
   552  				{V: EOF},
   553  			},
   554  		},
   555  		{
   556  			in: `-0`,
   557  			want: []R{
   558  				{V: F64{math.Copysign(0, -1)}},
   559  				{V: EOF},
   560  			},
   561  		},
   562  		{
   563  			in: `-0.0`,
   564  			want: []R{
   565  				{V: F32{float32(math.Copysign(0, -1))}},
   566  				{V: EOF},
   567  			},
   568  		},
   569  		{
   570  			in: `-0.0`,
   571  			want: []R{
   572  				{V: F64{math.Copysign(0, -1)}},
   573  				{V: EOF},
   574  			},
   575  		},
   576  		{
   577  			in: `-1.02`,
   578  			want: []R{
   579  				{V: F32{-1.02}},
   580  				{V: EOF},
   581  			},
   582  		},
   583  		{
   584  			in: `1.020000`,
   585  			want: []R{
   586  				{V: F32{1.02}},
   587  				{V: EOF},
   588  			},
   589  		},
   590  		{
   591  			in: `-1.0e0`,
   592  			want: []R{
   593  				{V: F32{-1}},
   594  				{V: EOF},
   595  			},
   596  		},
   597  		{
   598  			in: `1.0e-000`,
   599  			want: []R{
   600  				{V: F32{1}},
   601  				{V: EOF},
   602  			},
   603  		},
   604  		{
   605  			in: `1e+00`,
   606  			want: []R{
   607  				{V: F32{1}},
   608  				{V: EOF},
   609  			},
   610  		},
   611  		{
   612  			in: `1.02e3`,
   613  			want: []R{
   614  				{V: F32{1.02e3}},
   615  				{V: EOF},
   616  			},
   617  		},
   618  		{
   619  			in: `-1.02E03`,
   620  			want: []R{
   621  				{V: F32{-1.02e3}},
   622  				{V: EOF},
   623  			},
   624  		},
   625  		{
   626  			in: `1.0200e+3`,
   627  			want: []R{
   628  				{V: F32{1.02e3}},
   629  				{V: EOF},
   630  			},
   631  		},
   632  		{
   633  			in: `-1.0200E+03`,
   634  			want: []R{
   635  				{V: F32{-1.02e3}},
   636  				{V: EOF},
   637  			},
   638  		},
   639  		{
   640  			in: `1.0200e-3`,
   641  			want: []R{
   642  				{V: F32{1.02e-3}},
   643  				{V: EOF},
   644  			},
   645  		},
   646  		{
   647  			in: `-1.0200E-03`,
   648  			want: []R{
   649  				{V: F32{-1.02e-3}},
   650  				{V: EOF},
   651  			},
   652  		},
   653  		{
   654  			// Exceeds max float32 limit, but should be ok for float64.
   655  			in: `3.4e39`,
   656  			want: []R{
   657  				{V: F64{3.4e39}},
   658  				{V: EOF},
   659  			},
   660  		},
   661  
   662  		{
   663  			// Exceeds max float32 limit.
   664  			in: `3.4e39`,
   665  			want: []R{
   666  				{V: NotF32},
   667  				{V: EOF},
   668  			},
   669  		},
   670  		{
   671  			// Less than negative max float32 limit.
   672  			in: `-3.4e39`,
   673  			want: []R{
   674  				{V: NotF32},
   675  				{V: EOF},
   676  			},
   677  		},
   678  		{
   679  			// Exceeds max float64 limit.
   680  			in: `1.79e+309`,
   681  			want: []R{
   682  				{V: NotF64},
   683  				{V: EOF},
   684  			},
   685  		},
   686  		{
   687  			// Less than negative max float64 limit.
   688  			in: `-1.79e+309`,
   689  			want: []R{
   690  				{V: NotF64},
   691  				{V: EOF},
   692  			},
   693  		},
   694  
   695  		// JSON numbers as signed integers.
   696  		{
   697  			in: space + `0` + space,
   698  			want: []R{
   699  				{V: I32{0}},
   700  				{V: EOF},
   701  			},
   702  		},
   703  		{
   704  			in: space + `-0` + space,
   705  			want: []R{
   706  				{V: I32{0}},
   707  				{V: EOF},
   708  			},
   709  		},
   710  		{
   711  			// Fractional part equals 0 is ok.
   712  			in: `1.00000`,
   713  			want: []R{
   714  				{V: I32{1}},
   715  				{V: EOF},
   716  			},
   717  		},
   718  		{
   719  			// Fractional part not equals 0 returns error.
   720  			in: `1.0000000001`,
   721  			want: []R{
   722  				{V: NotI32},
   723  				{V: EOF},
   724  			},
   725  		},
   726  		{
   727  			in: `0e0`,
   728  			want: []R{
   729  				{V: I32{0}},
   730  				{V: EOF},
   731  			},
   732  		},
   733  		{
   734  			in: `0.0E0`,
   735  			want: []R{
   736  				{V: I32{0}},
   737  				{V: EOF},
   738  			},
   739  		},
   740  		{
   741  			in: `0.0E10`,
   742  			want: []R{
   743  				{V: I32{0}},
   744  				{V: EOF},
   745  			},
   746  		},
   747  		{
   748  			in: `-1`,
   749  			want: []R{
   750  				{V: I32{-1}},
   751  				{V: EOF},
   752  			},
   753  		},
   754  		{
   755  			in: `1.0e+0`,
   756  			want: []R{
   757  				{V: I32{1}},
   758  				{V: EOF},
   759  			},
   760  		},
   761  		{
   762  			in: `-1E-0`,
   763  			want: []R{
   764  				{V: I32{-1}},
   765  				{V: EOF},
   766  			},
   767  		},
   768  		{
   769  			in: `1E1`,
   770  			want: []R{
   771  				{V: I32{10}},
   772  				{V: EOF},
   773  			},
   774  		},
   775  		{
   776  			in: `-100.00e-02`,
   777  			want: []R{
   778  				{V: I32{-1}},
   779  				{V: EOF},
   780  			},
   781  		},
   782  		{
   783  			in: `0.1200E+02`,
   784  			want: []R{
   785  				{V: I64{12}},
   786  				{V: EOF},
   787  			},
   788  		},
   789  		{
   790  			in: `0.012e2`,
   791  			want: []R{
   792  				{V: NotI32},
   793  				{V: EOF},
   794  			},
   795  		},
   796  		{
   797  			in: `12e-2`,
   798  			want: []R{
   799  				{V: NotI32},
   800  				{V: EOF},
   801  			},
   802  		},
   803  		{
   804  			// Exceeds math.MaxInt32.
   805  			in: `2147483648`,
   806  			want: []R{
   807  				{V: NotI32},
   808  				{V: EOF},
   809  			},
   810  		},
   811  		{
   812  			// Exceeds math.MinInt32.
   813  			in: `-2147483649`,
   814  			want: []R{
   815  				{V: NotI32},
   816  				{V: EOF},
   817  			},
   818  		},
   819  		{
   820  			// Exceeds math.MaxInt32, but ok for int64.
   821  			in: `2147483648`,
   822  			want: []R{
   823  				{V: I64{2147483648}},
   824  				{V: EOF},
   825  			},
   826  		},
   827  		{
   828  			// Exceeds math.MinInt32, but ok for int64.
   829  			in: `-2147483649`,
   830  			want: []R{
   831  				{V: I64{-2147483649}},
   832  				{V: EOF},
   833  			},
   834  		},
   835  		{
   836  			// Exceeds math.MaxInt64.
   837  			in: `9223372036854775808`,
   838  			want: []R{
   839  				{V: NotI64},
   840  				{V: EOF},
   841  			},
   842  		},
   843  		{
   844  			// Exceeds math.MinInt64.
   845  			in: `-9223372036854775809`,
   846  			want: []R{
   847  				{V: NotI64},
   848  				{V: EOF},
   849  			},
   850  		},
   851  
   852  		// JSON numbers as unsigned integers.
   853  		{
   854  			in: space + `0` + space,
   855  			want: []R{
   856  				{V: Ui32{0}},
   857  				{V: EOF},
   858  			},
   859  		},
   860  		{
   861  			in: space + `-0` + space,
   862  			want: []R{
   863  				{V: Ui32{0}},
   864  				{V: EOF},
   865  			},
   866  		},
   867  		{
   868  			in: `-1`,
   869  			want: []R{
   870  				{V: NotUi32},
   871  				{V: EOF},
   872  			},
   873  		},
   874  		{
   875  			// Exceeds math.MaxUint32.
   876  			in: `4294967296`,
   877  			want: []R{
   878  				{V: NotUi32},
   879  				{V: EOF},
   880  			},
   881  		},
   882  		{
   883  			// Exceeds math.MaxUint64.
   884  			in: `18446744073709551616`,
   885  			want: []R{
   886  				{V: NotUi64},
   887  				{V: EOF},
   888  			},
   889  		},
   890  
   891  		// JSON sequence of values.
   892  		{
   893  			in: `true null`,
   894  			want: []R{
   895  				{V: Bool{true}},
   896  				{E: `(line 1:6): unexpected token null`},
   897  			},
   898  		},
   899  		{
   900  			in: "null false",
   901  			want: []R{
   902  				{V: Null},
   903  				{E: `unexpected token false`},
   904  			},
   905  		},
   906  		{
   907  			in: `true,false`,
   908  			want: []R{
   909  				{V: Bool{true}},
   910  				{E: `unexpected token ,`},
   911  			},
   912  		},
   913  		{
   914  			in: `47"hello"`,
   915  			want: []R{
   916  				{V: I32{47}},
   917  				{E: `unexpected token "hello"`},
   918  			},
   919  		},
   920  		{
   921  			in: `47 "hello"`,
   922  			want: []R{
   923  				{V: I32{47}},
   924  				{E: `unexpected token "hello"`},
   925  			},
   926  		},
   927  		{
   928  			in: `true 42`,
   929  			want: []R{
   930  				{V: Bool{true}},
   931  				{E: `unexpected token 42`},
   932  			},
   933  		},
   934  
   935  		// JSON arrays.
   936  		{
   937  			in: space + `[]` + space,
   938  			want: []R{
   939  				{V: ArrayOpen},
   940  				{V: ArrayClose},
   941  				{V: EOF},
   942  			},
   943  		},
   944  		{
   945  			in: space + `[` + space + `]` + space,
   946  			want: []R{
   947  				{V: ArrayOpen, P: len(space), RS: `[`},
   948  				{V: ArrayClose},
   949  				{V: EOF},
   950  			},
   951  		},
   952  		{
   953  			in: space + `[` + space,
   954  			want: []R{
   955  				{V: ArrayOpen},
   956  				{E: errEOF},
   957  			},
   958  		},
   959  		{
   960  			in:   space + `]` + space,
   961  			want: []R{{E: `unexpected token ]`}},
   962  		},
   963  		{
   964  			in: `[null,true,false,  1e1, "hello"   ]`,
   965  			want: []R{
   966  				{V: ArrayOpen},
   967  				{V: Null},
   968  				{V: Bool{true}},
   969  				{V: Bool{false}},
   970  				{V: I32{10}},
   971  				{V: Str{"hello"}},
   972  				{V: ArrayClose},
   973  				{V: EOF},
   974  			},
   975  		},
   976  		{
   977  			in: `[` + space + `true` + space + `,` + space + `"hello"` + space + `]`,
   978  			want: []R{
   979  				{V: ArrayOpen},
   980  				{V: Bool{true}},
   981  				{V: Str{"hello"}},
   982  				{V: ArrayClose},
   983  				{V: EOF},
   984  			},
   985  		},
   986  		{
   987  			in: `[` + space + `true` + space + `,` + space + `]`,
   988  			want: []R{
   989  				{V: ArrayOpen},
   990  				{V: Bool{true}},
   991  				{E: `unexpected token ]`},
   992  			},
   993  		},
   994  		{
   995  			in: `[` + space + `false` + space + `]`,
   996  			want: []R{
   997  				{V: ArrayOpen},
   998  				{V: Bool{false}},
   999  				{V: ArrayClose},
  1000  				{V: EOF},
  1001  			},
  1002  		},
  1003  		{
  1004  			in: `[` + space + `1` + space + `0` + space + `]`,
  1005  			want: []R{
  1006  				{V: ArrayOpen},
  1007  				{V: I64{1}},
  1008  				{E: `unexpected token 0`},
  1009  			},
  1010  		},
  1011  		{
  1012  			in: `[null`,
  1013  			want: []R{
  1014  				{V: ArrayOpen},
  1015  				{V: Null},
  1016  				{E: errEOF},
  1017  			},
  1018  		},
  1019  		{
  1020  			in: `[foo]`,
  1021  			want: []R{
  1022  				{V: ArrayOpen},
  1023  				{E: `invalid value foo`},
  1024  			},
  1025  		},
  1026  		{
  1027  			in: `[{}, "hello", [true, false], null]`,
  1028  			want: []R{
  1029  				{V: ArrayOpen},
  1030  				{V: ObjectOpen},
  1031  				{V: ObjectClose},
  1032  				{V: Str{"hello"}},
  1033  				{V: ArrayOpen},
  1034  				{V: Bool{true}},
  1035  				{V: Bool{false}},
  1036  				{V: ArrayClose},
  1037  				{V: Null},
  1038  				{V: ArrayClose},
  1039  				{V: EOF},
  1040  			},
  1041  		},
  1042  		{
  1043  			in: `[{ ]`,
  1044  			want: []R{
  1045  				{V: ArrayOpen},
  1046  				{V: ObjectOpen},
  1047  				{E: `unexpected token ]`},
  1048  			},
  1049  		},
  1050  		{
  1051  			in: `[[ ]`,
  1052  			want: []R{
  1053  				{V: ArrayOpen},
  1054  				{V: ArrayOpen},
  1055  				{V: ArrayClose},
  1056  				{E: errEOF},
  1057  			},
  1058  		},
  1059  		{
  1060  			in: `[,]`,
  1061  			want: []R{
  1062  				{V: ArrayOpen},
  1063  				{E: `unexpected token ,`},
  1064  			},
  1065  		},
  1066  		{
  1067  			in: `[true "hello"]`,
  1068  			want: []R{
  1069  				{V: ArrayOpen},
  1070  				{V: Bool{true}},
  1071  				{E: `unexpected token "hello"`},
  1072  			},
  1073  		},
  1074  		{
  1075  			in: `[] null`,
  1076  			want: []R{
  1077  				{V: ArrayOpen},
  1078  				{V: ArrayClose},
  1079  				{E: `unexpected token null`},
  1080  			},
  1081  		},
  1082  		{
  1083  			in: `true []`,
  1084  			want: []R{
  1085  				{V: Bool{true}},
  1086  				{E: `unexpected token [`},
  1087  			},
  1088  		},
  1089  
  1090  		// JSON objects.
  1091  		{
  1092  			in: space + `{}` + space,
  1093  			want: []R{
  1094  				{V: ObjectOpen},
  1095  				{V: ObjectClose},
  1096  				{V: EOF},
  1097  			},
  1098  		},
  1099  		{
  1100  			in: space + `{` + space + `}` + space,
  1101  			want: []R{
  1102  				{V: ObjectOpen},
  1103  				{V: ObjectClose},
  1104  				{V: EOF},
  1105  			},
  1106  		},
  1107  		{
  1108  			in: space + `{` + space,
  1109  			want: []R{
  1110  				{V: ObjectOpen},
  1111  				{E: errEOF},
  1112  			},
  1113  		},
  1114  		{
  1115  			in:   space + `}` + space,
  1116  			want: []R{{E: `unexpected token }`}},
  1117  		},
  1118  		{
  1119  			in: `{` + space + `null` + space + `}`,
  1120  			want: []R{
  1121  				{V: ObjectOpen},
  1122  				{E: `unexpected token null`},
  1123  			},
  1124  		},
  1125  		{
  1126  			in: `{[]}`,
  1127  			want: []R{
  1128  				{V: ObjectOpen},
  1129  				{E: `(line 1:2): unexpected token [`},
  1130  			},
  1131  		},
  1132  		{
  1133  			in: `{,}`,
  1134  			want: []R{
  1135  				{V: ObjectOpen},
  1136  				{E: `unexpected token ,`},
  1137  			},
  1138  		},
  1139  		{
  1140  			in: `{"345678"}`,
  1141  			want: []R{
  1142  				{V: ObjectOpen},
  1143  				{E: `(line 1:10): unexpected character }, missing ":" after field name`},
  1144  			},
  1145  		},
  1146  		{
  1147  			in: `{` + space + `"hello"` + space + `:` + space + `"world"` + space + `}`,
  1148  			want: []R{
  1149  				{V: ObjectOpen},
  1150  				{V: Name{"hello"}, P: len(space) + 1, RS: `"hello"`},
  1151  				{V: Str{"world"}, RS: `"world"`},
  1152  				{V: ObjectClose},
  1153  				{V: EOF},
  1154  			},
  1155  		},
  1156  		{
  1157  			in: `{"hello" "world"}`,
  1158  			want: []R{
  1159  				{V: ObjectOpen},
  1160  				{E: `(line 1:10): unexpected character ", missing ":" after field name`},
  1161  			},
  1162  		},
  1163  		{
  1164  			in: `{"hello":`,
  1165  			want: []R{
  1166  				{V: ObjectOpen},
  1167  				{V: Name{"hello"}},
  1168  				{E: errEOF},
  1169  			},
  1170  		},
  1171  		{
  1172  			in: `{"hello":"world"`,
  1173  			want: []R{
  1174  				{V: ObjectOpen},
  1175  				{V: Name{"hello"}},
  1176  				{V: Str{"world"}},
  1177  				{E: errEOF},
  1178  			},
  1179  		},
  1180  		{
  1181  			in: `{"hello":"world",`,
  1182  			want: []R{
  1183  				{V: ObjectOpen},
  1184  				{V: Name{"hello"}},
  1185  				{V: Str{"world"}},
  1186  				{E: errEOF},
  1187  			},
  1188  		},
  1189  		{
  1190  			in: `{""`,
  1191  			want: []R{
  1192  				{V: ObjectOpen},
  1193  				{E: errEOF},
  1194  			},
  1195  		},
  1196  		{
  1197  			in: `{"34":"89",}`,
  1198  			want: []R{
  1199  				{V: ObjectOpen},
  1200  				{V: Name{"34"}, RS: `"34"`},
  1201  				{V: Str{"89"}},
  1202  				{E: `syntax error (line 1:12): unexpected token }`},
  1203  			},
  1204  		},
  1205  		{
  1206  			in: `{
  1207  			  "number": 123e2,
  1208  			  "bool"  : false,
  1209  			  "object": {"string": "world"},
  1210  			  "null"  : null,
  1211  			  "array" : [1.01, "hello", true],
  1212  			  "string": "hello"
  1213  			}`,
  1214  			want: []R{
  1215  				{V: ObjectOpen},
  1216  
  1217  				{V: Name{"number"}},
  1218  				{V: I32{12300}},
  1219  
  1220  				{V: Name{"bool"}},
  1221  				{V: Bool{false}},
  1222  
  1223  				{V: Name{"object"}},
  1224  				{V: ObjectOpen},
  1225  				{V: Name{"string"}},
  1226  				{V: Str{"world"}},
  1227  				{V: ObjectClose},
  1228  
  1229  				{V: Name{"null"}},
  1230  				{V: Null},
  1231  
  1232  				{V: Name{"array"}},
  1233  				{V: ArrayOpen},
  1234  				{V: F32{1.01}},
  1235  				{V: Str{"hello"}},
  1236  				{V: Bool{true}},
  1237  				{V: ArrayClose},
  1238  
  1239  				{V: Name{"string"}},
  1240  				{V: Str{"hello"}},
  1241  
  1242  				{V: ObjectClose},
  1243  				{V: EOF},
  1244  			},
  1245  		},
  1246  		{
  1247  			in: `[
  1248  			  {"object": {"number": 47}},
  1249  			  ["list"],
  1250  			  null
  1251  			]`,
  1252  			want: []R{
  1253  				{V: ArrayOpen},
  1254  
  1255  				{V: ObjectOpen},
  1256  				{V: Name{"object"}},
  1257  				{V: ObjectOpen},
  1258  				{V: Name{"number"}},
  1259  				{V: I32{47}},
  1260  				{V: ObjectClose},
  1261  				{V: ObjectClose},
  1262  
  1263  				{V: ArrayOpen},
  1264  				{V: Str{"list"}},
  1265  				{V: ArrayClose},
  1266  
  1267  				{V: Null},
  1268  
  1269  				{V: ArrayClose},
  1270  				{V: EOF},
  1271  			},
  1272  		},
  1273  
  1274  		// Tests for line and column info.
  1275  		{
  1276  			in: `12345678 x`,
  1277  			want: []R{
  1278  				{V: I64{12345678}},
  1279  				{E: `syntax error (line 1:10): invalid value x`},
  1280  			},
  1281  		},
  1282  		{
  1283  			in: "\ntrue\n   x",
  1284  			want: []R{
  1285  				{V: Bool{true}},
  1286  				{E: `syntax error (line 3:4): invalid value x`},
  1287  			},
  1288  		},
  1289  		{
  1290  			in: `"💩"x`,
  1291  			want: []R{
  1292  				{V: Str{"💩"}},
  1293  				{E: `syntax error (line 1:4): invalid value x`},
  1294  			},
  1295  		},
  1296  		{
  1297  			in: "\n\n[\"🔥🔥🔥\"x",
  1298  			want: []R{
  1299  				{V: ArrayOpen},
  1300  				{V: Str{"🔥🔥🔥"}},
  1301  				{E: `syntax error (line 3:7): invalid value x`},
  1302  			},
  1303  		},
  1304  		{
  1305  			// Multi-rune emojis.
  1306  			in: `["👍🏻👍🏿"x`,
  1307  			want: []R{
  1308  				{V: ArrayOpen},
  1309  				{V: Str{"👍🏻👍🏿"}},
  1310  				{E: `syntax error (line 1:8): invalid value x`},
  1311  			},
  1312  		},
  1313  	}
  1314  
  1315  	for _, tc := range tests {
  1316  		tc := tc
  1317  		t.Run("", func(t *testing.T) {
  1318  			dec := json.NewDecoder([]byte(tc.in))
  1319  			for i, want := range tc.want {
  1320  				peekTok, peekErr := dec.Peek()
  1321  				tok, err := dec.Read()
  1322  				if err != nil {
  1323  					if want.E == "" {
  1324  						errorf(t, tc.in, "want#%d: Read() got unexpected error: %v", i, err)
  1325  					} else if !strings.Contains(err.Error(), want.E) {
  1326  						errorf(t, tc.in, "want#%d: Read() got %q, want %q", i, err, want.E)
  1327  					}
  1328  					return
  1329  				}
  1330  				if want.E != "" {
  1331  					errorf(t, tc.in, "want#%d: Read() got nil error, want %q", i, want.E)
  1332  					return
  1333  				}
  1334  				checkToken(t, tok, i, want, tc.in)
  1335  				if !cmp.Equal(tok, peekTok, cmp.Comparer(json.TokenEquals)) {
  1336  					errorf(t, tc.in, "want#%d: Peek() %+v != Read() token %+v", i, peekTok, tok)
  1337  				}
  1338  				if err != peekErr {
  1339  					errorf(t, tc.in, "want#%d: Peek() error %v != Read() error %v", i, err, peekErr)
  1340  				}
  1341  			}
  1342  		})
  1343  	}
  1344  }
  1345  
  1346  func checkToken(t *testing.T, tok json.Token, idx int, r R, in string) {
  1347  	// Validate Token.Pos() if R.P is set.
  1348  	if r.P > 0 {
  1349  		got := tok.Pos()
  1350  		if got != r.P {
  1351  			errorf(t, in, "want#%d: Token.Pos() got %v want %v", idx, got, r.P)
  1352  		}
  1353  	}
  1354  	// Validate Token.RawString if R.RS is set.
  1355  	if len(r.RS) > 0 {
  1356  		got := tok.RawString()
  1357  		if got != r.RS {
  1358  			errorf(t, in, "want#%d: Token.RawString() got %v want %v", idx, got, r.P)
  1359  		}
  1360  	}
  1361  
  1362  	// Skip checking for Token details if r.V is not set.
  1363  	if r.V == nil {
  1364  		return
  1365  	}
  1366  
  1367  	if err := r.V.check(tok); err != "" {
  1368  		errorf(t, in, "want#%d: %s", idx, err)
  1369  	}
  1370  	return
  1371  }
  1372  
  1373  func errorf(t *testing.T, in string, fmtStr string, args ...interface{}) {
  1374  	t.Helper()
  1375  	vargs := []interface{}{in}
  1376  	for _, arg := range args {
  1377  		vargs = append(vargs, arg)
  1378  	}
  1379  	t.Errorf("input:\n%s\n~end~\n"+fmtStr, vargs...)
  1380  }
  1381  
  1382  func TestClone(t *testing.T) {
  1383  	input := `{"outer":{"str":"hello", "number": 123}}`
  1384  	dec := json.NewDecoder([]byte(input))
  1385  
  1386  	// Clone at the start should produce the same reads as the original.
  1387  	clone := dec.Clone()
  1388  	compareDecoders(t, dec, clone)
  1389  
  1390  	// Advance to inner object, clone and compare again.
  1391  	dec.Read() // Read ObjectOpen.
  1392  	dec.Read() // Read Name.
  1393  	clone = dec.Clone()
  1394  	compareDecoders(t, dec, clone)
  1395  }
  1396  
  1397  func compareDecoders(t *testing.T, d1 *json.Decoder, d2 *json.Decoder) {
  1398  	for {
  1399  		tok1, err1 := d1.Read()
  1400  		tok2, err2 := d2.Read()
  1401  		if tok1.Kind() != tok2.Kind() {
  1402  			t.Errorf("cloned decoder: got Kind %v, want %v", tok2.Kind(), tok1.Kind())
  1403  		}
  1404  		if tok1.RawString() != tok2.RawString() {
  1405  			t.Errorf("cloned decoder: got RawString %v, want %v", tok2.RawString(), tok1.RawString())
  1406  		}
  1407  		if err1 != err2 {
  1408  			t.Errorf("cloned decoder: got error %v, want %v", err2, err1)
  1409  		}
  1410  		if tok1.Kind() == json.EOF {
  1411  			break
  1412  		}
  1413  	}
  1414  }
  1415  

View as plain text