diff --git a/patch.go b/patch.go index 8f75549..c105632 100644 --- a/patch.go +++ b/patch.go @@ -384,13 +384,17 @@ func (d *partialDoc) add(key string, val *lazyNode) error { } func (d *partialDoc) get(key string) (*lazyNode, error) { - return (*d)[key], nil + v, ok := (*d)[key] + if !ok { + return v, errors.Wrapf(ErrMissing, "unable to get nonexistent key: %s", key) + } + return v, nil } func (d *partialDoc) remove(key string) error { _, ok := (*d)[key] if !ok { - return errors.Wrapf(ErrMissing, "Unable to remove nonexistent key: %s", key) + return errors.Wrapf(ErrMissing, "unable to remove nonexistent key: %s", key) } delete(*d, key) @@ -612,7 +616,7 @@ func (p Patch) test(doc *container, op Operation) error { } val, err := con.get(key) - if err != nil { + if err != nil && errors.Cause(err) != ErrMissing { return errors.Wrapf(err, "error in test for path: '%s'", path) } diff --git a/patch_test.go b/patch_test.go index 3a45150..8e20cf3 100644 --- a/patch_test.go +++ b/patch_test.go @@ -186,6 +186,11 @@ var Cases = []Case{ `[{"op": "copy", "path": "/foo/0", "from": "/foo"}]`, `{ "foo": [["bar"], "bar"]}`, }, + { + `{ "foo": null}`, + `[{"op": "copy", "path": "/bar", "from": "/foo"}]`, + `{ "foo": null, "bar": null}`, + }, { `{ "foo": ["bar","qux","baz"]}`, `[ { "op": "remove", "path": "/foo/-2"}]`, @@ -332,6 +337,15 @@ var BadCases = []BadCase{ `{ "foo": [ "all", "grass", "cows", "eat" ] }`, `[ { "op": "move", "from": "/foo/1", "path": "/foo/4" } ]`, }, + { + `{ "baz": "qux" }`, + `[ { "op": "replace", "path": "/foo", "value": "bar" } ]`, + }, + // Can't copy from non-existent "from" key. + { + `{ "foo": "bar"}`, + `[{"op": "copy", "path": "/qux", "from": "/baz"}]`, + }, } // This is not thread safe, so we cannot run patch tests in parallel. @@ -459,6 +473,18 @@ var TestCases = []TestCase{ false, "/foo", }, + { + `{ "foo": "bar" }`, + `[ { "op": "test", "path": "/baz", "value": "bar" } ]`, + false, + "/baz", + }, + { + `{ "foo": "bar" }`, + `[ { "op": "test", "path": "/baz", "value": null } ]`, + true, + "/baz", + }, } func TestAllTest(t *testing.T) {