add prune and remove unused packages
This commit is contained in:
16
vendor/github.com/evanphx/json-patch/.travis.yml
generated
vendored
16
vendor/github.com/evanphx/json-patch/.travis.yml
generated
vendored
@@ -1,16 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.8
|
||||
- 1.7
|
||||
|
||||
install:
|
||||
- if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
|
||||
- go get github.com/jessevdk/go-flags
|
||||
|
||||
script:
|
||||
- go get
|
||||
- go test -cover ./...
|
||||
|
||||
notifications:
|
||||
email: false
|
292
vendor/github.com/evanphx/json-patch/README.md
generated
vendored
292
vendor/github.com/evanphx/json-patch/README.md
generated
vendored
@@ -1,292 +0,0 @@
|
||||
# JSON-Patch
|
||||
`jsonpatch` is a library which provides functionallity for both applying
|
||||
[RFC6902 JSON patches](http://tools.ietf.org/html/rfc6902) against documents, as
|
||||
well as for calculating & applying [RFC7396 JSON merge patches](https://tools.ietf.org/html/rfc7396).
|
||||
|
||||
[](http://godoc.org/github.com/evanphx/json-patch)
|
||||
[](https://travis-ci.org/evanphx/json-patch)
|
||||
[](https://goreportcard.com/report/github.com/evanphx/json-patch)
|
||||
|
||||
# Get It!
|
||||
|
||||
**Latest and greatest**:
|
||||
```bash
|
||||
go get -u github.com/evanphx/json-patch
|
||||
```
|
||||
|
||||
**Stable Versions**:
|
||||
* Version 4: `go get -u gopkg.in/evanphx/json-patch.v4`
|
||||
|
||||
(previous versions below `v3` are unavailable)
|
||||
|
||||
# Use It!
|
||||
* [Create and apply a merge patch](#create-and-apply-a-merge-patch)
|
||||
* [Create and apply a JSON Patch](#create-and-apply-a-json-patch)
|
||||
* [Comparing JSON documents](#comparing-json-documents)
|
||||
* [Combine merge patches](#combine-merge-patches)
|
||||
|
||||
|
||||
# Configuration
|
||||
|
||||
There is a single global configuration variable `jsonpatch.SupportNegativeIndices'. This
|
||||
defaults to `true` and enables the non-standard practice of allowing negative indices
|
||||
to mean indices starting at the end of an array. This functionality can be disabled
|
||||
by setting `jsonpatch.SupportNegativeIndices = false`.
|
||||
|
||||
## Create and apply a merge patch
|
||||
Given both an original JSON document and a modified JSON document, you can create
|
||||
a [Merge Patch](https://tools.ietf.org/html/rfc7396) document.
|
||||
|
||||
It can describe the changes needed to convert from the original to the
|
||||
modified JSON document.
|
||||
|
||||
Once you have a merge patch, you can apply it to other JSON documents using the
|
||||
`jsonpatch.MergePatch(document, patch)` function.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Let's create a merge patch from these two documents...
|
||||
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
|
||||
target := []byte(`{"name": "Jane", "age": 24}`)
|
||||
|
||||
patch, err := jsonpatch.CreateMergePatch(original, target)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Now lets apply the patch against a different JSON document...
|
||||
|
||||
alternative := []byte(`{"name": "Tina", "age": 28, "height": 3.75}`)
|
||||
modifiedAlternative, err := jsonpatch.MergePatch(alternative, patch)
|
||||
|
||||
fmt.Printf("patch document: %s\n", patch)
|
||||
fmt.Printf("updated alternative doc: %s\n", modifiedAlternative)
|
||||
}
|
||||
```
|
||||
|
||||
When ran, you get the following output:
|
||||
|
||||
```bash
|
||||
$ go run main.go
|
||||
patch document: {"height":null,"name":"Jane"}
|
||||
updated tina doc: {"age":28,"name":"Jane"}
|
||||
```
|
||||
|
||||
## Create and apply a JSON Patch
|
||||
You can create patch objects using `DecodePatch([]byte)`, which can then
|
||||
be applied against JSON documents.
|
||||
|
||||
The following is an example of creating a patch from two operations, and
|
||||
applying it against a JSON document.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
|
||||
patchJSON := []byte(`[
|
||||
{"op": "replace", "path": "/name", "value": "Jane"},
|
||||
{"op": "remove", "path": "/height"}
|
||||
]`)
|
||||
|
||||
patch, err := jsonpatch.DecodePatch(patchJSON)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
modified, err := patch.Apply(original)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Original document: %s\n", original)
|
||||
fmt.Printf("Modified document: %s\n", modified)
|
||||
}
|
||||
```
|
||||
|
||||
When ran, you get the following output:
|
||||
|
||||
```bash
|
||||
$ go run main.go
|
||||
Original document: {"name": "John", "age": 24, "height": 3.21}
|
||||
Modified document: {"age":24,"name":"Jane"}
|
||||
```
|
||||
|
||||
## Comparing JSON documents
|
||||
Due to potential whitespace and ordering differences, one cannot simply compare
|
||||
JSON strings or byte-arrays directly.
|
||||
|
||||
As such, you can instead use `jsonpatch.Equal(document1, document2)` to
|
||||
determine if two JSON documents are _structurally_ equal. This ignores
|
||||
whitespace differences, and key-value ordering.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
|
||||
similar := []byte(`
|
||||
{
|
||||
"age": 24,
|
||||
"height": 3.21,
|
||||
"name": "John"
|
||||
}
|
||||
`)
|
||||
different := []byte(`{"name": "Jane", "age": 20, "height": 3.37}`)
|
||||
|
||||
if jsonpatch.Equal(original, similar) {
|
||||
fmt.Println(`"original" is structurally equal to "similar"`)
|
||||
}
|
||||
|
||||
if !jsonpatch.Equal(original, different) {
|
||||
fmt.Println(`"original" is _not_ structurally equal to "similar"`)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When ran, you get the following output:
|
||||
```bash
|
||||
$ go run main.go
|
||||
"original" is structurally equal to "similar"
|
||||
"original" is _not_ structurally equal to "similar"
|
||||
```
|
||||
|
||||
## Combine merge patches
|
||||
Given two JSON merge patch documents, it is possible to combine them into a
|
||||
single merge patch which can describe both set of changes.
|
||||
|
||||
The resulting merge patch can be used such that applying it results in a
|
||||
document structurally similar as merging each merge patch to the document
|
||||
in succession.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
|
||||
|
||||
nameAndHeight := []byte(`{"height":null,"name":"Jane"}`)
|
||||
ageAndEyes := []byte(`{"age":4.23,"eyes":"blue"}`)
|
||||
|
||||
// Let's combine these merge patch documents...
|
||||
combinedPatch, err := jsonpatch.MergeMergePatches(nameAndHeight, ageAndEyes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Apply each patch individual against the original document
|
||||
withoutCombinedPatch, err := jsonpatch.MergePatch(original, nameAndHeight)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
withoutCombinedPatch, err = jsonpatch.MergePatch(withoutCombinedPatch, ageAndEyes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Apply the combined patch against the original document
|
||||
|
||||
withCombinedPatch, err := jsonpatch.MergePatch(original, combinedPatch)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Do both result in the same thing? They should!
|
||||
if jsonpatch.Equal(withCombinedPatch, withoutCombinedPatch) {
|
||||
fmt.Println("Both JSON documents are structurally the same!")
|
||||
}
|
||||
|
||||
fmt.Printf("combined merge patch: %s", combinedPatch)
|
||||
}
|
||||
```
|
||||
|
||||
When ran, you get the following output:
|
||||
```bash
|
||||
$ go run main.go
|
||||
Both JSON documents are structurally the same!
|
||||
combined merge patch: {"age":4.23,"eyes":"blue","height":null,"name":"Jane"}
|
||||
```
|
||||
|
||||
# CLI for comparing JSON documents
|
||||
You can install the commandline program `json-patch`.
|
||||
|
||||
This program can take multiple JSON patch documents as arguments,
|
||||
and fed a JSON document from `stdin`. It will apply the patch(es) against
|
||||
the document and output the modified doc.
|
||||
|
||||
**patch.1.json**
|
||||
```json
|
||||
[
|
||||
{"op": "replace", "path": "/name", "value": "Jane"},
|
||||
{"op": "remove", "path": "/height"}
|
||||
]
|
||||
```
|
||||
|
||||
**patch.2.json**
|
||||
```json
|
||||
[
|
||||
{"op": "add", "path": "/address", "value": "123 Main St"},
|
||||
{"op": "replace", "path": "/age", "value": "21"}
|
||||
]
|
||||
```
|
||||
|
||||
**document.json**
|
||||
```json
|
||||
{
|
||||
"name": "John",
|
||||
"age": 24,
|
||||
"height": 3.21
|
||||
}
|
||||
```
|
||||
|
||||
You can then run:
|
||||
|
||||
```bash
|
||||
$ go install github.com/evanphx/json-patch/cmd/json-patch
|
||||
$ cat document.json | json-patch -p patch.1.json -p patch.2.json
|
||||
{"address":"123 Main St","age":"21","name":"Jane"}
|
||||
```
|
||||
|
||||
# Help It!
|
||||
Contributions are welcomed! Leave [an issue](https://github.com/evanphx/json-patch/issues)
|
||||
or [create a PR](https://github.com/evanphx/json-patch/compare).
|
||||
|
||||
|
||||
Before creating a pull request, we'd ask that you make sure tests are passing
|
||||
and that you have added new tests when applicable.
|
||||
|
||||
Contributors can run tests using:
|
||||
|
||||
```bash
|
||||
go test -cover ./...
|
||||
```
|
||||
|
||||
Builds for pull requests are tested automatically
|
||||
using [TravisCI](https://travis-ci.org/evanphx/json-patch).
|
39
vendor/github.com/evanphx/json-patch/cmd/json-patch/file_flag.go
generated
vendored
39
vendor/github.com/evanphx/json-patch/cmd/json-patch/file_flag.go
generated
vendored
@@ -1,39 +0,0 @@
|
||||
package main
|
||||
|
||||
// Borrowed from Concourse: https://github.com/concourse/atc/blob/master/atccmd/file_flag.go
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// FileFlag is a flag for passing a path to a file on disk. The file is
|
||||
// expected to be a file, not a directory, that actually exists.
|
||||
type FileFlag string
|
||||
|
||||
// UnmarshalFlag implements go-flag's Unmarshaler interface
|
||||
func (f *FileFlag) UnmarshalFlag(value string) error {
|
||||
stat, err := os.Stat(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
return fmt.Errorf("path '%s' is a directory, not a file", value)
|
||||
}
|
||||
|
||||
abs, err := filepath.Abs(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*f = FileFlag(abs)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Path is the path to the file
|
||||
func (f FileFlag) Path() string {
|
||||
return string(f)
|
||||
}
|
56
vendor/github.com/evanphx/json-patch/cmd/json-patch/main.go
generated
vendored
56
vendor/github.com/evanphx/json-patch/cmd/json-patch/main.go
generated
vendored
@@ -1,56 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
||||
type opts struct {
|
||||
PatchFilePaths []FileFlag `long:"patch-file" short:"p" value-name:"PATH" description:"Path to file with one or more operations"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
var o opts
|
||||
_, err := flags.Parse(&o)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %s\n", err)
|
||||
}
|
||||
|
||||
patches := make([]jsonpatch.Patch, len(o.PatchFilePaths))
|
||||
|
||||
for i, patchFilePath := range o.PatchFilePaths {
|
||||
var bs []byte
|
||||
bs, err = ioutil.ReadFile(patchFilePath.Path())
|
||||
if err != nil {
|
||||
log.Fatalf("error reading patch file: %s", err)
|
||||
}
|
||||
|
||||
var patch jsonpatch.Patch
|
||||
patch, err = jsonpatch.DecodePatch(bs)
|
||||
if err != nil {
|
||||
log.Fatalf("error decoding patch file: %s", err)
|
||||
}
|
||||
|
||||
patches[i] = patch
|
||||
}
|
||||
|
||||
doc, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
log.Fatalf("error reading from stdin: %s", err)
|
||||
}
|
||||
|
||||
mdoc := doc
|
||||
for _, patch := range patches {
|
||||
mdoc, err = patch.Apply(mdoc)
|
||||
if err != nil {
|
||||
log.Fatalf("error applying patch: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("%s", mdoc)
|
||||
}
|
585
vendor/github.com/evanphx/json-patch/merge_test.go
generated
vendored
585
vendor/github.com/evanphx/json-patch/merge_test.go
generated
vendored
@@ -1,585 +0,0 @@
|
||||
package jsonpatch
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func mergePatch(doc, patch string) string {
|
||||
out, err := MergePatch([]byte(doc), []byte(patch))
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return string(out)
|
||||
}
|
||||
|
||||
func TestMergePatchReplaceKey(t *testing.T) {
|
||||
doc := `{ "title": "hello" }`
|
||||
pat := `{ "title": "goodbye" }`
|
||||
|
||||
res := mergePatch(doc, pat)
|
||||
|
||||
if !compareJSON(pat, res) {
|
||||
t.Fatalf("Key was not replaced")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePatchIgnoresOtherValues(t *testing.T) {
|
||||
doc := `{ "title": "hello", "age": 18 }`
|
||||
pat := `{ "title": "goodbye" }`
|
||||
|
||||
res := mergePatch(doc, pat)
|
||||
|
||||
exp := `{ "title": "goodbye", "age": 18 }`
|
||||
|
||||
if !compareJSON(exp, res) {
|
||||
t.Fatalf("Key was not replaced")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePatchNilDoc(t *testing.T) {
|
||||
doc := `{ "title": null }`
|
||||
pat := `{ "title": {"foo": "bar"} }`
|
||||
|
||||
res := mergePatch(doc, pat)
|
||||
|
||||
exp := `{ "title": {"foo": "bar"} }`
|
||||
|
||||
if !compareJSON(exp, res) {
|
||||
t.Fatalf("Key was not replaced")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePatchRecursesIntoObjects(t *testing.T) {
|
||||
doc := `{ "person": { "title": "hello", "age": 18 } }`
|
||||
pat := `{ "person": { "title": "goodbye" } }`
|
||||
|
||||
res := mergePatch(doc, pat)
|
||||
|
||||
exp := `{ "person": { "title": "goodbye", "age": 18 } }`
|
||||
|
||||
if !compareJSON(exp, res) {
|
||||
t.Fatalf("Key was not replaced")
|
||||
}
|
||||
}
|
||||
|
||||
type nonObjectCases struct {
|
||||
doc, pat, res string
|
||||
}
|
||||
|
||||
func TestMergePatchReplacesNonObjectsWholesale(t *testing.T) {
|
||||
a1 := `[1]`
|
||||
a2 := `[2]`
|
||||
o1 := `{ "a": 1 }`
|
||||
o2 := `{ "a": 2 }`
|
||||
o3 := `{ "a": 1, "b": 1 }`
|
||||
o4 := `{ "a": 2, "b": 1 }`
|
||||
|
||||
cases := []nonObjectCases{
|
||||
{a1, a2, a2},
|
||||
{o1, a2, a2},
|
||||
{a1, o1, o1},
|
||||
{o3, o2, o4},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
act := mergePatch(c.doc, c.pat)
|
||||
|
||||
if !compareJSON(c.res, act) {
|
||||
t.Errorf("whole object replacement failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePatchReturnsErrorOnBadJSON(t *testing.T) {
|
||||
_, err := MergePatch([]byte(`[[[[`), []byte(`1`))
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Did not return an error for bad json: %s", err)
|
||||
}
|
||||
|
||||
_, err = MergePatch([]byte(`1`), []byte(`[[[[`))
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Did not return an error for bad json: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePatchReturnsEmptyArrayOnEmptyArray(t *testing.T) {
|
||||
doc := `{ "array": ["one", "two"] }`
|
||||
pat := `{ "array": [] }`
|
||||
|
||||
exp := `{ "array": [] }`
|
||||
|
||||
res, err := MergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if !compareJSON(exp, string(res)) {
|
||||
t.Fatalf("Emtpy array did not return not return as empty array")
|
||||
}
|
||||
}
|
||||
|
||||
var rfcTests = []struct {
|
||||
target string
|
||||
patch string
|
||||
expected string
|
||||
}{
|
||||
// test cases from https://tools.ietf.org/html/rfc7386#appendix-A
|
||||
{target: `{"a":"b"}`, patch: `{"a":"c"}`, expected: `{"a":"c"}`},
|
||||
{target: `{"a":"b"}`, patch: `{"b":"c"}`, expected: `{"a":"b","b":"c"}`},
|
||||
{target: `{"a":"b"}`, patch: `{"a":null}`, expected: `{}`},
|
||||
{target: `{"a":"b","b":"c"}`, patch: `{"a":null}`, expected: `{"b":"c"}`},
|
||||
{target: `{"a":["b"]}`, patch: `{"a":"c"}`, expected: `{"a":"c"}`},
|
||||
{target: `{"a":"c"}`, patch: `{"a":["b"]}`, expected: `{"a":["b"]}`},
|
||||
{target: `{"a":{"b": "c"}}`, patch: `{"a": {"b": "d","c": null}}`, expected: `{"a":{"b":"d"}}`},
|
||||
{target: `{"a":[{"b":"c"}]}`, patch: `{"a":[1]}`, expected: `{"a":[1]}`},
|
||||
{target: `["a","b"]`, patch: `["c","d"]`, expected: `["c","d"]`},
|
||||
{target: `{"a":"b"}`, patch: `["c"]`, expected: `["c"]`},
|
||||
// {target: `{"a":"foo"}`, patch: `null`, expected: `null`},
|
||||
// {target: `{"a":"foo"}`, patch: `"bar"`, expected: `"bar"`},
|
||||
{target: `{"e":null}`, patch: `{"a":1}`, expected: `{"a":1,"e":null}`},
|
||||
{target: `[1,2]`, patch: `{"a":"b","c":null}`, expected: `{"a":"b"}`},
|
||||
{target: `{}`, patch: `{"a":{"bb":{"ccc":null}}}`, expected: `{"a":{"bb":{}}}`},
|
||||
}
|
||||
|
||||
func TestMergePatchRFCCases(t *testing.T) {
|
||||
for i, c := range rfcTests {
|
||||
out := mergePatch(c.target, c.patch)
|
||||
|
||||
if !compareJSON(out, c.expected) {
|
||||
t.Errorf("case[%d], patch '%s' did not apply properly to '%s'. expected:\n'%s'\ngot:\n'%s'", i, c.patch, c.target, c.expected, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rfcFailTests = `
|
||||
{"a":"foo"} | null
|
||||
{"a":"foo"} | "bar"
|
||||
`
|
||||
|
||||
func TestMergePatchFailRFCCases(t *testing.T) {
|
||||
tests := strings.Split(rfcFailTests, "\n")
|
||||
|
||||
for _, c := range tests {
|
||||
if strings.TrimSpace(c) == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
parts := strings.SplitN(c, "|", 2)
|
||||
|
||||
doc := strings.TrimSpace(parts[0])
|
||||
pat := strings.TrimSpace(parts[1])
|
||||
|
||||
out, err := MergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != errBadJSONPatch {
|
||||
t.Errorf("error not returned properly: %s, %s", err, string(out))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestResembleJSONArray(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input []byte
|
||||
expected bool
|
||||
}{
|
||||
// Failure cases
|
||||
{input: []byte(``), expected: false},
|
||||
{input: []byte(`not an array`), expected: false},
|
||||
{input: []byte(`{"foo": "bar"}`), expected: false},
|
||||
{input: []byte(`{"fizz": ["buzz"]}`), expected: false},
|
||||
{input: []byte(`[bad suffix`), expected: false},
|
||||
{input: []byte(`bad prefix]`), expected: false},
|
||||
{input: []byte(`][`), expected: false},
|
||||
|
||||
// Valid cases
|
||||
{input: []byte(`[]`), expected: true},
|
||||
{input: []byte(`["foo", "bar"]`), expected: true},
|
||||
{input: []byte(`[["foo", "bar"]]`), expected: true},
|
||||
{input: []byte(`[not valid syntax]`), expected: true},
|
||||
|
||||
// Valid cases with whitespace
|
||||
{input: []byte(` []`), expected: true},
|
||||
{input: []byte(`[] `), expected: true},
|
||||
{input: []byte(` [] `), expected: true},
|
||||
{input: []byte(` [ ] `), expected: true},
|
||||
{input: []byte("\t[]"), expected: true},
|
||||
{input: []byte("[]\n"), expected: true},
|
||||
{input: []byte("\n\t\r[]"), expected: true},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
result := resemblesJSONArray(test.input)
|
||||
if result != test.expected {
|
||||
t.Errorf(
|
||||
`expected "%t" but received "%t" for case: "%s"`,
|
||||
test.expected,
|
||||
result,
|
||||
string(test.input),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchReplaceKey(t *testing.T) {
|
||||
doc := `{ "title": "hello", "nested": {"one": 1, "two": 2} }`
|
||||
pat := `{ "title": "goodbye", "nested": {"one": 2, "two": 2} }`
|
||||
|
||||
exp := `{ "title": "goodbye", "nested": {"one": 2} }`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if !compareJSON(exp, string(res)) {
|
||||
t.Fatalf("Key was not replaced")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchGetArray(t *testing.T) {
|
||||
doc := `{ "title": "hello", "array": ["one", "two"], "notmatch": [1, 2, 3] }`
|
||||
pat := `{ "title": "hello", "array": ["one", "two", "three"], "notmatch": [1, 2, 3] }`
|
||||
|
||||
exp := `{ "array": ["one", "two", "three"] }`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if !compareJSON(exp, string(res)) {
|
||||
t.Fatalf("Array was not added")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchGetObjArray(t *testing.T) {
|
||||
doc := `{ "title": "hello", "array": [{"banana": true}, {"evil": false}], "notmatch": [{"one":1}, {"two":2}, {"three":3}] }`
|
||||
pat := `{ "title": "hello", "array": [{"banana": false}, {"evil": true}], "notmatch": [{"one":1}, {"two":2}, {"three":3}] }`
|
||||
|
||||
exp := `{ "array": [{"banana": false}, {"evil": true}] }`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if !compareJSON(exp, string(res)) {
|
||||
t.Fatalf("Object array was not added")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchDeleteKey(t *testing.T) {
|
||||
doc := `{ "title": "hello", "nested": {"one": 1, "two": 2} }`
|
||||
pat := `{ "title": "hello", "nested": {"one": 1} }`
|
||||
|
||||
exp := `{"nested":{"two":null}}`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
// We cannot use "compareJSON", since Equals does not report a difference if the value is null
|
||||
if exp != string(res) {
|
||||
t.Fatalf("Key was not removed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchEmptyArray(t *testing.T) {
|
||||
doc := `{ "array": null }`
|
||||
pat := `{ "array": [] }`
|
||||
|
||||
exp := `{"array":[]}`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
// We cannot use "compareJSON", since Equals does not report a difference if the value is null
|
||||
if exp != string(res) {
|
||||
t.Fatalf("Key was not removed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchNil(t *testing.T) {
|
||||
doc := `{ "title": "hello", "nested": {"one": 1, "two": [{"one":null}, {"two":null}, {"three":null}]} }`
|
||||
pat := doc
|
||||
|
||||
exp := `{}`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if !compareJSON(exp, string(res)) {
|
||||
t.Fatalf("Object array was not added")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchObjArray(t *testing.T) {
|
||||
doc := `{ "array": [ {"a": {"b": 2}}, {"a": {"b": 3}} ]}`
|
||||
exp := `{}`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(doc))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
// We cannot use "compareJSON", since Equals does not report a difference if the value is null
|
||||
if exp != string(res) {
|
||||
t.Fatalf("Array was not empty, was " + string(res))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchSameOuterArray(t *testing.T) {
|
||||
doc := `[{"foo": "bar"}]`
|
||||
pat := doc
|
||||
exp := `[{}]`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if !compareJSON(exp, string(res)) {
|
||||
t.Fatalf("Outer array was not unmodified")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchModifiedOuterArray(t *testing.T) {
|
||||
doc := `[{"name": "John"}, {"name": "Will"}]`
|
||||
pat := `[{"name": "Jane"}, {"name": "Will"}]`
|
||||
exp := `[{"name": "Jane"}, {}]`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if !compareJSON(exp, string(res)) {
|
||||
t.Fatalf("Expected %s but received %s", exp, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchMismatchedOuterArray(t *testing.T) {
|
||||
doc := `[{"name": "John"}, {"name": "Will"}]`
|
||||
pat := `[{"name": "Jane"}]`
|
||||
|
||||
_, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Expected error due to array length differences but received none")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchMismatchedOuterTypes(t *testing.T) {
|
||||
doc := `[{"name": "John"}]`
|
||||
pat := `{"name": "Jane"}`
|
||||
|
||||
_, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Expected error due to mismatched types but received none")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchNoDifferences(t *testing.T) {
|
||||
doc := `{ "title": "hello", "nested": {"one": 1, "two": 2} }`
|
||||
pat := doc
|
||||
|
||||
exp := `{}`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if !compareJSON(exp, string(res)) {
|
||||
t.Fatalf("Key was not replaced")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchComplexMatch(t *testing.T) {
|
||||
doc := `{"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4], "nested": {"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4]} }`
|
||||
empty := `{}`
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(doc))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
// We cannot use "compareJSON", since Equals does not report a difference if the value is null
|
||||
if empty != string(res) {
|
||||
t.Fatalf("Did not get empty result, was:%s", string(res))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchComplexAddAll(t *testing.T) {
|
||||
doc := `{"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4], "nested": {"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4]} }`
|
||||
empty := `{}`
|
||||
res, err := CreateMergePatch([]byte(empty), []byte(doc))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if !compareJSON(doc, string(res)) {
|
||||
t.Fatalf("Did not get everything as, it was:\n%s", string(res))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchComplexRemoveAll(t *testing.T) {
|
||||
doc := `{"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4], "nested": {"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4]} }`
|
||||
exp := `{"a":null,"f":null,"hello":null,"i":null,"n":null,"nested":null,"pi":null,"t":null}`
|
||||
empty := `{}`
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(empty))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if exp != string(res) {
|
||||
t.Fatalf("Did not get result, was:%s", string(res))
|
||||
}
|
||||
|
||||
// FIXME: Crashes if using compareJSON like this:
|
||||
/*
|
||||
if !compareJSON(doc, string(res)) {
|
||||
t.Fatalf("Did not get everything as, it was:\n%s", string(res))
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
func TestCreateMergePatchObjectWithInnerArray(t *testing.T) {
|
||||
stateString := `{
|
||||
"OuterArray": [
|
||||
{
|
||||
"InnerArray": [
|
||||
{
|
||||
"StringAttr": "abc123"
|
||||
}
|
||||
],
|
||||
"StringAttr": "def456"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
patch, err := CreateMergePatch([]byte(stateString), []byte(stateString))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if string(patch) != "{}" {
|
||||
t.Fatalf("Patch should have been {} but was: %v", string(patch))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMergePatchReplaceKeyNotEscape(t *testing.T) {
|
||||
doc := `{ "title": "hello", "nested": {"title/escaped": 1, "two": 2} }`
|
||||
pat := `{ "title": "goodbye", "nested": {"title/escaped": 2, "two": 2} }`
|
||||
|
||||
exp := `{ "title": "goodbye", "nested": {"title/escaped": 2} }`
|
||||
|
||||
res, err := CreateMergePatch([]byte(doc), []byte(pat))
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s, %s", err, string(res))
|
||||
}
|
||||
|
||||
if !compareJSON(exp, string(res)) {
|
||||
t.Log(string(res))
|
||||
t.Fatalf("Key was not replaced")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePatchReplaceKeyNotEscaping(t *testing.T) {
|
||||
doc := `{ "obj": { "title/escaped": "hello" } }`
|
||||
pat := `{ "obj": { "title/escaped": "goodbye" } }`
|
||||
exp := `{ "obj": { "title/escaped": "goodbye" } }`
|
||||
|
||||
res := mergePatch(doc, pat)
|
||||
|
||||
if !compareJSON(exp, res) {
|
||||
t.Fatalf("Key was not replaced")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeMergePatches(t *testing.T) {
|
||||
cases := []struct {
|
||||
demonstrates string
|
||||
p1 string
|
||||
p2 string
|
||||
exp string
|
||||
}{
|
||||
{
|
||||
demonstrates: "simple patches are merged normally",
|
||||
p1: `{"add1": 1}`,
|
||||
p2: `{"add2": 2}`,
|
||||
exp: `{"add1": 1, "add2": 2}`,
|
||||
},
|
||||
{
|
||||
demonstrates: "nulls are kept",
|
||||
p1: `{"del1": null}`,
|
||||
p2: `{"del2": null}`,
|
||||
exp: `{"del1": null, "del2": null}`,
|
||||
},
|
||||
{
|
||||
demonstrates: "a key added then deleted is kept deleted",
|
||||
p1: `{"add_then_delete": "atd"}`,
|
||||
p2: `{"add_then_delete": null}`,
|
||||
exp: `{"add_then_delete": null}`,
|
||||
},
|
||||
{
|
||||
demonstrates: "a key deleted then added is kept added",
|
||||
p1: `{"delete_then_add": null}`,
|
||||
p2: `{"delete_then_add": "dta"}`,
|
||||
exp: `{"delete_then_add": "dta"}`,
|
||||
},
|
||||
{
|
||||
demonstrates: "object overrides array",
|
||||
p1: `[]`,
|
||||
p2: `{"del": null, "add": "a"}`,
|
||||
exp: `{"del": null, "add": "a"}`,
|
||||
},
|
||||
{
|
||||
demonstrates: "array overrides object",
|
||||
p1: `{"del": null, "add": "a"}`,
|
||||
p2: `[]`,
|
||||
exp: `[]`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
out, err := MergeMergePatches([]byte(c.p1), []byte(c.p2))
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if !compareJSON(c.exp, string(out)) {
|
||||
t.Logf("Error while trying to demonstrate: %v", c.demonstrates)
|
||||
t.Logf("Got %v", string(out))
|
||||
t.Logf("Expected %v", c.exp)
|
||||
t.Fatalf("Merged merge patch is incorrect")
|
||||
}
|
||||
}
|
||||
}
|
421
vendor/github.com/evanphx/json-patch/patch_test.go
generated
vendored
421
vendor/github.com/evanphx/json-patch/patch_test.go
generated
vendored
@@ -1,421 +0,0 @@
|
||||
package jsonpatch
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func reformatJSON(j string) string {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
json.Indent(buf, []byte(j), "", " ")
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func compareJSON(a, b string) bool {
|
||||
// return Equal([]byte(a), []byte(b))
|
||||
|
||||
var objA, objB map[string]interface{}
|
||||
json.Unmarshal([]byte(a), &objA)
|
||||
json.Unmarshal([]byte(b), &objB)
|
||||
|
||||
// fmt.Printf("Comparing %#v\nagainst %#v\n", objA, objB)
|
||||
return reflect.DeepEqual(objA, objB)
|
||||
}
|
||||
|
||||
func applyPatch(doc, patch string) (string, error) {
|
||||
obj, err := DecodePatch([]byte(patch))
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
out, err := obj.Apply([]byte(doc))
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
type Case struct {
|
||||
doc, patch, result string
|
||||
}
|
||||
|
||||
var Cases = []Case{
|
||||
{
|
||||
`{ "foo": "bar"}`,
|
||||
`[
|
||||
{ "op": "add", "path": "/baz", "value": "qux" }
|
||||
]`,
|
||||
`{
|
||||
"baz": "qux",
|
||||
"foo": "bar"
|
||||
}`,
|
||||
},
|
||||
{
|
||||
`{ "foo": [ "bar", "baz" ] }`,
|
||||
`[
|
||||
{ "op": "add", "path": "/foo/1", "value": "qux" }
|
||||
]`,
|
||||
`{ "foo": [ "bar", "qux", "baz" ] }`,
|
||||
},
|
||||
{
|
||||
`{ "foo": [ "bar", "baz" ] }`,
|
||||
`[
|
||||
{ "op": "add", "path": "/foo/-1", "value": "qux" }
|
||||
]`,
|
||||
`{ "foo": [ "bar", "baz", "qux" ] }`,
|
||||
},
|
||||
{
|
||||
`{ "baz": "qux", "foo": "bar" }`,
|
||||
`[ { "op": "remove", "path": "/baz" } ]`,
|
||||
`{ "foo": "bar" }`,
|
||||
},
|
||||
{
|
||||
`{ "foo": [ "bar", "qux", "baz" ] }`,
|
||||
`[ { "op": "remove", "path": "/foo/1" } ]`,
|
||||
`{ "foo": [ "bar", "baz" ] }`,
|
||||
},
|
||||
{
|
||||
`{ "baz": "qux", "foo": "bar" }`,
|
||||
`[ { "op": "replace", "path": "/baz", "value": "boo" } ]`,
|
||||
`{ "baz": "boo", "foo": "bar" }`,
|
||||
},
|
||||
{
|
||||
`{
|
||||
"foo": {
|
||||
"bar": "baz",
|
||||
"waldo": "fred"
|
||||
},
|
||||
"qux": {
|
||||
"corge": "grault"
|
||||
}
|
||||
}`,
|
||||
`[ { "op": "move", "from": "/foo/waldo", "path": "/qux/thud" } ]`,
|
||||
`{
|
||||
"foo": {
|
||||
"bar": "baz"
|
||||
},
|
||||
"qux": {
|
||||
"corge": "grault",
|
||||
"thud": "fred"
|
||||
}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
`{ "foo": [ "all", "grass", "cows", "eat" ] }`,
|
||||
`[ { "op": "move", "from": "/foo/1", "path": "/foo/3" } ]`,
|
||||
`{ "foo": [ "all", "cows", "eat", "grass" ] }`,
|
||||
},
|
||||
{
|
||||
`{ "foo": "bar" }`,
|
||||
`[ { "op": "add", "path": "/child", "value": { "grandchild": { } } } ]`,
|
||||
`{ "foo": "bar", "child": { "grandchild": { } } }`,
|
||||
},
|
||||
{
|
||||
`{ "foo": ["bar"] }`,
|
||||
`[ { "op": "add", "path": "/foo/-", "value": ["abc", "def"] } ]`,
|
||||
`{ "foo": ["bar", ["abc", "def"]] }`,
|
||||
},
|
||||
{
|
||||
`{ "foo": "bar", "qux": { "baz": 1, "bar": null } }`,
|
||||
`[ { "op": "remove", "path": "/qux/bar" } ]`,
|
||||
`{ "foo": "bar", "qux": { "baz": 1 } }`,
|
||||
},
|
||||
{
|
||||
`{ "foo": "bar" }`,
|
||||
`[ { "op": "add", "path": "/baz", "value": null } ]`,
|
||||
`{ "baz": null, "foo": "bar" }`,
|
||||
},
|
||||
{
|
||||
`{ "foo": ["bar"]}`,
|
||||
`[ { "op": "replace", "path": "/foo/0", "value": "baz"}]`,
|
||||
`{ "foo": ["baz"]}`,
|
||||
},
|
||||
{
|
||||
`{ "foo": ["bar","baz"]}`,
|
||||
`[ { "op": "replace", "path": "/foo/0", "value": "bum"}]`,
|
||||
`{ "foo": ["bum","baz"]}`,
|
||||
},
|
||||
{
|
||||
`{ "foo": ["bar","qux","baz"]}`,
|
||||
`[ { "op": "replace", "path": "/foo/1", "value": "bum"}]`,
|
||||
`{ "foo": ["bar", "bum","baz"]}`,
|
||||
},
|
||||
{
|
||||
`[ {"foo": ["bar","qux","baz"]}]`,
|
||||
`[ { "op": "replace", "path": "/0/foo/0", "value": "bum"}]`,
|
||||
`[ {"foo": ["bum","qux","baz"]}]`,
|
||||
},
|
||||
{
|
||||
`[ {"foo": ["bar","qux","baz"], "bar": ["qux","baz"]}]`,
|
||||
`[ { "op": "copy", "from": "/0/foo/0", "path": "/0/bar/0"}]`,
|
||||
`[ {"foo": ["bar","qux","baz"], "bar": ["bar", "baz"]}]`,
|
||||
},
|
||||
{
|
||||
`[ {"foo": ["bar","qux","baz"], "bar": ["qux","baz"]}]`,
|
||||
`[ { "op": "copy", "from": "/0/foo/0", "path": "/0/bar"}]`,
|
||||
`[ {"foo": ["bar","qux","baz"], "bar": ["bar", "qux", "baz"]}]`,
|
||||
},
|
||||
{
|
||||
`[ { "foo": {"bar": ["qux","baz"]}, "baz": {"qux": "bum"}}]`,
|
||||
`[ { "op": "copy", "from": "/0/foo/bar", "path": "/0/baz/bar"}]`,
|
||||
`[ { "baz": {"bar": ["qux","baz"], "qux":"bum"}, "foo": {"bar": ["qux","baz"]}}]`,
|
||||
},
|
||||
{
|
||||
`{ "foo": ["bar","qux","baz"]}`,
|
||||
`[ { "op": "remove", "path": "/foo/-2"}]`,
|
||||
`{ "foo": ["bar", "baz"]}`,
|
||||
},
|
||||
{
|
||||
`{ "foo": []}`,
|
||||
`[ { "op": "add", "path": "/foo/-1", "value": "qux"}]`,
|
||||
`{ "foo": ["qux"]}`,
|
||||
},
|
||||
{
|
||||
`{ "bar": [{"baz": null}]}`,
|
||||
`[ { "op": "replace", "path": "/bar/0/baz", "value": 1 } ]`,
|
||||
`{ "bar": [{"baz": 1}]}`,
|
||||
},
|
||||
{
|
||||
`{ "bar": [{"baz": 1}]}`,
|
||||
`[ { "op": "replace", "path": "/bar/0/baz", "value": null } ]`,
|
||||
`{ "bar": [{"baz": null}]}`,
|
||||
},
|
||||
{
|
||||
`{ "bar": [null]}`,
|
||||
`[ { "op": "replace", "path": "/bar/0", "value": 1 } ]`,
|
||||
`{ "bar": [1]}`,
|
||||
},
|
||||
{
|
||||
`{ "bar": [1]}`,
|
||||
`[ { "op": "replace", "path": "/bar/0", "value": null } ]`,
|
||||
`{ "bar": [null]}`,
|
||||
},
|
||||
}
|
||||
|
||||
type BadCase struct {
|
||||
doc, patch string
|
||||
}
|
||||
|
||||
var MutationTestCases = []BadCase{
|
||||
{
|
||||
`{ "foo": "bar", "qux": { "baz": 1, "bar": null } }`,
|
||||
`[ { "op": "remove", "path": "/qux/bar" } ]`,
|
||||
},
|
||||
{
|
||||
`{ "foo": "bar", "qux": { "baz": 1, "bar": null } }`,
|
||||
`[ { "op": "replace", "path": "/qux/baz", "value": null } ]`,
|
||||
},
|
||||
}
|
||||
|
||||
var BadCases = []BadCase{
|
||||
{
|
||||
`{ "foo": "bar" }`,
|
||||
`[ { "op": "add", "path": "/baz/bat", "value": "qux" } ]`,
|
||||
},
|
||||
{
|
||||
`{ "a": { "b": { "d": 1 } } }`,
|
||||
`[ { "op": "remove", "path": "/a/b/c" } ]`,
|
||||
},
|
||||
{
|
||||
`{ "a": { "b": { "d": 1 } } }`,
|
||||
`[ { "op": "move", "from": "/a/b/c", "path": "/a/b/e" } ]`,
|
||||
},
|
||||
{
|
||||
`{ "a": { "b": [1] } }`,
|
||||
`[ { "op": "remove", "path": "/a/b/1" } ]`,
|
||||
},
|
||||
{
|
||||
`{ "a": { "b": [1] } }`,
|
||||
`[ { "op": "move", "from": "/a/b/1", "path": "/a/b/2" } ]`,
|
||||
},
|
||||
{
|
||||
`{ "foo": "bar" }`,
|
||||
`[ { "op": "add", "pathz": "/baz", "value": "qux" } ]`,
|
||||
},
|
||||
{
|
||||
`{ "foo": "bar" }`,
|
||||
`[ { "op": "add", "path": "", "value": "qux" } ]`,
|
||||
},
|
||||
{
|
||||
`{ "foo": ["bar","baz"]}`,
|
||||
`[ { "op": "replace", "path": "/foo/2", "value": "bum"}]`,
|
||||
},
|
||||
{
|
||||
`{ "foo": ["bar","baz"]}`,
|
||||
`[ { "op": "add", "path": "/foo/-4", "value": "bum"}]`,
|
||||
},
|
||||
{
|
||||
`{ "name":{ "foo": "bat", "qux": "bum"}}`,
|
||||
`[ { "op": "replace", "path": "/foo/bar", "value":"baz"}]`,
|
||||
},
|
||||
{
|
||||
`{ "foo": ["bar"]}`,
|
||||
`[ {"op": "add", "path": "/foo/2", "value": "bum"}]`,
|
||||
},
|
||||
{
|
||||
`{ "foo": []}`,
|
||||
`[ {"op": "remove", "path": "/foo/-"}]`,
|
||||
},
|
||||
{
|
||||
`{ "foo": []}`,
|
||||
`[ {"op": "remove", "path": "/foo/-1"}]`,
|
||||
},
|
||||
{
|
||||
`{ "foo": ["bar"]}`,
|
||||
`[ {"op": "remove", "path": "/foo/-2"}]`,
|
||||
},
|
||||
{
|
||||
`{}`,
|
||||
`[ {"op":null,"path":""} ]`,
|
||||
},
|
||||
{
|
||||
`{}`,
|
||||
`[ {"op":"add","path":null} ]`,
|
||||
},
|
||||
{
|
||||
`{}`,
|
||||
`[ { "op": "copy", "from": null }]`,
|
||||
},
|
||||
}
|
||||
|
||||
func TestAllCases(t *testing.T) {
|
||||
for _, c := range Cases {
|
||||
out, err := applyPatch(c.doc, c.patch)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unable to apply patch: %s", err)
|
||||
}
|
||||
|
||||
if !compareJSON(out, c.result) {
|
||||
t.Errorf("Patch did not apply. Expected:\n%s\n\nActual:\n%s",
|
||||
reformatJSON(c.result), reformatJSON(out))
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range MutationTestCases {
|
||||
out, err := applyPatch(c.doc, c.patch)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unable to apply patch: %s", err)
|
||||
}
|
||||
|
||||
if compareJSON(out, c.doc) {
|
||||
t.Errorf("Patch did not apply. Original:\n%s\n\nPatched:\n%s",
|
||||
reformatJSON(c.doc), reformatJSON(out))
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range BadCases {
|
||||
_, err := applyPatch(c.doc, c.patch)
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Patch should have failed to apply but it did not")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type TestCase struct {
|
||||
doc, patch string
|
||||
result bool
|
||||
failedPath string
|
||||
}
|
||||
|
||||
var TestCases = []TestCase{
|
||||
{
|
||||
`{
|
||||
"baz": "qux",
|
||||
"foo": [ "a", 2, "c" ]
|
||||
}`,
|
||||
`[
|
||||
{ "op": "test", "path": "/baz", "value": "qux" },
|
||||
{ "op": "test", "path": "/foo/1", "value": 2 }
|
||||
]`,
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`{ "baz": "qux" }`,
|
||||
`[ { "op": "test", "path": "/baz", "value": "bar" } ]`,
|
||||
false,
|
||||
"/baz",
|
||||
},
|
||||
{
|
||||
`{
|
||||
"baz": "qux",
|
||||
"foo": ["a", 2, "c"]
|
||||
}`,
|
||||
`[
|
||||
{ "op": "test", "path": "/baz", "value": "qux" },
|
||||
{ "op": "test", "path": "/foo/1", "value": "c" }
|
||||
]`,
|
||||
false,
|
||||
"/foo/1",
|
||||
},
|
||||
{
|
||||
`{ "baz": "qux" }`,
|
||||
`[ { "op": "test", "path": "/foo", "value": 42 } ]`,
|
||||
false,
|
||||
"/foo",
|
||||
},
|
||||
{
|
||||
`{ "baz": "qux" }`,
|
||||
`[ { "op": "test", "path": "/foo", "value": null } ]`,
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`{ "foo": null }`,
|
||||
`[ { "op": "test", "path": "/foo", "value": null } ]`,
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`{ "foo": {} }`,
|
||||
`[ { "op": "test", "path": "/foo", "value": null } ]`,
|
||||
false,
|
||||
"/foo",
|
||||
},
|
||||
{
|
||||
`{ "foo": [] }`,
|
||||
`[ { "op": "test", "path": "/foo", "value": null } ]`,
|
||||
false,
|
||||
"/foo",
|
||||
},
|
||||
{
|
||||
`{ "baz/foo": "qux" }`,
|
||||
`[ { "op": "test", "path": "/baz~1foo", "value": "qux"} ]`,
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`{ "foo": [] }`,
|
||||
`[ { "op": "test", "path": "/foo"} ]`,
|
||||
false,
|
||||
"/foo",
|
||||
},
|
||||
}
|
||||
|
||||
func TestAllTest(t *testing.T) {
|
||||
for _, c := range TestCases {
|
||||
_, err := applyPatch(c.doc, c.patch)
|
||||
|
||||
if c.result && err != nil {
|
||||
t.Errorf("Testing failed when it should have passed: %s", err)
|
||||
} else if !c.result && err == nil {
|
||||
t.Errorf("Testing passed when it should have faild: %s", err)
|
||||
} else if !c.result {
|
||||
expected := fmt.Sprintf("Testing value %s failed", c.failedPath)
|
||||
if err.Error() != expected {
|
||||
t.Errorf("Testing failed as expected but invalid message: expected [%s], got [%s]", expected, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user