k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/internal/third_party/go-json-experiment/json/decode_test.go (about)

     1  // Copyright 2020 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
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"io"
    12  	"math"
    13  	"net"
    14  	"path"
    15  	"reflect"
    16  	"strings"
    17  	"testing"
    18  	"testing/iotest"
    19  )
    20  
    21  // equalTokens reports whether to sequences of tokens formats the same way.
    22  func equalTokens(xs, ys []Token) bool {
    23  	if len(xs) != len(ys) {
    24  		return false
    25  	}
    26  	for i := range xs {
    27  		if !(reflect.DeepEqual(xs[i], ys[i]) || xs[i].String() == ys[i].String()) {
    28  			return false
    29  		}
    30  	}
    31  	return true
    32  }
    33  
    34  // TestDecoder tests whether we can parse JSON with either tokens or raw values.
    35  func TestDecoder(t *testing.T) {
    36  	for _, td := range coderTestdata {
    37  		for _, typeName := range []string{"Token", "Value", "TokenDelims"} {
    38  			t.Run(path.Join(td.name.name, typeName), func(t *testing.T) {
    39  				testDecoder(t, td.name.where, typeName, td)
    40  			})
    41  		}
    42  	}
    43  }
    44  func testDecoder(t *testing.T, where pc, typeName string, td coderTestdataEntry) {
    45  	dec := NewDecoder(bytes.NewBufferString(td.in))
    46  	switch typeName {
    47  	case "Token":
    48  		var tokens []Token
    49  		var pointers []string
    50  		for {
    51  			tok, err := dec.ReadToken()
    52  			if err != nil {
    53  				if err == io.EOF {
    54  					break
    55  				}
    56  				t.Fatalf("%s: Decoder.ReadToken error: %v", where, err)
    57  			}
    58  			tokens = append(tokens, tok.Clone())
    59  			if td.pointers != nil {
    60  				pointers = append(pointers, dec.StackPointer())
    61  			}
    62  		}
    63  		if !equalTokens(tokens, td.tokens) {
    64  			t.Fatalf("%s: tokens mismatch:\ngot  %v\nwant %v", where, tokens, td.tokens)
    65  		}
    66  		if !reflect.DeepEqual(pointers, td.pointers) {
    67  			t.Fatalf("%s: pointers mismatch:\ngot  %q\nwant %q", where, pointers, td.pointers)
    68  		}
    69  	case "Value":
    70  		val, err := dec.ReadValue()
    71  		if err != nil {
    72  			t.Fatalf("%s: Decoder.ReadValue error: %v", where, err)
    73  		}
    74  		got := string(val)
    75  		want := strings.TrimSpace(td.in)
    76  		if got != want {
    77  			t.Fatalf("%s: Decoder.ReadValue = %s, want %s", where, got, want)
    78  		}
    79  	case "TokenDelims":
    80  		// Use ReadToken for object/array delimiters, ReadValue otherwise.
    81  		var tokens []Token
    82  	loop:
    83  		for {
    84  			switch dec.PeekKind() {
    85  			case '{', '}', '[', ']':
    86  				tok, err := dec.ReadToken()
    87  				if err != nil {
    88  					if err == io.EOF {
    89  						break loop
    90  					}
    91  					t.Fatalf("%s: Decoder.ReadToken error: %v", where, err)
    92  				}
    93  				tokens = append(tokens, tok.Clone())
    94  			default:
    95  				val, err := dec.ReadValue()
    96  				if err != nil {
    97  					if err == io.EOF {
    98  						break loop
    99  					}
   100  					t.Fatalf("%s: Decoder.ReadValue error: %v", where, err)
   101  				}
   102  				tokens = append(tokens, rawToken(string(val)))
   103  			}
   104  		}
   105  		if !equalTokens(tokens, td.tokens) {
   106  			t.Fatalf("%s: tokens mismatch:\ngot  %v\nwant %v", where, tokens, td.tokens)
   107  		}
   108  	}
   109  }
   110  
   111  // TestFaultyDecoder tests that temporary I/O errors are not fatal.
   112  func TestFaultyDecoder(t *testing.T) {
   113  	for _, td := range coderTestdata {
   114  		for _, typeName := range []string{"Token", "Value"} {
   115  			t.Run(path.Join(td.name.name, typeName), func(t *testing.T) {
   116  				testFaultyDecoder(t, td.name.where, typeName, td)
   117  			})
   118  		}
   119  	}
   120  }
   121  func testFaultyDecoder(t *testing.T, where pc, typeName string, td coderTestdataEntry) {
   122  	b := &FaultyBuffer{
   123  		B:        []byte(td.in),
   124  		MaxBytes: 1,
   125  		MayError: io.ErrNoProgress,
   126  	}
   127  
   128  	// Read all the tokens.
   129  	// If the underlying io.Reader is faulty, then Read may return
   130  	// an error without changing the internal state machine.
   131  	// In other words, I/O errors occur before syntactic errors.
   132  	dec := NewDecoder(b)
   133  	switch typeName {
   134  	case "Token":
   135  		var tokens []Token
   136  		for {
   137  			tok, err := dec.ReadToken()
   138  			if err != nil {
   139  				if err == io.EOF {
   140  					break
   141  				}
   142  				if !errors.Is(err, io.ErrNoProgress) {
   143  					t.Fatalf("%s: %d: Decoder.ReadToken error: %v", where, len(tokens), err)
   144  				}
   145  				continue
   146  			}
   147  			tokens = append(tokens, tok.Clone())
   148  		}
   149  		if !equalTokens(tokens, td.tokens) {
   150  			t.Fatalf("%s: tokens mismatch:\ngot  %s\nwant %s", where, tokens, td.tokens)
   151  		}
   152  	case "Value":
   153  		for {
   154  			val, err := dec.ReadValue()
   155  			if err != nil {
   156  				if err == io.EOF {
   157  					break
   158  				}
   159  				if !errors.Is(err, io.ErrNoProgress) {
   160  					t.Fatalf("%s: Decoder.ReadValue error: %v", where, err)
   161  				}
   162  				continue
   163  			}
   164  			got := string(val)
   165  			want := strings.TrimSpace(td.in)
   166  			if got != want {
   167  				t.Fatalf("%s: Decoder.ReadValue = %s, want %s", where, got, want)
   168  			}
   169  		}
   170  	}
   171  }
   172  
   173  type decoderMethodCall struct {
   174  	wantKind    Kind
   175  	wantOut     tokOrVal
   176  	wantErr     error
   177  	wantPointer string
   178  }
   179  
   180  var decoderErrorTestdata = []struct {
   181  	name       testName
   182  	opts       DecodeOptions
   183  	in         string
   184  	calls      []decoderMethodCall
   185  	wantOffset int
   186  }{{
   187  	name: name("InvalidStart"),
   188  	in:   ` #`,
   189  	calls: []decoderMethodCall{
   190  		{'#', zeroToken, newInvalidCharacterError([]byte("#"), "at start of token").withOffset(int64(len(" "))), ""},
   191  		{'#', zeroValue, newInvalidCharacterError([]byte("#"), "at start of value").withOffset(int64(len(" "))), ""},
   192  	},
   193  }, {
   194  	name: name("StreamN0"),
   195  	in:   ` `,
   196  	calls: []decoderMethodCall{
   197  		{0, zeroToken, io.EOF, ""},
   198  		{0, zeroValue, io.EOF, ""},
   199  	},
   200  }, {
   201  	name: name("StreamN1"),
   202  	in:   ` null `,
   203  	calls: []decoderMethodCall{
   204  		{'n', Null, nil, ""},
   205  		{0, zeroToken, io.EOF, ""},
   206  		{0, zeroValue, io.EOF, ""},
   207  	},
   208  	wantOffset: len(` null`),
   209  }, {
   210  	name: name("StreamN2"),
   211  	in:   ` nullnull `,
   212  	calls: []decoderMethodCall{
   213  		{'n', Null, nil, ""},
   214  		{'n', Null, nil, ""},
   215  		{0, zeroToken, io.EOF, ""},
   216  		{0, zeroValue, io.EOF, ""},
   217  	},
   218  	wantOffset: len(` nullnull`),
   219  }, {
   220  	name: name("StreamN2/ExtraComma"), // stream is whitespace delimited, not comma delimited
   221  	in:   ` null , null `,
   222  	calls: []decoderMethodCall{
   223  		{'n', Null, nil, ""},
   224  		{0, zeroToken, newInvalidCharacterError([]byte(","), `before next token`).withOffset(int64(len(` null `))), ""},
   225  		{0, zeroValue, newInvalidCharacterError([]byte(","), `before next token`).withOffset(int64(len(` null `))), ""},
   226  	},
   227  	wantOffset: len(` null`),
   228  }, {
   229  	name: name("TruncatedNull"),
   230  	in:   `nul`,
   231  	calls: []decoderMethodCall{
   232  		{'n', zeroToken, io.ErrUnexpectedEOF, ""},
   233  		{'n', zeroValue, io.ErrUnexpectedEOF, ""},
   234  	},
   235  }, {
   236  	name: name("InvalidNull"),
   237  	in:   `nulL`,
   238  	calls: []decoderMethodCall{
   239  		{'n', zeroToken, newInvalidCharacterError([]byte("L"), `within literal null (expecting 'l')`).withOffset(int64(len(`nul`))), ""},
   240  		{'n', zeroValue, newInvalidCharacterError([]byte("L"), `within literal null (expecting 'l')`).withOffset(int64(len(`nul`))), ""},
   241  	},
   242  }, {
   243  	name: name("TruncatedFalse"),
   244  	in:   `fals`,
   245  	calls: []decoderMethodCall{
   246  		{'f', zeroToken, io.ErrUnexpectedEOF, ""},
   247  		{'f', zeroValue, io.ErrUnexpectedEOF, ""},
   248  	},
   249  }, {
   250  	name: name("InvalidFalse"),
   251  	in:   `falsE`,
   252  	calls: []decoderMethodCall{
   253  		{'f', zeroToken, newInvalidCharacterError([]byte("E"), `within literal false (expecting 'e')`).withOffset(int64(len(`fals`))), ""},
   254  		{'f', zeroValue, newInvalidCharacterError([]byte("E"), `within literal false (expecting 'e')`).withOffset(int64(len(`fals`))), ""},
   255  	},
   256  }, {
   257  	name: name("TruncatedTrue"),
   258  	in:   `tru`,
   259  	calls: []decoderMethodCall{
   260  		{'t', zeroToken, io.ErrUnexpectedEOF, ""},
   261  		{'t', zeroValue, io.ErrUnexpectedEOF, ""},
   262  	},
   263  }, {
   264  	name: name("InvalidTrue"),
   265  	in:   `truE`,
   266  	calls: []decoderMethodCall{
   267  		{'t', zeroToken, newInvalidCharacterError([]byte("E"), `within literal true (expecting 'e')`).withOffset(int64(len(`tru`))), ""},
   268  		{'t', zeroValue, newInvalidCharacterError([]byte("E"), `within literal true (expecting 'e')`).withOffset(int64(len(`tru`))), ""},
   269  	},
   270  }, {
   271  	name: name("TruncatedString"),
   272  	in:   `"start`,
   273  	calls: []decoderMethodCall{
   274  		{'"', zeroToken, io.ErrUnexpectedEOF, ""},
   275  		{'"', zeroValue, io.ErrUnexpectedEOF, ""},
   276  	},
   277  }, {
   278  	name: name("InvalidString"),
   279  	in:   `"ok` + "\x00",
   280  	calls: []decoderMethodCall{
   281  		{'"', zeroToken, newInvalidCharacterError([]byte("\x00"), `within string (expecting non-control character)`).withOffset(int64(len(`"ok`))), ""},
   282  		{'"', zeroValue, newInvalidCharacterError([]byte("\x00"), `within string (expecting non-control character)`).withOffset(int64(len(`"ok`))), ""},
   283  	},
   284  }, {
   285  	name: name("ValidString/AllowInvalidUTF8/Token"),
   286  	opts: DecodeOptions{AllowInvalidUTF8: true},
   287  	in:   "\"living\xde\xad\xbe\xef\"",
   288  	calls: []decoderMethodCall{
   289  		{'"', rawToken("\"living\xde\xad\xbe\xef\""), nil, ""},
   290  	},
   291  	wantOffset: len("\"living\xde\xad\xbe\xef\""),
   292  }, {
   293  	name: name("ValidString/AllowInvalidUTF8/Value"),
   294  	opts: DecodeOptions{AllowInvalidUTF8: true},
   295  	in:   "\"living\xde\xad\xbe\xef\"",
   296  	calls: []decoderMethodCall{
   297  		{'"', RawValue("\"living\xde\xad\xbe\xef\""), nil, ""},
   298  	},
   299  	wantOffset: len("\"living\xde\xad\xbe\xef\""),
   300  }, {
   301  	name: name("InvalidString/RejectInvalidUTF8"),
   302  	opts: DecodeOptions{AllowInvalidUTF8: false},
   303  	in:   "\"living\xde\xad\xbe\xef\"",
   304  	calls: []decoderMethodCall{
   305  		{'"', zeroToken, (&SyntacticError{str: "invalid UTF-8 within string"}).withOffset(int64(len("\"living\xde\xad"))), ""},
   306  		{'"', zeroValue, (&SyntacticError{str: "invalid UTF-8 within string"}).withOffset(int64(len("\"living\xde\xad"))), ""},
   307  	},
   308  }, {
   309  	name: name("TruncatedNumber"),
   310  	in:   `0.`,
   311  	calls: []decoderMethodCall{
   312  		{'0', zeroToken, io.ErrUnexpectedEOF, ""},
   313  		{'0', zeroValue, io.ErrUnexpectedEOF, ""},
   314  	},
   315  }, {
   316  	name: name("InvalidNumber"),
   317  	in:   `0.e`,
   318  	calls: []decoderMethodCall{
   319  		{'0', zeroToken, newInvalidCharacterError([]byte("e"), "within number (expecting digit)").withOffset(int64(len(`0.`))), ""},
   320  		{'0', zeroValue, newInvalidCharacterError([]byte("e"), "within number (expecting digit)").withOffset(int64(len(`0.`))), ""},
   321  	},
   322  }, {
   323  	name: name("TruncatedObject/AfterStart"),
   324  	in:   `{`,
   325  	calls: []decoderMethodCall{
   326  		{'{', zeroValue, io.ErrUnexpectedEOF, ""},
   327  		{'{', ObjectStart, nil, ""},
   328  		{0, zeroToken, io.ErrUnexpectedEOF, ""},
   329  		{0, zeroValue, io.ErrUnexpectedEOF, ""},
   330  	},
   331  	wantOffset: len(`{`),
   332  }, {
   333  	name: name("TruncatedObject/AfterName"),
   334  	in:   `{"0"`,
   335  	calls: []decoderMethodCall{
   336  		{'{', zeroValue, io.ErrUnexpectedEOF, ""},
   337  		{'{', ObjectStart, nil, ""},
   338  		{'"', String("0"), nil, ""},
   339  		{0, zeroToken, io.ErrUnexpectedEOF, ""},
   340  		{0, zeroValue, io.ErrUnexpectedEOF, ""},
   341  	},
   342  	wantOffset: len(`{"0"`),
   343  }, {
   344  	name: name("TruncatedObject/AfterColon"),
   345  	in:   `{"0":`,
   346  	calls: []decoderMethodCall{
   347  		{'{', zeroValue, io.ErrUnexpectedEOF, ""},
   348  		{'{', ObjectStart, nil, ""},
   349  		{'"', String("0"), nil, ""},
   350  		{0, zeroToken, io.ErrUnexpectedEOF, ""},
   351  		{0, zeroValue, io.ErrUnexpectedEOF, ""},
   352  	},
   353  	wantOffset: len(`{"0"`),
   354  }, {
   355  	name: name("TruncatedObject/AfterValue"),
   356  	in:   `{"0":0`,
   357  	calls: []decoderMethodCall{
   358  		{'{', zeroValue, io.ErrUnexpectedEOF, ""},
   359  		{'{', ObjectStart, nil, ""},
   360  		{'"', String("0"), nil, ""},
   361  		{'0', Uint(0), nil, ""},
   362  		{0, zeroToken, io.ErrUnexpectedEOF, ""},
   363  		{0, zeroValue, io.ErrUnexpectedEOF, ""},
   364  	},
   365  	wantOffset: len(`{"0":0`),
   366  }, {
   367  	name: name("TruncatedObject/AfterComma"),
   368  	in:   `{"0":0,`,
   369  	calls: []decoderMethodCall{
   370  		{'{', zeroValue, io.ErrUnexpectedEOF, ""},
   371  		{'{', ObjectStart, nil, ""},
   372  		{'"', String("0"), nil, ""},
   373  		{'0', Uint(0), nil, ""},
   374  		{0, zeroToken, io.ErrUnexpectedEOF, ""},
   375  		{0, zeroValue, io.ErrUnexpectedEOF, ""},
   376  	},
   377  	wantOffset: len(`{"0":0`),
   378  }, {
   379  	name: name("InvalidObject/MissingColon"),
   380  	in:   ` { "fizz" "buzz" } `,
   381  	calls: []decoderMethodCall{
   382  		{'{', zeroValue, newInvalidCharacterError([]byte("\""), "after object name (expecting ':')").withOffset(int64(len(` { "fizz" `))), ""},
   383  		{'{', ObjectStart, nil, ""},
   384  		{'"', String("fizz"), nil, ""},
   385  		{0, zeroToken, errMissingColon.withOffset(int64(len(` { "fizz" `))), ""},
   386  		{0, zeroValue, errMissingColon.withOffset(int64(len(` { "fizz" `))), ""},
   387  	},
   388  	wantOffset: len(` { "fizz"`),
   389  }, {
   390  	name: name("InvalidObject/MissingColon/GotComma"),
   391  	in:   ` { "fizz" , "buzz" } `,
   392  	calls: []decoderMethodCall{
   393  		{'{', zeroValue, newInvalidCharacterError([]byte(","), "after object name (expecting ':')").withOffset(int64(len(` { "fizz" `))), ""},
   394  		{'{', ObjectStart, nil, ""},
   395  		{'"', String("fizz"), nil, ""},
   396  		{0, zeroToken, errMissingColon.withOffset(int64(len(` { "fizz" `))), ""},
   397  		{0, zeroValue, errMissingColon.withOffset(int64(len(` { "fizz" `))), ""},
   398  	},
   399  	wantOffset: len(` { "fizz"`),
   400  }, {
   401  	name: name("InvalidObject/MissingColon/GotHash"),
   402  	in:   ` { "fizz" # "buzz" } `,
   403  	calls: []decoderMethodCall{
   404  		{'{', zeroValue, newInvalidCharacterError([]byte("#"), "after object name (expecting ':')").withOffset(int64(len(` { "fizz" `))), ""},
   405  		{'{', ObjectStart, nil, ""},
   406  		{'"', String("fizz"), nil, ""},
   407  		{0, zeroToken, errMissingColon.withOffset(int64(len(` { "fizz" `))), ""},
   408  		{0, zeroValue, errMissingColon.withOffset(int64(len(` { "fizz" `))), ""},
   409  	},
   410  	wantOffset: len(` { "fizz"`),
   411  }, {
   412  	name: name("InvalidObject/MissingComma"),
   413  	in:   ` { "fizz" : "buzz" "gazz" } `,
   414  	calls: []decoderMethodCall{
   415  		{'{', zeroValue, newInvalidCharacterError([]byte("\""), "after object value (expecting ',' or '}')").withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   416  		{'{', ObjectStart, nil, ""},
   417  		{'"', String("fizz"), nil, ""},
   418  		{'"', String("buzz"), nil, ""},
   419  		{0, zeroToken, errMissingComma.withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   420  		{0, zeroValue, errMissingComma.withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   421  	},
   422  	wantOffset: len(` { "fizz" : "buzz"`),
   423  }, {
   424  	name: name("InvalidObject/MissingComma/GotColon"),
   425  	in:   ` { "fizz" : "buzz" : "gazz" } `,
   426  	calls: []decoderMethodCall{
   427  		{'{', zeroValue, newInvalidCharacterError([]byte(":"), "after object value (expecting ',' or '}')").withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   428  		{'{', ObjectStart, nil, ""},
   429  		{'"', String("fizz"), nil, ""},
   430  		{'"', String("buzz"), nil, ""},
   431  		{0, zeroToken, errMissingComma.withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   432  		{0, zeroValue, errMissingComma.withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   433  	},
   434  	wantOffset: len(` { "fizz" : "buzz"`),
   435  }, {
   436  	name: name("InvalidObject/MissingComma/GotHash"),
   437  	in:   ` { "fizz" : "buzz" # "gazz" } `,
   438  	calls: []decoderMethodCall{
   439  		{'{', zeroValue, newInvalidCharacterError([]byte("#"), "after object value (expecting ',' or '}')").withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   440  		{'{', ObjectStart, nil, ""},
   441  		{'"', String("fizz"), nil, ""},
   442  		{'"', String("buzz"), nil, ""},
   443  		{0, zeroToken, errMissingComma.withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   444  		{0, zeroValue, errMissingComma.withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   445  	},
   446  	wantOffset: len(` { "fizz" : "buzz"`),
   447  }, {
   448  	name: name("InvalidObject/ExtraComma/AfterStart"),
   449  	in:   ` { , } `,
   450  	calls: []decoderMethodCall{
   451  		{'{', zeroValue, newInvalidCharacterError([]byte(","), `at start of string (expecting '"')`).withOffset(int64(len(` { `))), ""},
   452  		{'{', ObjectStart, nil, ""},
   453  		{0, zeroToken, newInvalidCharacterError([]byte(","), `before next token`).withOffset(int64(len(` { `))), ""},
   454  		{0, zeroValue, newInvalidCharacterError([]byte(","), `before next token`).withOffset(int64(len(` { `))), ""},
   455  	},
   456  	wantOffset: len(` {`),
   457  }, {
   458  	name: name("InvalidObject/ExtraComma/AfterValue"),
   459  	in:   ` { "fizz" : "buzz" , } `,
   460  	calls: []decoderMethodCall{
   461  		{'{', zeroValue, newInvalidCharacterError([]byte("}"), `at start of string (expecting '"')`).withOffset(int64(len(` { "fizz" : "buzz" , `))), ""},
   462  		{'{', ObjectStart, nil, ""},
   463  		{'"', String("fizz"), nil, ""},
   464  		{'"', String("buzz"), nil, ""},
   465  		{0, zeroToken, newInvalidCharacterError([]byte(","), `before next token`).withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   466  		{0, zeroValue, newInvalidCharacterError([]byte(","), `before next token`).withOffset(int64(len(` { "fizz" : "buzz" `))), ""},
   467  	},
   468  	wantOffset: len(` { "fizz" : "buzz"`),
   469  }, {
   470  	name: name("InvalidObject/InvalidName/GotNull"),
   471  	in:   ` { null : null } `,
   472  	calls: []decoderMethodCall{
   473  		{'{', zeroValue, newInvalidCharacterError([]byte("n"), "at start of string (expecting '\"')").withOffset(int64(len(` { `))), ""},
   474  		{'{', ObjectStart, nil, ""},
   475  		{'n', zeroToken, errMissingName.withOffset(int64(len(` { `))), ""},
   476  		{'n', zeroValue, errMissingName.withOffset(int64(len(` { `))), ""},
   477  	},
   478  	wantOffset: len(` {`),
   479  }, {
   480  	name: name("InvalidObject/InvalidName/GotFalse"),
   481  	in:   ` { false : false } `,
   482  	calls: []decoderMethodCall{
   483  		{'{', zeroValue, newInvalidCharacterError([]byte("f"), "at start of string (expecting '\"')").withOffset(int64(len(` { `))), ""},
   484  		{'{', ObjectStart, nil, ""},
   485  		{'f', zeroToken, errMissingName.withOffset(int64(len(` { `))), ""},
   486  		{'f', zeroValue, errMissingName.withOffset(int64(len(` { `))), ""},
   487  	},
   488  	wantOffset: len(` {`),
   489  }, {
   490  	name: name("InvalidObject/InvalidName/GotTrue"),
   491  	in:   ` { true : true } `,
   492  	calls: []decoderMethodCall{
   493  		{'{', zeroValue, newInvalidCharacterError([]byte("t"), "at start of string (expecting '\"')").withOffset(int64(len(` { `))), ""},
   494  		{'{', ObjectStart, nil, ""},
   495  		{'t', zeroToken, errMissingName.withOffset(int64(len(` { `))), ""},
   496  		{'t', zeroValue, errMissingName.withOffset(int64(len(` { `))), ""},
   497  	},
   498  	wantOffset: len(` {`),
   499  }, {
   500  	name: name("InvalidObject/InvalidName/GotNumber"),
   501  	in:   ` { 0 : 0 } `,
   502  	calls: []decoderMethodCall{
   503  		{'{', zeroValue, newInvalidCharacterError([]byte("0"), "at start of string (expecting '\"')").withOffset(int64(len(` { `))), ""},
   504  		{'{', ObjectStart, nil, ""},
   505  		{'0', zeroToken, errMissingName.withOffset(int64(len(` { `))), ""},
   506  		{'0', zeroValue, errMissingName.withOffset(int64(len(` { `))), ""},
   507  	},
   508  	wantOffset: len(` {`),
   509  }, {
   510  	name: name("InvalidObject/InvalidName/GotObject"),
   511  	in:   ` { {} : {} } `,
   512  	calls: []decoderMethodCall{
   513  		{'{', zeroValue, newInvalidCharacterError([]byte("{"), "at start of string (expecting '\"')").withOffset(int64(len(` { `))), ""},
   514  		{'{', ObjectStart, nil, ""},
   515  		{'{', zeroToken, errMissingName.withOffset(int64(len(` { `))), ""},
   516  		{'{', zeroValue, errMissingName.withOffset(int64(len(` { `))), ""},
   517  	},
   518  	wantOffset: len(` {`),
   519  }, {
   520  	name: name("InvalidObject/InvalidName/GotArray"),
   521  	in:   ` { [] : [] } `,
   522  	calls: []decoderMethodCall{
   523  		{'{', zeroValue, newInvalidCharacterError([]byte("["), "at start of string (expecting '\"')").withOffset(int64(len(` { `))), ""},
   524  		{'{', ObjectStart, nil, ""},
   525  		{'[', zeroToken, errMissingName.withOffset(int64(len(` { `))), ""},
   526  		{'[', zeroValue, errMissingName.withOffset(int64(len(` { `))), ""},
   527  	},
   528  	wantOffset: len(` {`),
   529  }, {
   530  	name: name("InvalidObject/MismatchingDelim"),
   531  	in:   ` { ] `,
   532  	calls: []decoderMethodCall{
   533  		{'{', zeroValue, newInvalidCharacterError([]byte("]"), "at start of string (expecting '\"')").withOffset(int64(len(` { `))), ""},
   534  		{'{', ObjectStart, nil, ""},
   535  		{']', zeroToken, errMismatchDelim.withOffset(int64(len(` { `))), ""},
   536  		{']', zeroValue, newInvalidCharacterError([]byte("]"), "at start of value").withOffset(int64(len(` { `))), ""},
   537  	},
   538  	wantOffset: len(` {`),
   539  }, {
   540  	name: name("ValidObject/InvalidValue"),
   541  	in:   ` { } `,
   542  	calls: []decoderMethodCall{
   543  		{'{', ObjectStart, nil, ""},
   544  		{'}', zeroValue, newInvalidCharacterError([]byte("}"), "at start of value").withOffset(int64(len(" { "))), ""},
   545  	},
   546  	wantOffset: len(` {`),
   547  }, {
   548  	name: name("ValidObject/UniqueNames"),
   549  	in:   `{"0":0,"1":1} `,
   550  	calls: []decoderMethodCall{
   551  		{'{', ObjectStart, nil, ""},
   552  		{'"', String("0"), nil, ""},
   553  		{'0', Uint(0), nil, ""},
   554  		{'"', String("1"), nil, ""},
   555  		{'0', Uint(1), nil, ""},
   556  		{'}', ObjectEnd, nil, ""},
   557  	},
   558  	wantOffset: len(`{"0":0,"1":1}`),
   559  }, {
   560  	name: name("ValidObject/DuplicateNames"),
   561  	opts: DecodeOptions{AllowDuplicateNames: true},
   562  	in:   `{"0":0,"0":0} `,
   563  	calls: []decoderMethodCall{
   564  		{'{', ObjectStart, nil, ""},
   565  		{'"', String("0"), nil, ""},
   566  		{'0', Uint(0), nil, ""},
   567  		{'"', String("0"), nil, ""},
   568  		{'0', Uint(0), nil, ""},
   569  		{'}', ObjectEnd, nil, ""},
   570  	},
   571  	wantOffset: len(`{"0":0,"0":0}`),
   572  }, {
   573  	name: name("InvalidObject/DuplicateNames"),
   574  	in:   `{"0":{},"1":{},"0":{}} `,
   575  	calls: []decoderMethodCall{
   576  		{'{', zeroValue, (&SyntacticError{str: `duplicate name "0" in object`}).withOffset(int64(len(`{"0":{},"1":{},`))), ""},
   577  		{'{', ObjectStart, nil, ""},
   578  		{'"', String("0"), nil, ""},
   579  		{'{', ObjectStart, nil, ""},
   580  		{'}', ObjectEnd, nil, ""},
   581  		{'"', String("1"), nil, ""},
   582  		{'{', ObjectStart, nil, ""},
   583  		{'}', ObjectEnd, nil, ""},
   584  		{'"', zeroToken, (&SyntacticError{str: `duplicate name "0" in object`}).withOffset(int64(len(`{"0":{},"1":{},`))), "/1"},
   585  		{'"', zeroValue, (&SyntacticError{str: `duplicate name "0" in object`}).withOffset(int64(len(`{"0":{},"1":{},`))), "/1"},
   586  	},
   587  	wantOffset: len(`{"0":{},"1":{}`),
   588  }, {
   589  	name: name("TruncatedArray/AfterStart"),
   590  	in:   `[`,
   591  	calls: []decoderMethodCall{
   592  		{'[', zeroValue, io.ErrUnexpectedEOF, ""},
   593  		{'[', ArrayStart, nil, ""},
   594  		{0, zeroToken, io.ErrUnexpectedEOF, ""},
   595  		{0, zeroValue, io.ErrUnexpectedEOF, ""},
   596  	},
   597  	wantOffset: len(`[`),
   598  }, {
   599  	name: name("TruncatedArray/AfterValue"),
   600  	in:   `[0`,
   601  	calls: []decoderMethodCall{
   602  		{'[', zeroValue, io.ErrUnexpectedEOF, ""},
   603  		{'[', ArrayStart, nil, ""},
   604  		{'0', Uint(0), nil, ""},
   605  		{0, zeroToken, io.ErrUnexpectedEOF, ""},
   606  		{0, zeroValue, io.ErrUnexpectedEOF, ""},
   607  	},
   608  	wantOffset: len(`[0`),
   609  }, {
   610  	name: name("TruncatedArray/AfterComma"),
   611  	in:   `[0,`,
   612  	calls: []decoderMethodCall{
   613  		{'[', zeroValue, io.ErrUnexpectedEOF, ""},
   614  		{'[', ArrayStart, nil, ""},
   615  		{'0', Uint(0), nil, ""},
   616  		{0, zeroToken, io.ErrUnexpectedEOF, ""},
   617  		{0, zeroValue, io.ErrUnexpectedEOF, ""},
   618  	},
   619  	wantOffset: len(`[0`),
   620  }, {
   621  	name: name("InvalidArray/MissingComma"),
   622  	in:   ` [ "fizz" "buzz" ] `,
   623  	calls: []decoderMethodCall{
   624  		{'[', zeroValue, newInvalidCharacterError([]byte("\""), "after array value (expecting ',' or ']')").withOffset(int64(len(` [ "fizz" `))), ""},
   625  		{'[', ArrayStart, nil, ""},
   626  		{'"', String("fizz"), nil, ""},
   627  		{0, zeroToken, errMissingComma.withOffset(int64(len(` [ "fizz" `))), ""},
   628  		{0, zeroValue, errMissingComma.withOffset(int64(len(` [ "fizz" `))), ""},
   629  	},
   630  	wantOffset: len(` [ "fizz"`),
   631  }, {
   632  	name: name("InvalidArray/MismatchingDelim"),
   633  	in:   ` [ } `,
   634  	calls: []decoderMethodCall{
   635  		{'[', zeroValue, newInvalidCharacterError([]byte("}"), "at start of value").withOffset(int64(len(` [ `))), ""},
   636  		{'[', ArrayStart, nil, ""},
   637  		{'}', zeroToken, errMismatchDelim.withOffset(int64(len(` { `))), ""},
   638  		{'}', zeroValue, newInvalidCharacterError([]byte("}"), "at start of value").withOffset(int64(len(` [ `))), ""},
   639  	},
   640  	wantOffset: len(` [`),
   641  }, {
   642  	name: name("ValidArray/InvalidValue"),
   643  	in:   ` [ ] `,
   644  	calls: []decoderMethodCall{
   645  		{'[', ArrayStart, nil, ""},
   646  		{']', zeroValue, newInvalidCharacterError([]byte("]"), "at start of value").withOffset(int64(len(" [ "))), ""},
   647  	},
   648  	wantOffset: len(` [`),
   649  }}
   650  
   651  // TestDecoderErrors test that Decoder errors occur when we expect and
   652  // leaves the Decoder in a consistent state.
   653  func TestDecoderErrors(t *testing.T) {
   654  	for _, td := range decoderErrorTestdata {
   655  		t.Run(path.Join(td.name.name), func(t *testing.T) {
   656  			testDecoderErrors(t, td.name.where, td.opts, td.in, td.calls, td.wantOffset)
   657  		})
   658  	}
   659  }
   660  func testDecoderErrors(t *testing.T, where pc, opts DecodeOptions, in string, calls []decoderMethodCall, wantOffset int) {
   661  	src := bytes.NewBufferString(in)
   662  	dec := opts.NewDecoder(src)
   663  	for i, call := range calls {
   664  		gotKind := dec.PeekKind()
   665  		if gotKind != call.wantKind {
   666  			t.Fatalf("%s: %d: Decoder.PeekKind = %v, want %v", where, i, gotKind, call.wantKind)
   667  		}
   668  
   669  		var gotErr error
   670  		switch wantOut := call.wantOut.(type) {
   671  		case Token:
   672  			var gotOut Token
   673  			gotOut, gotErr = dec.ReadToken()
   674  			if gotOut.String() != wantOut.String() {
   675  				t.Fatalf("%s: %d: Decoder.ReadToken = %v, want %v", where, i, gotOut, wantOut)
   676  			}
   677  		case RawValue:
   678  			var gotOut RawValue
   679  			gotOut, gotErr = dec.ReadValue()
   680  			if string(gotOut) != string(wantOut) {
   681  				t.Fatalf("%s: %d: Decoder.ReadValue = %s, want %s", where, i, gotOut, wantOut)
   682  			}
   683  		}
   684  		if !reflect.DeepEqual(gotErr, call.wantErr) {
   685  			t.Fatalf("%s: %d: error mismatch: got %#v, want %#v", where, i, gotErr, call.wantErr)
   686  		}
   687  		if call.wantPointer != "" {
   688  			gotPointer := dec.StackPointer()
   689  			if gotPointer != call.wantPointer {
   690  				t.Fatalf("%s: %d: Decoder.StackPointer = %s, want %s", where, i, gotPointer, call.wantPointer)
   691  			}
   692  		}
   693  	}
   694  	gotOffset := int(dec.InputOffset())
   695  	if gotOffset != wantOffset {
   696  		t.Fatalf("%s: Decoder.InputOffset = %v, want %v", where, gotOffset, wantOffset)
   697  	}
   698  	gotUnread := string(dec.unreadBuffer()) // should be a prefix of wantUnread
   699  	wantUnread := in[wantOffset:]
   700  	if !strings.HasPrefix(wantUnread, gotUnread) {
   701  		t.Fatalf("%s: Decoder.UnreadBuffer = %v, want %v", where, gotUnread, wantUnread)
   702  	}
   703  }
   704  
   705  var resumableDecoderTestdata = []string{
   706  	`0`,
   707  	`123456789`,
   708  	`0.0`,
   709  	`0.123456789`,
   710  	`0e0`,
   711  	`0e+0`,
   712  	`0e123456789`,
   713  	`0e+123456789`,
   714  	`123456789.123456789e+123456789`,
   715  	`-0`,
   716  	`-123456789`,
   717  	`-0.0`,
   718  	`-0.123456789`,
   719  	`-0e0`,
   720  	`-0e-0`,
   721  	`-0e123456789`,
   722  	`-0e-123456789`,
   723  	`-123456789.123456789e-123456789`,
   724  
   725  	`""`,
   726  	`"a"`,
   727  	`"ab"`,
   728  	`"abc"`,
   729  	`"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"`,
   730  	`"\"\\\/\b\f\n\r\t"`,
   731  	`"\u0022\u005c\u002f\u0008\u000c\u000a\u000d\u0009"`,
   732  	`"\ud800\udead"`,
   733  	"\"\u0080\u00f6\u20ac\ud799\ue000\ufb33\ufffd\U0001f602\"",
   734  	`"\u0080\u00f6\u20ac\ud799\ue000\ufb33\ufffd\ud83d\ude02"`,
   735  }
   736  
   737  // TestBufferDecoder tests that we detect misuses of bytes.Buffer with Decoder.
   738  func TestBufferDecoder(t *testing.T) {
   739  	bb := bytes.NewBufferString("[null, false, true]")
   740  	dec := NewDecoder(bb)
   741  	var err error
   742  	for {
   743  		if _, err = dec.ReadToken(); err != nil {
   744  			break
   745  		}
   746  		bb.WriteByte(' ') // not allowed to write to the buffer while reading
   747  	}
   748  	want := &ioError{action: "read", err: errBufferWriteAfterNext}
   749  	if !reflect.DeepEqual(err, want) {
   750  		t.Fatalf("error mismatch: got %v, want %v", err, want)
   751  	}
   752  }
   753  
   754  // TestResumableDecoder tests that resume logic for parsing a
   755  // JSON string and number properly works across every possible split point.
   756  func TestResumableDecoder(t *testing.T) {
   757  	for _, want := range resumableDecoderTestdata {
   758  		t.Run("", func(t *testing.T) {
   759  			dec := NewDecoder(iotest.OneByteReader(strings.NewReader(want)))
   760  			got, err := dec.ReadValue()
   761  			if err != nil {
   762  				t.Fatalf("Decoder.ReadValue error: %v", err)
   763  			}
   764  			if string(got) != want {
   765  				t.Fatalf("Decoder.ReadValue = %s, want %s", got, want)
   766  			}
   767  		})
   768  	}
   769  }
   770  
   771  // TestBlockingDecoder verifies that JSON values except numbers can be
   772  // synchronously sent and received on a blocking pipe without a deadlock.
   773  // Numbers are the exception since termination cannot be determined until
   774  // either the pipe ends or a non-numeric character is encountered.
   775  func TestBlockingDecoder(t *testing.T) {
   776  	values := []string{"null", "false", "true", `""`, `{}`, `[]`}
   777  
   778  	r, w := net.Pipe()
   779  	defer r.Close()
   780  	defer w.Close()
   781  
   782  	enc := NewEncoder(w)
   783  	enc.options.omitTopLevelNewline = true
   784  	dec := NewDecoder(r)
   785  
   786  	errCh := make(chan error)
   787  
   788  	// Test synchronous ReadToken calls.
   789  	for _, want := range values {
   790  		go func() {
   791  			errCh <- enc.WriteValue(RawValue(want))
   792  		}()
   793  
   794  		tok, err := dec.ReadToken()
   795  		if err != nil {
   796  			t.Fatalf("Decoder.ReadToken error: %v", err)
   797  		}
   798  		got := tok.String()
   799  		switch tok.Kind() {
   800  		case '"':
   801  			got = `"` + got + `"`
   802  		case '{', '[':
   803  			tok, err := dec.ReadToken()
   804  			if err != nil {
   805  				t.Fatalf("Decoder.ReadToken error: %v", err)
   806  			}
   807  			got += tok.String()
   808  		}
   809  		if got != want {
   810  			t.Fatalf("ReadTokens = %s, want %s", got, want)
   811  		}
   812  
   813  		if err := <-errCh; err != nil {
   814  			t.Fatalf("Encoder.WriteValue error: %v", err)
   815  		}
   816  	}
   817  
   818  	// Test synchronous ReadValue calls.
   819  	for _, want := range values {
   820  		go func() {
   821  			errCh <- enc.WriteValue(RawValue(want))
   822  		}()
   823  
   824  		got, err := dec.ReadValue()
   825  		if err != nil {
   826  			t.Fatalf("Decoder.ReadValue error: %v", err)
   827  		}
   828  		if string(got) != want {
   829  			t.Fatalf("ReadValue = %s, want %s", got, want)
   830  		}
   831  
   832  		if err := <-errCh; err != nil {
   833  			t.Fatalf("Encoder.WriteValue error: %v", err)
   834  		}
   835  	}
   836  }
   837  
   838  func TestPeekableDecoder(t *testing.T) {
   839  	type operation any // PeekKind | ReadToken | ReadValue | BufferWrite
   840  	type PeekKind struct {
   841  		want Kind
   842  	}
   843  	type ReadToken struct {
   844  		wantKind Kind
   845  		wantErr  error
   846  	}
   847  	type ReadValue struct {
   848  		wantKind Kind
   849  		wantErr  error
   850  	}
   851  	type WriteString struct {
   852  		in string
   853  	}
   854  	ops := []operation{
   855  		PeekKind{0},
   856  		WriteString{"[ "},
   857  		ReadToken{0, io.EOF}, // previous error from PeekKind is cached once
   858  		ReadToken{'[', nil},
   859  
   860  		PeekKind{0},
   861  		WriteString{"] "},
   862  		ReadValue{0, io.ErrUnexpectedEOF}, // previous error from PeekKind is cached once
   863  		ReadValue{0, newInvalidCharacterError([]byte("]"), "at start of value").withOffset(2)},
   864  		ReadToken{']', nil},
   865  
   866  		WriteString{"[ "},
   867  		ReadToken{'[', nil},
   868  
   869  		WriteString{" null "},
   870  		PeekKind{'n'},
   871  		PeekKind{'n'},
   872  		ReadToken{'n', nil},
   873  
   874  		WriteString{", "},
   875  		PeekKind{0},
   876  		WriteString{"fal"},
   877  		PeekKind{'f'},
   878  		ReadValue{0, io.ErrUnexpectedEOF},
   879  		WriteString{"se "},
   880  		ReadValue{'f', nil},
   881  
   882  		PeekKind{0},
   883  		WriteString{" , "},
   884  		PeekKind{0},
   885  		WriteString{` "" `},
   886  		ReadValue{0, io.ErrUnexpectedEOF}, // previous error from PeekKind is cached once
   887  		ReadValue{'"', nil},
   888  
   889  		WriteString{" , 0"},
   890  		PeekKind{'0'},
   891  		ReadToken{'0', nil},
   892  
   893  		WriteString{" , {} , []"},
   894  		PeekKind{'{'},
   895  		ReadValue{'{', nil},
   896  		ReadValue{'[', nil},
   897  
   898  		WriteString{"]"},
   899  		ReadToken{']', nil},
   900  	}
   901  
   902  	bb := struct{ *bytes.Buffer }{new(bytes.Buffer)}
   903  	d := NewDecoder(bb)
   904  	for i, op := range ops {
   905  		switch op := op.(type) {
   906  		case PeekKind:
   907  			if got := d.PeekKind(); got != op.want {
   908  				t.Fatalf("%d: Decoder.PeekKind() = %v, want %v", i, got, op.want)
   909  			}
   910  		case ReadToken:
   911  			gotTok, gotErr := d.ReadToken()
   912  			gotKind := gotTok.Kind()
   913  			if gotKind != op.wantKind || !reflect.DeepEqual(gotErr, op.wantErr) {
   914  				t.Fatalf("%d: Decoder.ReadToken() = (%v, %v), want (%v, %v)", i, gotKind, gotErr, op.wantKind, op.wantErr)
   915  			}
   916  		case ReadValue:
   917  			gotVal, gotErr := d.ReadValue()
   918  			gotKind := gotVal.Kind()
   919  			if gotKind != op.wantKind || !reflect.DeepEqual(gotErr, op.wantErr) {
   920  				t.Fatalf("%d: Decoder.ReadValue() = (%v, %v), want (%v, %v)", i, gotKind, gotErr, op.wantKind, op.wantErr)
   921  			}
   922  		case WriteString:
   923  			bb.WriteString(op.in)
   924  		default:
   925  			panic(fmt.Sprintf("unknown operation: %T", op))
   926  		}
   927  	}
   928  }
   929  
   930  func TestConsumeWhitespace(t *testing.T) {
   931  	tests := []struct {
   932  		in   string
   933  		want int
   934  	}{
   935  		{"", 0},
   936  		{"a", 0},
   937  		{" a", 1},
   938  		{" a ", 1},
   939  		{" \n\r\ta", 4},
   940  		{" \n\r\t \n\r\t \n\r\t \n\r\t", 16},
   941  		{"\u00a0", 0}, // non-breaking space is not JSON whitespace
   942  	}
   943  
   944  	for _, tt := range tests {
   945  		t.Run("", func(t *testing.T) {
   946  			if got := consumeWhitespace([]byte(tt.in)); got != tt.want {
   947  				t.Errorf("consumeWhitespace(%q) = %v, want %v", tt.in, got, tt.want)
   948  			}
   949  		})
   950  	}
   951  }
   952  
   953  func TestConsumeLiteral(t *testing.T) {
   954  	tests := []struct {
   955  		literal string
   956  		in      string
   957  		want    int
   958  		wantErr error
   959  	}{
   960  		{"null", "", 0, io.ErrUnexpectedEOF},
   961  		{"null", "n", 1, io.ErrUnexpectedEOF},
   962  		{"null", "nu", 2, io.ErrUnexpectedEOF},
   963  		{"null", "nul", 3, io.ErrUnexpectedEOF},
   964  		{"null", "null", 4, nil},
   965  		{"null", "nullx", 4, nil},
   966  		{"null", "x", 0, newInvalidCharacterError([]byte("x"), "within literal null (expecting 'n')")},
   967  		{"null", "nuxx", 2, newInvalidCharacterError([]byte("x"), "within literal null (expecting 'l')")},
   968  
   969  		{"false", "", 0, io.ErrUnexpectedEOF},
   970  		{"false", "f", 1, io.ErrUnexpectedEOF},
   971  		{"false", "fa", 2, io.ErrUnexpectedEOF},
   972  		{"false", "fal", 3, io.ErrUnexpectedEOF},
   973  		{"false", "fals", 4, io.ErrUnexpectedEOF},
   974  		{"false", "false", 5, nil},
   975  		{"false", "falsex", 5, nil},
   976  		{"false", "x", 0, newInvalidCharacterError([]byte("x"), "within literal false (expecting 'f')")},
   977  		{"false", "falsx", 4, newInvalidCharacterError([]byte("x"), "within literal false (expecting 'e')")},
   978  
   979  		{"true", "", 0, io.ErrUnexpectedEOF},
   980  		{"true", "t", 1, io.ErrUnexpectedEOF},
   981  		{"true", "tr", 2, io.ErrUnexpectedEOF},
   982  		{"true", "tru", 3, io.ErrUnexpectedEOF},
   983  		{"true", "true", 4, nil},
   984  		{"true", "truex", 4, nil},
   985  		{"true", "x", 0, newInvalidCharacterError([]byte("x"), "within literal true (expecting 't')")},
   986  		{"true", "trux", 3, newInvalidCharacterError([]byte("x"), "within literal true (expecting 'e')")},
   987  	}
   988  
   989  	for _, tt := range tests {
   990  		t.Run("", func(t *testing.T) {
   991  			var got int
   992  			switch tt.literal {
   993  			case "null":
   994  				got = consumeNull([]byte(tt.in))
   995  			case "false":
   996  				got = consumeFalse([]byte(tt.in))
   997  			case "true":
   998  				got = consumeTrue([]byte(tt.in))
   999  			default:
  1000  				t.Errorf("invalid literal: %v", tt.literal)
  1001  			}
  1002  			switch {
  1003  			case tt.wantErr == nil && got != tt.want:
  1004  				t.Errorf("consume%v(%q) = %v, want %v", strings.Title(tt.literal), tt.in, got, tt.want)
  1005  			case tt.wantErr != nil && got != 0:
  1006  				t.Errorf("consume%v(%q) = %v, want %v", strings.Title(tt.literal), tt.in, got, 0)
  1007  			}
  1008  
  1009  			got, gotErr := consumeLiteral([]byte(tt.in), tt.literal)
  1010  			if got != tt.want || !reflect.DeepEqual(gotErr, tt.wantErr) {
  1011  				t.Errorf("consumeLiteral(%q, %q) = (%v, %v), want (%v, %v)", tt.in, tt.literal, got, gotErr, tt.want, tt.wantErr)
  1012  			}
  1013  		})
  1014  	}
  1015  }
  1016  
  1017  func TestConsumeString(t *testing.T) {
  1018  	tests := []struct {
  1019  		in          string
  1020  		simple      bool
  1021  		want        int
  1022  		wantFlags   valueFlags
  1023  		wantStr     string
  1024  		wantErr     error
  1025  		wantErrUTF8 error // error if validateUTF8 is specified
  1026  	}{
  1027  		{``, false, 0, 0, "", io.ErrUnexpectedEOF, nil},
  1028  		{`"`, false, 1, 0, "", io.ErrUnexpectedEOF, nil},
  1029  		{`""`, true, 2, 0, "", nil, nil},
  1030  		{`""x`, true, 2, 0, "", nil, nil},
  1031  		{` ""x`, false, 0, 0, "", newInvalidCharacterError([]byte(" "), "at start of string (expecting '\"')"), nil},
  1032  		{`"hello`, false, 6, 0, "hello", io.ErrUnexpectedEOF, nil},
  1033  		{`"hello"`, true, 7, 0, "hello", nil, nil},
  1034  		{"\"\x00\"", false, 1, stringNonVerbatim | stringNonCanonical, "", newInvalidCharacterError([]byte("\x00"), "within string (expecting non-control character)"), nil},
  1035  		{`"\u0000"`, false, 8, stringNonVerbatim, "\x00", nil, nil},
  1036  		{"\"\x1f\"", false, 1, stringNonVerbatim | stringNonCanonical, "", newInvalidCharacterError([]byte("\x1f"), "within string (expecting non-control character)"), nil},
  1037  		{`"\u001f"`, false, 8, stringNonVerbatim, "\x1f", nil, nil},
  1038  		{`"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"`, true, 54, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", nil, nil},
  1039  		{"\" !#$%&'()*+,-./0123456789:;<=>?@[]^_`{|}~\x7f\"", true, 44, 0, " !#$%&'()*+,-./0123456789:;<=>?@[]^_`{|}~\x7f", nil, nil},
  1040  		{"\"x\x80\"", false, 4, stringNonVerbatim | stringNonCanonical, "x\ufffd", nil, &SyntacticError{str: "invalid UTF-8 within string"}},
  1041  		{"\"x\xff\"", false, 4, stringNonVerbatim | stringNonCanonical, "x\ufffd", nil, &SyntacticError{str: "invalid UTF-8 within string"}},
  1042  		{"\"x\xc0", false, 3, stringNonVerbatim | stringNonCanonical, "x\ufffd", io.ErrUnexpectedEOF, &SyntacticError{str: "invalid UTF-8 within string"}},
  1043  		{"\"x\xc0\x80\"", false, 5, stringNonVerbatim | stringNonCanonical, "x\ufffd\ufffd", nil, &SyntacticError{str: "invalid UTF-8 within string"}},
  1044  		{"\"x\xe0", false, 2, 0, "x", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF},
  1045  		{"\"x\xe0\x80", false, 4, stringNonVerbatim | stringNonCanonical, "x\ufffd\ufffd", io.ErrUnexpectedEOF, &SyntacticError{str: "invalid UTF-8 within string"}},
  1046  		{"\"x\xe0\x80\x80\"", false, 6, stringNonVerbatim | stringNonCanonical, "x\ufffd\ufffd\ufffd", nil, &SyntacticError{str: "invalid UTF-8 within string"}},
  1047  		{"\"x\xf0", false, 2, 0, "x", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF},
  1048  		{"\"x\xf0\x80", false, 4, stringNonVerbatim | stringNonCanonical, "x\ufffd\ufffd", io.ErrUnexpectedEOF, &SyntacticError{str: "invalid UTF-8 within string"}},
  1049  		{"\"x\xf0\x80\x80", false, 5, stringNonVerbatim | stringNonCanonical, "x\ufffd\ufffd\ufffd", io.ErrUnexpectedEOF, &SyntacticError{str: "invalid UTF-8 within string"}},
  1050  		{"\"x\xf0\x80\x80\x80\"", false, 7, stringNonVerbatim | stringNonCanonical, "x\ufffd\ufffd\ufffd\ufffd", nil, &SyntacticError{str: "invalid UTF-8 within string"}},
  1051  		{"\"x\xed\xba\xad\"", false, 6, stringNonVerbatim | stringNonCanonical, "x\ufffd\ufffd\ufffd", nil, &SyntacticError{str: "invalid UTF-8 within string"}},
  1052  		{"\"\u0080\u00f6\u20ac\ud799\ue000\ufb33\ufffd\U0001f602\"", false, 25, 0, "\u0080\u00f6\u20ac\ud799\ue000\ufb33\ufffd\U0001f602", nil, nil},
  1053  		{`"¢"`[:2], false, 1, 0, "", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF},
  1054  		{`"¢"`[:3], false, 3, 0, "¢", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF}, // missing terminating quote
  1055  		{`"¢"`[:4], false, 4, 0, "¢", nil, nil},
  1056  		{`"€"`[:2], false, 1, 0, "", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF},
  1057  		{`"€"`[:3], false, 1, 0, "", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF},
  1058  		{`"€"`[:4], false, 4, 0, "€", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF}, // missing terminating quote
  1059  		{`"€"`[:5], false, 5, 0, "€", nil, nil},
  1060  		{`"𐍈"`[:2], false, 1, 0, "", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF},
  1061  		{`"𐍈"`[:3], false, 1, 0, "", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF},
  1062  		{`"𐍈"`[:4], false, 1, 0, "", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF},
  1063  		{`"𐍈"`[:5], false, 5, 0, "𐍈", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF}, // missing terminating quote
  1064  		{`"𐍈"`[:6], false, 6, 0, "𐍈", nil, nil},
  1065  		{`"x\`, false, 2, stringNonVerbatim, "x", io.ErrUnexpectedEOF, nil},
  1066  		{`"x\"`, false, 4, stringNonVerbatim, "x\"", io.ErrUnexpectedEOF, nil},
  1067  		{`"x\x"`, false, 2, stringNonVerbatim | stringNonCanonical, "x", &SyntacticError{str: `invalid escape sequence "\\x" within string`}, nil},
  1068  		{`"\"\\\b\f\n\r\t"`, false, 16, stringNonVerbatim, "\"\\\b\f\n\r\t", nil, nil},
  1069  		{`"/"`, true, 3, 0, "/", nil, nil},
  1070  		{`"\/"`, false, 4, stringNonVerbatim | stringNonCanonical, "/", nil, nil},
  1071  		{`"\u002f"`, false, 8, stringNonVerbatim | stringNonCanonical, "/", nil, nil},
  1072  		{`"\u`, false, 1, stringNonVerbatim, "", io.ErrUnexpectedEOF, nil},
  1073  		{`"\uf`, false, 1, stringNonVerbatim, "", io.ErrUnexpectedEOF, nil},
  1074  		{`"\uff`, false, 1, stringNonVerbatim, "", io.ErrUnexpectedEOF, nil},
  1075  		{`"\ufff`, false, 1, stringNonVerbatim, "", io.ErrUnexpectedEOF, nil},
  1076  		{`"\ufffd`, false, 7, stringNonVerbatim | stringNonCanonical, "\ufffd", io.ErrUnexpectedEOF, nil},
  1077  		{`"\ufffd"`, false, 8, stringNonVerbatim | stringNonCanonical, "\ufffd", nil, nil},
  1078  		{`"\uABCD"`, false, 8, stringNonVerbatim | stringNonCanonical, "\uabcd", nil, nil},
  1079  		{`"\uefX0"`, false, 1, stringNonVerbatim | stringNonCanonical, "", &SyntacticError{str: `invalid escape sequence "\\uefX0" within string`}, nil},
  1080  		{`"\uDEAD`, false, 7, stringNonVerbatim | stringNonCanonical, "\ufffd", io.ErrUnexpectedEOF, io.ErrUnexpectedEOF},
  1081  		{`"\uDEAD"`, false, 8, stringNonVerbatim | stringNonCanonical, "\ufffd", nil, &SyntacticError{str: `invalid escape sequence "\"" within string`}},
  1082  		{`"\uDEAD______"`, false, 14, stringNonVerbatim | stringNonCanonical, "\ufffd______", nil, &SyntacticError{str: "invalid unpaired surrogate half within string"}},
  1083  		{`"\uDEAD\uXXXX"`, false, 7, stringNonVerbatim | stringNonCanonical, "\ufffd", &SyntacticError{str: `invalid escape sequence "\\uXXXX" within string`}, nil},
  1084  		{`"\uDEAD\uBEEF"`, false, 14, stringNonVerbatim | stringNonCanonical, "\ufffd\ubeef", nil, &SyntacticError{str: `invalid surrogate pair in string`}},
  1085  		{`"\uD800\udead"`, false, 14, stringNonVerbatim | stringNonCanonical, "\U000102ad", nil, nil},
  1086  		{`"\u0022\u005c\u002f\u0008\u000c\u000a\u000d\u0009"`, false, 50, stringNonVerbatim | stringNonCanonical, "\"\\/\b\f\n\r\t", nil, nil},
  1087  		{`"\u0080\u00f6\u20ac\ud799\ue000\ufb33\ufffd\ud83d\ude02"`, false, 56, stringNonVerbatim | stringNonCanonical, "\u0080\u00f6\u20ac\ud799\ue000\ufb33\ufffd\U0001f602", nil, nil},
  1088  	}
  1089  
  1090  	for _, tt := range tests {
  1091  		t.Run("", func(t *testing.T) {
  1092  			switch got := consumeSimpleString([]byte(tt.in)); {
  1093  			case tt.simple && got != tt.want:
  1094  				t.Errorf("consumeSimpleString(%q) = %v, want %v", tt.in, got, tt.want)
  1095  			case !tt.simple && got != 0:
  1096  				t.Errorf("consumeSimpleString(%q) = %v, want %v", tt.in, got, 0)
  1097  			}
  1098  
  1099  			var gotFlags valueFlags
  1100  			got, gotErr := consumeString(&gotFlags, []byte(tt.in), false)
  1101  			if gotFlags != tt.wantFlags {
  1102  				t.Errorf("consumeString(%q, false) flags = %v, want %v", tt.in, gotFlags, tt.wantFlags)
  1103  			}
  1104  			if got != tt.want || !reflect.DeepEqual(gotErr, tt.wantErr) {
  1105  				t.Errorf("consumeString(%q, false) = (%v, %v), want (%v, %v)", tt.in, got, gotErr, tt.want, tt.wantErr)
  1106  			}
  1107  			switch got, gotErr := consumeString(&gotFlags, []byte(tt.in), true); {
  1108  			case tt.wantErrUTF8 == nil && (got != tt.want || !reflect.DeepEqual(gotErr, tt.wantErr)):
  1109  				t.Errorf("consumeString(%q, true) = (%v, %v), want (%v, %v)", tt.in, got, gotErr, tt.want, tt.wantErr)
  1110  			case tt.wantErrUTF8 != nil && (got > tt.want || !reflect.DeepEqual(gotErr, tt.wantErrUTF8)):
  1111  				t.Errorf("consumeString(%q, true) = (%v, %v), want (%v, %v)", tt.in, got, gotErr, tt.want, tt.wantErrUTF8)
  1112  			}
  1113  
  1114  			gotStr, gotOk := unescapeString(nil, []byte(tt.in[:got]))
  1115  			wantOk := tt.wantErr == nil
  1116  			if string(gotStr) != tt.wantStr || gotOk != wantOk {
  1117  				t.Errorf("unescapeString(nil, %q) = (%q, %v), want (%q, %v)", tt.in[:got], gotStr, gotOk, tt.wantStr, wantOk)
  1118  			}
  1119  			if _, gotOk := unescapeString(nil, []byte(tt.in)); got < len(tt.in) && gotOk {
  1120  				t.Errorf("unescapeString(nil, %q) = (_, true), want (_, false)", tt.in)
  1121  			}
  1122  		})
  1123  	}
  1124  }
  1125  
  1126  func TestConsumeNumber(t *testing.T) {
  1127  	tests := []struct {
  1128  		in      string
  1129  		simple  bool
  1130  		want    int
  1131  		wantErr error
  1132  	}{
  1133  		{"", false, 0, io.ErrUnexpectedEOF},
  1134  		{`"NaN"`, false, 0, newInvalidCharacterError([]byte("\""), "within number (expecting digit)")},
  1135  		{`"Infinity"`, false, 0, newInvalidCharacterError([]byte("\""), "within number (expecting digit)")},
  1136  		{`"-Infinity"`, false, 0, newInvalidCharacterError([]byte("\""), "within number (expecting digit)")},
  1137  		{".0", false, 0, newInvalidCharacterError([]byte("."), "within number (expecting digit)")},
  1138  		{"0", true, 1, nil},
  1139  		{"-0", false, 2, nil},
  1140  		{"+0", false, 0, newInvalidCharacterError([]byte("+"), "within number (expecting digit)")},
  1141  		{"1", true, 1, nil},
  1142  		{"-1", false, 2, nil},
  1143  		{"00", true, 1, nil},
  1144  		{"-00", false, 2, nil},
  1145  		{"01", true, 1, nil},
  1146  		{"-01", false, 2, nil},
  1147  		{"0i", true, 1, nil},
  1148  		{"-0i", false, 2, nil},
  1149  		{"0f", true, 1, nil},
  1150  		{"-0f", false, 2, nil},
  1151  		{"9876543210", true, 10, nil},
  1152  		{"-9876543210", false, 11, nil},
  1153  		{"9876543210x", true, 10, nil},
  1154  		{"-9876543210x", false, 11, nil},
  1155  		{" 9876543210", true, 0, newInvalidCharacterError([]byte(" "), "within number (expecting digit)")},
  1156  		{"- 9876543210", false, 1, newInvalidCharacterError([]byte(" "), "within number (expecting digit)")},
  1157  		{strings.Repeat("9876543210", 1000), true, 10000, nil},
  1158  		{"-" + strings.Repeat("9876543210", 1000), false, 1 + 10000, nil},
  1159  		{"0.", false, 1, io.ErrUnexpectedEOF},
  1160  		{"-0.", false, 2, io.ErrUnexpectedEOF},
  1161  		{"0e", false, 1, io.ErrUnexpectedEOF},
  1162  		{"-0e", false, 2, io.ErrUnexpectedEOF},
  1163  		{"0E", false, 1, io.ErrUnexpectedEOF},
  1164  		{"-0E", false, 2, io.ErrUnexpectedEOF},
  1165  		{"0.0", false, 3, nil},
  1166  		{"-0.0", false, 4, nil},
  1167  		{"0e0", false, 3, nil},
  1168  		{"-0e0", false, 4, nil},
  1169  		{"0E0", false, 3, nil},
  1170  		{"-0E0", false, 4, nil},
  1171  		{"0.0123456789", false, 12, nil},
  1172  		{"-0.0123456789", false, 13, nil},
  1173  		{"1.f", false, 2, newInvalidCharacterError([]byte("f"), "within number (expecting digit)")},
  1174  		{"-1.f", false, 3, newInvalidCharacterError([]byte("f"), "within number (expecting digit)")},
  1175  		{"1.e", false, 2, newInvalidCharacterError([]byte("e"), "within number (expecting digit)")},
  1176  		{"-1.e", false, 3, newInvalidCharacterError([]byte("e"), "within number (expecting digit)")},
  1177  		{"1e0", false, 3, nil},
  1178  		{"-1e0", false, 4, nil},
  1179  		{"1E0", false, 3, nil},
  1180  		{"-1E0", false, 4, nil},
  1181  		{"1Ex", false, 2, newInvalidCharacterError([]byte("x"), "within number (expecting digit)")},
  1182  		{"-1Ex", false, 3, newInvalidCharacterError([]byte("x"), "within number (expecting digit)")},
  1183  		{"1e-0", false, 4, nil},
  1184  		{"-1e-0", false, 5, nil},
  1185  		{"1e+0", false, 4, nil},
  1186  		{"-1e+0", false, 5, nil},
  1187  		{"1E-0", false, 4, nil},
  1188  		{"-1E-0", false, 5, nil},
  1189  		{"1E+0", false, 4, nil},
  1190  		{"-1E+0", false, 5, nil},
  1191  		{"1E+00500", false, 8, nil},
  1192  		{"-1E+00500", false, 9, nil},
  1193  		{"1E+00500x", false, 8, nil},
  1194  		{"-1E+00500x", false, 9, nil},
  1195  		{"9876543210.0123456789e+01234589x", false, 31, nil},
  1196  		{"-9876543210.0123456789e+01234589x", false, 32, nil},
  1197  		{"1_000_000", true, 1, nil},
  1198  		{"0x12ef", true, 1, nil},
  1199  		{"0x1p-2", true, 1, nil},
  1200  	}
  1201  
  1202  	for _, tt := range tests {
  1203  		t.Run("", func(t *testing.T) {
  1204  			switch got := consumeSimpleNumber([]byte(tt.in)); {
  1205  			case tt.simple && got != tt.want:
  1206  				t.Errorf("consumeSimpleNumber(%q) = %v, want %v", tt.in, got, tt.want)
  1207  			case !tt.simple && got != 0:
  1208  				t.Errorf("consumeSimpleNumber(%q) = %v, want %v", tt.in, got, 0)
  1209  			}
  1210  
  1211  			got, gotErr := consumeNumber([]byte(tt.in))
  1212  			if got != tt.want || !reflect.DeepEqual(gotErr, tt.wantErr) {
  1213  				t.Errorf("consumeNumber(%q) = (%v, %v), want (%v, %v)", tt.in, got, gotErr, tt.want, tt.wantErr)
  1214  			}
  1215  		})
  1216  	}
  1217  }
  1218  
  1219  func TestParseHexUint16(t *testing.T) {
  1220  	tests := []struct {
  1221  		in     string
  1222  		want   uint16
  1223  		wantOk bool
  1224  	}{
  1225  		{"", 0, false},
  1226  		{"a", 0, false},
  1227  		{"ab", 0, false},
  1228  		{"abc", 0, false},
  1229  		{"abcd", 0xabcd, true},
  1230  		{"abcde", 0, false},
  1231  		{"9eA1", 0x9ea1, true},
  1232  		{"gggg", 0, false},
  1233  		{"0000", 0x0000, true},
  1234  		{"1234", 0x1234, true},
  1235  	}
  1236  
  1237  	for _, tt := range tests {
  1238  		t.Run("", func(t *testing.T) {
  1239  			got, gotOk := parseHexUint16([]byte(tt.in))
  1240  			if got != tt.want || gotOk != tt.wantOk {
  1241  				t.Errorf("parseHexUint16(%q) = (0x%04x, %v), want (0x%04x, %v)", tt.in, got, gotOk, tt.want, tt.wantOk)
  1242  			}
  1243  		})
  1244  	}
  1245  }
  1246  
  1247  func TestParseDecUint(t *testing.T) {
  1248  	tests := []struct {
  1249  		in     string
  1250  		want   uint64
  1251  		wantOk bool
  1252  	}{
  1253  		{"", 0, false},
  1254  		{"0", 0, true},
  1255  		{"1", 1, true},
  1256  		{"-1", 0, false},
  1257  		{"1f", 0, false},
  1258  		{"00", 0, true},
  1259  		{"01", 1, true},
  1260  		{"10", 10, true},
  1261  		{"10.9", 0, false},
  1262  		{" 10", 0, false},
  1263  		{"10 ", 0, false},
  1264  		{"123456789", 123456789, true},
  1265  		{"123456789d", 0, false},
  1266  		{"18446744073709551614", math.MaxUint64 - 1, true},
  1267  		{"18446744073709551615", math.MaxUint64, true},
  1268  		{"99999999999999999999999999999999", math.MaxUint64, false},
  1269  		{"99999999999999999999999999999999f", 0, false},
  1270  	}
  1271  
  1272  	for _, tt := range tests {
  1273  		t.Run("", func(t *testing.T) {
  1274  			got, gotOk := parseDecUint([]byte(tt.in))
  1275  			if got != tt.want || gotOk != tt.wantOk {
  1276  				t.Errorf("parseDecUint(%q) = (%v, %v), want (%v, %v)", tt.in, got, gotOk, tt.want, tt.wantOk)
  1277  			}
  1278  		})
  1279  	}
  1280  }
  1281  
  1282  func TestParseFloat(t *testing.T) {
  1283  	tests := []struct {
  1284  		in     string
  1285  		want32 float64
  1286  		want64 float64
  1287  		wantOk bool
  1288  	}{
  1289  		{"0", 0, 0, true},
  1290  		{"-1", -1, -1, true},
  1291  		{"1", 1, 1, true},
  1292  
  1293  		{"-16777215", -16777215, -16777215, true}, // -(1<<24 - 1)
  1294  		{"16777215", 16777215, 16777215, true},    // +(1<<24 - 1)
  1295  		{"-16777216", -16777216, -16777216, true}, // -(1<<24)
  1296  		{"16777216", 16777216, 16777216, true},    // +(1<<24)
  1297  		{"-16777217", -16777216, -16777217, true}, // -(1<<24 + 1)
  1298  		{"16777217", 16777216, 16777217, true},    // +(1<<24 + 1)
  1299  
  1300  		{"-9007199254740991", -9007199254740992, -9007199254740991, true}, // -(1<<53 - 1)
  1301  		{"9007199254740991", 9007199254740992, 9007199254740991, true},    // +(1<<53 - 1)
  1302  		{"-9007199254740992", -9007199254740992, -9007199254740992, true}, // -(1<<53)
  1303  		{"9007199254740992", 9007199254740992, 9007199254740992, true},    // +(1<<53)
  1304  		{"-9007199254740993", -9007199254740992, -9007199254740992, true}, // -(1<<53 + 1)
  1305  		{"9007199254740993", 9007199254740992, 9007199254740992, true},    // +(1<<53 + 1)
  1306  
  1307  		{"-1e1000", -math.MaxFloat32, -math.MaxFloat64, true},
  1308  		{"1e1000", +math.MaxFloat32, +math.MaxFloat64, true},
  1309  	}
  1310  
  1311  	for _, tt := range tests {
  1312  		t.Run("", func(t *testing.T) {
  1313  			got32, gotOk32 := parseFloat([]byte(tt.in), 32)
  1314  			if got32 != tt.want32 || gotOk32 != tt.wantOk {
  1315  				t.Errorf("parseFloat(%q, 32) = (%v, %v), want (%v, %v)", tt.in, got32, gotOk32, tt.want32, tt.wantOk)
  1316  			}
  1317  
  1318  			got64, gotOk64 := parseFloat([]byte(tt.in), 64)
  1319  			if got64 != tt.want64 || gotOk64 != tt.wantOk {
  1320  				t.Errorf("parseFloat(%q, 64) = (%v, %v), want (%v, %v)", tt.in, got64, gotOk64, tt.want64, tt.wantOk)
  1321  			}
  1322  		})
  1323  	}
  1324  }