| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package json // import "github.com/tdewolff/parse/json"
- import (
- "bytes"
- "fmt"
- "io"
- "testing"
- "github.com/tdewolff/parse"
- "github.com/tdewolff/test"
- )
- type GTs []GrammarType
- func TestGrammars(t *testing.T) {
- var grammarTests = []struct {
- json string
- expected []GrammarType
- }{
- {" \t\n\r", GTs{}}, // WhitespaceGrammar
- {"null", GTs{LiteralGrammar}},
- {"[]", GTs{StartArrayGrammar, EndArrayGrammar}},
- {"15.2", GTs{NumberGrammar}},
- {"0.4", GTs{NumberGrammar}},
- {"5e9", GTs{NumberGrammar}},
- {"-4E-3", GTs{NumberGrammar}},
- {"true", GTs{LiteralGrammar}},
- {"false", GTs{LiteralGrammar}},
- {"null", GTs{LiteralGrammar}},
- {`""`, GTs{StringGrammar}},
- {`"abc"`, GTs{StringGrammar}},
- {`"\""`, GTs{StringGrammar}},
- {`"\\"`, GTs{StringGrammar}},
- {"{}", GTs{StartObjectGrammar, EndObjectGrammar}},
- {`{"a": "b", "c": "d"}`, GTs{StartObjectGrammar, StringGrammar, StringGrammar, StringGrammar, StringGrammar, EndObjectGrammar}},
- {`{"a": [1, 2], "b": {"c": 3}}`, GTs{StartObjectGrammar, StringGrammar, StartArrayGrammar, NumberGrammar, NumberGrammar, EndArrayGrammar, StringGrammar, StartObjectGrammar, StringGrammar, NumberGrammar, EndObjectGrammar, EndObjectGrammar}},
- {"[null,]", GTs{StartArrayGrammar, LiteralGrammar, EndArrayGrammar}},
- // {"[\"x\\\x00y\", 0]", GTs{StartArrayGrammar, StringGrammar, NumberGrammar, EndArrayGrammar}},
- }
- for _, tt := range grammarTests {
- t.Run(tt.json, func(t *testing.T) {
- p := NewParser(bytes.NewBufferString(tt.json))
- i := 0
- for {
- grammar, _ := p.Next()
- if grammar == ErrorGrammar {
- test.T(t, p.Err(), io.EOF)
- test.T(t, i, len(tt.expected), "when error occurred we must be at the end")
- break
- } else if grammar == WhitespaceGrammar {
- continue
- }
- test.That(t, i < len(tt.expected), "index", i, "must not exceed expected grammar types size", len(tt.expected))
- if i < len(tt.expected) {
- test.T(t, grammar, tt.expected[i], "grammar types must match")
- }
- i++
- }
- })
- }
- test.T(t, WhitespaceGrammar.String(), "Whitespace")
- test.T(t, GrammarType(100).String(), "Invalid(100)")
- test.T(t, ValueState.String(), "Value")
- test.T(t, ObjectKeyState.String(), "ObjectKey")
- test.T(t, ObjectValueState.String(), "ObjectValue")
- test.T(t, ArrayState.String(), "Array")
- test.T(t, State(100).String(), "Invalid(100)")
- }
- func TestGrammarsError(t *testing.T) {
- var grammarErrorTests = []struct {
- json string
- col int
- }{
- {"true, false", 5},
- {"[true false]", 7},
- {"]", 1},
- {"}", 1},
- {"{0: 1}", 2},
- {"{\"a\" 1}", 6},
- {"1.", 2},
- {"1e+", 2},
- {`{"":"`, 0},
- {"\"a\\", 0},
- }
- for _, tt := range grammarErrorTests {
- t.Run(tt.json, func(t *testing.T) {
- p := NewParser(bytes.NewBufferString(tt.json))
- for {
- grammar, _ := p.Next()
- if grammar == ErrorGrammar {
- if tt.col == 0 {
- test.T(t, p.Err(), io.EOF)
- } else if perr, ok := p.Err().(*parse.Error); ok {
- _, col, _ := perr.Position()
- test.T(t, col, tt.col)
- } else {
- test.Fail(t, "bad error:", p.Err())
- }
- break
- }
- }
- })
- }
- }
- func TestStates(t *testing.T) {
- var stateTests = []struct {
- json string
- expected []State
- }{
- {"null", []State{ValueState}},
- {"[null]", []State{ArrayState, ArrayState, ValueState}},
- {"{\"\":null}", []State{ObjectKeyState, ObjectValueState, ObjectKeyState, ValueState}},
- }
- for _, tt := range stateTests {
- t.Run(tt.json, func(t *testing.T) {
- p := NewParser(bytes.NewBufferString(tt.json))
- i := 0
- for {
- grammar, _ := p.Next()
- state := p.State()
- if grammar == ErrorGrammar {
- test.T(t, p.Err(), io.EOF)
- test.T(t, i, len(tt.expected), "when error occurred we must be at the end")
- break
- } else if grammar == WhitespaceGrammar {
- continue
- }
- test.That(t, i < len(tt.expected), "index", i, "must not exceed expected states size", len(tt.expected))
- if i < len(tt.expected) {
- test.T(t, state, tt.expected[i], "states must match")
- }
- i++
- }
- })
- }
- }
- ////////////////////////////////////////////////////////////////
- func ExampleNewParser() {
- p := NewParser(bytes.NewBufferString(`{"key": 5}`))
- out := ""
- for {
- state := p.State()
- gt, data := p.Next()
- if gt == ErrorGrammar {
- break
- }
- out += string(data)
- if state == ObjectKeyState && gt != EndObjectGrammar {
- out += ":"
- }
- // not handling comma insertion
- }
- fmt.Println(out)
- // Output: {"key":5}
- }
|