parser_test.go 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668
  1. package jsonparser
  2. import (
  3. "bytes"
  4. "fmt"
  5. _ "fmt"
  6. "reflect"
  7. "testing"
  8. )
  9. // Set it to non-empty value if want to run only specific test
  10. var activeTest = ""
  11. func toArray(data []byte) (result [][]byte) {
  12. ArrayEach(data, func(value []byte, dataType ValueType, offset int, err error) {
  13. result = append(result, value)
  14. })
  15. return
  16. }
  17. func toStringArray(data []byte) (result []string) {
  18. ArrayEach(data, func(value []byte, dataType ValueType, offset int, err error) {
  19. result = append(result, string(value))
  20. })
  21. return
  22. }
  23. type GetTest struct {
  24. desc string
  25. json string
  26. path []string
  27. isErr bool
  28. isFound bool
  29. data interface{}
  30. }
  31. type SetTest struct {
  32. desc string
  33. json string
  34. setData string
  35. path []string
  36. isErr bool
  37. isFound bool
  38. data interface{}
  39. }
  40. type DeleteTest struct {
  41. desc string
  42. json string
  43. path []string
  44. data interface{}
  45. }
  46. var deleteTests = []DeleteTest{
  47. {
  48. desc: "Delete test key",
  49. json: `{"test":"input"}`,
  50. path: []string{"test"},
  51. data: `{}`,
  52. },
  53. {
  54. desc: "Delete object",
  55. json: `{"test":"input"}`,
  56. path: []string{},
  57. data: ``,
  58. },
  59. {
  60. desc: "Delete a nested object",
  61. json: `{"test":"input","new.field":{"key": "new object"}}`,
  62. path: []string{"new.field", "key"},
  63. data: `{"test":"input","new.field":{}}`,
  64. },
  65. {
  66. desc: "Deleting a key that doesn't exist should return the same object",
  67. json: `{"test":"input"}`,
  68. path: []string{"test2"},
  69. data: `{"test":"input"}`,
  70. },
  71. {
  72. desc: "Delete object in an array",
  73. json: `{"test":[{"key":"val-obj1"}]}`,
  74. path: []string{"test", "[0]"},
  75. data: `{"test":[]}`,
  76. },
  77. {
  78. desc: "Deleting a object in an array that doesn't exists should return the same object",
  79. json: `{"test":[{"key":"val-obj1"}]}`,
  80. path: []string{"test", "[1]"},
  81. data: `{"test":[{"key":"val-obj1"}]}`,
  82. },
  83. {
  84. desc: "Delete a complex object in a nested array",
  85. json: `{"test":[{"key":[{"innerKey":"innerKeyValue"}]}]}`,
  86. path: []string{"test", "[0]", "key", "[0]"},
  87. data: `{"test":[{"key":[]}]}`,
  88. },
  89. {
  90. desc: "Delete known key (simple type within nested array)",
  91. json: `{"test":[{"key":["innerKey"]}]}`,
  92. path: []string{"test", "[0]", "key", "[0]"},
  93. data: `{"test":[{"key":[]}]}`,
  94. },
  95. {
  96. desc: "Delete in empty json",
  97. json: `{}`,
  98. path: []string{},
  99. data: ``,
  100. },
  101. {
  102. desc: "Delete empty array",
  103. json: `[]`,
  104. path: []string{},
  105. data: ``,
  106. },
  107. {
  108. desc: "Deleting non json should return the same value",
  109. json: `1.323`,
  110. path: []string{"foo"},
  111. data: `1.323`,
  112. },
  113. {
  114. desc: "Delete known key (top level array)",
  115. json: `[{"key":"val-obj1"}]`,
  116. path: []string{"[0]"},
  117. data: `[]`,
  118. },
  119. { // This test deletes the key instead of returning a parse error, as checking for the malformed JSON would reduce performance (this is not ideal)
  120. desc: `malformed with trailing whitespace`,
  121. json: `{"a":1 `,
  122. path: []string{"a"},
  123. data: `{ `,
  124. },
  125. { // This test dels the key instead of returning a parse error, as checking for the malformed JSON would reduce performance (this is not ideal)
  126. desc: "malformed 'colon chain', delete b",
  127. json: `{"a":"b":"c"}`,
  128. path: []string{"b"},
  129. data: `{"a":}`,
  130. },
  131. {
  132. desc: "Delete object without inner array",
  133. json: `{"a": {"b": 1}, "b": 2}`,
  134. path: []string{"b"},
  135. data: `{"a": {"b": 1}}`,
  136. },
  137. {
  138. desc: "Delete object without inner array",
  139. json: `{"a": [{"b": 1}], "b": 2}`,
  140. path: []string{"b"},
  141. data: `{"a": [{"b": 1}]}`,
  142. },
  143. {
  144. desc: "Delete object without inner array",
  145. json: `{"a": {"c": {"b": 3}, "b": 1}, "b": 2}`,
  146. path: []string{"a", "b"},
  147. data: `{"a": {"c": {"b": 3}}, "b": 2}`,
  148. },
  149. {
  150. desc: "Delete object without inner array",
  151. json: `{"a": [{"c": {"b": 3}, "b": 1}], "b": 2}`,
  152. path: []string{"a", "[0]", "b"},
  153. data: `{"a": [{"c": {"b": 3}}], "b": 2}`,
  154. },
  155. {
  156. desc: "Remove trailing comma if last object is deleted",
  157. json: `{"a": "1", "b": "2"}`,
  158. path: []string{"b"},
  159. data: `{"a": "1"}`,
  160. },
  161. {
  162. desc: "Correctly delete first element with space-comma",
  163. json: `{"a": "1" ,"b": "2" }`,
  164. path: []string{"a"},
  165. data: `{"b": "2" }`,
  166. },
  167. {
  168. desc: "Correctly delete middle element with space-comma",
  169. json: `{"a": "1" ,"b": "2" , "c": 3}`,
  170. path: []string{"b"},
  171. data: `{"a": "1" , "c": 3}`,
  172. },
  173. }
  174. var setTests = []SetTest{
  175. {
  176. desc: "set unknown key (string)",
  177. json: `{"test":"input"}`,
  178. isFound: true,
  179. path: []string{"new.field"},
  180. setData: `"new value"`,
  181. data: `{"test":"input","new.field":"new value"}`,
  182. },
  183. {
  184. desc: "set known key (string)",
  185. json: `{"test":"input"}`,
  186. isFound: true,
  187. path: []string{"test"},
  188. setData: `"new value"`,
  189. data: `{"test":"new value"}`,
  190. },
  191. {
  192. desc: "set unknown key (object)",
  193. json: `{"test":"input"}`,
  194. isFound: true,
  195. path: []string{"new.field"},
  196. setData: `{"key": "new object"}`,
  197. data: `{"test":"input","new.field":{"key": "new object"}}`,
  198. },
  199. {
  200. desc: "set known key (object)",
  201. json: `{"test":"input"}`,
  202. isFound: true,
  203. path: []string{"test"},
  204. setData: `{"key": "new object"}`,
  205. data: `{"test":{"key": "new object"}}`,
  206. },
  207. {
  208. desc: "set known key (object within array)",
  209. json: `{"test":[{"key":"val-obj1"}]}`,
  210. isFound: true,
  211. path: []string{"test", "[0]"},
  212. setData: `{"key":"new object"}`,
  213. data: `{"test":[{"key":"new object"}]}`,
  214. },
  215. {
  216. desc: "set unknown key (replace object)",
  217. json: `{"test":[{"key":"val-obj1"}]}`,
  218. isFound: true,
  219. path: []string{"test", "newKey"},
  220. setData: `"new object"`,
  221. data: `{"test":{"newKey":"new object"}}`,
  222. },
  223. {
  224. desc: "set unknown key (complex object within nested array)",
  225. json: `{"test":[{"key":[{"innerKey":"innerKeyValue"}]}]}`,
  226. isFound: true,
  227. path: []string{"test", "[0]", "key", "[0]", "newInnerKey"},
  228. setData: `{"key":"new object"}`,
  229. data: `{"test":[{"key":[{"innerKey":"innerKeyValue","newInnerKey":{"key":"new object"}}]}]}`,
  230. },
  231. {
  232. desc: "set known key (complex object within nested array)",
  233. json: `{"test":[{"key":[{"innerKey":"innerKeyValue"}]}]}`,
  234. isFound: true,
  235. path: []string{"test", "[0]", "key", "[0]", "innerKey"},
  236. setData: `{"key":"new object"}`,
  237. data: `{"test":[{"key":[{"innerKey":{"key":"new object"}}]}]}`,
  238. },
  239. {
  240. desc: "set unknown key (object, partial subtree exists)",
  241. json: `{"test":{"input":"output"}}`,
  242. isFound: true,
  243. path: []string{"test", "new.field"},
  244. setData: `{"key":"new object"}`,
  245. data: `{"test":{"input":"output","new.field":{"key":"new object"}}}`,
  246. },
  247. {
  248. desc: "set unknown key (object, empty partial subtree exists)",
  249. json: `{"test":{}}`,
  250. isFound: true,
  251. path: []string{"test", "new.field"},
  252. setData: `{"key":"new object"}`,
  253. data: `{"test":{"new.field":{"key":"new object"}}}`,
  254. },
  255. {
  256. desc: "set unknown key (object, no subtree exists)",
  257. json: `{"test":"input"}`,
  258. isFound: true,
  259. path: []string{"new.field", "nested", "value"},
  260. setData: `{"key": "new object"}`,
  261. data: `{"test":"input","new.field":{"nested":{"value":{"key": "new object"}}}}`,
  262. },
  263. {
  264. desc: "set in empty json",
  265. json: `{}`,
  266. isFound: true,
  267. path: []string{"foo"},
  268. setData: `"null"`,
  269. data: `{"foo":"null"}`,
  270. },
  271. {
  272. desc: "set subtree in empty json",
  273. json: `{}`,
  274. isFound: true,
  275. path: []string{"foo", "bar"},
  276. setData: `"null"`,
  277. data: `{"foo":{"bar":"null"}}`,
  278. },
  279. {
  280. desc: "set in empty string - not found",
  281. json: ``,
  282. isFound: false,
  283. path: []string{"foo"},
  284. setData: `"null"`,
  285. data: ``,
  286. },
  287. {
  288. desc: "set in Number - not found",
  289. json: `1.323`,
  290. isFound: false,
  291. path: []string{"foo"},
  292. setData: `"null"`,
  293. data: `1.323`,
  294. },
  295. {
  296. desc: "set known key (top level array)",
  297. json: `[{"key":"val-obj1"}]`,
  298. isFound: true,
  299. path: []string{"[0]", "key"},
  300. setData: `"new object"`,
  301. data: `[{"key":"new object"}]`,
  302. },
  303. {
  304. desc: "set unknown key (trailing whitespace)",
  305. json: `{"key":"val-obj1"} `,
  306. isFound: true,
  307. path: []string{"alt-key"},
  308. setData: `"new object"`,
  309. data: `{"key":"val-obj1","alt-key":"new object"} `,
  310. },
  311. { // This test sets the key instead of returning a parse error, as checking for the malformed JSON would reduce performance (this is not ideal)
  312. desc: `malformed with trailing whitespace`,
  313. json: `{"a":1 `,
  314. path: []string{"a"},
  315. setData: `2`,
  316. isFound: true,
  317. data: `{"a":2 `,
  318. },
  319. { // This test sets the key instead of returning a parse error, as checking for the malformed JSON would reduce performance (this is not ideal)
  320. desc: "malformed 'colon chain', set second string",
  321. json: `{"a":"b":"c"}`,
  322. path: []string{"b"},
  323. setData: `"d"`,
  324. isFound: true,
  325. data: `{"a":"b":"d"}`,
  326. },
  327. {
  328. desc: "set indexed path to object on empty JSON",
  329. json: `{}`,
  330. path: []string{"top", "[0]", "middle", "[0]", "bottom"},
  331. setData: `"value"`,
  332. isFound: true,
  333. data: `{"top":[{"middle":[{"bottom":"value"}]}]}`,
  334. },
  335. {
  336. desc: "set indexed path on existing object with object",
  337. json: `{"top":[{"middle":[]}]}`,
  338. path: []string{"top", "[0]", "middle", "[0]", "bottom"},
  339. setData: `"value"`,
  340. isFound: true,
  341. data: `{"top":[{"middle":[{"bottom":"value"}]}]}`,
  342. },
  343. {
  344. desc: "set indexed path on existing object with value",
  345. json: `{"top":[{"middle":[]}]}`,
  346. path: []string{"top", "[0]", "middle", "[0]"},
  347. setData: `"value"`,
  348. isFound: true,
  349. data: `{"top":[{"middle":["value"]}]}`,
  350. },
  351. {
  352. desc: "set indexed path on empty object with value",
  353. json: `{}`,
  354. path: []string{"top", "[0]", "middle", "[0]"},
  355. setData: `"value"`,
  356. isFound: true,
  357. data: `{"top":[{"middle":["value"]}]}`,
  358. },
  359. {
  360. desc: "set indexed path on object with existing array",
  361. json: `{"top":["one", "two", "three"]}`,
  362. path: []string{"top", "[2]"},
  363. setData: `"value"`,
  364. isFound: true,
  365. data: `{"top":["one", "two", "value"]}`,
  366. },
  367. }
  368. var getTests = []GetTest{
  369. // Trivial tests
  370. {
  371. desc: "read string",
  372. json: `""`,
  373. isFound: true,
  374. data: ``,
  375. },
  376. {
  377. desc: "read number",
  378. json: `0`,
  379. isFound: true,
  380. data: `0`,
  381. },
  382. {
  383. desc: "read object",
  384. json: `{}`,
  385. isFound: true,
  386. data: `{}`,
  387. },
  388. {
  389. desc: "read array",
  390. json: `[]`,
  391. isFound: true,
  392. data: `[]`,
  393. },
  394. {
  395. desc: "read boolean",
  396. json: `true`,
  397. isFound: true,
  398. data: `true`,
  399. },
  400. // Found key tests
  401. {
  402. desc: "handling multiple nested keys with same name",
  403. json: `{"a":[{"b":1},{"b":2},3],"c":{"c":[1,2]}} }`,
  404. path: []string{"c", "c"},
  405. isFound: true,
  406. data: `[1,2]`,
  407. },
  408. {
  409. desc: "read basic key",
  410. json: `{"a":"b"}`,
  411. path: []string{"a"},
  412. isFound: true,
  413. data: `b`,
  414. },
  415. {
  416. desc: "read basic key with space",
  417. json: `{"a": "b"}`,
  418. path: []string{"a"},
  419. isFound: true,
  420. data: `b`,
  421. },
  422. {
  423. desc: "read composite key",
  424. json: `{"a": { "b":{"c":"d" }}}`,
  425. path: []string{"a", "b", "c"},
  426. isFound: true,
  427. data: `d`,
  428. },
  429. {
  430. desc: `read numberic value as string`,
  431. json: `{"a": "b", "c": 1}`,
  432. path: []string{"c"},
  433. isFound: true,
  434. data: `1`,
  435. },
  436. {
  437. desc: `handle multiple nested keys with same name`,
  438. json: `{"a":[{"b":1},{"b":2},3],"c":{"c":[1,2]}} }`,
  439. path: []string{"c", "c"},
  440. isFound: true,
  441. data: `[1,2]`,
  442. },
  443. {
  444. desc: `read string values with quotes`,
  445. json: `{"a": "string\"with\"quotes"}`,
  446. path: []string{"a"},
  447. isFound: true,
  448. data: `string\"with\"quotes`,
  449. },
  450. {
  451. desc: `read object`,
  452. json: `{"a": { "b":{"c":"d" }}}`,
  453. path: []string{"a", "b"},
  454. isFound: true,
  455. data: `{"c":"d" }`,
  456. },
  457. {
  458. desc: `empty path`,
  459. json: `{"c":"d" }`,
  460. path: []string{},
  461. isFound: true,
  462. data: `{"c":"d" }`,
  463. },
  464. {
  465. desc: `formatted JSON value`,
  466. json: "{\n \"a\": \"b\"\n}",
  467. path: []string{"a"},
  468. isFound: true,
  469. data: `b`,
  470. },
  471. {
  472. desc: `formatted JSON value 2`,
  473. json: "{\n \"a\":\n {\n\"b\":\n {\"c\":\"d\",\n\"e\": \"f\"}\n}\n}",
  474. path: []string{"a", "b"},
  475. isFound: true,
  476. data: "{\"c\":\"d\",\n\"e\": \"f\"}",
  477. },
  478. {
  479. desc: `whitespace`,
  480. json: " \n\r\t{ \n\r\t\"whitespace\" \n\r\t: \n\r\t333 \n\r\t} \n\r\t",
  481. path: []string{"whitespace"},
  482. isFound: true,
  483. data: "333",
  484. },
  485. {
  486. desc: `escaped backslash quote`,
  487. json: `{"a": "\\\""}`,
  488. path: []string{"a"},
  489. isFound: true,
  490. data: `\\\"`,
  491. },
  492. {
  493. desc: `unescaped backslash quote`,
  494. json: `{"a": "\\"}`,
  495. path: []string{"a"},
  496. isFound: true,
  497. data: `\\`,
  498. },
  499. {
  500. desc: `unicode in JSON`,
  501. json: `{"a": "15°C"}`,
  502. path: []string{"a"},
  503. isFound: true,
  504. data: `15°C`,
  505. },
  506. {
  507. desc: `no padding + nested`,
  508. json: `{"a":{"a":"1"},"b":2}`,
  509. path: []string{"b"},
  510. isFound: true,
  511. data: `2`,
  512. },
  513. {
  514. desc: `no padding + nested + array`,
  515. json: `{"a":{"b":[1,2]},"c":3}`,
  516. path: []string{"c"},
  517. isFound: true,
  518. data: `3`,
  519. },
  520. {
  521. desc: `empty key`,
  522. json: `{"":{"":{"":true}}}`,
  523. path: []string{"", "", ""},
  524. isFound: true,
  525. data: `true`,
  526. },
  527. // Escaped key tests
  528. {
  529. desc: `key with simple escape`,
  530. json: `{"a\\b":1}`,
  531. path: []string{"a\\b"},
  532. isFound: true,
  533. data: `1`,
  534. },
  535. {
  536. desc: `key and value with whitespace escapes`,
  537. json: `{"key\b\f\n\r\tkey":"value\b\f\n\r\tvalue"}`,
  538. path: []string{"key\b\f\n\r\tkey"},
  539. isFound: true,
  540. data: `value\b\f\n\r\tvalue`, // value is not unescaped since this is Get(), but the key should work correctly
  541. },
  542. {
  543. desc: `key with Unicode escape`,
  544. json: `{"a\u00B0b":1}`,
  545. path: []string{"a\u00B0b"},
  546. isFound: true,
  547. data: `1`,
  548. },
  549. {
  550. desc: `key with complex escape`,
  551. json: `{"a\uD83D\uDE03b":1}`,
  552. path: []string{"a\U0001F603b"},
  553. isFound: true,
  554. data: `1`,
  555. },
  556. { // This test returns a match instead of a parse error, as checking for the malformed JSON would reduce performance
  557. desc: `malformed with trailing whitespace`,
  558. json: `{"a":1 `,
  559. path: []string{"a"},
  560. isFound: true,
  561. data: `1`,
  562. },
  563. { // This test returns a match instead of a parse error, as checking for the malformed JSON would reduce performance
  564. desc: `malformed with wrong closing bracket`,
  565. json: `{"a":1]`,
  566. path: []string{"a"},
  567. isFound: true,
  568. data: `1`,
  569. },
  570. // Not found key tests
  571. {
  572. desc: `empty input`,
  573. json: ``,
  574. path: []string{"a"},
  575. isFound: false,
  576. },
  577. {
  578. desc: "non-existent key 1",
  579. json: `{"a":"b"}`,
  580. path: []string{"c"},
  581. isFound: false,
  582. },
  583. {
  584. desc: "non-existent key 2",
  585. json: `{"a":"b"}`,
  586. path: []string{"b"},
  587. isFound: false,
  588. },
  589. {
  590. desc: "non-existent key 3",
  591. json: `{"aa":"b"}`,
  592. path: []string{"a"},
  593. isFound: false,
  594. },
  595. {
  596. desc: "apply scope of parent when search for nested key",
  597. json: `{"a": { "b": 1}, "c": 2 }`,
  598. path: []string{"a", "b", "c"},
  599. isFound: false,
  600. },
  601. {
  602. desc: `apply scope to key level`,
  603. json: `{"a": { "b": 1}, "c": 2 }`,
  604. path: []string{"b"},
  605. isFound: false,
  606. },
  607. {
  608. desc: `handle escaped quote in key name in JSON`,
  609. json: `{"key\"key": 1}`,
  610. path: []string{"key"},
  611. isFound: false,
  612. },
  613. {
  614. desc: "handling multiple keys with different name",
  615. json: `{"a":{"a":1},"b":{"a":3,"c":[1,2]}}`,
  616. path: []string{"a", "c"},
  617. isFound: false,
  618. },
  619. {
  620. desc: "handling nested json",
  621. json: `{"a":{"b":{"c":1},"d":4}}`,
  622. path: []string{"a", "d"},
  623. isFound: true,
  624. data: `4`,
  625. },
  626. // Error/invalid tests
  627. {
  628. desc: `handle escaped quote in key name in JSON`,
  629. json: `{"key\"key": 1}`,
  630. path: []string{"key"},
  631. isFound: false,
  632. },
  633. {
  634. desc: `missing closing brace, but can still find key`,
  635. json: `{"a":"b"`,
  636. path: []string{"a"},
  637. isFound: true,
  638. data: `b`,
  639. },
  640. {
  641. desc: `missing value closing quote`,
  642. json: `{"a":"b`,
  643. path: []string{"a"},
  644. isErr: true,
  645. },
  646. {
  647. desc: `missing value closing curly brace`,
  648. json: `{"a": { "b": "c"`,
  649. path: []string{"a"},
  650. isErr: true,
  651. },
  652. {
  653. desc: `missing value closing square bracket`,
  654. json: `{"a": [1, 2, 3 }`,
  655. path: []string{"a"},
  656. isErr: true,
  657. },
  658. {
  659. desc: `missing value 1`,
  660. json: `{"a":`,
  661. path: []string{"a"},
  662. isErr: true,
  663. },
  664. {
  665. desc: `missing value 2`,
  666. json: `{"a": `,
  667. path: []string{"a"},
  668. isErr: true,
  669. },
  670. {
  671. desc: `missing value 3`,
  672. json: `{"a":}`,
  673. path: []string{"a"},
  674. isErr: true,
  675. },
  676. {
  677. desc: `malformed array (no closing brace)`,
  678. json: `{"a":[, "b":123}`,
  679. path: []string{"b"},
  680. isFound: false,
  681. },
  682. { // Issue #81
  683. desc: `missing key in object in array`,
  684. json: `{"p":{"a":[{"u":"abc","t":"th"}]}}`,
  685. path: []string{"p", "a", "[0]", "x"},
  686. isFound: false,
  687. },
  688. { // Issue #81 counter test
  689. desc: `existing key in object in array`,
  690. json: `{"p":{"a":[{"u":"abc","t":"th"}]}}`,
  691. path: []string{"p", "a", "[0]", "u"},
  692. isFound: true,
  693. data: "abc",
  694. },
  695. { // This test returns not found instead of a parse error, as checking for the malformed JSON would reduce performance
  696. desc: "malformed key (followed by comma followed by colon)",
  697. json: `{"a",:1}`,
  698. path: []string{"a"},
  699. isFound: false,
  700. },
  701. { // This test returns a match instead of a parse error, as checking for the malformed JSON would reduce performance (this is not ideal)
  702. desc: "malformed 'colon chain', lookup first string",
  703. json: `{"a":"b":"c"}`,
  704. path: []string{"a"},
  705. isFound: true,
  706. data: "b",
  707. },
  708. { // This test returns a match instead of a parse error, as checking for the malformed JSON would reduce performance (this is not ideal)
  709. desc: "malformed 'colon chain', lookup second string",
  710. json: `{"a":"b":"c"}`,
  711. path: []string{"b"},
  712. isFound: true,
  713. data: "c",
  714. },
  715. // Array index paths
  716. {
  717. desc: "last key in path is index",
  718. json: `{"a":[{"b":1},{"b":"2"}, 3],"c":{"c":[1,2]}}`,
  719. path: []string{"a", "[1]"},
  720. isFound: true,
  721. data: `{"b":"2"}`,
  722. },
  723. {
  724. desc: "get string from array",
  725. json: `{"a":[{"b":1},"foo", 3],"c":{"c":[1,2]}}`,
  726. path: []string{"a", "[1]"},
  727. isFound: true,
  728. data: "foo",
  729. },
  730. {
  731. desc: "key in path is index",
  732. json: `{"a":[{"b":"1"},{"b":"2"},3],"c":{"c":[1,2]}}`,
  733. path: []string{"a", "[0]", "b"},
  734. isFound: true,
  735. data: `1`,
  736. },
  737. {
  738. desc: "last key in path is an index to value in array (formatted json)",
  739. json: `{
  740. "a": [
  741. {
  742. "b": 1
  743. },
  744. {"b":"2"},
  745. 3
  746. ],
  747. "c": {
  748. "c": [
  749. 1,
  750. 2
  751. ]
  752. }
  753. }`,
  754. path: []string{"a", "[1]"},
  755. isFound: true,
  756. data: `{"b":"2"}`,
  757. },
  758. {
  759. desc: "key in path is index (formatted json)",
  760. json: `{
  761. "a": [
  762. {"b": 1},
  763. {"b": "2"},
  764. 3
  765. ],
  766. "c": {
  767. "c": [
  768. 1,
  769. 2
  770. ]
  771. }
  772. }`,
  773. path: []string{"a", "[0]", "b"},
  774. isFound: true,
  775. data: `1`,
  776. },
  777. }
  778. var getIntTests = []GetTest{
  779. {
  780. desc: `read numeric value as number`,
  781. json: `{"a": "b", "c": 1}`,
  782. path: []string{"c"},
  783. isFound: true,
  784. data: int64(1),
  785. },
  786. {
  787. desc: `read numeric value as number in formatted JSON`,
  788. json: "{\"a\": \"b\", \"c\": 1 \n}",
  789. path: []string{"c"},
  790. isFound: true,
  791. data: int64(1),
  792. },
  793. }
  794. var getFloatTests = []GetTest{
  795. {
  796. desc: `read numeric value as number`,
  797. json: `{"a": "b", "c": 1.123}`,
  798. path: []string{"c"},
  799. isFound: true,
  800. data: float64(1.123),
  801. },
  802. {
  803. desc: `read numeric value as number in formatted JSON`,
  804. json: "{\"a\": \"b\", \"c\": 23.41323 \n}",
  805. path: []string{"c"},
  806. isFound: true,
  807. data: float64(23.41323),
  808. },
  809. }
  810. var getStringTests = []GetTest{
  811. {
  812. desc: `Translate Unicode symbols`,
  813. json: `{"c": "test"}`,
  814. path: []string{"c"},
  815. isFound: true,
  816. data: `test`,
  817. },
  818. {
  819. desc: `Translate Unicode symbols`,
  820. json: `{"c": "15\u00b0C"}`,
  821. path: []string{"c"},
  822. isFound: true,
  823. data: `15°C`,
  824. },
  825. {
  826. desc: `Translate supplementary Unicode symbols`,
  827. json: `{"c": "\uD83D\uDE03"}`, // Smiley face (UTF16 surrogate pair)
  828. path: []string{"c"},
  829. isFound: true,
  830. data: "\U0001F603", // Smiley face
  831. },
  832. {
  833. desc: `Translate escape symbols`,
  834. json: `{"c": "\\\""}`,
  835. path: []string{"c"},
  836. isFound: true,
  837. data: `\"`,
  838. },
  839. {
  840. desc: `key and value with whitespace escapes`,
  841. json: `{"key\b\f\n\r\tkey":"value\b\f\n\r\tvalue"}`,
  842. path: []string{"key\b\f\n\r\tkey"},
  843. isFound: true,
  844. data: "value\b\f\n\r\tvalue", // value is unescaped since this is GetString()
  845. },
  846. }
  847. var getBoolTests = []GetTest{
  848. {
  849. desc: `read boolean true as boolean`,
  850. json: `{"a": "b", "c": true}`,
  851. path: []string{"c"},
  852. isFound: true,
  853. data: true,
  854. },
  855. {
  856. desc: `boolean true in formatted JSON`,
  857. json: "{\"a\": \"b\", \"c\": true \n}",
  858. path: []string{"c"},
  859. isFound: true,
  860. data: true,
  861. },
  862. {
  863. desc: `read boolean false as boolean`,
  864. json: `{"a": "b", "c": false}`,
  865. path: []string{"c"},
  866. isFound: true,
  867. data: false,
  868. },
  869. {
  870. desc: `boolean true in formatted JSON`,
  871. json: "{\"a\": \"b\", \"c\": false \n}",
  872. path: []string{"c"},
  873. isFound: true,
  874. data: false,
  875. },
  876. {
  877. desc: `read fake boolean true`,
  878. json: `{"a": txyz}`,
  879. path: []string{"a"},
  880. isErr: true,
  881. },
  882. {
  883. desc: `read fake boolean false`,
  884. json: `{"a": fwxyz}`,
  885. path: []string{"a"},
  886. isErr: true,
  887. },
  888. {
  889. desc: `read boolean true with whitespace and another key`,
  890. json: "{\r\t\n \"a\"\r\t\n :\r\t\n true\r\t\n ,\r\t\n \"b\": 1}",
  891. path: []string{"a"},
  892. isFound: true,
  893. data: true,
  894. },
  895. }
  896. var getArrayTests = []GetTest{
  897. {
  898. desc: `read array of simple values`,
  899. json: `{"a": { "b":[1,2,3,4]}}`,
  900. path: []string{"a", "b"},
  901. isFound: true,
  902. data: []string{`1`, `2`, `3`, `4`},
  903. },
  904. {
  905. desc: `read array via empty path`,
  906. json: `[1,2,3,4]`,
  907. path: []string{},
  908. isFound: true,
  909. data: []string{`1`, `2`, `3`, `4`},
  910. },
  911. {
  912. desc: `read array of objects`,
  913. json: `{"a": { "b":[{"x":1},{"x":2},{"x":3},{"x":4}]}}`,
  914. path: []string{"a", "b"},
  915. isFound: true,
  916. data: []string{`{"x":1}`, `{"x":2}`, `{"x":3}`, `{"x":4}`},
  917. },
  918. {
  919. desc: `read nested array`,
  920. json: `{"a": [[[1]],[[2]]]}`,
  921. path: []string{"a"},
  922. isFound: true,
  923. data: []string{`[[1]]`, `[[2]]`},
  924. },
  925. }
  926. // checkFoundAndNoError checks the dataType and error return from Get*() against the test case expectations.
  927. // Returns true the test should proceed to checking the actual data returned from Get*(), or false if the test is finished.
  928. func getTestCheckFoundAndNoError(t *testing.T, testKind string, test GetTest, jtype ValueType, value interface{}, err error) bool {
  929. isFound := (err != KeyPathNotFoundError)
  930. isErr := (err != nil && err != KeyPathNotFoundError)
  931. if test.isErr != isErr {
  932. // If the call didn't match the error expectation, fail
  933. t.Errorf("%s test '%s' isErr mismatch: expected %t, obtained %t (err %v). Value: %v", testKind, test.desc, test.isErr, isErr, err, value)
  934. return false
  935. } else if isErr {
  936. // Else, if there was an error, don't fail and don't check isFound or the value
  937. return false
  938. } else if test.isFound != isFound {
  939. // Else, if the call didn't match the is-found expectation, fail
  940. t.Errorf("%s test '%s' isFound mismatch: expected %t, obtained %t", testKind, test.desc, test.isFound, isFound)
  941. return false
  942. } else if !isFound {
  943. // Else, if no value was found, don't fail and don't check the value
  944. return false
  945. } else {
  946. // Else, there was no error and a value was found, so check the value
  947. return true
  948. }
  949. }
  950. func runGetTests(t *testing.T, testKind string, tests []GetTest, runner func(GetTest) (interface{}, ValueType, error), resultChecker func(GetTest, interface{}) (bool, interface{})) {
  951. for _, test := range tests {
  952. if activeTest != "" && test.desc != activeTest {
  953. continue
  954. }
  955. fmt.Println("Running:", test.desc)
  956. value, dataType, err := runner(test)
  957. if getTestCheckFoundAndNoError(t, testKind, test, dataType, value, err) {
  958. if test.data == nil {
  959. t.Errorf("MALFORMED TEST: %v", test)
  960. continue
  961. }
  962. if ok, expected := resultChecker(test, value); !ok {
  963. if expectedBytes, ok := expected.([]byte); ok {
  964. expected = string(expectedBytes)
  965. }
  966. if valueBytes, ok := value.([]byte); ok {
  967. value = string(valueBytes)
  968. }
  969. t.Errorf("%s test '%s' expected to return value %v, but did returned %v instead", testKind, test.desc, expected, value)
  970. }
  971. }
  972. }
  973. }
  974. func setTestCheckFoundAndNoError(t *testing.T, testKind string, test SetTest, value interface{}, err error) bool {
  975. isFound := (err != KeyPathNotFoundError)
  976. isErr := (err != nil && err != KeyPathNotFoundError)
  977. if test.isErr != isErr {
  978. // If the call didn't match the error expectation, fail
  979. t.Errorf("%s test '%s' isErr mismatch: expected %t, obtained %t (err %v). Value: %v", testKind, test.desc, test.isErr, isErr, err, value)
  980. return false
  981. } else if isErr {
  982. // Else, if there was an error, don't fail and don't check isFound or the value
  983. return false
  984. } else if test.isFound != isFound {
  985. // Else, if the call didn't match the is-found expectation, fail
  986. t.Errorf("%s test '%s' isFound mismatch: expected %t, obtained %t", testKind, test.desc, test.isFound, isFound)
  987. return false
  988. } else if !isFound {
  989. // Else, if no value was found, don't fail and don't check the value
  990. return false
  991. } else {
  992. // Else, there was no error and a value was found, so check the value
  993. return true
  994. }
  995. }
  996. func runSetTests(t *testing.T, testKind string, tests []SetTest, runner func(SetTest) (interface{}, ValueType, error), resultChecker func(SetTest, interface{}) (bool, interface{})) {
  997. for _, test := range tests {
  998. if activeTest != "" && test.desc != activeTest {
  999. continue
  1000. }
  1001. fmt.Println("Running:", test.desc)
  1002. value, _, err := runner(test)
  1003. if setTestCheckFoundAndNoError(t, testKind, test, value, err) {
  1004. if test.data == nil {
  1005. t.Errorf("MALFORMED TEST: %v", test)
  1006. continue
  1007. }
  1008. if string(value.([]byte)) != test.data {
  1009. t.Errorf("Unexpected result on %s test '%s'", testKind, test.desc)
  1010. t.Log("Got: ", string(value.([]byte)))
  1011. t.Log("Expected:", test.data)
  1012. t.Log("Error: ", err)
  1013. }
  1014. }
  1015. }
  1016. }
  1017. func runDeleteTests(t *testing.T, testKind string, tests []DeleteTest, runner func(DeleteTest) interface{}, resultChecker func(DeleteTest, interface{}) (bool, interface{})) {
  1018. for _, test := range tests {
  1019. if activeTest != "" && test.desc != activeTest {
  1020. continue
  1021. }
  1022. fmt.Println("Running:", test.desc)
  1023. value := runner(test)
  1024. if test.data == nil {
  1025. t.Errorf("MALFORMED TEST: %v", test)
  1026. continue
  1027. }
  1028. if ok, expected := resultChecker(test, value); !ok {
  1029. if expectedBytes, ok := expected.([]byte); ok {
  1030. expected = string(expectedBytes)
  1031. }
  1032. if valueBytes, ok := value.([]byte); ok {
  1033. value = string(valueBytes)
  1034. }
  1035. t.Errorf("%s test '%s' expected to return value %v, but did returned %v instead", testKind, test.desc, expected, value)
  1036. }
  1037. }
  1038. }
  1039. func TestSet(t *testing.T) {
  1040. runSetTests(t, "Set()", setTests,
  1041. func(test SetTest) (value interface{}, dataType ValueType, err error) {
  1042. value, err = Set([]byte(test.json), []byte(test.setData), test.path...)
  1043. return
  1044. },
  1045. func(test SetTest, value interface{}) (bool, interface{}) {
  1046. expected := []byte(test.data.(string))
  1047. return bytes.Equal(expected, value.([]byte)), expected
  1048. },
  1049. )
  1050. }
  1051. func TestDelete(t *testing.T) {
  1052. runDeleteTests(t, "Delete()", deleteTests,
  1053. func(test DeleteTest) interface{} {
  1054. return Delete([]byte(test.json), test.path...)
  1055. },
  1056. func(test DeleteTest, value interface{}) (bool, interface{}) {
  1057. expected := []byte(test.data.(string))
  1058. return bytes.Equal(expected, value.([]byte)), expected
  1059. },
  1060. )
  1061. }
  1062. func TestGet(t *testing.T) {
  1063. runGetTests(t, "Get()", getTests,
  1064. func(test GetTest) (value interface{}, dataType ValueType, err error) {
  1065. value, dataType, _, err = Get([]byte(test.json), test.path...)
  1066. return
  1067. },
  1068. func(test GetTest, value interface{}) (bool, interface{}) {
  1069. expected := []byte(test.data.(string))
  1070. return bytes.Equal(expected, value.([]byte)), expected
  1071. },
  1072. )
  1073. }
  1074. func TestGetString(t *testing.T) {
  1075. runGetTests(t, "GetString()", getStringTests,
  1076. func(test GetTest) (value interface{}, dataType ValueType, err error) {
  1077. value, err = GetString([]byte(test.json), test.path...)
  1078. return value, String, err
  1079. },
  1080. func(test GetTest, value interface{}) (bool, interface{}) {
  1081. expected := test.data.(string)
  1082. return expected == value.(string), expected
  1083. },
  1084. )
  1085. }
  1086. func TestGetInt(t *testing.T) {
  1087. runGetTests(t, "GetInt()", getIntTests,
  1088. func(test GetTest) (value interface{}, dataType ValueType, err error) {
  1089. value, err = GetInt([]byte(test.json), test.path...)
  1090. return value, Number, err
  1091. },
  1092. func(test GetTest, value interface{}) (bool, interface{}) {
  1093. expected := test.data.(int64)
  1094. return expected == value.(int64), expected
  1095. },
  1096. )
  1097. }
  1098. func TestGetFloat(t *testing.T) {
  1099. runGetTests(t, "GetFloat()", getFloatTests,
  1100. func(test GetTest) (value interface{}, dataType ValueType, err error) {
  1101. value, err = GetFloat([]byte(test.json), test.path...)
  1102. return value, Number, err
  1103. },
  1104. func(test GetTest, value interface{}) (bool, interface{}) {
  1105. expected := test.data.(float64)
  1106. return expected == value.(float64), expected
  1107. },
  1108. )
  1109. }
  1110. func TestGetBoolean(t *testing.T) {
  1111. runGetTests(t, "GetBoolean()", getBoolTests,
  1112. func(test GetTest) (value interface{}, dataType ValueType, err error) {
  1113. value, err = GetBoolean([]byte(test.json), test.path...)
  1114. return value, Boolean, err
  1115. },
  1116. func(test GetTest, value interface{}) (bool, interface{}) {
  1117. expected := test.data.(bool)
  1118. return expected == value.(bool), expected
  1119. },
  1120. )
  1121. }
  1122. func TestGetSlice(t *testing.T) {
  1123. runGetTests(t, "Get()-for-arrays", getArrayTests,
  1124. func(test GetTest) (value interface{}, dataType ValueType, err error) {
  1125. value, dataType, _, err = Get([]byte(test.json), test.path...)
  1126. return
  1127. },
  1128. func(test GetTest, value interface{}) (bool, interface{}) {
  1129. expected := test.data.([]string)
  1130. return reflect.DeepEqual(expected, toStringArray(value.([]byte))), expected
  1131. },
  1132. )
  1133. }
  1134. func TestArrayEach(t *testing.T) {
  1135. mock := []byte(`{"a": { "b":[{"x": 1} ,{"x":2},{ "x":3}, {"x":4} ]}}`)
  1136. count := 0
  1137. ArrayEach(mock, func(value []byte, dataType ValueType, offset int, err error) {
  1138. count++
  1139. switch count {
  1140. case 1:
  1141. if string(value) != `{"x": 1}` {
  1142. t.Errorf("Wrong first item: %s", string(value))
  1143. }
  1144. case 2:
  1145. if string(value) != `{"x":2}` {
  1146. t.Errorf("Wrong second item: %s", string(value))
  1147. }
  1148. case 3:
  1149. if string(value) != `{ "x":3}` {
  1150. t.Errorf("Wrong third item: %s", string(value))
  1151. }
  1152. case 4:
  1153. if string(value) != `{"x":4}` {
  1154. t.Errorf("Wrong forth item: %s", string(value))
  1155. }
  1156. default:
  1157. t.Errorf("Should process only 4 items")
  1158. }
  1159. }, "a", "b")
  1160. }
  1161. func TestArrayEachEmpty(t *testing.T) {
  1162. funcError := func([]byte, ValueType, int, error) { t.Errorf("Run func not allow") }
  1163. type args struct {
  1164. data []byte
  1165. cb func(value []byte, dataType ValueType, offset int, err error)
  1166. keys []string
  1167. }
  1168. tests := []struct {
  1169. name string
  1170. args args
  1171. wantOffset int
  1172. wantErr bool
  1173. }{
  1174. {"Empty array", args{[]byte("[]"), funcError, []string{}}, 1, false},
  1175. {"Empty array with space", args{[]byte("[ ]"), funcError, []string{}}, 2, false},
  1176. {"Empty array with \n", args{[]byte("[\n]"), funcError, []string{}}, 2, false},
  1177. {"Empty field array", args{[]byte("{\"data\": []}"), funcError, []string{"data"}}, 10, false},
  1178. {"Empty field array with space", args{[]byte("{\"data\": [ ]}"), funcError, []string{"data"}}, 11, false},
  1179. {"Empty field array with \n", args{[]byte("{\"data\": [\n]}"), funcError, []string{"data"}}, 11, false},
  1180. }
  1181. for _, tt := range tests {
  1182. t.Run(tt.name, func(t *testing.T) {
  1183. gotOffset, err := ArrayEach(tt.args.data, tt.args.cb, tt.args.keys...)
  1184. if (err != nil) != tt.wantErr {
  1185. t.Errorf("ArrayEach() error = %v, wantErr %v", err, tt.wantErr)
  1186. return
  1187. }
  1188. if gotOffset != tt.wantOffset {
  1189. t.Errorf("ArrayEach() = %v, want %v", gotOffset, tt.wantOffset)
  1190. }
  1191. })
  1192. }
  1193. }
  1194. type keyValueEntry struct {
  1195. key string
  1196. value string
  1197. valueType ValueType
  1198. }
  1199. func (kv keyValueEntry) String() string {
  1200. return fmt.Sprintf("[%s: %s (%s)]", kv.key, kv.value, kv.valueType)
  1201. }
  1202. type ObjectEachTest struct {
  1203. desc string
  1204. json string
  1205. isErr bool
  1206. entries []keyValueEntry
  1207. }
  1208. var objectEachTests = []ObjectEachTest{
  1209. {
  1210. desc: "empty object",
  1211. json: `{}`,
  1212. entries: []keyValueEntry{},
  1213. },
  1214. {
  1215. desc: "single key-value object",
  1216. json: `{"key": "value"}`,
  1217. entries: []keyValueEntry{
  1218. {"key", "value", String},
  1219. },
  1220. },
  1221. {
  1222. desc: "multiple key-value object with many value types",
  1223. json: `{
  1224. "key1": null,
  1225. "key2": true,
  1226. "key3": 1.23,
  1227. "key4": "string value",
  1228. "key5": [1,2,3],
  1229. "key6": {"a":"b"}
  1230. }`,
  1231. entries: []keyValueEntry{
  1232. {"key1", "null", Null},
  1233. {"key2", "true", Boolean},
  1234. {"key3", "1.23", Number},
  1235. {"key4", "string value", String},
  1236. {"key5", "[1,2,3]", Array},
  1237. {"key6", `{"a":"b"}`, Object},
  1238. },
  1239. },
  1240. {
  1241. desc: "escaped key",
  1242. json: `{"key\"\\\/\b\f\n\r\t\u00B0": "value"}`,
  1243. entries: []keyValueEntry{
  1244. {"key\"\\/\b\f\n\r\t\u00B0", "value", String},
  1245. },
  1246. },
  1247. // Error cases
  1248. {
  1249. desc: "no object present",
  1250. json: ` \t\n\r`,
  1251. isErr: true,
  1252. },
  1253. {
  1254. desc: "unmatched braces 1",
  1255. json: `{`,
  1256. isErr: true,
  1257. },
  1258. {
  1259. desc: "unmatched braces 2",
  1260. json: `}`,
  1261. isErr: true,
  1262. },
  1263. {
  1264. desc: "unmatched braces 3",
  1265. json: `}{}`,
  1266. isErr: true,
  1267. },
  1268. {
  1269. desc: "bad key (number)",
  1270. json: `{123: "value"}`,
  1271. isErr: true,
  1272. },
  1273. {
  1274. desc: "bad key (unclosed quote)",
  1275. json: `{"key: 123}`,
  1276. isErr: true,
  1277. },
  1278. {
  1279. desc: "bad value (no value)",
  1280. json: `{"key":}`,
  1281. isErr: true,
  1282. },
  1283. {
  1284. desc: "bad value (bogus value)",
  1285. json: `{"key": notavalue}`,
  1286. isErr: true,
  1287. },
  1288. {
  1289. desc: "bad entry (missing colon)",
  1290. json: `{"key" "value"}`,
  1291. isErr: true,
  1292. },
  1293. {
  1294. desc: "bad entry (no trailing comma)",
  1295. json: `{"key": "value" "key2": "value2"}`,
  1296. isErr: true,
  1297. },
  1298. {
  1299. desc: "bad entry (two commas)",
  1300. json: `{"key": "value",, "key2": "value2"}`,
  1301. isErr: true,
  1302. },
  1303. }
  1304. func TestObjectEach(t *testing.T) {
  1305. for _, test := range objectEachTests {
  1306. if activeTest != "" && test.desc != activeTest {
  1307. continue
  1308. }
  1309. // Execute ObjectEach and capture all of the entries visited, in order
  1310. var entries []keyValueEntry
  1311. err := ObjectEach([]byte(test.json), func(key, value []byte, valueType ValueType, off int) error {
  1312. entries = append(entries, keyValueEntry{
  1313. key: string(key),
  1314. value: string(value),
  1315. valueType: valueType,
  1316. })
  1317. return nil
  1318. })
  1319. // Check the correctness of the result
  1320. isErr := (err != nil)
  1321. if test.isErr != isErr {
  1322. // If the call didn't match the error expectation, fail
  1323. t.Errorf("ObjectEach test '%s' isErr mismatch: expected %t, obtained %t (err %v)", test.desc, test.isErr, isErr, err)
  1324. } else if isErr {
  1325. // Else, if there was an expected error, don't fail and don't check anything further
  1326. } else if len(test.entries) != len(entries) {
  1327. t.Errorf("ObjectEach test '%s' mismatch in number of key-value entries: expected %d, obtained %d (entries found: %s)", test.desc, len(test.entries), len(entries), entries)
  1328. } else {
  1329. for i, entry := range entries {
  1330. expectedEntry := test.entries[i]
  1331. if expectedEntry.key != entry.key {
  1332. t.Errorf("ObjectEach test '%s' key mismatch at entry %d: expected %s, obtained %s", test.desc, i, expectedEntry.key, entry.key)
  1333. break
  1334. } else if expectedEntry.value != entry.value {
  1335. t.Errorf("ObjectEach test '%s' value mismatch at entry %d: expected %s, obtained %s", test.desc, i, expectedEntry.value, entry.value)
  1336. break
  1337. } else if expectedEntry.valueType != entry.valueType {
  1338. t.Errorf("ObjectEach test '%s' value type mismatch at entry %d: expected %s, obtained %s", test.desc, i, expectedEntry.valueType, entry.valueType)
  1339. break
  1340. } else {
  1341. // Success for this entry
  1342. }
  1343. }
  1344. }
  1345. }
  1346. }
  1347. var testJson = []byte(`{"name": "Name", "order": "Order", "sum": 100, "len": 12, "isPaid": true, "nested": {"a":"test", "b":2, "nested3":{"a":"test3","b":4}, "c": "unknown"}, "nested2": {"a":"test2", "b":3}, "arr": [{"a":"zxc", "b": 1}, {"a":"123", "b":2}], "arrInt": [1,2,3,4], "intPtr": 10}`)
  1348. func TestEachKey(t *testing.T) {
  1349. paths := [][]string{
  1350. {"name"},
  1351. {"order"},
  1352. {"nested", "a"},
  1353. {"nested", "b"},
  1354. {"nested2", "a"},
  1355. {"nested", "nested3", "b"},
  1356. {"arr", "[1]", "b"},
  1357. {"arrInt", "[3]"},
  1358. {"arrInt", "[5]"}, // Should not find last key
  1359. }
  1360. keysFound := 0
  1361. EachKey(testJson, func(idx int, value []byte, vt ValueType, err error) {
  1362. keysFound++
  1363. switch idx {
  1364. case 0:
  1365. if string(value) != "Name" {
  1366. t.Error("Should find 1 key", string(value))
  1367. }
  1368. case 1:
  1369. if string(value) != "Order" {
  1370. t.Errorf("Should find 2 key")
  1371. }
  1372. case 2:
  1373. if string(value) != "test" {
  1374. t.Errorf("Should find 3 key")
  1375. }
  1376. case 3:
  1377. if string(value) != "2" {
  1378. t.Errorf("Should find 4 key")
  1379. }
  1380. case 4:
  1381. if string(value) != "test2" {
  1382. t.Error("Should find 5 key", string(value))
  1383. }
  1384. case 5:
  1385. if string(value) != "4" {
  1386. t.Errorf("Should find 6 key")
  1387. }
  1388. case 6:
  1389. if string(value) != "2" {
  1390. t.Errorf("Should find 7 key")
  1391. }
  1392. case 7:
  1393. if string(value) != "4" {
  1394. t.Error("Should find 8 key", string(value))
  1395. }
  1396. default:
  1397. t.Errorf("Should found only 8 keys")
  1398. }
  1399. }, paths...)
  1400. if keysFound != 8 {
  1401. t.Errorf("Should find 8 keys: %d", keysFound)
  1402. }
  1403. }
  1404. type ParseTest struct {
  1405. in string
  1406. intype ValueType
  1407. out interface{}
  1408. isErr bool
  1409. }
  1410. var parseBoolTests = []ParseTest{
  1411. {
  1412. in: "true",
  1413. intype: Boolean,
  1414. out: true,
  1415. },
  1416. {
  1417. in: "false",
  1418. intype: Boolean,
  1419. out: false,
  1420. },
  1421. {
  1422. in: "foo",
  1423. intype: Boolean,
  1424. isErr: true,
  1425. },
  1426. {
  1427. in: "trux",
  1428. intype: Boolean,
  1429. isErr: true,
  1430. },
  1431. {
  1432. in: "truex",
  1433. intype: Boolean,
  1434. isErr: true,
  1435. },
  1436. {
  1437. in: "",
  1438. intype: Boolean,
  1439. isErr: true,
  1440. },
  1441. }
  1442. var parseFloatTest = []ParseTest{
  1443. {
  1444. in: "0",
  1445. intype: Number,
  1446. out: float64(0),
  1447. },
  1448. {
  1449. in: "0.0",
  1450. intype: Number,
  1451. out: float64(0.0),
  1452. },
  1453. {
  1454. in: "1",
  1455. intype: Number,
  1456. out: float64(1),
  1457. },
  1458. {
  1459. in: "1.234",
  1460. intype: Number,
  1461. out: float64(1.234),
  1462. },
  1463. {
  1464. in: "1.234e5",
  1465. intype: Number,
  1466. out: float64(1.234e5),
  1467. },
  1468. {
  1469. in: "-1.234e5",
  1470. intype: Number,
  1471. out: float64(-1.234e5),
  1472. },
  1473. {
  1474. in: "+1.234e5", // Note: + sign not allowed under RFC7159, but our parser accepts it since it uses strconv.ParseFloat
  1475. intype: Number,
  1476. out: float64(1.234e5),
  1477. },
  1478. {
  1479. in: "1.2.3",
  1480. intype: Number,
  1481. isErr: true,
  1482. },
  1483. {
  1484. in: "1..1",
  1485. intype: Number,
  1486. isErr: true,
  1487. },
  1488. {
  1489. in: "1a",
  1490. intype: Number,
  1491. isErr: true,
  1492. },
  1493. {
  1494. in: "",
  1495. intype: Number,
  1496. isErr: true,
  1497. },
  1498. }
  1499. // parseTestCheckNoError checks the error return from Parse*() against the test case expectations.
  1500. // Returns true the test should proceed to checking the actual data returned from Parse*(), or false if the test is finished.
  1501. func parseTestCheckNoError(t *testing.T, testKind string, test ParseTest, value interface{}, err error) bool {
  1502. if isErr := (err != nil); test.isErr != isErr {
  1503. // If the call didn't match the error expectation, fail
  1504. t.Errorf("%s test '%s' isErr mismatch: expected %t, obtained %t (err %v). Obtained value: %v", testKind, test.in, test.isErr, isErr, err, value)
  1505. return false
  1506. } else if isErr {
  1507. // Else, if there was an error, don't fail and don't check isFound or the value
  1508. return false
  1509. } else {
  1510. // Else, there was no error and a value was found, so check the value
  1511. return true
  1512. }
  1513. }
  1514. func runParseTests(t *testing.T, testKind string, tests []ParseTest, runner func(ParseTest) (interface{}, error), resultChecker func(ParseTest, interface{}) (bool, interface{})) {
  1515. for _, test := range tests {
  1516. value, err := runner(test)
  1517. if parseTestCheckNoError(t, testKind, test, value, err) {
  1518. if test.out == nil {
  1519. t.Errorf("MALFORMED TEST: %v", test)
  1520. continue
  1521. }
  1522. if ok, expected := resultChecker(test, value); !ok {
  1523. if expectedBytes, ok := expected.([]byte); ok {
  1524. expected = string(expectedBytes)
  1525. }
  1526. if valueBytes, ok := value.([]byte); ok {
  1527. value = string(valueBytes)
  1528. }
  1529. t.Errorf("%s test '%s' expected to return value %v, but did returned %v instead", testKind, test.in, expected, value)
  1530. }
  1531. }
  1532. }
  1533. }
  1534. func TestParseBoolean(t *testing.T) {
  1535. runParseTests(t, "ParseBoolean()", parseBoolTests,
  1536. func(test ParseTest) (value interface{}, err error) {
  1537. return ParseBoolean([]byte(test.in))
  1538. },
  1539. func(test ParseTest, obtained interface{}) (bool, interface{}) {
  1540. expected := test.out.(bool)
  1541. return obtained.(bool) == expected, expected
  1542. },
  1543. )
  1544. }
  1545. func TestParseFloat(t *testing.T) {
  1546. runParseTests(t, "ParseFloat()", parseFloatTest,
  1547. func(test ParseTest) (value interface{}, err error) {
  1548. return ParseFloat([]byte(test.in))
  1549. },
  1550. func(test ParseTest, obtained interface{}) (bool, interface{}) {
  1551. expected := test.out.(float64)
  1552. return obtained.(float64) == expected, expected
  1553. },
  1554. )
  1555. }
  1556. var parseStringTest = []ParseTest{
  1557. {
  1558. in: `\uFF11`,
  1559. intype: String,
  1560. out: "\uFF11",
  1561. },
  1562. {
  1563. in: `\uFFFF`,
  1564. intype: String,
  1565. out: "\uFFFF",
  1566. },
  1567. {
  1568. in: `\uDF00`,
  1569. intype: String,
  1570. isErr: true,
  1571. },
  1572. }
  1573. func TestParseString(t *testing.T) {
  1574. runParseTests(t, "ParseString()", parseStringTest,
  1575. func(test ParseTest) (value interface{}, err error) {
  1576. return ParseString([]byte(test.in))
  1577. },
  1578. func(test ParseTest, obtained interface{}) (bool, interface{}) {
  1579. expected := test.out.(string)
  1580. return obtained.(string) == expected, expected
  1581. },
  1582. )
  1583. }