| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089 |
- // Copyright 2019 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package json_test
- import (
- "strings"
- "testing"
- "unicode/utf8"
- "github.com/golang/protobuf/v2/internal/encoding/json"
- )
- type R struct {
- // T is expected Type returned from calling Decoder.Read.
- T json.Type
- // E is expected error substring from calling Decoder.Read if set.
- E string
- // V is expected value from calling
- // Value.{Bool()|Float()|Int()|Uint()|String()} depending on type.
- V interface{}
- // VE is expected error substring from calling
- // Value.{Bool()|Float()|Int()|Uint()|String()} depending on type if set.
- VE string
- }
- func TestDecoder(t *testing.T) {
- const space = " \n\r\t"
- tests := []struct {
- input string
- // want is a list of expected values returned from calling
- // Decoder.Read. An item makes the test code invoke
- // Decoder.Read and compare against R.T and R.E. For Bool,
- // Number and String tokens, it invokes the corresponding getter method
- // and compares the returned value against R.V or R.VE if it returned an
- // error.
- want []R
- }{
- {
- input: ``,
- want: []R{{T: json.EOF}},
- },
- {
- input: space,
- want: []R{{T: json.EOF}},
- },
- {
- // Calling Read after EOF will keep returning EOF for
- // succeeding Read calls.
- input: space,
- want: []R{
- {T: json.EOF},
- {T: json.EOF},
- {T: json.EOF},
- },
- },
- // JSON literals.
- {
- input: space + `null` + space,
- want: []R{
- {T: json.Null},
- {T: json.EOF},
- },
- },
- {
- input: space + `true` + space,
- want: []R{
- {T: json.Bool, V: true},
- {T: json.EOF},
- },
- },
- {
- input: space + `false` + space,
- want: []R{
- {T: json.Bool, V: false},
- {T: json.EOF},
- },
- },
- {
- // Error returned will produce the same error again.
- input: space + `foo` + space,
- want: []R{
- {E: `invalid value foo`},
- {E: `invalid value foo`},
- },
- },
- // JSON strings.
- {
- input: space + `""` + space,
- want: []R{
- {T: json.String, V: ""},
- {T: json.EOF},
- },
- },
- {
- input: space + `"hello"` + space,
- want: []R{
- {T: json.String, V: "hello"},
- {T: json.EOF},
- },
- },
- {
- input: `"hello`,
- want: []R{{E: `unexpected EOF`}},
- },
- {
- input: "\"\x00\"",
- want: []R{{E: `invalid character '\x00' in string`}},
- },
- {
- input: "\"\u0031\u0032\"",
- want: []R{
- {T: json.String, V: "12"},
- {T: json.EOF},
- },
- },
- {
- // Invalid UTF-8 error is returned in ReadString instead of Read.
- input: "\"\xff\"",
- want: []R{
- {T: json.String, E: `invalid UTF-8 detected`, V: string("\xff")},
- {T: json.EOF},
- },
- },
- {
- input: `"` + string(utf8.RuneError) + `"`,
- want: []R{
- {T: json.String, V: string(utf8.RuneError)},
- {T: json.EOF},
- },
- },
- {
- input: `"\uFFFD"`,
- want: []R{
- {T: json.String, V: string(utf8.RuneError)},
- {T: json.EOF},
- },
- },
- {
- input: `"\x"`,
- want: []R{{E: `invalid escape code "\\x" in string`}},
- },
- {
- input: `"\uXXXX"`,
- want: []R{{E: `invalid escape code "\\uXXXX" in string`}},
- },
- {
- input: `"\uDEAD"`, // unmatched surrogate pair
- want: []R{{E: `unexpected EOF`}},
- },
- {
- input: `"\uDEAD\uBEEF"`, // invalid surrogate half
- want: []R{{E: `invalid escape code "\\uBEEF" in string`}},
- },
- {
- input: `"\uD800\udead"`, // valid surrogate pair
- want: []R{
- {T: json.String, V: `𐊭`},
- {T: json.EOF},
- },
- },
- {
- input: `"\u0000\"\\\/\b\f\n\r\t"`,
- want: []R{
- {T: json.String, V: "\u0000\"\\/\b\f\n\r\t"},
- {T: json.EOF},
- },
- },
- // Invalid JSON numbers.
- {
- input: `-`,
- want: []R{{E: `invalid number -`}},
- },
- {
- input: `+0`,
- want: []R{{E: `invalid value +0`}},
- },
- {
- input: `-+`,
- want: []R{{E: `invalid number -+`}},
- },
- {
- input: `0.`,
- want: []R{{E: `invalid number 0.`}},
- },
- {
- input: `.1`,
- want: []R{{E: `invalid value .1`}},
- },
- {
- input: `1.0.1`,
- want: []R{{E: `invalid number 1.0.1`}},
- },
- {
- input: `1..1`,
- want: []R{{E: `invalid number 1..1`}},
- },
- {
- input: `-1-2`,
- want: []R{{E: `invalid number -1-2`}},
- },
- {
- input: `01`,
- want: []R{{E: `invalid number 01`}},
- },
- {
- input: `1e`,
- want: []R{{E: `invalid number 1e`}},
- },
- {
- input: `1e1.2`,
- want: []R{{E: `invalid number 1e1.2`}},
- },
- {
- input: `1Ee`,
- want: []R{{E: `invalid number 1Ee`}},
- },
- {
- input: `1.e1`,
- want: []R{{E: `invalid number 1.e1`}},
- },
- {
- input: `1.e+`,
- want: []R{{E: `invalid number 1.e+`}},
- },
- {
- input: `1e+-2`,
- want: []R{{E: `invalid number 1e+-2`}},
- },
- {
- input: `1e--2`,
- want: []R{{E: `invalid number 1e--2`}},
- },
- {
- input: `1.0true`,
- want: []R{{E: `invalid number 1.0true`}},
- },
- // JSON numbers as floating point.
- {
- input: space + `0.0` + space,
- want: []R{
- {T: json.Number, V: float32(0)},
- {T: json.EOF},
- },
- },
- {
- input: space + `0` + space,
- want: []R{
- {T: json.Number, V: float32(0)},
- {T: json.EOF},
- },
- },
- {
- input: space + `-0` + space,
- want: []R{
- {T: json.Number, V: float32(0)},
- {T: json.EOF},
- },
- },
- {
- input: `-1.02`,
- want: []R{
- {T: json.Number, V: float32(-1.02)},
- {T: json.EOF},
- },
- },
- {
- input: `1.020000`,
- want: []R{
- {T: json.Number, V: float32(1.02)},
- {T: json.EOF},
- },
- },
- {
- input: `-1.0e0`,
- want: []R{
- {T: json.Number, V: float32(-1)},
- {T: json.EOF},
- },
- },
- {
- input: `1.0e-000`,
- want: []R{
- {T: json.Number, V: float32(1)},
- {T: json.EOF},
- },
- },
- {
- input: `1e+00`,
- want: []R{
- {T: json.Number, V: float32(1)},
- {T: json.EOF},
- },
- },
- {
- input: `1.02e3`,
- want: []R{
- {T: json.Number, V: float32(1.02e3)},
- {T: json.EOF},
- },
- },
- {
- input: `-1.02E03`,
- want: []R{
- {T: json.Number, V: float32(-1.02e3)},
- {T: json.EOF},
- },
- },
- {
- input: `1.0200e+3`,
- want: []R{
- {T: json.Number, V: float32(1.02e3)},
- {T: json.EOF},
- },
- },
- {
- input: `-1.0200E+03`,
- want: []R{
- {T: json.Number, V: float32(-1.02e3)},
- {T: json.EOF},
- },
- },
- {
- input: `1.0200e-3`,
- want: []R{
- {T: json.Number, V: float32(1.02e-3)},
- {T: json.EOF},
- },
- },
- {
- input: `-1.0200E-03`,
- want: []R{
- {T: json.Number, V: float32(-1.02e-3)},
- {T: json.EOF},
- },
- },
- {
- // Exceeds max float32 limit, but should be ok for float64.
- input: `3.4e39`,
- want: []R{
- {T: json.Number, V: float64(3.4e39)},
- {T: json.EOF},
- },
- },
- {
- // Exceeds max float32 limit.
- input: `3.4e39`,
- want: []R{
- {T: json.Number, V: float32(0), VE: `value out of range`},
- {T: json.EOF},
- },
- },
- {
- // Less than negative max float32 limit.
- input: `-3.4e39`,
- want: []R{
- {T: json.Number, V: float32(0), VE: `value out of range`},
- {T: json.EOF},
- },
- },
- {
- // Exceeds max float64 limit.
- input: `1.79e+309`,
- want: []R{
- {T: json.Number, V: float64(0), VE: `value out of range`},
- {T: json.EOF},
- },
- },
- {
- // Less than negative max float64 limit.
- input: `-1.79e+309`,
- want: []R{
- {T: json.Number, V: float64(0), VE: `value out of range`},
- {T: json.EOF},
- },
- },
- // JSON numbers as signed integers.
- {
- input: space + `0` + space,
- want: []R{
- {T: json.Number, V: int32(0)},
- {T: json.EOF},
- },
- },
- {
- input: space + `-0` + space,
- want: []R{
- {T: json.Number, V: int32(0)},
- {T: json.EOF},
- },
- },
- {
- // Fractional part equals 0 is ok.
- input: `1.00000`,
- want: []R{
- {T: json.Number, V: int32(1)},
- {T: json.EOF},
- },
- },
- {
- // Fractional part not equals 0 returns error.
- input: `1.0000000001`,
- want: []R{
- {T: json.Number, V: int32(0), VE: `cannot convert 1.0000000001 to integer`},
- {T: json.EOF},
- },
- },
- {
- input: `0e0`,
- want: []R{
- {T: json.Number, V: int32(0)},
- {T: json.EOF},
- },
- },
- {
- input: `0.0E0`,
- want: []R{
- {T: json.Number, V: int32(0)},
- {T: json.EOF},
- },
- },
- {
- input: `0.0E10`,
- want: []R{
- {T: json.Number, V: int32(0)},
- {T: json.EOF},
- },
- },
- {
- input: `-1`,
- want: []R{
- {T: json.Number, V: int32(-1)},
- {T: json.EOF},
- },
- },
- {
- input: `1.0e+0`,
- want: []R{
- {T: json.Number, V: int32(1)},
- {T: json.EOF},
- },
- },
- {
- input: `-1E-0`,
- want: []R{
- {T: json.Number, V: int32(-1)},
- {T: json.EOF},
- },
- },
- {
- input: `1E1`,
- want: []R{
- {T: json.Number, V: int32(10)},
- {T: json.EOF},
- },
- },
- {
- input: `-100.00e-02`,
- want: []R{
- {T: json.Number, V: int32(-1)},
- {T: json.EOF},
- },
- },
- {
- input: `0.1200E+02`,
- want: []R{
- {T: json.Number, V: int64(12)},
- {T: json.EOF},
- },
- },
- {
- input: `0.012e2`,
- want: []R{
- {T: json.Number, V: int32(0), VE: `cannot convert 0.012e2 to integer`},
- {T: json.EOF},
- },
- },
- {
- input: `12e-2`,
- want: []R{
- {T: json.Number, V: int32(0), VE: `cannot convert 12e-2 to integer`},
- {T: json.EOF},
- },
- },
- {
- // Exceeds math.MaxInt32.
- input: `2147483648`,
- want: []R{
- {T: json.Number, V: int32(0), VE: `value out of range`},
- {T: json.EOF},
- },
- },
- {
- // Exceeds math.MinInt32.
- input: `-2147483649`,
- want: []R{
- {T: json.Number, V: int32(0), VE: `value out of range`},
- {T: json.EOF},
- },
- },
- {
- // Exceeds math.MaxInt32, but ok for int64.
- input: `2147483648`,
- want: []R{
- {T: json.Number, V: int64(2147483648)},
- {T: json.EOF},
- },
- },
- {
- // Exceeds math.MinInt32, but ok for int64.
- input: `-2147483649`,
- want: []R{
- {T: json.Number, V: int64(-2147483649)},
- {T: json.EOF},
- },
- },
- {
- // Exceeds math.MaxInt64.
- input: `9223372036854775808`,
- want: []R{
- {T: json.Number, V: int64(0), VE: `value out of range`},
- {T: json.EOF},
- },
- },
- {
- // Exceeds math.MinInt64.
- input: `-9223372036854775809`,
- want: []R{
- {T: json.Number, V: int64(0), VE: `value out of range`},
- {T: json.EOF},
- },
- },
- // JSON numbers as unsigned integers.
- {
- input: space + `0` + space,
- want: []R{
- {T: json.Number, V: uint32(0)},
- {T: json.EOF},
- },
- },
- {
- input: space + `-0` + space,
- want: []R{
- {T: json.Number, V: uint32(0)},
- {T: json.EOF},
- },
- },
- {
- input: `-1`,
- want: []R{
- {T: json.Number, V: uint32(0), VE: `invalid syntax`},
- {T: json.EOF},
- },
- },
- {
- // Exceeds math.MaxUint32.
- input: `4294967296`,
- want: []R{
- {T: json.Number, V: uint32(0), VE: `value out of range`},
- {T: json.EOF},
- },
- },
- {
- // Exceeds math.MaxUint64.
- input: `18446744073709551616`,
- want: []R{
- {T: json.Number, V: uint64(0), VE: `value out of range`},
- {T: json.EOF},
- },
- },
- // JSON sequence of values.
- {
- input: `true null`,
- want: []R{
- {T: json.Bool, V: true},
- {E: `unexpected value null`},
- },
- },
- {
- input: "null false",
- want: []R{
- {T: json.Null},
- {E: `unexpected value false`},
- },
- },
- {
- input: `true,false`,
- want: []R{
- {T: json.Bool, V: true},
- {E: `unexpected character ,`},
- },
- },
- {
- input: `47"hello"`,
- want: []R{
- {T: json.Number, V: int32(47)},
- {E: `unexpected value "hello"`},
- },
- },
- {
- input: `47 "hello"`,
- want: []R{
- {T: json.Number, V: int32(47)},
- {E: `unexpected value "hello"`},
- },
- },
- {
- input: `true 42`,
- want: []R{
- {T: json.Bool, V: true},
- {E: `unexpected value 42`},
- },
- },
- // JSON arrays.
- {
- input: space + `[]` + space,
- want: []R{
- {T: json.StartArray},
- {T: json.EndArray},
- {T: json.EOF},
- },
- },
- {
- input: space + `[` + space + `]` + space,
- want: []R{
- {T: json.StartArray},
- {T: json.EndArray},
- {T: json.EOF},
- },
- },
- {
- input: space + `[` + space,
- want: []R{
- {T: json.StartArray},
- {E: `unexpected EOF`},
- },
- },
- {
- input: space + `]` + space,
- want: []R{{E: `unexpected character ]`}},
- },
- {
- input: `[null,true,false, 1e1, "hello" ]`,
- want: []R{
- {T: json.StartArray},
- {T: json.Null},
- {T: json.Bool, V: true},
- {T: json.Bool, V: false},
- {T: json.Number, V: int32(10)},
- {T: json.String, V: "hello"},
- {T: json.EndArray},
- {T: json.EOF},
- },
- },
- {
- input: `[` + space + `true` + space + `,` + space + `"hello"` + space + `]`,
- want: []R{
- {T: json.StartArray},
- {T: json.Bool, V: true},
- {T: json.String, V: "hello"},
- {T: json.EndArray},
- {T: json.EOF},
- },
- },
- {
- input: `[` + space + `true` + space + `,` + space + `]`,
- want: []R{
- {T: json.StartArray},
- {T: json.Bool, V: true},
- {E: `unexpected character ]`},
- },
- },
- {
- input: `[` + space + `false` + space + `]`,
- want: []R{
- {T: json.StartArray},
- {T: json.Bool, V: false},
- {T: json.EndArray},
- {T: json.EOF},
- },
- },
- {
- input: `[` + space + `1` + space + `0` + space + `]`,
- want: []R{
- {T: json.StartArray},
- {T: json.Number, V: int64(1)},
- {E: `unexpected value 0`},
- },
- },
- {
- input: `[null`,
- want: []R{
- {T: json.StartArray},
- {T: json.Null},
- {E: `unexpected EOF`},
- },
- },
- {
- input: `[foo]`,
- want: []R{
- {T: json.StartArray},
- {E: `invalid value foo`},
- },
- },
- {
- input: `[{}, "hello", [true, false], null]`,
- want: []R{
- {T: json.StartArray},
- {T: json.StartObject},
- {T: json.EndObject},
- {T: json.String, V: "hello"},
- {T: json.StartArray},
- {T: json.Bool, V: true},
- {T: json.Bool, V: false},
- {T: json.EndArray},
- {T: json.Null},
- {T: json.EndArray},
- {T: json.EOF},
- },
- },
- {
- input: `[{ ]`,
- want: []R{
- {T: json.StartArray},
- {T: json.StartObject},
- {E: `unexpected character ]`},
- },
- },
- {
- input: `[[ ]`,
- want: []R{
- {T: json.StartArray},
- {T: json.StartArray},
- {T: json.EndArray},
- {E: `unexpected EOF`},
- },
- },
- {
- input: `[,]`,
- want: []R{
- {T: json.StartArray},
- {E: `unexpected character ,`},
- },
- },
- {
- input: `[true "hello"]`,
- want: []R{
- {T: json.StartArray},
- {T: json.Bool, V: true},
- {E: `unexpected value "hello"`},
- },
- },
- {
- input: `[] null`,
- want: []R{
- {T: json.StartArray},
- {T: json.EndArray},
- {E: `unexpected value null`},
- },
- },
- {
- input: `true []`,
- want: []R{
- {T: json.Bool, V: true},
- {E: `unexpected character [`},
- },
- },
- // JSON objects.
- {
- input: space + `{}` + space,
- want: []R{
- {T: json.StartObject},
- {T: json.EndObject},
- {T: json.EOF},
- },
- },
- {
- input: space + `{` + space + `}` + space,
- want: []R{
- {T: json.StartObject},
- {T: json.EndObject},
- {T: json.EOF},
- },
- },
- {
- input: space + `{` + space,
- want: []R{
- {T: json.StartObject},
- {E: `unexpected EOF`},
- },
- },
- {
- input: space + `}` + space,
- want: []R{{E: `unexpected character }`}},
- },
- {
- input: `{` + space + `null` + space + `}`,
- want: []R{
- {T: json.StartObject},
- {E: `unexpected value null`},
- },
- },
- {
- input: `{[]}`,
- want: []R{
- {T: json.StartObject},
- {E: `unexpected character [`},
- },
- },
- {
- input: `{,}`,
- want: []R{
- {T: json.StartObject},
- {E: `unexpected character ,`},
- },
- },
- {
- input: `{"345678"}`,
- want: []R{
- {T: json.StartObject},
- {E: `unexpected character }, missing ":" after object name`},
- },
- },
- {
- input: `{` + space + `"hello"` + space + `:` + space + `"world"` + space + `}`,
- want: []R{
- {T: json.StartObject},
- {T: json.Name, V: "hello"},
- {T: json.String, V: "world"},
- {T: json.EndObject},
- {T: json.EOF},
- },
- },
- {
- input: `{"hello" "world"}`,
- want: []R{
- {T: json.StartObject},
- {E: `unexpected character ", missing ":" after object name`},
- },
- },
- {
- input: `{"hello":`,
- want: []R{
- {T: json.StartObject},
- {T: json.Name, V: "hello"},
- {E: `unexpected EOF`},
- },
- },
- {
- input: `{"hello":"world"`,
- want: []R{
- {T: json.StartObject},
- {T: json.Name, V: "hello"},
- {T: json.String, V: "world"},
- {E: `unexpected EOF`},
- },
- },
- {
- input: `{"hello":"world",`,
- want: []R{
- {T: json.StartObject},
- {T: json.Name, V: "hello"},
- {T: json.String, V: "world"},
- {E: `unexpected EOF`},
- },
- },
- {
- input: `{"34":"89",}`,
- want: []R{
- {T: json.StartObject},
- {T: json.Name, V: "34"},
- {T: json.String, V: "89"},
- {E: `syntax error (line 1:12): unexpected character }`},
- },
- },
- {
- input: `{
- "number": 123e2,
- "bool" : false,
- "object": {"string": "world"},
- "null" : null,
- "array" : [1.01, "hello", true],
- "string": "hello"
- }`,
- want: []R{
- {T: json.StartObject},
- {T: json.Name, V: "number"},
- {T: json.Number, V: int32(12300)},
- {T: json.Name, V: "bool"},
- {T: json.Bool, V: false},
- {T: json.Name, V: "object"},
- {T: json.StartObject},
- {T: json.Name, V: "string"},
- {T: json.String, V: "world"},
- {T: json.EndObject},
- {T: json.Name, V: "null"},
- {T: json.Null},
- {T: json.Name, V: "array"},
- {T: json.StartArray},
- {T: json.Number, V: float32(1.01)},
- {T: json.String, V: "hello"},
- {T: json.Bool, V: true},
- {T: json.EndArray},
- {T: json.Name, V: "string"},
- {T: json.String, V: "hello"},
- {T: json.EndObject},
- {T: json.EOF},
- },
- },
- {
- input: `[
- {"object": {"number": 47}},
- ["list"],
- null
- ]`,
- want: []R{
- {T: json.StartArray},
- {T: json.StartObject},
- {T: json.Name, V: "object"},
- {T: json.StartObject},
- {T: json.Name, V: "number"},
- {T: json.Number, V: uint32(47)},
- {T: json.EndObject},
- {T: json.EndObject},
- {T: json.StartArray},
- {T: json.String, V: "list"},
- {T: json.EndArray},
- {T: json.Null},
- {T: json.EndArray},
- {T: json.EOF},
- },
- },
- // Tests for line and column info.
- {
- input: `12345678 x`,
- want: []R{
- {T: json.Number, V: int64(12345678)},
- {E: `syntax error (line 1:10): invalid value x`},
- },
- },
- {
- input: "\ntrue\n x",
- want: []R{
- {T: json.Bool, V: true},
- {E: `syntax error (line 3:4): invalid value x`},
- },
- },
- {
- input: `"💩"x`,
- want: []R{
- {T: json.String, V: "💩"},
- {E: `syntax error (line 1:4): invalid value x`},
- },
- },
- {
- input: "\n\n[\"🔥🔥🔥\"x",
- want: []R{
- {T: json.StartArray},
- {T: json.String, V: "🔥🔥🔥"},
- {E: `syntax error (line 3:7): invalid value x`},
- },
- },
- {
- // Multi-rune emojis.
- input: `["👍🏻👍🏿"x`,
- want: []R{
- {T: json.StartArray},
- {T: json.String, V: "👍🏻👍🏿"},
- {E: `syntax error (line 1:8): invalid value x`},
- },
- },
- {
- input: `{
- "45678":-1
- }`,
- want: []R{
- {T: json.StartObject},
- {T: json.Name, V: "45678"},
- {T: json.Number, V: uint64(1), VE: "error (line 2:11)"},
- },
- },
- }
- for _, tc := range tests {
- tc := tc
- t.Run("", func(t *testing.T) {
- dec := json.NewDecoder([]byte(tc.input))
- for i, want := range tc.want {
- typ := dec.Peek()
- if typ != want.T {
- t.Errorf("input: %v\nPeek() got %v want %v", tc.input, typ, want.T)
- }
- value, err := dec.Read()
- if err != nil {
- if want.E == "" {
- t.Errorf("input: %v\nRead() got unexpected error: %v", tc.input, err)
- } else if !strings.Contains(err.Error(), want.E) {
- t.Errorf("input: %v\nRead() got %q, want %q", tc.input, err, want.E)
- }
- } else {
- if want.E != "" {
- t.Errorf("input: %v\nRead() got nil error, want %q", tc.input, want.E)
- }
- }
- token := value.Type()
- if token != want.T {
- t.Errorf("input: %v\nRead() got %v, want %v", tc.input, token, want.T)
- break
- }
- checkValue(t, value, i, want)
- }
- })
- }
- }
- func checkValue(t *testing.T, value json.Value, wantIdx int, want R) {
- var got interface{}
- var err error
- switch value.Type() {
- case json.Bool:
- got, err = value.Bool()
- case json.String:
- got = value.String()
- case json.Name:
- got, err = value.Name()
- case json.Number:
- switch want.V.(type) {
- case float32:
- got, err = value.Float(32)
- got = float32(got.(float64))
- case float64:
- got, err = value.Float(64)
- case int32:
- got, err = value.Int(32)
- got = int32(got.(int64))
- case int64:
- got, err = value.Int(64)
- case uint32:
- got, err = value.Uint(32)
- got = uint32(got.(uint64))
- case uint64:
- got, err = value.Uint(64)
- }
- default:
- return
- }
- if err != nil {
- if want.VE == "" {
- t.Errorf("want%d: %v got unexpected error: %v", wantIdx, value, err)
- } else if !strings.Contains(err.Error(), want.VE) {
- t.Errorf("want#%d: %v got %q, want %q", wantIdx, value, err, want.VE)
- }
- return
- } else {
- if want.VE != "" {
- t.Errorf("want#%d: %v got nil error, want %q", wantIdx, value, want.VE)
- return
- }
- }
- if got != want.V {
- t.Errorf("want#%d: %v got %v, want %v", wantIdx, value, got, want.V)
- }
- }
|