lexer_test.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. package jlexer
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "reflect"
  6. "testing"
  7. )
  8. func TestString(t *testing.T) {
  9. for i, test := range []struct {
  10. toParse string
  11. want string
  12. wantError bool
  13. }{
  14. {toParse: `"simple string"`, want: "simple string"},
  15. {toParse: " \r\r\n\t " + `"test"`, want: "test"},
  16. {toParse: `"\n\t\"\/\\\f\r"`, want: "\n\t\"/\\\f\r"},
  17. {toParse: `"\u0020"`, want: " "},
  18. {toParse: `"\u0020-\t"`, want: " -\t"},
  19. {toParse: `"\ufffd\uFFFD"`, want: "\ufffd\ufffd"},
  20. {toParse: `"\ud83d\ude00"`, want: "😀"},
  21. {toParse: `"\ud83d\ude08"`, want: "😈"},
  22. {toParse: `"\ud8"`, wantError: true},
  23. {toParse: `"test"junk`, want: "test"},
  24. {toParse: `5`, wantError: true}, // not a string
  25. {toParse: `"\x"`, wantError: true}, // invalid escape
  26. {toParse: `"\ud800"`, want: "�"}, // invalid utf-8 char; return replacement char
  27. } {
  28. l := Lexer{Data: []byte(test.toParse)}
  29. got := l.String()
  30. if got != test.want {
  31. t.Errorf("[%d, %q] String() = %v; want %v", i, test.toParse, got, test.want)
  32. }
  33. err := l.Error()
  34. if err != nil && !test.wantError {
  35. t.Errorf("[%d, %q] String() error: %v", i, test.toParse, err)
  36. } else if err == nil && test.wantError {
  37. t.Errorf("[%d, %q] String() ok; want error", i, test.toParse)
  38. }
  39. }
  40. }
  41. func TestBytes(t *testing.T) {
  42. for i, test := range []struct {
  43. toParse string
  44. want string
  45. wantError bool
  46. }{
  47. {toParse: `"c2ltcGxlIHN0cmluZw=="`, want: "simple string"},
  48. {toParse: " \r\r\n\t " + `"dGVzdA=="`, want: "test"},
  49. {toParse: `5`, wantError: true}, // not a JSON string
  50. {toParse: `"foobar"`, wantError: true}, // not base64 encoded
  51. {toParse: `"c2ltcGxlIHN0cmluZw="`, wantError: true}, // invalid base64 padding
  52. } {
  53. l := Lexer{Data: []byte(test.toParse)}
  54. got := l.Bytes()
  55. if bytes.Compare(got, []byte(test.want)) != 0 {
  56. t.Errorf("[%d, %q] Bytes() = %v; want: %v", i, test.toParse, got, []byte(test.want))
  57. }
  58. err := l.Error()
  59. if err != nil && !test.wantError {
  60. t.Errorf("[%d, %q] Bytes() error: %v", i, test.toParse, err)
  61. } else if err == nil && test.wantError {
  62. t.Errorf("[%d, %q] Bytes() ok; want error", i, test.toParse)
  63. }
  64. }
  65. }
  66. func TestNumber(t *testing.T) {
  67. for i, test := range []struct {
  68. toParse string
  69. want string
  70. wantError bool
  71. }{
  72. {toParse: "123", want: "123"},
  73. {toParse: "-123", want: "-123"},
  74. {toParse: "\r\n12.35", want: "12.35"},
  75. {toParse: "12.35e+1", want: "12.35e+1"},
  76. {toParse: "12.35e-15", want: "12.35e-15"},
  77. {toParse: "12.35E-15", want: "12.35E-15"},
  78. {toParse: "12.35E15", want: "12.35E15"},
  79. {toParse: `"a"`, wantError: true},
  80. {toParse: "123junk", wantError: true},
  81. {toParse: "1.2.3", wantError: true},
  82. {toParse: "1e2e3", wantError: true},
  83. {toParse: "1e2.3", wantError: true},
  84. } {
  85. l := Lexer{Data: []byte(test.toParse)}
  86. got := l.number()
  87. if got != test.want {
  88. t.Errorf("[%d, %q] number() = %v; want %v", i, test.toParse, got, test.want)
  89. }
  90. err := l.Error()
  91. if err != nil && !test.wantError {
  92. t.Errorf("[%d, %q] number() error: %v", i, test.toParse, err)
  93. } else if err == nil && test.wantError {
  94. t.Errorf("[%d, %q] number() ok; want error", i, test.toParse)
  95. }
  96. }
  97. }
  98. func TestBool(t *testing.T) {
  99. for i, test := range []struct {
  100. toParse string
  101. want bool
  102. wantError bool
  103. }{
  104. {toParse: "true", want: true},
  105. {toParse: "false", want: false},
  106. {toParse: "1", wantError: true},
  107. {toParse: "truejunk", wantError: true},
  108. {toParse: `false"junk"`, wantError: true},
  109. {toParse: "True", wantError: true},
  110. {toParse: "False", wantError: true},
  111. } {
  112. l := Lexer{Data: []byte(test.toParse)}
  113. got := l.Bool()
  114. if got != test.want {
  115. t.Errorf("[%d, %q] Bool() = %v; want %v", i, test.toParse, got, test.want)
  116. }
  117. err := l.Error()
  118. if err != nil && !test.wantError {
  119. t.Errorf("[%d, %q] Bool() error: %v", i, test.toParse, err)
  120. } else if err == nil && test.wantError {
  121. t.Errorf("[%d, %q] Bool() ok; want error", i, test.toParse)
  122. }
  123. }
  124. }
  125. func TestSkipRecursive(t *testing.T) {
  126. for i, test := range []struct {
  127. toParse string
  128. left string
  129. wantError bool
  130. }{
  131. {toParse: "5, 4", left: ", 4"},
  132. {toParse: "[5, 6], 4", left: ", 4"},
  133. {toParse: "[5, [7,8]]: 4", left: ": 4"},
  134. {toParse: `{"a":1}, 4`, left: ", 4"},
  135. {toParse: `{"a":1, "b":{"c": 5}, "e":[12,15]}, 4`, left: ", 4"},
  136. // array start/end chars in a string
  137. {toParse: `[5, "]"], 4`, left: ", 4"},
  138. {toParse: `[5, "\"]"], 4`, left: ", 4"},
  139. {toParse: `[5, "["], 4`, left: ", 4"},
  140. {toParse: `[5, "\"["], 4`, left: ", 4"},
  141. // object start/end chars in a string
  142. {toParse: `{"a}":1}, 4`, left: ", 4"},
  143. {toParse: `{"a\"}":1}, 4`, left: ", 4"},
  144. {toParse: `{"a{":1}, 4`, left: ", 4"},
  145. {toParse: `{"a\"{":1}, 4`, left: ", 4"},
  146. // object with double slashes at the end of string
  147. {toParse: `{"a":"hey\\"}, 4`, left: ", 4"},
  148. } {
  149. l := Lexer{Data: []byte(test.toParse)}
  150. l.SkipRecursive()
  151. got := string(l.Data[l.pos:])
  152. if got != test.left {
  153. t.Errorf("[%d, %q] SkipRecursive() left = %v; want %v", i, test.toParse, got, test.left)
  154. }
  155. err := l.Error()
  156. if err != nil && !test.wantError {
  157. t.Errorf("[%d, %q] SkipRecursive() error: %v", i, test.toParse, err)
  158. } else if err == nil && test.wantError {
  159. t.Errorf("[%d, %q] SkipRecursive() ok; want error", i, test.toParse)
  160. }
  161. }
  162. }
  163. func TestInterface(t *testing.T) {
  164. for i, test := range []struct {
  165. toParse string
  166. want interface{}
  167. wantError bool
  168. }{
  169. {toParse: "null", want: nil},
  170. {toParse: "true", want: true},
  171. {toParse: `"a"`, want: "a"},
  172. {toParse: "5", want: float64(5)},
  173. {toParse: `{}`, want: map[string]interface{}{}},
  174. {toParse: `[]`, want: []interface{}(nil)},
  175. {toParse: `{"a": "b"}`, want: map[string]interface{}{"a": "b"}},
  176. {toParse: `[5]`, want: []interface{}{float64(5)}},
  177. {toParse: `{"a":5 , "b" : "string"}`, want: map[string]interface{}{"a": float64(5), "b": "string"}},
  178. {toParse: `["a", 5 , null, true]`, want: []interface{}{"a", float64(5), nil, true}},
  179. {toParse: `{"a" "b"}`, wantError: true},
  180. {toParse: `{"a": "b",}`, wantError: true},
  181. {toParse: `{"a":"b","c" "b"}`, wantError: true},
  182. {toParse: `{"a": "b","c":"d",}`, wantError: true},
  183. {toParse: `{,}`, wantError: true},
  184. {toParse: `[1, 2,]`, wantError: true},
  185. {toParse: `[1 2]`, wantError: true},
  186. {toParse: `[,]`, wantError: true},
  187. } {
  188. l := Lexer{Data: []byte(test.toParse)}
  189. got := l.Interface()
  190. if !reflect.DeepEqual(got, test.want) {
  191. t.Errorf("[%d, %q] Interface() = %v; want %v", i, test.toParse, got, test.want)
  192. }
  193. err := l.Error()
  194. if err != nil && !test.wantError {
  195. t.Errorf("[%d, %q] Interface() error: %v", i, test.toParse, err)
  196. } else if err == nil && test.wantError {
  197. t.Errorf("[%d, %q] Interface() ok; want error", i, test.toParse)
  198. }
  199. }
  200. }
  201. func TestConsumed(t *testing.T) {
  202. for i, test := range []struct {
  203. toParse string
  204. wantError bool
  205. }{
  206. {toParse: "", wantError: false},
  207. {toParse: " ", wantError: false},
  208. {toParse: "\r\n", wantError: false},
  209. {toParse: "\t\t", wantError: false},
  210. {toParse: "{", wantError: true},
  211. } {
  212. l := Lexer{Data: []byte(test.toParse)}
  213. l.Consumed()
  214. err := l.Error()
  215. if err != nil && !test.wantError {
  216. t.Errorf("[%d, %q] Consumed() error: %v", i, test.toParse, err)
  217. } else if err == nil && test.wantError {
  218. t.Errorf("[%d, %q] Consumed() ok; want error", i, test.toParse)
  219. }
  220. }
  221. }
  222. func TestJsonNumber(t *testing.T) {
  223. for i, test := range []struct {
  224. toParse string
  225. want json.Number
  226. wantLexerError bool
  227. wantValue interface{}
  228. wantValueError bool
  229. }{
  230. {toParse: `10`, want: json.Number("10"), wantValue: int64(10)},
  231. {toParse: `0`, want: json.Number("0"), wantValue: int64(0)},
  232. {toParse: `0.12`, want: json.Number("0.12"), wantValue: 0.12},
  233. {toParse: `25E-4`, want: json.Number("25E-4"), wantValue: 25E-4},
  234. {toParse: `"10"`, want: json.Number("10"), wantValue: int64(10)},
  235. {toParse: `"0"`, want: json.Number("0"), wantValue: int64(0)},
  236. {toParse: `"0.12"`, want: json.Number("0.12"), wantValue: 0.12},
  237. {toParse: `"25E-4"`, want: json.Number("25E-4"), wantValue: 25E-4},
  238. {toParse: `"foo"`, want: json.Number("foo"), wantValueError: true},
  239. {toParse: `null`, want: json.Number(""), wantValueError: true},
  240. {toParse: `"a""`, want: json.Number("a"), wantValueError: true},
  241. {toParse: `[1]`, want: json.Number(""), wantLexerError: true, wantValueError: true},
  242. {toParse: `{}`, want: json.Number(""), wantLexerError: true, wantValueError: true},
  243. {toParse: `a`, want: json.Number(""), wantLexerError: true, wantValueError: true},
  244. } {
  245. l := Lexer{Data: []byte(test.toParse)}
  246. got := l.JsonNumber()
  247. if got != test.want {
  248. t.Errorf("[%d, %q] JsonNumber() = %v; want %v", i, test.toParse, got, test.want)
  249. }
  250. err := l.Error()
  251. if err != nil && !test.wantLexerError {
  252. t.Errorf("[%d, %q] JsonNumber() lexer error: %v", i, test.toParse, err)
  253. } else if err == nil && test.wantLexerError {
  254. t.Errorf("[%d, %q] JsonNumber() ok; want lexer error", i, test.toParse)
  255. }
  256. var valueErr error
  257. var gotValue interface{}
  258. switch test.wantValue.(type) {
  259. case float64:
  260. gotValue, valueErr = got.Float64()
  261. default:
  262. gotValue, valueErr = got.Int64()
  263. }
  264. if !reflect.DeepEqual(gotValue, test.wantValue) && !test.wantLexerError && !test.wantValueError {
  265. t.Errorf("[%d, %q] JsonNumber() = %v; want %v", i, test.toParse, gotValue, test.wantValue)
  266. }
  267. if valueErr != nil && !test.wantValueError {
  268. t.Errorf("[%d, %q] JsonNumber() value error: %v", i, test.toParse, valueErr)
  269. } else if valueErr == nil && test.wantValueError {
  270. t.Errorf("[%d, %q] JsonNumber() ok; want value error", i, test.toParse)
  271. }
  272. }
  273. }