JSON Pointer API Test Suite This tests all functions exposed in json_pointer.mli. ================================================================================ Index Functions (mem, nth, pp_index, equal_index, compare_index) ================================================================================ Creating indices with mem: $ ./test_pointer.exe mem "foo" mem(foo) = /foo $ ./test_pointer.exe mem "" mem() = / $ ./test_pointer.exe mem "a/b" mem(a/b) = /a~1b $ ./test_pointer.exe mem "m~n" mem(m~n) = /m~0n Creating indices with nth: $ ./test_pointer.exe nth 0 nth(0) = /0 $ ./test_pointer.exe nth 5 nth(5) = /5 $ ./test_pointer.exe nth 123 nth(123) = /123 Testing index equality: $ ./test_pointer.exe equal-index "foo" "foo" true $ ./test_pointer.exe equal-index "foo" "bar" false $ ./test_pointer.exe equal-index "0" "0" true $ ./test_pointer.exe equal-index "0" "1" false $ ./test_pointer.exe equal-index "foo" "0" false Testing index comparison: $ ./test_pointer.exe compare-index "foo" "foo" EQ $ ./test_pointer.exe compare-index "aaa" "bbb" LT $ ./test_pointer.exe compare-index "bbb" "aaa" GT $ ./test_pointer.exe compare-index "0" "0" EQ $ ./test_pointer.exe compare-index "0" "5" LT $ ./test_pointer.exe compare-index "5" "0" GT $ ./test_pointer.exe compare-index "foo" "0" LT $ ./test_pointer.exe compare-index "0" "foo" GT ================================================================================ Pointer Constructors (root, is_root, make, /, append_index, at_end, concat, parent, last) ================================================================================ Root pointer: $ ./test_pointer.exe root root = is_root(root) = true Testing is_root: $ ./test_pointer.exe is-root "" true $ ./test_pointer.exe is-root "/foo" false $ ./test_pointer.exe is-root "/foo/bar" false Making pointers from indices: $ ./test_pointer.exe make "foo" /foo $ ./test_pointer.exe make "foo,bar" /foo/bar $ ./test_pointer.exe make "foo,0,bar" /foo/0/bar $ ./test_pointer.exe make "0,1,2" /0/1/2 Appending index to pointer: $ ./test_pointer.exe append-index "" "foo" /foo $ ./test_pointer.exe append-index "/foo" "bar" /foo/bar $ ./test_pointer.exe append-index "/foo" "0" /foo/0 $ ./test_pointer.exe append-index "/foo/bar" "baz" /foo/bar/baz Creating append pointers with at_end: $ ./test_pointer.exe at-end "" /- $ ./test_pointer.exe at-end "/foo" /foo/- $ ./test_pointer.exe at-end "/foo/bar" /foo/bar/- Concatenating pointers: $ ./test_pointer.exe concat "" "" $ ./test_pointer.exe concat "/foo" "" /foo $ ./test_pointer.exe concat "" "/bar" /bar $ ./test_pointer.exe concat "/foo" "/bar" /foo/bar $ ./test_pointer.exe concat "/a/b" "/c/d" /a/b/c/d Getting parent pointer: $ ./test_pointer.exe parent "" None $ ./test_pointer.exe parent "/foo" Some() $ ./test_pointer.exe parent "/foo/bar" Some(/foo) $ ./test_pointer.exe parent "/a/b/c" Some(/a/b) Getting last index: $ ./test_pointer.exe last "" None $ ./test_pointer.exe last "/foo" Some(/foo) $ ./test_pointer.exe last "/foo/bar" Some(/bar) $ ./test_pointer.exe last "/foo/0" Some(/0) Getting all indices: $ ./test_pointer.exe indices "" [] $ ./test_pointer.exe indices "/foo" [Mem:foo] $ ./test_pointer.exe indices "/foo/bar" [Mem:foo, Mem:bar] $ ./test_pointer.exe indices "/foo/0/bar" [Mem:foo, Nth:0, Mem:bar] $ ./test_pointer.exe indices "/foo/-" [Mem:foo] ================================================================================ Coercion Functions (any, is_nav, to_nav, to_nav_exn) ================================================================================ Note: is_nav is tested indirectly via the parse tests. Testing to_nav: $ ./test_pointer.exe to-nav "" Some() $ ./test_pointer.exe to-nav "/foo" Some(/foo) $ ./test_pointer.exe to-nav "/foo/bar" Some(/foo/bar) $ ./test_pointer.exe to-nav "/-" None $ ./test_pointer.exe to-nav "/foo/-" None Testing to_nav_exn: $ ./test_pointer.exe to-nav-exn "" OK: $ ./test_pointer.exe to-nav-exn "/foo" OK: /foo $ ./test_pointer.exe to-nav-exn "/-" ERROR: JSON Pointer: cannot convert append pointer to nav pointer $ ./test_pointer.exe to-nav-exn "/foo/-" ERROR: JSON Pointer: cannot convert append pointer to nav pointer ================================================================================ Parsing Functions (of_string_kind, of_string_result, of_uri_fragment_nav, of_uri_fragment_result) ================================================================================ Testing of_string_kind: $ ./test_pointer.exe of-string-kind "" Nav() $ ./test_pointer.exe of-string-kind "/foo" Nav(/foo) $ ./test_pointer.exe of-string-kind "/-" Append(/-) $ ./test_pointer.exe of-string-kind "/foo/-" Append(/foo/-) $ ./test_pointer.exe of-string-kind "/foo/bar" Nav(/foo/bar) Testing of_string_result: $ ./test_pointer.exe of-string-result "" Ok() $ ./test_pointer.exe of-string-result "/foo" Ok(/foo) $ ./test_pointer.exe of-string-result "/-" Ok(/-) $ ./test_pointer.exe of-string-result "invalid" Error(Invalid JSON Pointer: must be empty or start with '/': invalid) $ ./test_pointer.exe of-string-result "/~" Error(Invalid JSON Pointer: incomplete escape sequence at end) Testing of_uri_fragment_nav: $ ./test_pointer.exe of-uri-fragment-nav "" OK: $ ./test_pointer.exe of-uri-fragment-nav "/foo" OK: /foo $ ./test_pointer.exe of-uri-fragment-nav "/foo/bar" OK: /foo/bar $ ./test_pointer.exe of-uri-fragment-nav "/foo%2Fbar" OK: /foo/bar $ ./test_pointer.exe of-uri-fragment-nav "/-" ERROR: Invalid JSON Pointer: '-' not allowed in navigation pointer Testing of_uri_fragment_result: $ ./test_pointer.exe of-uri-fragment-result "" Ok() $ ./test_pointer.exe of-uri-fragment-result "/foo" Ok(/foo) $ ./test_pointer.exe of-uri-fragment-result "/-" Ok(/-) $ ./test_pointer.exe of-uri-fragment-result "invalid" Error(Invalid JSON Pointer: must be empty or start with '/': invalid) ================================================================================ Pretty Printing (pp, pp_verbose) ================================================================================ Testing pp: $ ./test_pointer.exe pp "" $ ./test_pointer.exe pp "/foo" /foo $ ./test_pointer.exe pp "/foo/bar" /foo/bar $ ./test_pointer.exe pp "/-" /- $ ./test_pointer.exe pp "/foo/-" /foo/- Testing pp_verbose: $ ./test_pointer.exe pp-verbose "" [] $ ./test_pointer.exe pp-verbose "/foo" [Mem "foo"] $ ./test_pointer.exe pp-verbose "/foo/0" [Mem "foo"; Nth 0] $ ./test_pointer.exe pp-verbose "/foo/bar/baz" [Mem "foo"; Mem "bar"; Mem "baz"] $ ./test_pointer.exe pp-verbose "/-" [] /- $ ./test_pointer.exe pp-verbose "/foo/-" [Mem "foo"] /- ================================================================================ Comparison (equal, compare) ================================================================================ Testing equal: $ ./test_pointer.exe equal "" "" true $ ./test_pointer.exe equal "/foo" "/foo" true $ ./test_pointer.exe equal "/foo" "/bar" false $ ./test_pointer.exe equal "/foo/0" "/foo/0" true $ ./test_pointer.exe equal "/foo/0" "/foo/1" false $ ./test_pointer.exe equal "/-" "/-" true $ ./test_pointer.exe equal "/foo/-" "/foo/-" true $ ./test_pointer.exe equal "/foo" "/foo/-" false Testing compare: $ ./test_pointer.exe compare "" "" EQ $ ./test_pointer.exe compare "/foo" "/foo" EQ $ ./test_pointer.exe compare "/aaa" "/bbb" LT $ ./test_pointer.exe compare "/bbb" "/aaa" GT $ ./test_pointer.exe compare "/foo" "/foo/bar" LT $ ./test_pointer.exe compare "/foo/bar" "/foo" GT $ ./test_pointer.exe compare "/foo" "/foo/-" LT $ ./test_pointer.exe compare "/foo/-" "/foo" GT ================================================================================ Jsont.Path Conversion (of_path, to_path) ================================================================================ Testing of_path (builds a path programmatically): $ ./test_pointer.exe of-path /0/foo/1 Testing to_path: $ ./test_pointer.exe to-path "" [] $ ./test_pointer.exe to-path "/foo" [Mem:foo] $ ./test_pointer.exe to-path "/foo/0" [Mem:foo, Nth:0] $ ./test_pointer.exe to-path "/a/b/c" [Mem:a, Mem:b, Mem:c] ================================================================================ Evaluation (get_result, set) ================================================================================ Testing get_result: $ ./test_pointer.exe get-result '{"foo":"bar"}' '/foo' Ok("bar") $ ./test_pointer.exe get-result '{"foo":{"bar":"baz"}}' '/foo/bar' Ok("baz") $ ./test_pointer.exe get-result '["a","b","c"]' '/1' Ok("b") $ ./test_pointer.exe get-result '{"foo":"bar"}' '/baz' Error(JSON Pointer: member 'baz' not found File "-":) $ ./test_pointer.exe get-result '["a","b"]' '/5' Error(JSON Pointer: index 5 out of bounds (array has 2 elements) File "-":) Testing set (with nav pointer): $ ./test_pointer.exe set '{"foo":"bar"}' '/foo' '"baz"' {"foo":"baz"} $ ./test_pointer.exe set '{"foo":{"bar":"old"}}' '/foo/bar' '"new"' {"foo":{"bar":"new"}} $ ./test_pointer.exe set '["a","b","c"]' '/1' '"x"' ["a","x","c"] Testing set (with append pointer): $ ./test_pointer.exe set '["a","b"]' '/-' '"c"' ["a","b","c"] $ ./test_pointer.exe set '{"arr":["x"]}' '/arr/-' '"y"' {"arr":["x","y"]} ================================================================================ Jsont Codecs (jsont, jsont_kind, jsont_nav, jsont_uri_fragment) ================================================================================ Testing jsont codec roundtrip: $ ./test_pointer.exe jsont-codec "" "" $ ./test_pointer.exe jsont-codec "/foo" "/foo" $ ./test_pointer.exe jsont-codec "/foo/bar" "/foo/bar" $ ./test_pointer.exe jsont-codec "/-" "/-" $ ./test_pointer.exe jsont-codec "/foo/-" "/foo/-" Testing jsont_kind codec: $ ./test_pointer.exe jsont-kind "" Nav() $ ./test_pointer.exe jsont-kind "/foo" Nav(/foo) $ ./test_pointer.exe jsont-kind "/-" Append(/-) $ ./test_pointer.exe jsont-kind "/foo/-" Append(/foo/-) Testing jsont_nav codec: $ ./test_pointer.exe jsont-nav "" OK: $ ./test_pointer.exe jsont-nav "/foo" OK: /foo $ ./test_pointer.exe jsont-nav "/-" ERROR: Invalid JSON Pointer: '-' not allowed in navigation pointer $ ./test_pointer.exe jsont-nav "/foo/-" ERROR: Invalid JSON Pointer: '-' not allowed in navigation pointer Testing jsont_uri_fragment codec: $ ./test_pointer.exe jsont-uri-fragment "" "" $ ./test_pointer.exe jsont-uri-fragment "/foo" "/foo" $ ./test_pointer.exe jsont-uri-fragment "/a~1b" "/a~1b" ================================================================================ Query Combinators (path, set_path, update_path, delete_path) ================================================================================ Testing path combinator: $ ./test_pointer.exe query-path '{"name":"alice"}' '/name' OK: alice $ ./test_pointer.exe query-path '{"user":{"name":"bob"}}' '/user/name' OK: bob Testing path combinator with absent: $ ./test_pointer.exe query-path-absent '{"name":"alice"}' '/name' 'default' OK: alice $ ./test_pointer.exe query-path-absent '{"other":"value"}' '/name' 'default' OK: default Testing set_path combinator: $ ./test_pointer.exe set-path '{"name":"alice"}' '/name' 'bob' {"name":"bob"} $ ./test_pointer.exe set-path '{"user":{"name":"old"}}' '/user/name' 'new' {"user":{"name":"new"}} Testing update_path combinator: $ ./test_pointer.exe update-path '{"name":"alice"}' '/name' {"name":"alice"} $ ./test_pointer.exe update-path '{"user":{"name":"bob"}}' '/user/name' {"user":{"name":"bob"}} Testing delete_path combinator: $ ./test_pointer.exe delete-path '{"foo":"bar","baz":"qux"}' '/foo' {"baz":"qux"} $ ./test_pointer.exe delete-path '{"user":{"name":"bob","age":30}}' '/user/name' {"user":{"age":30}} Testing delete_path with allow_absent: $ ./test_pointer.exe delete-path-absent '{"foo":"bar"}' '/baz' {"foo":"bar"} $ ./test_pointer.exe delete-path-absent '{"foo":"bar"}' '/foo' {} ================================================================================ JMAP Extended Pointers - Additional Tests ================================================================================ Testing Jmap.of_string_result: $ ./test_pointer.exe jmap-of-string-result "" Ok() $ ./test_pointer.exe jmap-of-string-result "/foo" Ok(/foo) $ ./test_pointer.exe jmap-of-string-result "/*" Ok(/*) $ ./test_pointer.exe jmap-of-string-result "/list/*/id" Ok(/list/*/id) $ ./test_pointer.exe jmap-of-string-result "invalid" Error(Invalid JMAP Pointer: must be empty or start with '/': invalid) $ ./test_pointer.exe jmap-of-string-result "/-" Error(Invalid JMAP Pointer: '-' not supported in result reference paths) Testing Jmap.pp: $ ./test_pointer.exe jmap-pp "" $ ./test_pointer.exe jmap-pp "/foo" /foo $ ./test_pointer.exe jmap-pp "/*" /* $ ./test_pointer.exe jmap-pp "/list/*/id" /list/*/id Testing Jmap.eval_result: $ ./test_pointer.exe jmap-eval-result '{"foo":"bar"}' '/foo' Ok("bar") $ ./test_pointer.exe jmap-eval-result '{"list":[{"id":"a"},{"id":"b"}]}' '/list/*/id' Ok(["a","b"]) $ ./test_pointer.exe jmap-eval-result '{"foo":"bar"}' '/baz' Error(JMAP Pointer: member 'baz' not found File "-":) Testing Jmap.find: $ ./test_pointer.exe jmap-find '{"foo":"bar"}' '/foo' Some("bar") $ ./test_pointer.exe jmap-find '{"list":[{"id":"a"},{"id":"b"}]}' '/list/*/id' Some(["a","b"]) $ ./test_pointer.exe jmap-find '{"foo":"bar"}' '/baz' None $ ./test_pointer.exe jmap-find '{"obj":{"a":1}}' '/obj/*' None Testing Jmap.jsont codec: $ ./test_pointer.exe jmap-jsont "" "" $ ./test_pointer.exe jmap-jsont "/foo" "/foo" $ ./test_pointer.exe jmap-jsont "/*" "/*" $ ./test_pointer.exe jmap-jsont "/list/*/id" "/list/*/id"