parse_test.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package json // import "github.com/tdewolff/parse/json"
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "testing"
  7. "github.com/tdewolff/parse"
  8. "github.com/tdewolff/test"
  9. )
  10. type GTs []GrammarType
  11. func TestGrammars(t *testing.T) {
  12. var grammarTests = []struct {
  13. json string
  14. expected []GrammarType
  15. }{
  16. {" \t\n\r", GTs{}}, // WhitespaceGrammar
  17. {"null", GTs{LiteralGrammar}},
  18. {"[]", GTs{StartArrayGrammar, EndArrayGrammar}},
  19. {"15.2", GTs{NumberGrammar}},
  20. {"0.4", GTs{NumberGrammar}},
  21. {"5e9", GTs{NumberGrammar}},
  22. {"-4E-3", GTs{NumberGrammar}},
  23. {"true", GTs{LiteralGrammar}},
  24. {"false", GTs{LiteralGrammar}},
  25. {"null", GTs{LiteralGrammar}},
  26. {`""`, GTs{StringGrammar}},
  27. {`"abc"`, GTs{StringGrammar}},
  28. {`"\""`, GTs{StringGrammar}},
  29. {`"\\"`, GTs{StringGrammar}},
  30. {"{}", GTs{StartObjectGrammar, EndObjectGrammar}},
  31. {`{"a": "b", "c": "d"}`, GTs{StartObjectGrammar, StringGrammar, StringGrammar, StringGrammar, StringGrammar, EndObjectGrammar}},
  32. {`{"a": [1, 2], "b": {"c": 3}}`, GTs{StartObjectGrammar, StringGrammar, StartArrayGrammar, NumberGrammar, NumberGrammar, EndArrayGrammar, StringGrammar, StartObjectGrammar, StringGrammar, NumberGrammar, EndObjectGrammar, EndObjectGrammar}},
  33. {"[null,]", GTs{StartArrayGrammar, LiteralGrammar, EndArrayGrammar}},
  34. // {"[\"x\\\x00y\", 0]", GTs{StartArrayGrammar, StringGrammar, NumberGrammar, EndArrayGrammar}},
  35. }
  36. for _, tt := range grammarTests {
  37. t.Run(tt.json, func(t *testing.T) {
  38. p := NewParser(bytes.NewBufferString(tt.json))
  39. i := 0
  40. for {
  41. grammar, _ := p.Next()
  42. if grammar == ErrorGrammar {
  43. test.T(t, p.Err(), io.EOF)
  44. test.T(t, i, len(tt.expected), "when error occurred we must be at the end")
  45. break
  46. } else if grammar == WhitespaceGrammar {
  47. continue
  48. }
  49. test.That(t, i < len(tt.expected), "index", i, "must not exceed expected grammar types size", len(tt.expected))
  50. if i < len(tt.expected) {
  51. test.T(t, grammar, tt.expected[i], "grammar types must match")
  52. }
  53. i++
  54. }
  55. })
  56. }
  57. test.T(t, WhitespaceGrammar.String(), "Whitespace")
  58. test.T(t, GrammarType(100).String(), "Invalid(100)")
  59. test.T(t, ValueState.String(), "Value")
  60. test.T(t, ObjectKeyState.String(), "ObjectKey")
  61. test.T(t, ObjectValueState.String(), "ObjectValue")
  62. test.T(t, ArrayState.String(), "Array")
  63. test.T(t, State(100).String(), "Invalid(100)")
  64. }
  65. func TestGrammarsError(t *testing.T) {
  66. var grammarErrorTests = []struct {
  67. json string
  68. col int
  69. }{
  70. {"true, false", 5},
  71. {"[true false]", 7},
  72. {"]", 1},
  73. {"}", 1},
  74. {"{0: 1}", 2},
  75. {"{\"a\" 1}", 6},
  76. {"1.", 2},
  77. {"1e+", 2},
  78. {`{"":"`, 0},
  79. {"\"a\\", 0},
  80. }
  81. for _, tt := range grammarErrorTests {
  82. t.Run(tt.json, func(t *testing.T) {
  83. p := NewParser(bytes.NewBufferString(tt.json))
  84. for {
  85. grammar, _ := p.Next()
  86. if grammar == ErrorGrammar {
  87. if tt.col == 0 {
  88. test.T(t, p.Err(), io.EOF)
  89. } else if perr, ok := p.Err().(*parse.Error); ok {
  90. _, col, _ := perr.Position()
  91. test.T(t, col, tt.col)
  92. } else {
  93. test.Fail(t, "bad error:", p.Err())
  94. }
  95. break
  96. }
  97. }
  98. })
  99. }
  100. }
  101. func TestStates(t *testing.T) {
  102. var stateTests = []struct {
  103. json string
  104. expected []State
  105. }{
  106. {"null", []State{ValueState}},
  107. {"[null]", []State{ArrayState, ArrayState, ValueState}},
  108. {"{\"\":null}", []State{ObjectKeyState, ObjectValueState, ObjectKeyState, ValueState}},
  109. }
  110. for _, tt := range stateTests {
  111. t.Run(tt.json, func(t *testing.T) {
  112. p := NewParser(bytes.NewBufferString(tt.json))
  113. i := 0
  114. for {
  115. grammar, _ := p.Next()
  116. state := p.State()
  117. if grammar == ErrorGrammar {
  118. test.T(t, p.Err(), io.EOF)
  119. test.T(t, i, len(tt.expected), "when error occurred we must be at the end")
  120. break
  121. } else if grammar == WhitespaceGrammar {
  122. continue
  123. }
  124. test.That(t, i < len(tt.expected), "index", i, "must not exceed expected states size", len(tt.expected))
  125. if i < len(tt.expected) {
  126. test.T(t, state, tt.expected[i], "states must match")
  127. }
  128. i++
  129. }
  130. })
  131. }
  132. }
  133. ////////////////////////////////////////////////////////////////
  134. func ExampleNewParser() {
  135. p := NewParser(bytes.NewBufferString(`{"key": 5}`))
  136. out := ""
  137. for {
  138. state := p.State()
  139. gt, data := p.Next()
  140. if gt == ErrorGrammar {
  141. break
  142. }
  143. out += string(data)
  144. if state == ObjectKeyState && gt != EndObjectGrammar {
  145. out += ":"
  146. }
  147. // not handling comma insertion
  148. }
  149. fmt.Println(out)
  150. // Output: {"key":5}
  151. }