RFC6901 JSON Pointer implementation in OCaml using jsont
1JSON Pointer API Test Suite
2
3This tests all functions exposed in json_pointer.mli.
4
5================================================================================
6Index Functions (mem, nth, pp_index, equal_index, compare_index)
7================================================================================
8
9Creating indices with mem:
10 $ ./test_pointer.exe mem "foo"
11 mem(foo) = /foo
12 $ ./test_pointer.exe mem ""
13 mem() = /
14 $ ./test_pointer.exe mem "a/b"
15 mem(a/b) = /a~1b
16 $ ./test_pointer.exe mem "m~n"
17 mem(m~n) = /m~0n
18
19Creating indices with nth:
20 $ ./test_pointer.exe nth 0
21 nth(0) = /0
22 $ ./test_pointer.exe nth 5
23 nth(5) = /5
24 $ ./test_pointer.exe nth 123
25 nth(123) = /123
26
27Testing index equality:
28 $ ./test_pointer.exe equal-index "foo" "foo"
29 true
30 $ ./test_pointer.exe equal-index "foo" "bar"
31 false
32 $ ./test_pointer.exe equal-index "0" "0"
33 true
34 $ ./test_pointer.exe equal-index "0" "1"
35 false
36 $ ./test_pointer.exe equal-index "foo" "0"
37 false
38
39Testing index comparison:
40 $ ./test_pointer.exe compare-index "foo" "foo"
41 EQ
42 $ ./test_pointer.exe compare-index "aaa" "bbb"
43 LT
44 $ ./test_pointer.exe compare-index "bbb" "aaa"
45 GT
46 $ ./test_pointer.exe compare-index "0" "0"
47 EQ
48 $ ./test_pointer.exe compare-index "0" "5"
49 LT
50 $ ./test_pointer.exe compare-index "5" "0"
51 GT
52 $ ./test_pointer.exe compare-index "foo" "0"
53 LT
54 $ ./test_pointer.exe compare-index "0" "foo"
55 GT
56
57================================================================================
58Pointer Constructors (root, is_root, make, /, append_index, at_end, concat, parent, last)
59================================================================================
60
61Root pointer:
62 $ ./test_pointer.exe root
63 root =
64 is_root(root) = true
65
66Testing is_root:
67 $ ./test_pointer.exe is-root ""
68 true
69 $ ./test_pointer.exe is-root "/foo"
70 false
71 $ ./test_pointer.exe is-root "/foo/bar"
72 false
73
74Making pointers from indices:
75 $ ./test_pointer.exe make "foo"
76 /foo
77 $ ./test_pointer.exe make "foo,bar"
78 /foo/bar
79 $ ./test_pointer.exe make "foo,0,bar"
80 /foo/0/bar
81 $ ./test_pointer.exe make "0,1,2"
82 /0/1/2
83
84Appending index to pointer:
85 $ ./test_pointer.exe append-index "" "foo"
86 /foo
87 $ ./test_pointer.exe append-index "/foo" "bar"
88 /foo/bar
89 $ ./test_pointer.exe append-index "/foo" "0"
90 /foo/0
91 $ ./test_pointer.exe append-index "/foo/bar" "baz"
92 /foo/bar/baz
93
94Creating append pointers with at_end:
95 $ ./test_pointer.exe at-end ""
96 /-
97 $ ./test_pointer.exe at-end "/foo"
98 /foo/-
99 $ ./test_pointer.exe at-end "/foo/bar"
100 /foo/bar/-
101
102Concatenating pointers:
103 $ ./test_pointer.exe concat "" ""
104
105
106 $ ./test_pointer.exe concat "/foo" ""
107 /foo
108 $ ./test_pointer.exe concat "" "/bar"
109 /bar
110 $ ./test_pointer.exe concat "/foo" "/bar"
111 /foo/bar
112 $ ./test_pointer.exe concat "/a/b" "/c/d"
113 /a/b/c/d
114
115Getting parent pointer:
116 $ ./test_pointer.exe parent ""
117 None
118 $ ./test_pointer.exe parent "/foo"
119 Some()
120 $ ./test_pointer.exe parent "/foo/bar"
121 Some(/foo)
122 $ ./test_pointer.exe parent "/a/b/c"
123 Some(/a/b)
124
125Getting last index:
126 $ ./test_pointer.exe last ""
127 None
128 $ ./test_pointer.exe last "/foo"
129 Some(/foo)
130 $ ./test_pointer.exe last "/foo/bar"
131 Some(/bar)
132 $ ./test_pointer.exe last "/foo/0"
133 Some(/0)
134
135Getting all indices:
136 $ ./test_pointer.exe indices ""
137 []
138 $ ./test_pointer.exe indices "/foo"
139 [Mem:foo]
140 $ ./test_pointer.exe indices "/foo/bar"
141 [Mem:foo, Mem:bar]
142 $ ./test_pointer.exe indices "/foo/0/bar"
143 [Mem:foo, Nth:0, Mem:bar]
144 $ ./test_pointer.exe indices "/foo/-"
145 [Mem:foo]
146
147================================================================================
148Coercion Functions (any, is_nav, to_nav, to_nav_exn)
149================================================================================
150
151Note: is_nav is tested indirectly via the parse tests. Testing to_nav:
152
153 $ ./test_pointer.exe to-nav ""
154 Some()
155 $ ./test_pointer.exe to-nav "/foo"
156 Some(/foo)
157 $ ./test_pointer.exe to-nav "/foo/bar"
158 Some(/foo/bar)
159 $ ./test_pointer.exe to-nav "/-"
160 None
161 $ ./test_pointer.exe to-nav "/foo/-"
162 None
163
164Testing to_nav_exn:
165 $ ./test_pointer.exe to-nav-exn ""
166 OK:
167 $ ./test_pointer.exe to-nav-exn "/foo"
168 OK: /foo
169 $ ./test_pointer.exe to-nav-exn "/-"
170 ERROR: JSON Pointer: cannot convert append pointer to nav pointer
171 $ ./test_pointer.exe to-nav-exn "/foo/-"
172 ERROR: JSON Pointer: cannot convert append pointer to nav pointer
173
174================================================================================
175Parsing Functions (of_string_kind, of_string_result, of_uri_fragment_nav, of_uri_fragment_result)
176================================================================================
177
178Testing of_string_kind:
179 $ ./test_pointer.exe of-string-kind ""
180 Nav()
181 $ ./test_pointer.exe of-string-kind "/foo"
182 Nav(/foo)
183 $ ./test_pointer.exe of-string-kind "/-"
184 Append(/-)
185 $ ./test_pointer.exe of-string-kind "/foo/-"
186 Append(/foo/-)
187 $ ./test_pointer.exe of-string-kind "/foo/bar"
188 Nav(/foo/bar)
189
190Testing of_string_result:
191 $ ./test_pointer.exe of-string-result ""
192 Ok()
193 $ ./test_pointer.exe of-string-result "/foo"
194 Ok(/foo)
195 $ ./test_pointer.exe of-string-result "/-"
196 Ok(/-)
197 $ ./test_pointer.exe of-string-result "invalid"
198 Error(Invalid JSON Pointer: must be empty or start with '/': invalid)
199 $ ./test_pointer.exe of-string-result "/~"
200 Error(Invalid JSON Pointer: incomplete escape sequence at end)
201
202Testing of_uri_fragment_nav:
203 $ ./test_pointer.exe of-uri-fragment-nav ""
204 OK:
205 $ ./test_pointer.exe of-uri-fragment-nav "/foo"
206 OK: /foo
207 $ ./test_pointer.exe of-uri-fragment-nav "/foo/bar"
208 OK: /foo/bar
209 $ ./test_pointer.exe of-uri-fragment-nav "/foo%2Fbar"
210 OK: /foo/bar
211 $ ./test_pointer.exe of-uri-fragment-nav "/-"
212 ERROR: Invalid JSON Pointer: '-' not allowed in navigation pointer
213
214Testing of_uri_fragment_result:
215 $ ./test_pointer.exe of-uri-fragment-result ""
216 Ok()
217 $ ./test_pointer.exe of-uri-fragment-result "/foo"
218 Ok(/foo)
219 $ ./test_pointer.exe of-uri-fragment-result "/-"
220 Ok(/-)
221 $ ./test_pointer.exe of-uri-fragment-result "invalid"
222 Error(Invalid JSON Pointer: must be empty or start with '/': invalid)
223
224================================================================================
225Pretty Printing (pp, pp_verbose)
226================================================================================
227
228Testing pp:
229 $ ./test_pointer.exe pp ""
230
231
232 $ ./test_pointer.exe pp "/foo"
233 /foo
234 $ ./test_pointer.exe pp "/foo/bar"
235 /foo/bar
236 $ ./test_pointer.exe pp "/-"
237 /-
238 $ ./test_pointer.exe pp "/foo/-"
239 /foo/-
240
241Testing pp_verbose:
242 $ ./test_pointer.exe pp-verbose ""
243 []
244 $ ./test_pointer.exe pp-verbose "/foo"
245 [Mem "foo"]
246 $ ./test_pointer.exe pp-verbose "/foo/0"
247 [Mem "foo"; Nth 0]
248 $ ./test_pointer.exe pp-verbose "/foo/bar/baz"
249 [Mem "foo"; Mem "bar"; Mem "baz"]
250 $ ./test_pointer.exe pp-verbose "/-"
251 [] /-
252 $ ./test_pointer.exe pp-verbose "/foo/-"
253 [Mem "foo"] /-
254
255================================================================================
256Comparison (equal, compare)
257================================================================================
258
259Testing equal:
260 $ ./test_pointer.exe equal "" ""
261 true
262 $ ./test_pointer.exe equal "/foo" "/foo"
263 true
264 $ ./test_pointer.exe equal "/foo" "/bar"
265 false
266 $ ./test_pointer.exe equal "/foo/0" "/foo/0"
267 true
268 $ ./test_pointer.exe equal "/foo/0" "/foo/1"
269 false
270 $ ./test_pointer.exe equal "/-" "/-"
271 true
272 $ ./test_pointer.exe equal "/foo/-" "/foo/-"
273 true
274 $ ./test_pointer.exe equal "/foo" "/foo/-"
275 false
276
277Testing compare:
278 $ ./test_pointer.exe compare "" ""
279 EQ
280 $ ./test_pointer.exe compare "/foo" "/foo"
281 EQ
282 $ ./test_pointer.exe compare "/aaa" "/bbb"
283 LT
284 $ ./test_pointer.exe compare "/bbb" "/aaa"
285 GT
286 $ ./test_pointer.exe compare "/foo" "/foo/bar"
287 LT
288 $ ./test_pointer.exe compare "/foo/bar" "/foo"
289 GT
290 $ ./test_pointer.exe compare "/foo" "/foo/-"
291 LT
292 $ ./test_pointer.exe compare "/foo/-" "/foo"
293 GT
294
295================================================================================
296Jsont.Path Conversion (of_path, to_path)
297================================================================================
298
299Testing of_path (builds a path programmatically):
300 $ ./test_pointer.exe of-path
301 /0/foo/1
302
303Testing to_path:
304 $ ./test_pointer.exe to-path ""
305 []
306 $ ./test_pointer.exe to-path "/foo"
307 [Mem:foo]
308 $ ./test_pointer.exe to-path "/foo/0"
309 [Mem:foo, Nth:0]
310 $ ./test_pointer.exe to-path "/a/b/c"
311 [Mem:a, Mem:b, Mem:c]
312
313================================================================================
314Evaluation (get_result, set)
315================================================================================
316
317Testing get_result:
318 $ ./test_pointer.exe get-result '{"foo":"bar"}' '/foo'
319 Ok("bar")
320 $ ./test_pointer.exe get-result '{"foo":{"bar":"baz"}}' '/foo/bar'
321 Ok("baz")
322 $ ./test_pointer.exe get-result '["a","b","c"]' '/1'
323 Ok("b")
324 $ ./test_pointer.exe get-result '{"foo":"bar"}' '/baz'
325 Error(JSON Pointer: member 'baz' not found
326 File "-":)
327 $ ./test_pointer.exe get-result '["a","b"]' '/5'
328 Error(JSON Pointer: index 5 out of bounds (array has 2 elements)
329 File "-":)
330
331Testing set (with nav pointer):
332 $ ./test_pointer.exe set '{"foo":"bar"}' '/foo' '"baz"'
333 {"foo":"baz"}
334 $ ./test_pointer.exe set '{"foo":{"bar":"old"}}' '/foo/bar' '"new"'
335 {"foo":{"bar":"new"}}
336 $ ./test_pointer.exe set '["a","b","c"]' '/1' '"x"'
337 ["a","x","c"]
338
339Testing set (with append pointer):
340 $ ./test_pointer.exe set '["a","b"]' '/-' '"c"'
341 ["a","b","c"]
342 $ ./test_pointer.exe set '{"arr":["x"]}' '/arr/-' '"y"'
343 {"arr":["x","y"]}
344
345================================================================================
346Jsont Codecs (jsont, jsont_kind, jsont_nav, jsont_uri_fragment)
347================================================================================
348
349Testing jsont codec roundtrip:
350 $ ./test_pointer.exe jsont-codec ""
351 ""
352 $ ./test_pointer.exe jsont-codec "/foo"
353 "/foo"
354 $ ./test_pointer.exe jsont-codec "/foo/bar"
355 "/foo/bar"
356 $ ./test_pointer.exe jsont-codec "/-"
357 "/-"
358 $ ./test_pointer.exe jsont-codec "/foo/-"
359 "/foo/-"
360
361Testing jsont_kind codec:
362 $ ./test_pointer.exe jsont-kind ""
363 Nav()
364 $ ./test_pointer.exe jsont-kind "/foo"
365 Nav(/foo)
366 $ ./test_pointer.exe jsont-kind "/-"
367 Append(/-)
368 $ ./test_pointer.exe jsont-kind "/foo/-"
369 Append(/foo/-)
370
371Testing jsont_nav codec:
372 $ ./test_pointer.exe jsont-nav ""
373 OK:
374 $ ./test_pointer.exe jsont-nav "/foo"
375 OK: /foo
376 $ ./test_pointer.exe jsont-nav "/-"
377 ERROR: Invalid JSON Pointer: '-' not allowed in navigation pointer
378 $ ./test_pointer.exe jsont-nav "/foo/-"
379 ERROR: Invalid JSON Pointer: '-' not allowed in navigation pointer
380
381Testing jsont_uri_fragment codec:
382 $ ./test_pointer.exe jsont-uri-fragment ""
383 ""
384 $ ./test_pointer.exe jsont-uri-fragment "/foo"
385 "/foo"
386 $ ./test_pointer.exe jsont-uri-fragment "/a~1b"
387 "/a~1b"
388
389================================================================================
390Query Combinators (path, set_path, update_path, delete_path)
391================================================================================
392
393Testing path combinator:
394 $ ./test_pointer.exe query-path '{"name":"alice"}' '/name'
395 OK: alice
396 $ ./test_pointer.exe query-path '{"user":{"name":"bob"}}' '/user/name'
397 OK: bob
398
399Testing path combinator with absent:
400 $ ./test_pointer.exe query-path-absent '{"name":"alice"}' '/name' 'default'
401 OK: alice
402 $ ./test_pointer.exe query-path-absent '{"other":"value"}' '/name' 'default'
403 OK: default
404
405Testing set_path combinator:
406 $ ./test_pointer.exe set-path '{"name":"alice"}' '/name' 'bob'
407 {"name":"bob"}
408 $ ./test_pointer.exe set-path '{"user":{"name":"old"}}' '/user/name' 'new'
409 {"user":{"name":"new"}}
410
411Testing update_path combinator:
412 $ ./test_pointer.exe update-path '{"name":"alice"}' '/name'
413 {"name":"alice"}
414 $ ./test_pointer.exe update-path '{"user":{"name":"bob"}}' '/user/name'
415 {"user":{"name":"bob"}}
416
417Testing delete_path combinator:
418 $ ./test_pointer.exe delete-path '{"foo":"bar","baz":"qux"}' '/foo'
419 {"baz":"qux"}
420 $ ./test_pointer.exe delete-path '{"user":{"name":"bob","age":30}}' '/user/name'
421 {"user":{"age":30}}
422
423Testing delete_path with allow_absent:
424 $ ./test_pointer.exe delete-path-absent '{"foo":"bar"}' '/baz'
425 {"foo":"bar"}
426 $ ./test_pointer.exe delete-path-absent '{"foo":"bar"}' '/foo'
427 {}
428
429================================================================================
430JMAP Extended Pointers - Additional Tests
431================================================================================
432
433Testing Jmap.of_string_result:
434 $ ./test_pointer.exe jmap-of-string-result ""
435 Ok()
436 $ ./test_pointer.exe jmap-of-string-result "/foo"
437 Ok(/foo)
438 $ ./test_pointer.exe jmap-of-string-result "/*"
439 Ok(/*)
440 $ ./test_pointer.exe jmap-of-string-result "/list/*/id"
441 Ok(/list/*/id)
442 $ ./test_pointer.exe jmap-of-string-result "invalid"
443 Error(Invalid JMAP Pointer: must be empty or start with '/': invalid)
444 $ ./test_pointer.exe jmap-of-string-result "/-"
445 Error(Invalid JMAP Pointer: '-' not supported in result reference paths)
446
447Testing Jmap.pp:
448 $ ./test_pointer.exe jmap-pp ""
449
450
451 $ ./test_pointer.exe jmap-pp "/foo"
452 /foo
453 $ ./test_pointer.exe jmap-pp "/*"
454 /*
455 $ ./test_pointer.exe jmap-pp "/list/*/id"
456 /list/*/id
457
458Testing Jmap.eval_result:
459 $ ./test_pointer.exe jmap-eval-result '{"foo":"bar"}' '/foo'
460 Ok("bar")
461 $ ./test_pointer.exe jmap-eval-result '{"list":[{"id":"a"},{"id":"b"}]}' '/list/*/id'
462 Ok(["a","b"])
463 $ ./test_pointer.exe jmap-eval-result '{"foo":"bar"}' '/baz'
464 Error(JMAP Pointer: member 'baz' not found
465 File "-":)
466
467Testing Jmap.find:
468 $ ./test_pointer.exe jmap-find '{"foo":"bar"}' '/foo'
469 Some("bar")
470 $ ./test_pointer.exe jmap-find '{"list":[{"id":"a"},{"id":"b"}]}' '/list/*/id'
471 Some(["a","b"])
472 $ ./test_pointer.exe jmap-find '{"foo":"bar"}' '/baz'
473 None
474 $ ./test_pointer.exe jmap-find '{"obj":{"a":1}}' '/obj/*'
475 None
476
477Testing Jmap.jsont codec:
478 $ ./test_pointer.exe jmap-jsont ""
479 ""
480 $ ./test_pointer.exe jmap-jsont "/foo"
481 "/foo"
482 $ ./test_pointer.exe jmap-jsont "/*"
483 "/*"
484 $ ./test_pointer.exe jmap-jsont "/list/*/id"
485 "/list/*/id"