hana-1.3.7/0000755000004100000410000000000014053160515012461 5ustar www-datawww-datahana-1.3.7/test/0000755000004100000410000000000014053160515013440 5ustar www-datawww-datahana-1.3.7/test/test_ietf.rb0000644000004100000410000000077014053160515015757 0ustar www-datawww-datarequire 'helper' module Hana class TestIETF < TestCase filename = File.join TESTDIR, 'json-patch-tests', 'tests.json' include read_test_json_file filename end class TestSpec < TestCase filename = File.join TESTDIR, 'json-patch-tests', 'spec_tests.json' include read_test_json_file filename skip(/A\.13/, 'This test depends on the JSON parser') end class MyTests < TestCase filename = File.join TESTDIR, 'mine.json' include read_test_json_file filename end end hana-1.3.7/test/helper.rb0000644000004100000410000000467414053160515015257 0ustar www-datawww-datarequire 'minitest/autorun' require 'hana' require 'json' module Hana class TestCase < Minitest::Test TESTDIR = File.dirname File.expand_path __FILE__ def self.read_test_json_file file Module.new { tests = JSON.load File.read file tests.each_with_index do |test, i| next unless test['doc'] method = "test_#{test['comment'] || i }" loop do if method_defined? method method = "test_#{test['comment'] || i } x" else break end end define_method(method) do skip "disabled" if test['disabled'] doc = test['doc'] patch = test['patch'] patch = Hana::Patch.new patch if test['error'] assert_raises(*ex(test['error']), test['error']) do patch.apply doc end else assert_equal(test['expected'] || doc, patch.apply(doc)) end end end } end def self.skip regexp, message instance_methods.grep(regexp).each do |method| define_method(method) { skip message } end end private def ex msg case msg when /Out of bounds/i then [Hana::Patch::OutOfBoundsException] when /index is greater than/i then [Hana::Patch::OutOfBoundsException] when /Object operation on array/ then [Hana::Patch::ObjectOperationOnArrayException] when /test op shouldn't get array element/ then [Hana::Patch::IndexError, Hana::Patch::ObjectOperationOnArrayException] when /bad number$/ then [Hana::Patch::IndexError, Hana::Patch::ObjectOperationOnArrayException] when /removing a nonexistent (field|index)/ then [Hana::Patch::MissingTargetException, Hana::Patch::OutOfBoundsException] when /test op should reject the array value, it has leading zeros/ then [Hana::Patch::IndexError] when /missing '(from|value)' parameter/ then [KeyError] when /Unrecognized op 'spam'/ then [Hana::Patch::Exception] when /missing 'path'|null is not valid value for 'path'/ then [Hana::Patch::InvalidPath] when /missing|non-existent/ then [Hana::Patch::MissingTargetException] when /JSON Pointer should start with a slash/ then [Hana::Pointer::FormatError] else [Hana::Patch::FailedTestException] end end end end hana-1.3.7/test/test_hana.rb0000644000004100000410000000603214053160515015734 0ustar www-datawww-datarequire 'helper' class TestHana < Hana::TestCase def test_no_eval patch = Hana::Patch.new [ { 'op' => 'eval', 'value' => '1' } ] assert_raises(Hana::Patch::Exception) do patch.apply('foo' => 'bar') end end def test_mutate_to_a_does_not_impact_original pointer = Hana::Pointer.new '/foo/bar/baz' x = pointer.to_a x << "omg" assert_equal %w{ foo bar baz omg }, x assert_equal %w{ foo bar baz }, pointer.to_a end def test_split_many pointer = Hana::Pointer.new '/foo/bar/baz' assert_equal %w{ foo bar baz }, pointer.to_a end def test_split_with_trailing pointer = Hana::Pointer.new '/foo/' assert_equal ["foo", ""], pointer.to_a end def test_root pointer = Hana::Pointer.new '/' assert_equal [''], pointer.to_a end def test_escape pointer = Hana::Pointer.new '/f^/oo/bar' assert_equal ['f/oo', 'bar'], pointer.to_a pointer = Hana::Pointer.new '/f^^oo/bar' assert_equal ['f^oo', 'bar'], pointer.to_a end def test_eval_hash pointer = Hana::Pointer.new '/foo' assert_equal 'bar', pointer.eval('foo' => 'bar') pointer = Hana::Pointer.new '/foo/bar' assert_equal 'baz', pointer.eval('foo' => { 'bar' => 'baz' }) end def test_eval_array pointer = Hana::Pointer.new '/foo/1' assert_equal 'baz', pointer.eval('foo' => ['bar', 'baz']) pointer = Hana::Pointer.new '/foo/0/bar' assert_equal 'omg', pointer.eval('foo' => [{'bar' => 'omg'}, 'baz']) end def test_eval_number_as_key pointer = Hana::Pointer.new '/foo/1' assert_equal 'baz', pointer.eval('foo' => { '1' => 'baz' }) end def test_eval_many_below_missing pointer = Hana::Pointer.new '/baz/foo/bar' assert_nil pointer.eval('foo' => 'bar') pointer = Hana::Pointer.new '/foo/bar/baz' assert_nil pointer.eval('foo' => nil) end def test_remove_missing_object_key patch = Hana::Patch.new [ { 'op' => 'remove', 'path' => '/missing_key' } ] assert_raises(Hana::Patch::MissingTargetException) do patch.apply('foo' => 'bar') end end def test_remove_deep_missing_path patch = Hana::Patch.new [ { 'op' => 'remove', 'path' => '/missing_key1/missing_key2' } ] assert_raises(Hana::Patch::MissingTargetException) do patch.apply('foo' => 'bar') end end def test_remove_missing_array_index patch = Hana::Patch.new [ { 'op' => 'remove', 'path' => '/1' } ] assert_raises(Hana::Patch::OutOfBoundsException) do patch.apply([0]) end end def test_remove_missing_object_key_in_array patch = Hana::Patch.new [ { 'op' => 'remove', 'path' => '/1/baz' } ] assert_raises(Hana::Patch::MissingTargetException) do patch.apply([ { 'foo' => 'bar' }, { 'foo' => 'bar' } ]) end end def test_replace_missing_key patch = Hana::Patch.new [ { 'op' => 'replace', 'path' => '/missing_key/field', 'value' => 'asdf' } ] assert_raises(Hana::Patch::MissingTargetException) do patch.apply('foo' => 'bar') end end end hana-1.3.7/test/mine.json0000644000004100000410000000274314053160515015271 0ustar www-datawww-data[ { "comment": "test remove with bad number should fail", "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, "patch": [{"op": "remove", "path": "/baz/1e0/qux"}], "error": "remove op shouldn't remove from array with bad number" }, { "comment": "test remove on array", "doc": [1, 2, 3, 4], "patch": [{"op": "remove", "path": "/0"}], "expected": [2, 3, 4] }, { "comment": "test remove with bad index should fail", "doc": [1, 2, 3, 4], "patch": [{"op": "remove", "path": "/1e0"}], "error": "remove op shouldn't remove from array with bad number" }, { "comment": "test replace with bad number should fail", "doc": [""], "patch": [{"op": "replace", "path": "/1e0", "value": false}], "error": "replace op shouldn't replace in array with bad number" }, { "comment": "test copy with bad number should fail", "doc": {"baz": [1,2,3], "bar": 1}, "patch": [{"op": "copy", "from": "/baz/1e0", "path": "/boo"}], "error": "copy op shouldn't work with bad number" }, { "comment": "test move with bad number should fail", "doc": {"foo": 1, "baz": [1,2,3,4]}, "patch": [{"op": "move", "from": "/baz/1e0", "path": "/foo"}], "error": "move op shouldn't work with bad number" }, { "comment": "test add with bad number should fail", "doc": ["foo", "sil"], "patch": [{"op": "add", "path": "/1e0", "value": "bar"}], "error": "add op shouldn't add to array with bad number" } ] hana-1.3.7/test/json-patch-tests/0000755000004100000410000000000014053160515016646 5ustar www-datawww-datahana-1.3.7/test/json-patch-tests/README.md0000644000004100000410000000440214053160515020125 0ustar www-datawww-dataJSON Patch Tests ================ These are test cases for implementations of [IETF JSON Patch (RFC6902)](http://tools.ietf.org/html/rfc6902). Some implementations can be found at [jsonpatch.com](http://jsonpatch.com). Test Format ----------- Each test file is a JSON document that contains an array of test records. A test record is an object with the following members: - doc: The JSON document to test against - patch: The patch(es) to apply - expected: The expected resulting document, OR - error: A string describing an expected error - comment: A string describing the test - disabled: True if the test should be skipped All fields except 'doc' and 'patch' are optional. Test records consisting only of a comment are also OK. Files ----- - tests.json: the main test file - spec_tests.json: tests from the RFC6902 spec Writing Tests ------------- All tests should have a descriptive comment. Tests should be as simple as possible - just what's required to test a specific piece of behavior. If you want to test interacting behaviors, create tests for each behavior as well as the interaction. If an 'error' member is specified, the error text should describe the error the implementation should raise - *not* what's being tested. Implementation error strings will vary, but the suggested error should be easily matched to the implementation error string. Try to avoid creating error tests that might pass because an incorrect error was reported. Please feel free to contribute! Credits ------- The seed test set was adapted from Byron Ruth's [jsonpatch-js](https://github.com/bruth/jsonpatch-js/blob/master/test.js) and extended by [Mike McCabe](https://github.com/mikemccabe). License ------- Copyright 2014 The Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. hana-1.3.7/test/json-patch-tests/package.json0000644000004100000410000000061114053160515021132 0ustar www-datawww-data{ "name": "json-patch-test-suite", "version": "1.1.0", "description": "JSON Patch RFC 6902 test suite", "repository": "github:json-patch/json-patch-tests", "homepage": "https://github.com/json-patch/json-patch-tests", "bugs": "https://github.com/json-patch/json-patch-tests/issues", "keywords": [ "JSON", "Patch", "test", "suite" ], "license": "Apache-2.0" } hana-1.3.7/test/json-patch-tests/.editorconfig0000644000004100000410000000026714053160515021330 0ustar www-datawww-data# EditorConfig is awesome: http://EditorConfig.org root = true [*] end_of_line = lf insert_final_newline = true charset = utf-8 trim_trailing_whitespace = true indent_style = space hana-1.3.7/test/json-patch-tests/.npmignore0000644000004100000410000000003114053160515020637 0ustar www-datawww-data.editorconfig .gitignore hana-1.3.7/test/json-patch-tests/tests.json0000644000004100000410000004304414053160515020710 0ustar www-datawww-data[ { "comment": "empty list, empty docs", "doc": {}, "patch": [], "expected": {} }, { "comment": "empty patch list", "doc": {"foo": 1}, "patch": [], "expected": {"foo": 1} }, { "comment": "rearrangements OK?", "doc": {"foo": 1, "bar": 2}, "patch": [], "expected": {"bar":2, "foo": 1} }, { "comment": "rearrangements OK? How about one level down ... array", "doc": [{"foo": 1, "bar": 2}], "patch": [], "expected": [{"bar":2, "foo": 1}] }, { "comment": "rearrangements OK? How about one level down...", "doc": {"foo":{"foo": 1, "bar": 2}}, "patch": [], "expected": {"foo":{"bar":2, "foo": 1}} }, { "comment": "add replaces any existing field", "doc": {"foo": null}, "patch": [{"op": "add", "path": "/foo", "value":1}], "expected": {"foo": 1} }, { "comment": "toplevel array", "doc": [], "patch": [{"op": "add", "path": "/0", "value": "foo"}], "expected": ["foo"] }, { "comment": "toplevel array, no change", "doc": ["foo"], "patch": [], "expected": ["foo"] }, { "comment": "toplevel object, numeric string", "doc": {}, "patch": [{"op": "add", "path": "/foo", "value": "1"}], "expected": {"foo":"1"} }, { "comment": "toplevel object, integer", "doc": {}, "patch": [{"op": "add", "path": "/foo", "value": 1}], "expected": {"foo":1} }, { "comment": "Toplevel scalar values OK?", "doc": "foo", "patch": [{"op": "replace", "path": "", "value": "bar"}], "expected": "bar", "disabled": true }, { "comment": "replace object document with array document?", "doc": {}, "patch": [{"op": "add", "path": "", "value": []}], "expected": [] }, { "comment": "replace array document with object document?", "doc": [], "patch": [{"op": "add", "path": "", "value": {}}], "expected": {} }, { "comment": "append to root array document?", "doc": [], "patch": [{"op": "add", "path": "/-", "value": "hi"}], "expected": ["hi"] }, { "comment": "Add, / target", "doc": {}, "patch": [ {"op": "add", "path": "/", "value":1 } ], "expected": {"":1} }, { "comment": "Add, /foo/ deep target (trailing slash)", "doc": {"foo": {}}, "patch": [ {"op": "add", "path": "/foo/", "value":1 } ], "expected": {"foo":{"": 1}} }, { "comment": "Add composite value at top level", "doc": {"foo": 1}, "patch": [{"op": "add", "path": "/bar", "value": [1, 2]}], "expected": {"foo": 1, "bar": [1, 2]} }, { "comment": "Add into composite value", "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, "patch": [{"op": "add", "path": "/baz/0/foo", "value": "world"}], "expected": {"foo": 1, "baz": [{"qux": "hello", "foo": "world"}]} }, { "doc": {"bar": [1, 2]}, "patch": [{"op": "add", "path": "/bar/8", "value": "5"}], "error": "Out of bounds (upper)" }, { "doc": {"bar": [1, 2]}, "patch": [{"op": "add", "path": "/bar/-1", "value": "5"}], "error": "Out of bounds (lower)" }, { "doc": {"foo": 1}, "patch": [{"op": "add", "path": "/bar", "value": true}], "expected": {"foo": 1, "bar": true} }, { "doc": {"foo": 1}, "patch": [{"op": "add", "path": "/bar", "value": false}], "expected": {"foo": 1, "bar": false} }, { "doc": {"foo": 1}, "patch": [{"op": "add", "path": "/bar", "value": null}], "expected": {"foo": 1, "bar": null} }, { "comment": "0 can be an array index or object element name", "doc": {"foo": 1}, "patch": [{"op": "add", "path": "/0", "value": "bar"}], "expected": {"foo": 1, "0": "bar" } }, { "doc": ["foo"], "patch": [{"op": "add", "path": "/1", "value": "bar"}], "expected": ["foo", "bar"] }, { "doc": ["foo", "sil"], "patch": [{"op": "add", "path": "/1", "value": "bar"}], "expected": ["foo", "bar", "sil"] }, { "doc": ["foo", "sil"], "patch": [{"op": "add", "path": "/0", "value": "bar"}], "expected": ["bar", "foo", "sil"] }, { "comment": "push item to array via last index + 1", "doc": ["foo", "sil"], "patch": [{"op":"add", "path": "/2", "value": "bar"}], "expected": ["foo", "sil", "bar"] }, { "comment": "add item to array at index > length should fail", "doc": ["foo", "sil"], "patch": [{"op":"add", "path": "/3", "value": "bar"}], "error": "index is greater than number of items in array" }, { "comment": "test against implementation-specific numeric parsing", "doc": {"1e0": "foo"}, "patch": [{"op": "test", "path": "/1e0", "value": "foo"}], "expected": {"1e0": "foo"} }, { "comment": "test with bad number should fail", "doc": ["foo", "bar"], "patch": [{"op": "test", "path": "/1e0", "value": "bar"}], "error": "test op shouldn't get array element 1" }, { "doc": ["foo", "sil"], "patch": [{"op": "add", "path": "/bar", "value": 42}], "error": "Object operation on array target" }, { "doc": ["foo", "sil"], "patch": [{"op": "add", "path": "/1", "value": ["bar", "baz"]}], "expected": ["foo", ["bar", "baz"], "sil"], "comment": "value in array add not flattened" }, { "doc": {"foo": 1, "bar": [1, 2, 3, 4]}, "patch": [{"op": "remove", "path": "/bar"}], "expected": {"foo": 1} }, { "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, "patch": [{"op": "remove", "path": "/baz/0/qux"}], "expected": {"foo": 1, "baz": [{}]} }, { "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, "patch": [{"op": "replace", "path": "/foo", "value": [1, 2, 3, 4]}], "expected": {"foo": [1, 2, 3, 4], "baz": [{"qux": "hello"}]} }, { "doc": {"foo": [1, 2, 3, 4], "baz": [{"qux": "hello"}]}, "patch": [{"op": "replace", "path": "/baz/0/qux", "value": "world"}], "expected": {"foo": [1, 2, 3, 4], "baz": [{"qux": "world"}]} }, { "doc": ["foo"], "patch": [{"op": "replace", "path": "/0", "value": "bar"}], "expected": ["bar"] }, { "doc": [""], "patch": [{"op": "replace", "path": "/0", "value": 0}], "expected": [0] }, { "doc": [""], "patch": [{"op": "replace", "path": "/0", "value": true}], "expected": [true] }, { "doc": [""], "patch": [{"op": "replace", "path": "/0", "value": false}], "expected": [false] }, { "doc": [""], "patch": [{"op": "replace", "path": "/0", "value": null}], "expected": [null] }, { "doc": ["foo", "sil"], "patch": [{"op": "replace", "path": "/1", "value": ["bar", "baz"]}], "expected": ["foo", ["bar", "baz"]], "comment": "value in array replace not flattened" }, { "comment": "replace whole document", "doc": {"foo": "bar"}, "patch": [{"op": "replace", "path": "", "value": {"baz": "qux"}}], "expected": {"baz": "qux"} }, { "comment": "test replace with missing parent key should fail", "doc": {"bar": "baz"}, "patch": [{"op": "replace", "path": "/foo/bar", "value": false}], "error": "replace op should fail with missing parent key" }, { "comment": "spurious patch properties", "doc": {"foo": 1}, "patch": [{"op": "test", "path": "/foo", "value": 1, "spurious": 1}], "expected": {"foo": 1} }, { "doc": {"foo": null}, "patch": [{"op": "test", "path": "/foo", "value": null}], "expected": {"foo": null}, "comment": "null value should be valid obj property" }, { "doc": {"foo": null}, "patch": [{"op": "replace", "path": "/foo", "value": "truthy"}], "expected": {"foo": "truthy"}, "comment": "null value should be valid obj property to be replaced with something truthy" }, { "doc": {"foo": null}, "patch": [{"op": "move", "from": "/foo", "path": "/bar"}], "expected": {"bar": null}, "comment": "null value should be valid obj property to be moved" }, { "doc": {"foo": null}, "patch": [{"op": "copy", "from": "/foo", "path": "/bar"}], "expected": {"foo": null, "bar": null}, "comment": "null value should be valid obj property to be copied" }, { "doc": {"foo": null}, "patch": [{"op": "remove", "path": "/foo"}], "expected": {}, "comment": "null value should be valid obj property to be removed" }, { "doc": {"foo": "bar"}, "patch": [{"op": "replace", "path": "/foo", "value": null}], "expected": {"foo": null}, "comment": "null value should still be valid obj property replace other value" }, { "doc": {"foo": {"foo": 1, "bar": 2}}, "patch": [{"op": "test", "path": "/foo", "value": {"bar": 2, "foo": 1}}], "expected": {"foo": {"foo": 1, "bar": 2}}, "comment": "test should pass despite rearrangement" }, { "doc": {"foo": [{"foo": 1, "bar": 2}]}, "patch": [{"op": "test", "path": "/foo", "value": [{"bar": 2, "foo": 1}]}], "expected": {"foo": [{"foo": 1, "bar": 2}]}, "comment": "test should pass despite (nested) rearrangement" }, { "doc": {"foo": {"bar": [1, 2, 5, 4]}}, "patch": [{"op": "test", "path": "/foo", "value": {"bar": [1, 2, 5, 4]}}], "expected": {"foo": {"bar": [1, 2, 5, 4]}}, "comment": "test should pass - no error" }, { "doc": {"foo": {"bar": [1, 2, 5, 4]}}, "patch": [{"op": "test", "path": "/foo", "value": [1, 2]}], "error": "test op should fail" }, { "comment": "Whole document", "doc": { "foo": 1 }, "patch": [{"op": "test", "path": "", "value": {"foo": 1}}], "disabled": true }, { "comment": "Empty-string element", "doc": { "": 1 }, "patch": [{"op": "test", "path": "/", "value": 1}], "expected": { "": 1 } }, { "doc": { "foo": ["bar", "baz"], "": 0, "a/b": 1, "c%d": 2, "e^f": 3, "g|h": 4, "i\\j": 5, "k\"l": 6, " ": 7, "m~n": 8 }, "patch": [{"op": "test", "path": "/foo", "value": ["bar", "baz"]}, {"op": "test", "path": "/foo/0", "value": "bar"}, {"op": "test", "path": "/", "value": 0}, {"op": "test", "path": "/a~1b", "value": 1}, {"op": "test", "path": "/c%d", "value": 2}, {"op": "test", "path": "/e^f", "value": 3}, {"op": "test", "path": "/g|h", "value": 4}, {"op": "test", "path": "/i\\j", "value": 5}, {"op": "test", "path": "/k\"l", "value": 6}, {"op": "test", "path": "/ ", "value": 7}, {"op": "test", "path": "/m~0n", "value": 8}], "expected": { "": 0, " ": 7, "a/b": 1, "c%d": 2, "e^f": 3, "foo": [ "bar", "baz" ], "g|h": 4, "i\\j": 5, "k\"l": 6, "m~n": 8 } }, { "comment": "Move to same location has no effect", "doc": {"foo": 1}, "patch": [{"op": "move", "from": "/foo", "path": "/foo"}], "expected": {"foo": 1} }, { "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, "patch": [{"op": "move", "from": "/foo", "path": "/bar"}], "expected": {"baz": [{"qux": "hello"}], "bar": 1} }, { "doc": {"baz": [{"qux": "hello"}], "bar": 1}, "patch": [{"op": "move", "from": "/baz/0/qux", "path": "/baz/1"}], "expected": {"baz": [{}, "hello"], "bar": 1} }, { "doc": {"baz": [{"qux": "hello"}], "bar": 1}, "patch": [{"op": "copy", "from": "/baz/0", "path": "/boo"}], "expected": {"baz":[{"qux":"hello"}],"bar":1,"boo":{"qux":"hello"}} }, { "comment": "replacing the root of the document is possible with add", "doc": {"foo": "bar"}, "patch": [{"op": "add", "path": "", "value": {"baz": "qux"}}], "expected": {"baz":"qux"}}, { "comment": "Adding to \"/-\" adds to the end of the array", "doc": [ 1, 2 ], "patch": [ { "op": "add", "path": "/-", "value": { "foo": [ "bar", "baz" ] } } ], "expected": [ 1, 2, { "foo": [ "bar", "baz" ] } ]}, { "comment": "Adding to \"/-\" adds to the end of the array, even n levels down", "doc": [ 1, 2, [ 3, [ 4, 5 ] ] ], "patch": [ { "op": "add", "path": "/2/1/-", "value": { "foo": [ "bar", "baz" ] } } ], "expected": [ 1, 2, [ 3, [ 4, 5, { "foo": [ "bar", "baz" ] } ] ] ]}, { "comment": "test remove with bad number should fail", "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, "patch": [{"op": "remove", "path": "/baz/1e0/qux"}], "error": "remove op shouldn't remove from array with bad number" }, { "comment": "test remove on array", "doc": [1, 2, 3, 4], "patch": [{"op": "remove", "path": "/0"}], "expected": [2, 3, 4] }, { "comment": "test repeated removes", "doc": [1, 2, 3, 4], "patch": [{ "op": "remove", "path": "/1" }, { "op": "remove", "path": "/2" }], "expected": [1, 3] }, { "comment": "test remove with bad index should fail", "doc": [1, 2, 3, 4], "patch": [{"op": "remove", "path": "/1e0"}], "error": "remove op shouldn't remove from array with bad number" }, { "comment": "test replace with bad number should fail", "doc": [""], "patch": [{"op": "replace", "path": "/1e0", "value": false}], "error": "replace op shouldn't replace in array with bad number" }, { "comment": "test copy with bad number should fail", "doc": {"baz": [1,2,3], "bar": 1}, "patch": [{"op": "copy", "from": "/baz/1e0", "path": "/boo"}], "error": "copy op shouldn't work with bad number" }, { "comment": "test move with bad number should fail", "doc": {"foo": 1, "baz": [1,2,3,4]}, "patch": [{"op": "move", "from": "/baz/1e0", "path": "/foo"}], "error": "move op shouldn't work with bad number" }, { "comment": "test add with bad number should fail", "doc": ["foo", "sil"], "patch": [{"op": "add", "path": "/1e0", "value": "bar"}], "error": "add op shouldn't add to array with bad number" }, { "comment": "missing 'path' parameter", "doc": {}, "patch": [ { "op": "add", "value": "bar" } ], "error": "missing 'path' parameter" }, { "comment": "'path' parameter with null value", "doc": {}, "patch": [ { "op": "add", "path": null, "value": "bar" } ], "error": "null is not valid value for 'path'" }, { "comment": "invalid JSON Pointer token", "doc": {}, "patch": [ { "op": "add", "path": "foo", "value": "bar" } ], "error": "JSON Pointer should start with a slash" }, { "comment": "missing 'value' parameter to add", "doc": [ 1 ], "patch": [ { "op": "add", "path": "/-" } ], "error": "missing 'value' parameter" }, { "comment": "missing 'value' parameter to replace", "doc": [ 1 ], "patch": [ { "op": "replace", "path": "/0" } ], "error": "missing 'value' parameter" }, { "comment": "missing 'value' parameter to test", "doc": [ null ], "patch": [ { "op": "test", "path": "/0" } ], "error": "missing 'value' parameter" }, { "comment": "missing value parameter to test - where undef is falsy", "doc": [ false ], "patch": [ { "op": "test", "path": "/0" } ], "error": "missing 'value' parameter" }, { "comment": "missing from parameter to copy", "doc": [ 1 ], "patch": [ { "op": "copy", "path": "/-" } ], "error": "missing 'from' parameter" }, { "comment": "missing from location to copy", "doc": { "foo": 1 }, "patch": [ { "op": "copy", "from": "/bar", "path": "/foo" } ], "error": "missing 'from' location" }, { "comment": "missing from parameter to move", "doc": { "foo": 1 }, "patch": [ { "op": "move", "path": "" } ], "error": "missing 'from' parameter" }, { "comment": "missing from location to move", "doc": { "foo": 1 }, "patch": [ { "op": "move", "from": "/bar", "path": "/foo" } ], "error": "missing 'from' location" }, { "comment": "duplicate ops", "doc": { "foo": "bar" }, "patch": [ { "op": "add", "path": "/baz", "value": "qux", "op": "move", "from":"/foo" } ], "error": "patch has two 'op' members", "disabled": true }, { "comment": "unrecognized op should fail", "doc": {"foo": 1}, "patch": [{"op": "spam", "path": "/foo", "value": 1}], "error": "Unrecognized op 'spam'" }, { "comment": "test with bad array number that has leading zeros", "doc": ["foo", "bar"], "patch": [{"op": "test", "path": "/00", "value": "foo"}], "error": "test op should reject the array value, it has leading zeros" }, { "comment": "test with bad array number that has leading zeros", "doc": ["foo", "bar"], "patch": [{"op": "test", "path": "/01", "value": "bar"}], "error": "test op should reject the array value, it has leading zeros" }, { "comment": "Removing nonexistent field", "doc": {"foo" : "bar"}, "patch": [{"op": "remove", "path": "/baz"}], "error": "removing a nonexistent field should fail" }, { "comment": "Removing deep nonexistent path", "doc": {"foo" : "bar"}, "patch": [{"op": "remove", "path": "/missing1/missing2"}], "error": "removing a nonexistent field should fail" }, { "comment": "Removing nonexistent index", "doc": ["foo", "bar"], "patch": [{"op": "remove", "path": "/2"}], "error": "removing a nonexistent index should fail" }, { "comment": "Patch with different capitalisation than doc", "doc": {"foo":"bar"}, "patch": [{"op": "add", "path": "/FOO", "value": "BAR"}], "expected": {"foo": "bar", "FOO": "BAR"} } ] hana-1.3.7/test/json-patch-tests/spec_tests.json0000644000004100000410000000767714053160515021736 0ustar www-datawww-data[ { "comment": "4.1. add with missing object", "doc": { "q": { "bar": 2 } }, "patch": [ {"op": "add", "path": "/a/b", "value": 1} ], "error": "path /a does not exist -- missing objects are not created recursively" }, { "comment": "A.1. Adding an Object Member", "doc": { "foo": "bar" }, "patch": [ { "op": "add", "path": "/baz", "value": "qux" } ], "expected": { "baz": "qux", "foo": "bar" } }, { "comment": "A.2. Adding an Array Element", "doc": { "foo": [ "bar", "baz" ] }, "patch": [ { "op": "add", "path": "/foo/1", "value": "qux" } ], "expected": { "foo": [ "bar", "qux", "baz" ] } }, { "comment": "A.3. Removing an Object Member", "doc": { "baz": "qux", "foo": "bar" }, "patch": [ { "op": "remove", "path": "/baz" } ], "expected": { "foo": "bar" } }, { "comment": "A.4. Removing an Array Element", "doc": { "foo": [ "bar", "qux", "baz" ] }, "patch": [ { "op": "remove", "path": "/foo/1" } ], "expected": { "foo": [ "bar", "baz" ] } }, { "comment": "A.5. Replacing a Value", "doc": { "baz": "qux", "foo": "bar" }, "patch": [ { "op": "replace", "path": "/baz", "value": "boo" } ], "expected": { "baz": "boo", "foo": "bar" } }, { "comment": "A.6. Moving a Value", "doc": { "foo": { "bar": "baz", "waldo": "fred" }, "qux": { "corge": "grault" } }, "patch": [ { "op": "move", "from": "/foo/waldo", "path": "/qux/thud" } ], "expected": { "foo": { "bar": "baz" }, "qux": { "corge": "grault", "thud": "fred" } } }, { "comment": "A.7. Moving an Array Element", "doc": { "foo": [ "all", "grass", "cows", "eat" ] }, "patch": [ { "op": "move", "from": "/foo/1", "path": "/foo/3" } ], "expected": { "foo": [ "all", "cows", "eat", "grass" ] } }, { "comment": "A.8. Testing a Value: Success", "doc": { "baz": "qux", "foo": [ "a", 2, "c" ] }, "patch": [ { "op": "test", "path": "/baz", "value": "qux" }, { "op": "test", "path": "/foo/1", "value": 2 } ], "expected": { "baz": "qux", "foo": [ "a", 2, "c" ] } }, { "comment": "A.9. Testing a Value: Error", "doc": { "baz": "qux" }, "patch": [ { "op": "test", "path": "/baz", "value": "bar" } ], "error": "string not equivalent" }, { "comment": "A.10. Adding a nested Member Object", "doc": { "foo": "bar" }, "patch": [ { "op": "add", "path": "/child", "value": { "grandchild": { } } } ], "expected": { "foo": "bar", "child": { "grandchild": { } } } }, { "comment": "A.11. Ignoring Unrecognized Elements", "doc": { "foo":"bar" }, "patch": [ { "op": "add", "path": "/baz", "value": "qux", "xyz": 123 } ], "expected": { "foo":"bar", "baz":"qux" } }, { "comment": "A.12. Adding to a Non-existent Target", "doc": { "foo": "bar" }, "patch": [ { "op": "add", "path": "/baz/bat", "value": "qux" } ], "error": "add to a non-existent target" }, { "comment": "A.13 Invalid JSON Patch Document", "doc": { "foo": "bar" }, "patch": [ { "op": "add", "path": "/baz", "value": "qux", "op": "remove" } ], "error": "operation has two 'op' members", "disabled": true }, { "comment": "A.14. ~ Escape Ordering", "doc": { "/": 9, "~1": 10 }, "patch": [{"op": "test", "path": "/~01", "value": 10}], "expected": { "/": 9, "~1": 10 } }, { "comment": "A.15. Comparing Strings and Numbers", "doc": { "/": 9, "~1": 10 }, "patch": [{"op": "test", "path": "/~01", "value": "10"}], "error": "number is not equal to string" }, { "comment": "A.16. Adding an Array Value", "doc": { "foo": ["bar"] }, "patch": [{ "op": "add", "path": "/foo/-", "value": ["abc", "def"] }], "expected": { "foo": ["bar", ["abc", "def"]] } } ] hana-1.3.7/README.md0000644000004100000410000000332514053160515013743 0ustar www-datawww-data# hana * http://github.com/tenderlove/hana ## DESCRIPTION: Implementation of [JSON Patch][1] and [JSON Pointer][2] RFC. ## FEATURES/PROBLEMS: Implements specs of the [JSON Patch][1] and [JSON pointer][2] RFCs: This works against Ruby objects, so you should load the JSON to Ruby, process it, then emit as JSON again. ## SYNOPSIS: ```ruby patch = Hana::Patch.new [ { 'op' => 'add', 'path' => '/baz', 'value' => 'qux' } ] patch.apply('foo' => 'bar') # => {'baz' => 'qux', 'foo' => 'bar'} ``` ## REQUIREMENTS: * Ruby ## INSTALL: $ gem install hana ## LICENSE: (The MIT License) Copyright (c) 2012-2020 Aaron Patterson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. [1]: https://datatracker.ietf.org/doc/rfc6902/ [2]: http://tools.ietf.org/html/rfc6901 hana-1.3.7/hana.gemspec0000644000004100000410000000435614053160515014745 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: hana 1.3.7 ruby lib Gem::Specification.new do |s| s.name = "hana".freeze s.version = "1.3.7" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "homepage_uri" => "http://github.com/tenderlove/hana" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Aaron Patterson".freeze] s.date = "2020-12-03" s.description = "Implementation of [JSON Patch][1] and [JSON Pointer][2] RFC.".freeze s.email = ["aaron@tenderlovemaking.com".freeze] s.extra_rdoc_files = ["Manifest.txt".freeze, "README.md".freeze] s.files = ["Manifest.txt".freeze, "README.md".freeze, "Rakefile".freeze, "lib/hana.rb".freeze, "test/helper.rb".freeze, "test/json-patch-tests/.editorconfig".freeze, "test/json-patch-tests/.npmignore".freeze, "test/json-patch-tests/README.md".freeze, "test/json-patch-tests/package.json".freeze, "test/json-patch-tests/spec_tests.json".freeze, "test/json-patch-tests/tests.json".freeze, "test/mine.json".freeze, "test/test_hana.rb".freeze, "test/test_ietf.rb".freeze] s.homepage = "http://github.com/tenderlove/hana".freeze s.licenses = ["MIT".freeze] s.rdoc_options = ["--main".freeze, "README.md".freeze] s.rubygems_version = "2.7.6.2".freeze s.summary = "Implementation of [JSON Patch][1] and [JSON Pointer][2] RFC.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 3.22"]) s.add_development_dependency(%q.freeze, ["~> 5.14"]) s.add_development_dependency(%q.freeze, ["< 7", ">= 4.0"]) else s.add_dependency(%q.freeze, ["~> 3.22"]) s.add_dependency(%q.freeze, ["~> 5.14"]) s.add_dependency(%q.freeze, ["< 7", ">= 4.0"]) end else s.add_dependency(%q.freeze, ["~> 3.22"]) s.add_dependency(%q.freeze, ["~> 5.14"]) s.add_dependency(%q.freeze, ["< 7", ">= 4.0"]) end end hana-1.3.7/Rakefile0000644000004100000410000000075714053160515014137 0ustar www-datawww-data# -*- ruby -*- require 'rubygems' begin require 'hoe' rescue LoadError Gem.install 'hoe' retry end Hoe.plugins.delete :rubyforge Hoe.plugin :minitest Hoe.plugin :gemspec # `gem install hoe-gemspec` Hoe.plugin :git # `gem install hoe-git` Hoe.spec 'hana' do developer('Aaron Patterson', 'aaron@tenderlovemaking.com') license 'MIT' self.readme_file = 'README.md' self.extra_rdoc_files = FileList['*.rdoc'] extra_dev_deps << ["minitest", "~> 5.0"] end # vim: syntax=ruby hana-1.3.7/lib/0000755000004100000410000000000014053160515013227 5ustar www-datawww-datahana-1.3.7/lib/hana.rb0000644000004100000410000001353114053160515014466 0ustar www-datawww-data# frozen_string_literal: true module Hana VERSION = '1.3.7' class Pointer include Enumerable class Exception < StandardError end class FormatError < Exception end def initialize path @path = Pointer.parse path end def each(&block); @path.each(&block); end def eval object Pointer.eval @path, object end ESC = {'^/' => '/', '^^' => '^', '~0' => '~', '~1' => '/'} # :nodoc: def self.eval list, object list.inject(object) { |o, part| return nil unless o if Array === o raise Patch::IndexError unless part =~ /\A(?:\d|[1-9]\d+)\Z/ part = part.to_i end o[part] } end def self.parse path return [''] if path == '/' return [] if path == '' unless path.start_with? '/' raise FormatError, "JSON Pointer should start with a slash" end parts = path.sub(/^\//, '').split(/(? obj.length || idx < 0 idx end def add_op dest, key, obj if Array === dest dest.insert check_index(dest, key), obj else raise Patch::InvalidObjectOperationException, "cannot add key '#{key}' to non-object" unless Hash === dest dest[key] = obj end end def rm_op obj, key if Array === obj raise Patch::ObjectOperationOnArrayException, "cannot apply non-numeric key '#{key}' to array" unless key =~ /\A\d+\Z/ key = key.to_i raise Patch::OutOfBoundsException, "key '#{key}' is out of bounds for array" if key >= obj.length obj.delete_at key else begin raise Patch::MissingTargetException, "key '#{key}' not found" unless obj&.key? key obj.delete key rescue ::NoMethodError raise Patch::InvalidObjectOperationException, "cannot remove key '#{key}' from non-object" end end end end end hana-1.3.7/Manifest.txt0000644000004100000410000000047514053160515014776 0ustar www-datawww-dataManifest.txt README.md Rakefile lib/hana.rb test/helper.rb test/json-patch-tests/.editorconfig test/json-patch-tests/.npmignore test/json-patch-tests/README.md test/json-patch-tests/package.json test/json-patch-tests/spec_tests.json test/json-patch-tests/tests.json test/mine.json test/test_hana.rb test/test_ietf.rb