From c5945d6a4cd0aa0857a6aa0caaa1f4f6131de6cf Mon Sep 17 00:00:00 2001 From: Lucas Bremgartner Date: Sat, 1 Jun 2024 13:30:35 +0200 Subject: [PATCH 1/6] Add more json patch libs --- cmd/go.mod | 18 ++++++++++++++- cmd/go.sum | 28 ++++++++++++++++++++++++ cmd/jd/main.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++--- go.work | 4 +++- go.work.sum | 10 ++++++++- 5 files changed, 113 insertions(+), 6 deletions(-) diff --git a/cmd/go.mod b/cmd/go.mod index 6aca20a..62d1e17 100644 --- a/cmd/go.mod +++ b/cmd/go.mod @@ -1,6 +1,8 @@ module github.com/breml/jsondiffprinter/cmd -go 1.21.7 +go 1.22 + +toolchain go1.22.3 require ( github.com/breml/jsondiffprinter v0.0.5 @@ -10,6 +12,20 @@ require ( ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/evanphx/json-patch v0.5.2 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/snorwin/jsonpatch v1.5.0 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect +) + +require ( + github.com/520MianXiangDuiXiang520/json-diff v0.2.2 + github.com/VictorLowther/jsonpatch2 v1.0.1 + github.com/cameront/go-jsonpatch v0.0.0-20180223123257-a8710867776e + github.com/herkyl/patchwerk v0.0.0-20190629103337-f0ea77068152 + github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38 github.com/tidwall/gjson v1.17.1 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect diff --git a/cmd/go.sum b/cmd/go.sum index b580fe7..34f9a83 100644 --- a/cmd/go.sum +++ b/cmd/go.sum @@ -1,5 +1,28 @@ +github.com/520MianXiangDuiXiang520/json-diff v0.2.2 h1:F9LvnoP8OXuOcEJDK7YKbFwGaQfZZrsstgSaEYpq3xA= +github.com/520MianXiangDuiXiang520/json-diff v0.2.2/go.mod h1:CvZu4GzZOS8w/et7AeljQUa/O2mplywH0gfc04ZOhKs= +github.com/VictorLowther/jsonpatch2 v1.0.1 h1:+r9GAjpCFyIDvv/xnqqlWURFF1FcQpYQXF9ezLZYkEI= +github.com/VictorLowther/jsonpatch2 v1.0.1/go.mod h1:MagdKGtUJ6bwyDgLk502ME/LDMKy9Rqh9iOf41iG5ds= +github.com/cameront/go-jsonpatch v0.0.0-20180223123257-a8710867776e h1:6c3+GQuYUWljNcReOg4gxMUss9Gjll+5Y9vqDM+ILy8= +github.com/cameront/go-jsonpatch v0.0.0-20180223123257-a8710867776e/go.mod h1:kdPJxKAfR3ZdD+MWYorN1oTdV9+qwJy9jO/0meJmcxU= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/herkyl/patchwerk v0.0.0-20190629103337-f0ea77068152 h1:GITUy7r2Eijl7u/Xe5AOs3HBV3Gt/3+l0j2bTh2UO5Y= +github.com/herkyl/patchwerk v0.0.0-20190629103337-f0ea77068152/go.mod h1:bRtCxY0f88xmUw+Y0Xfl/uGaCWMUy04wUGSKbnQdsJs= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38 h1:hQWBtNqRYrI7CWIaUSXXtNKR90KzcUA5uiuxFVWw7sU= +github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/qri-io/jsonpointer v0.1.1 h1:prVZBZLL6TW5vsSB9fFHFAMBLI4b0ri5vribQlTJiBA= github.com/qri-io/jsonpointer v0.1.1/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64= +github.com/snorwin/jsonpatch v1.5.0 h1:0m56YSt9cHiJOn8U+OcqdPGcDQZmhPM/zsG7Dv5QQP0= +github.com/snorwin/jsonpatch v1.5.0/go.mod h1:e0IDKlyFBLTFPqM0wa79dnMwjMs3XFvmKcrgCRpDqok= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -10,7 +33,12 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/wI2L/jsondiff v0.5.2 h1:f68drsfk/Xgvt3BpLVDlGkQzOC4o+qUCl9jtGr0sbfE= github.com/wI2L/jsondiff v0.5.2/go.mod h1:96+qu+Fhb323v//55RjkiTWYaGkiNWUqRV/w670bTAE= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cmd/jd/main.go b/cmd/jd/main.go index b0cdbb0..44f2da4 100644 --- a/cmd/jd/main.go +++ b/cmd/jd/main.go @@ -6,12 +6,23 @@ import ( "fmt" "os" - "github.com/wI2L/jsondiff" + MianXiangDuiXiang520 "github.com/520MianXiangDuiXiang520/json-diff" + victorLowther "github.com/VictorLowther/jsonpatch2" + cameront "github.com/cameront/go-jsonpatch" + herkyl "github.com/herkyl/patchwerk" + mattbaird "github.com/mattbaird/jsonpatch" + snorwin "github.com/snorwin/jsonpatch" + wI2L "github.com/wI2L/jsondiff" "github.com/breml/jsondiffprinter" ) -var format = flag.String("format", "ascii", "output format to use (ascii, terraform)") +var ( + // Call it showPatch? + debug = flag.Bool("debug", false, "enable debug output") + format = flag.String("format", "ascii", "output format to use (ascii, terraform)") + patchLib = flag.String("patchlib", "wI2L/jsondiff", "patch library to use (wI2L/jsondiff, mattbaird/jsonpatch, herkyl/patchwerk, snorwin/jsonpatch, VictorLowther/jsonpatch2, VictorLowther/jsonpatch2-paranoid, cameront/go-jsonpatch, 520MianXiangDuiXiang520/json-diff)") +) func main() { flag.Parse() @@ -49,11 +60,34 @@ func run(args []string) error { return err } - patch, err := jsondiff.Compare(before, after) + var patch any + switch *patchLib { + case "wI2L/jsondiff": + patch, err = wI2L.Compare(before, after) + case "mattbaird/jsonpatch": + patch, err = mattbaird.CreatePatch(beforeJSON, afterJSON) + case "herkyl/patchwerk": + patch, err = herkyl.Diff(beforeJSON, afterJSON) + case "snorwin/jsonpatch": + var patchList snorwin.JSONPatchList + patchList, err = snorwin.CreateJSONPatch(after, before) + patch = patchList.Raw() + case "VictorLowther/jsonpatch2": + patch, err = victorLowther.Generate(beforeJSON, afterJSON, false) + case "VictorLowther/jsonpatch2-paranoid": + patch, err = victorLowther.Generate(beforeJSON, afterJSON, true) + case "cameront/go-jsonpatch": + patch, err = cameront.MakePatch(before, after) + case "520MianXiangDuiXiang520/json-diff": + // TODO: consider options offered by 520MianXiangDuiXiang520/json-diff + patch, err = MianXiangDuiXiang520.AsDiffs(beforeJSON, afterJSON) + } if err != nil { return err } + printPatch(patch) + switch *format { case "ascii": err = jsondiffprinter.NewJSONFormatter(os.Stdout).Format(before, patch) @@ -65,3 +99,22 @@ func run(args []string) error { return err } + +func printPatch(patch any) { + if !*debug { + return + } + + switch p := patch.(type) { + case []byte: + fmt.Println(string(p)) + default: + patchJSON, err := json.MarshalIndent(patch, "", " ") + if err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + return + } + + fmt.Println(string(patchJSON)) + } +} diff --git a/go.work b/go.work index c57c3d3..058956c 100644 --- a/go.work +++ b/go.work @@ -1,4 +1,6 @@ -go 1.21.9 +go 1.22 + +toolchain go1.22.3 use ( . diff --git a/go.work.sum b/go.work.sum index 1eb0853..45e93c6 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,4 +1,12 @@ +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/go-faker/faker/v4 v4.4.1/go.mod h1:HRLrjis+tYsbFtIHufEPTAIzcZiRu0rS9EYl2Ccwme4= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= +github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= @@ -7,4 +15,4 @@ golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= -golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= From 9a8c20b4b3011f17487793e5d462429aae28880d Mon Sep 17 00:00:00 2001 From: Lucas Bremgartner Date: Sat, 1 Jun 2024 13:30:52 +0200 Subject: [PATCH 2/6] Add some testdata --- cmd/jd/testdata/{ => extended}/after.json | 0 cmd/jd/testdata/{ => extended}/before.json | 0 cmd/jd/testdata/simple_array/after.json | 7 +++++++ cmd/jd/testdata/simple_array/before.json | 7 +++++++ cmd/jd/testdata/simple_object/after.json | 8 ++++++++ cmd/jd/testdata/simple_object/before.json | 7 +++++++ 6 files changed, 29 insertions(+) rename cmd/jd/testdata/{ => extended}/after.json (100%) rename cmd/jd/testdata/{ => extended}/before.json (100%) create mode 100644 cmd/jd/testdata/simple_array/after.json create mode 100644 cmd/jd/testdata/simple_array/before.json create mode 100644 cmd/jd/testdata/simple_object/after.json create mode 100644 cmd/jd/testdata/simple_object/before.json diff --git a/cmd/jd/testdata/after.json b/cmd/jd/testdata/extended/after.json similarity index 100% rename from cmd/jd/testdata/after.json rename to cmd/jd/testdata/extended/after.json diff --git a/cmd/jd/testdata/before.json b/cmd/jd/testdata/extended/before.json similarity index 100% rename from cmd/jd/testdata/before.json rename to cmd/jd/testdata/extended/before.json diff --git a/cmd/jd/testdata/simple_array/after.json b/cmd/jd/testdata/simple_array/after.json new file mode 100644 index 0000000..db525eb --- /dev/null +++ b/cmd/jd/testdata/simple_array/after.json @@ -0,0 +1,7 @@ +{ + "append": [1, 2, 3, 4], + "insert": [1, 2, 3], + "prepend": [0, 1, 2, 3], + "remove": [1, 3], + "update": [1, 22, 3] +} diff --git a/cmd/jd/testdata/simple_array/before.json b/cmd/jd/testdata/simple_array/before.json new file mode 100644 index 0000000..1175f82 --- /dev/null +++ b/cmd/jd/testdata/simple_array/before.json @@ -0,0 +1,7 @@ +{ + "append": [1, 2, 3], + "insert": [1, 3], + "prepend": [1, 2, 3], + "remove": [1, 2, 3], + "update": [1, 2, 3] +} diff --git a/cmd/jd/testdata/simple_object/after.json b/cmd/jd/testdata/simple_object/after.json new file mode 100644 index 0000000..f47538b --- /dev/null +++ b/cmd/jd/testdata/simple_object/after.json @@ -0,0 +1,8 @@ +{ + "a": 2, + "b": { + "b1": "a", + "b2": "b1" + }, + "c": true +} diff --git a/cmd/jd/testdata/simple_object/before.json b/cmd/jd/testdata/simple_object/before.json new file mode 100644 index 0000000..4c5ac58 --- /dev/null +++ b/cmd/jd/testdata/simple_object/before.json @@ -0,0 +1,7 @@ +{ + "a": 1, + "b": { + "b1": "a", + "b2": "b" + } +} From f667d7f19265335119743ef1af05db100059a8d6 Mon Sep 17 00:00:00 2001 From: Lucas Bremgartner Date: Sat, 1 Jun 2024 14:41:26 +0200 Subject: [PATCH 3/6] Allow patchlib in test cases --- Taskfile.yml | 2 + cmd/generate_testdata/main.go | 98 +++++++++++++++++++++++-------- cmd/jd/main.go | 39 ++++++------ testdata/generated/advanced.txtar | 2 + 4 files changed, 97 insertions(+), 44 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 28ad8da..6643c63 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -4,4 +4,6 @@ tasks: generate: dir: './cmd/generate_testdata' cmds: + - rm -rf ../../testdata/generated + - mkdir -p ../../testdata/generated - go generate . diff --git a/cmd/generate_testdata/main.go b/cmd/generate_testdata/main.go index e274c43..c4b4d7e 100644 --- a/cmd/generate_testdata/main.go +++ b/cmd/generate_testdata/main.go @@ -9,9 +9,17 @@ import ( "log" "os" "path/filepath" + "strings" + + mianxiang "github.com/520MianXiangDuiXiang520/json-diff" + victorlowther "github.com/VictorLowther/jsonpatch2" + cameront "github.com/cameront/go-jsonpatch" + herkyl "github.com/herkyl/patchwerk" + mattbaird "github.com/mattbaird/jsonpatch" + snorwin "github.com/snorwin/jsonpatch" + wI2L "github.com/wI2L/jsondiff" "github.com/qri-io/jsonpointer" - "github.com/wI2L/jsondiff" "golang.org/x/tools/txtar" ) @@ -31,6 +39,7 @@ type metadata struct { } `json:"terraform,omitempty"` Metadata map[string]map[string]any `json:"metadata,omitempty"` JSONInJSON []string `json:"jsonInJSON,omitempty"` + PatchLib *string `json:"patchLib,omitempty"` } func main() { @@ -50,24 +59,22 @@ func main() { err = json.Unmarshal(txtarchive.Comment, &metadata) die(err) - var before, after interface{} - err = json.Unmarshal(txtarchive.Files[0].Data, &before) - die(err) + beforeJSON := txtarchive.Files[0].Data + afterJSON := txtarchive.Files[1].Data - err = json.Unmarshal(txtarchive.Files[1].Data, &after) + var before, after interface{} + err = json.Unmarshal(beforeJSON, &before) die(err) - patch, err := jsondiff.Compare(before, after) + err = json.Unmarshal(afterJSON, &after) die(err) - buf := bytes.Buffer{} - encoder := json.NewEncoder(&buf) - encoder.SetIndent("", " ") - encoder.SetEscapeHTML(false) - err = encoder.Encode(patch) - die(err) + patchLib := "wI2L" + if metadata.PatchLib != nil { + patchLib = *metadata.PatchLib + } - txtarchive.Files[1].Data = buf.Bytes() + txtarchive.Files[1].Data = compare(patchLib, beforeJSON, afterJSON) txtarchive.Files[1].Name = "patch.json" for i, pointer := range metadata.JSONInJSON { @@ -80,18 +87,7 @@ func main() { afterStr, err := ptr.Eval(after) die(err) - var before, after interface{} - err = json.Unmarshal([]byte(beforeStr.(string)), &before) - die(err) - - err = json.Unmarshal([]byte(afterStr.(string)), &after) - die(err) - - patch, err := jsondiff.Compare(before, after) - die(err) - - patchData, err := json.MarshalIndent(patch, "", " ") - die(err) + patchData := compare(patchLib, []byte(beforeStr.(string)), []byte(afterStr.(string))) patchFile := txtar.File{ Name: fmt.Sprintf("jsonInJSON.%d.json", i), @@ -102,6 +98,7 @@ func main() { } metadata.JSONInJSON = nil + metadata.PatchLib = nil txtarchive.Comment, err = json.MarshalIndent(metadata, "", " ") die(err) @@ -118,6 +115,57 @@ func main() { } } +func compare(patchLib string, beforeJSON, afterJSON []byte) []byte { + var before, after interface{} + err := json.Unmarshal(beforeJSON, &before) + die(err) + + err = json.Unmarshal(afterJSON, &after) + die(err) + + var marshal bool + var patch any + switch strings.ToLower(patchLib) { + case "cameront": + patch, err = cameront.MakePatch(before, after) + marshal = true + case "herkyl": + patch, err = herkyl.Diff(beforeJSON, afterJSON) + marshal = true + case "mattbaird": + patch, err = mattbaird.CreatePatch(beforeJSON, afterJSON) + marshal = true + case "mianxiang": + patch, err = mianxiang.AsDiffs(beforeJSON, afterJSON) + case "snorwin": + var patchList snorwin.JSONPatchList + patchList, err = snorwin.CreateJSONPatch(after, before) + patch = patchList.Raw() + case "victorlowther": + patch, err = victorlowther.Generate(beforeJSON, afterJSON, false) + marshal = true + case "victorlowther-paranoid": + patch, err = victorlowther.Generate(beforeJSON, afterJSON, true) + marshal = true + default: // "wI2L" + patch, err = wI2L.Compare(before, after) + marshal = true + } + die(err) + + if marshal { + buf := bytes.Buffer{} + encoder := json.NewEncoder(&buf) + encoder.SetIndent("", " ") + encoder.SetEscapeHTML(false) + err = encoder.Encode(patch) + die(err) + patch = buf.Bytes() + } + + return patch.([]byte) +} + func die(err error) { if err != nil { log.Panic(err) diff --git a/cmd/jd/main.go b/cmd/jd/main.go index 44f2da4..73aae13 100644 --- a/cmd/jd/main.go +++ b/cmd/jd/main.go @@ -5,9 +5,10 @@ import ( "flag" "fmt" "os" + "strings" - MianXiangDuiXiang520 "github.com/520MianXiangDuiXiang520/json-diff" - victorLowther "github.com/VictorLowther/jsonpatch2" + mianxiang "github.com/520MianXiangDuiXiang520/json-diff" + victorlowther "github.com/VictorLowther/jsonpatch2" cameront "github.com/cameront/go-jsonpatch" herkyl "github.com/herkyl/patchwerk" mattbaird "github.com/mattbaird/jsonpatch" @@ -21,7 +22,7 @@ var ( // Call it showPatch? debug = flag.Bool("debug", false, "enable debug output") format = flag.String("format", "ascii", "output format to use (ascii, terraform)") - patchLib = flag.String("patchlib", "wI2L/jsondiff", "patch library to use (wI2L/jsondiff, mattbaird/jsonpatch, herkyl/patchwerk, snorwin/jsonpatch, VictorLowther/jsonpatch2, VictorLowther/jsonpatch2-paranoid, cameront/go-jsonpatch, 520MianXiangDuiXiang520/json-diff)") + patchLib = flag.String("patchlib", "wI2L", "patch library to use (cameront, herkyl, mattbaird, MianXiang, snorwin, VictorLowther, VictorLowther-paranoid, wI2L)") ) func main() { @@ -61,26 +62,26 @@ func run(args []string) error { } var patch any - switch *patchLib { - case "wI2L/jsondiff": - patch, err = wI2L.Compare(before, after) - case "mattbaird/jsonpatch": - patch, err = mattbaird.CreatePatch(beforeJSON, afterJSON) - case "herkyl/patchwerk": + switch strings.ToLower(*patchLib) { + case "cameront": + patch, err = cameront.MakePatch(before, after) + case "herkyl": patch, err = herkyl.Diff(beforeJSON, afterJSON) - case "snorwin/jsonpatch": + case "mattbaird": + patch, err = mattbaird.CreatePatch(beforeJSON, afterJSON) + case "mianxiang": + // TODO: consider options offered by 520MianXiangDuiXiang520/json-diff + patch, err = mianxiang.AsDiffs(beforeJSON, afterJSON) + case "snorwin": var patchList snorwin.JSONPatchList patchList, err = snorwin.CreateJSONPatch(after, before) patch = patchList.Raw() - case "VictorLowther/jsonpatch2": - patch, err = victorLowther.Generate(beforeJSON, afterJSON, false) - case "VictorLowther/jsonpatch2-paranoid": - patch, err = victorLowther.Generate(beforeJSON, afterJSON, true) - case "cameront/go-jsonpatch": - patch, err = cameront.MakePatch(before, after) - case "520MianXiangDuiXiang520/json-diff": - // TODO: consider options offered by 520MianXiangDuiXiang520/json-diff - patch, err = MianXiangDuiXiang520.AsDiffs(beforeJSON, afterJSON) + case "victorlowther": + patch, err = victorlowther.Generate(beforeJSON, afterJSON, false) + case "victorlowther-paranoid": + patch, err = victorlowther.Generate(beforeJSON, afterJSON, true) + default: // "wI2L" + patch, err = wI2L.Compare(before, after) } if err != nil { return err diff --git a/testdata/generated/advanced.txtar b/testdata/generated/advanced.txtar index da59cf2..fa7ed36 100644 --- a/testdata/generated/advanced.txtar +++ b/testdata/generated/advanced.txtar @@ -96,6 +96,7 @@ "path": "/-" } ] + -- jsonInJSON.1.json -- [ { @@ -180,3 +181,4 @@ "path": "/string_removed" } ] + From 1f1e6083dd5e243788d4f1105a79fc0961292ed9 Mon Sep 17 00:00:00 2001 From: Lucas Bremgartner Date: Sat, 1 Jun 2024 17:56:38 +0200 Subject: [PATCH 4/6] Add more test cases, fix arrays with LCS --- cmd/generate_testdata/main.go | 8 +- cmd/jd/testdata/type_change/after.json | 5 + cmd/jd/testdata/type_change/before.json | 5 + formatter.go | 29 +++- formatter_internal_test.go | 133 +++++++++++++++++- formatter_test.go | 6 +- internal/jsonpointer/jsonpointer.go | 11 ++ internal/require/require.go | 38 ++++- testdata/array.txtar | 63 +++++++++ testdata/array_mianxiang.txtar | 60 ++++++++ testdata/base_example_mianxiang.txtar | 96 +++++++++++++ testdata/generated/array.txtar | 127 +++++++++++++++++ testdata/generated/array_mianxiang.txtar | 51 +++++++ .../generated/base_example_mianxiang.txtar | 63 +++++++++ 14 files changed, 685 insertions(+), 10 deletions(-) create mode 100644 cmd/jd/testdata/type_change/after.json create mode 100644 cmd/jd/testdata/type_change/before.json create mode 100644 testdata/array.txtar create mode 100644 testdata/array_mianxiang.txtar create mode 100644 testdata/base_example_mianxiang.txtar create mode 100644 testdata/generated/array.txtar create mode 100644 testdata/generated/array_mianxiang.txtar create mode 100644 testdata/generated/base_example_mianxiang.txtar diff --git a/cmd/generate_testdata/main.go b/cmd/generate_testdata/main.go index c4b4d7e..373cefc 100644 --- a/cmd/generate_testdata/main.go +++ b/cmd/generate_testdata/main.go @@ -153,6 +153,7 @@ func compare(patchLib string, beforeJSON, afterJSON []byte) []byte { } die(err) + var patchData []byte if marshal { buf := bytes.Buffer{} encoder := json.NewEncoder(&buf) @@ -160,10 +161,13 @@ func compare(patchLib string, beforeJSON, afterJSON []byte) []byte { encoder.SetEscapeHTML(false) err = encoder.Encode(patch) die(err) - patch = buf.Bytes() + patchData = buf.Bytes() + } else { + patchData = patch.([]byte) + patchData = append(patchData, '\n') } - return patch.([]byte) + return patchData } func die(err error) { diff --git a/cmd/jd/testdata/type_change/after.json b/cmd/jd/testdata/type_change/after.json new file mode 100644 index 0000000..ebf70f0 --- /dev/null +++ b/cmd/jd/testdata/type_change/after.json @@ -0,0 +1,5 @@ +{ + "object_to_array": [ + 1 + ] +} diff --git a/cmd/jd/testdata/type_change/before.json b/cmd/jd/testdata/type_change/before.json new file mode 100644 index 0000000..f9d7ddb --- /dev/null +++ b/cmd/jd/testdata/type_change/before.json @@ -0,0 +1,5 @@ +{ + "object_to_array": { + "a": 1 + } +} diff --git a/formatter.go b/formatter.go index 817db18..520cf7c 100644 --- a/formatter.go +++ b/formatter.go @@ -618,7 +618,8 @@ func asPatchTestSeries(value any, path jsonpointer.Pointer) jsonpatch.Patch { func compileDiffPatchSeries(src jsonpatch.Patch, patch jsonpatch.Patch) (jsonpatch.Patch, error) { deletePath := jsonpointer.Pointer{} res := make(jsonpatch.Patch, 0, len(src)+len(patch)) - for _, op := range src { + for opIndex := 0; opIndex < len(src); opIndex++ { + op := src[opIndex] if !deletePath.IsEmpty() && deletePath.IsParentOf(op.Path) { continue } @@ -685,6 +686,20 @@ func compileDiffPatchSeries(src jsonpatch.Patch, patch jsonpatch.Patch) (jsonpat } res = append(res, patchop) + + if patchop.Operation == jsonpatch.OperationAdd { + res = append(res, op) + } + + if patchop.Operation == jsonpatch.OperationRemove && parentIsArray(src, patchop.Path) { + for j := opIndex + 1; j < len(src); j++ { + if src[j].Path.HasSameAncestorsAs(patchop.Path) { + src[j].Path.DecrementIndex() + continue + } + break + } + } } for i := 0; i < len(patch); i++ { @@ -704,13 +719,23 @@ func compileDiffPatchSeries(src jsonpatch.Patch, patch jsonpatch.Patch) (jsonpat return nil, fmt.Errorf("patch is not empty after it has been applied") } - sort.Slice(res, func(i, j int) bool { + sort.SliceStable(res, func(i, j int) bool { return res[i].Path.LessThan(res[j].Path) }) return res, nil } +func parentIsArray(patch jsonpatch.Patch, path jsonpointer.Pointer) bool { + for i := range patch { + if patch[i].Path.IsParentOf(path) { + _, ok := patch[i].Value.([]any) + return ok + } + } + return false +} + func findPatchIndex(patch jsonpatch.Patch, path jsonpointer.Pointer) (int, bool) { for i := range patch { if patch[i].Path.Equals(path) { diff --git a/formatter_internal_test.go b/formatter_internal_test.go index 9d45916..e561159 100644 --- a/formatter_internal_test.go +++ b/formatter_internal_test.go @@ -9,9 +9,10 @@ import ( ) func Test_compileDiffPatchSeries(t *testing.T) { - tt := []struct { + tests := []struct { name string + src jsonpatch.Patch patch jsonpatch.Patch assertErr require.ErrorAssertionFunc @@ -62,12 +63,138 @@ func Test_compileDiffPatchSeries(t *testing.T) { assertErr: require.Error, }, + + { + name: "array append with index", + + src: jsonpatch.Patch{ + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointer(), Value: map[string]any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array"), Value: []any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/0"), Value: 0}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 1}, + }, + patch: jsonpatch.Patch{ + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/2"), Value: 2}, + }, + + assertErr: require.NoError, + want: jsonpatch.Patch{ + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointer(), Value: map[string]any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array"), Value: []any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/0"), Value: 0}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 1}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/2"), Value: 2}, + }, + }, + { + name: "array insert", + + src: jsonpatch.Patch{ + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointer(), Value: map[string]any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array"), Value: []any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/0"), Value: 0}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 2}, + }, + patch: jsonpatch.Patch{ + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 1}, + }, + + assertErr: require.NoError, + want: jsonpatch.Patch{ + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointer(), Value: map[string]any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array"), Value: []any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/0"), Value: 0}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 1}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 2}, + }, + }, + { + name: "array insert without LCS", + + src: jsonpatch.Patch{ + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointer(), Value: map[string]any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array"), Value: []any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/0"), Value: 0}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 2}, + }, + patch: jsonpatch.Patch{ + {Operation: jsonpatch.OperationReplace, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 1}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/-"), Value: 2}, + }, + + assertErr: require.NoError, + want: jsonpatch.Patch{ + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointer(), Value: map[string]any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array"), Value: []any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/0"), Value: 0}, + {Operation: jsonpatch.OperationReplace, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 1, OldValue: 2}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/-"), Value: 2}, + }, + }, + { + name: "array multi change", + + src: jsonpatch.Patch{ + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointer(), Value: map[string]any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array"), Value: []any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/0"), Value: 5}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 6}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/2"), Value: 7}, + }, + patch: jsonpatch.Patch{ + {Operation: jsonpatch.OperationRemove, Path: jsonpointer.NewPointerFromPath("/array/1")}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/2"), Value: 8}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/3"), Value: 9}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/4"), Value: 10}, + }, + + assertErr: require.NoError, + want: jsonpatch.Patch{ + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointer(), Value: map[string]any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array"), Value: []any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/0"), Value: 5}, + {Operation: jsonpatch.OperationRemove, Path: jsonpointer.NewPointerFromPath("/array/1"), OldValue: 6}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 7}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/2"), Value: 8}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/3"), Value: 9}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/4"), Value: 10}, + }, + }, + { + name: "array multi change without LCS", + + src: jsonpatch.Patch{ + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointer(), Value: map[string]any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array"), Value: []any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/0"), Value: 5}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 6}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/2"), Value: 7}, + }, + patch: jsonpatch.Patch{ + {Operation: jsonpatch.OperationReplace, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 7}, + {Operation: jsonpatch.OperationReplace, Path: jsonpointer.NewPointerFromPath("/array/2"), Value: 8}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/-"), Value: 9}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/-"), Value: 10}, + }, + + assertErr: require.NoError, + want: jsonpatch.Patch{ + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointer(), Value: map[string]any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array"), Value: []any{}}, + {Operation: jsonpatch.OperationTest, Path: jsonpointer.NewPointerFromPath("/array/0"), Value: 5}, + {Operation: jsonpatch.OperationReplace, Path: jsonpointer.NewPointerFromPath("/array/1"), Value: 7, OldValue: 6}, + {Operation: jsonpatch.OperationReplace, Path: jsonpointer.NewPointerFromPath("/array/2"), Value: 8, OldValue: 7}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/-"), Value: 9}, + {Operation: jsonpatch.OperationAdd, Path: jsonpointer.NewPointerFromPath("/array/-"), Value: 10}, + }, + }, } - for _, tc := range tt { + for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - got, err := compileDiffPatchSeries(nil, tc.patch) + got, err := compileDiffPatchSeries(tc.src, tc.patch) tc.assertErr(t, err) + // require.EqualStringWithTabwriter(t, fmt.Sprintf("%#v", tc.want), fmt.Sprintf("%#v", got)) require.Equal(t, tc.want, got) }) } diff --git a/formatter_test.go b/formatter_test.go index 3a67293..aaea478 100644 --- a/formatter_test.go +++ b/formatter_test.go @@ -122,13 +122,16 @@ func TestFormatter(t *testing.T) { for _, formatter := range formatters { formatter := formatter t.Run(formatter.name, func(t *testing.T) { + if txtarFileByName(t, txtar, formatter.wantFilename) == nil { + t.Skip("no want file found") + } jsonInJSONInvocation = 0 buf.Reset() err := formatter.formatter.Format(before, txtarFileByName(t, txtar, "patch.json").Data) require.NoError(t, err) - require.Equal(t, string(txtarFileByName(t, txtar, formatter.wantFilename).Data), buf.String()) + require.EqualStringWithTabwriter(t, string(txtarFileByName(t, txtar, formatter.wantFilename).Data), buf.String()) }) } }) @@ -144,7 +147,6 @@ func txtarFileByName(t *testing.T, txtar *txtar.Archive, name string) *txtar.Fil } } - t.Fatalf("file %q not found", name) return nil } diff --git a/internal/jsonpointer/jsonpointer.go b/internal/jsonpointer/jsonpointer.go index f2ba8ec..049979e 100644 --- a/internal/jsonpointer/jsonpointer.go +++ b/internal/jsonpointer/jsonpointer.go @@ -48,6 +48,17 @@ func (p Pointer) AppendIndex(i int) Pointer { return pp } +func (p *Pointer) DecrementIndex() { + if len(*p) == 0 { + return + } + i, err := strconv.ParseInt((*p)[len(*p)-1], 10, 64) + if err != nil { + return + } + (*p)[len(*p)-1] = strconv.Itoa(int(i - 1)) +} + func (p Pointer) LessThan(alt Pointer) (b bool) { if p.HasSameAncestorsAs(alt) && (p[len(p)-1] == "-" || alt[len(alt)-1] == "-") { return p[len(p)-1] != "-" diff --git a/internal/require/require.go b/internal/require/require.go index fc410ca..0a54989 100644 --- a/internal/require/require.go +++ b/internal/require/require.go @@ -1,8 +1,12 @@ package require import ( + "bytes" + "fmt" "reflect" + "strings" "testing" + "text/tabwriter" ) type ErrorAssertionFunc func(t *testing.T, err error) @@ -24,6 +28,38 @@ func Error(t *testing.T, err error) { func Equal(t *testing.T, want, got any) { t.Helper() if !reflect.DeepEqual(want, got) { - t.Fatalf("unexpected value: want:\n%v, got:\n%v", want, got) + t.Fatalf("unexpected value: want:\n%v, got:\n%v\n%s", want, got, withTabwriter(fmt.Sprintf("%#v", want), fmt.Sprintf("%#v", got))) } } + +func EqualStringWithTabwriter(t *testing.T, want, got string) { + t.Helper() + if want == got { + return + } + + t.Fatal(withTabwriter(want, got)) +} + +func withTabwriter(want, got string) string { + buf := bytes.NewBufferString("\n") + w := tabwriter.NewWriter(buf, 0, 0, 3, ' ', 0) + fmt.Fprintln(w, "want:\tgot:\n=====\t====\n\t") + + wantLines := strings.Split(want, "\n") + gotLines := strings.Split(got, "\n") + + minLens := min(len(wantLines), len(gotLines)) + for i := 0; i < minLens; i++ { + fmt.Fprintf(w, "%s\t%s\n", wantLines[i], gotLines[i]) + } + for i := minLens; i < len(wantLines); i++ { + fmt.Fprintf(w, "%s\n", wantLines[i]) + } + for i := minLens; i < len(gotLines); i++ { + fmt.Fprintf(w, "\t%s\n", gotLines[i]) + } + w.Flush() + + return buf.String() +} diff --git a/testdata/array.txtar b/testdata/array.txtar new file mode 100644 index 0000000..c4bf2f5 --- /dev/null +++ b/testdata/array.txtar @@ -0,0 +1,63 @@ +-- before.json -- +{ + "append": [1, 2, 3], + "insert": [1, 3], + "multi_change": [5, 6, 7], + "prepend": [1, 2, 3], + "remove": [1, 2, 3], + "update": [1, 2, 3] +} +-- after.json -- +{ + "append": [1, 2, 3, 4], + "insert": [1, 2, 3], + "multi_change": [5, 7, 8, 9, 10], + "prepend": [0, 1, 2, 3], + "remove": [1, 3], + "update": [1, 22, 3] +} +-- diff.json -- + { + "append": [ + 1, + 2, + 3, ++ 4 + ], + "insert": [ + 1, +- 3, ++ 2, ++ 3 + ], + "multi_change": [ + 5, +- 6, ++ 7, +- 7, ++ 8, ++ 9, ++ 10 + ], + "prepend": [ +- 1, ++ 0, +- 2, ++ 1, +- 3, ++ 2, ++ 3 + ], + "remove": [ + 1, +- 2, ++ 3, +- 3 + ], + "update": [ + 1, +- 2, ++ 22, + 3 + ] + } diff --git a/testdata/array_mianxiang.txtar b/testdata/array_mianxiang.txtar new file mode 100644 index 0000000..d26b335 --- /dev/null +++ b/testdata/array_mianxiang.txtar @@ -0,0 +1,60 @@ +{ + "patchLib": "mianxiang" +} +-- before.json -- +{ + "append": [1, 2, 3], + "insert": [1, 3], + "multi_change": [5, 6, 7], + "prepend": [1, 2, 3], + "remove": [1, 2, 3], + "update": [1, 2, 3] +} +-- after.json -- +{ + "append": [1, 2, 3, 4], + "insert": [1, 2, 3], + "multi_change": [5, 7, 8, 9, 10], + "prepend": [0, 1, 2, 3], + "remove": [1, 3], + "update": [1, 22, 3] +} +-- diff.json -- + { + "append": [ + 1, + 2, + 3, ++ 4 + ], + "insert": [ + 1, ++ 2, + 3 + ], + "multi_change": [ + 5, +- 6, + 7, ++ 8, ++ 9, ++ 10 + ], + "prepend": [ ++ 0, + 1, + 2, + 3 + ], + "remove": [ + 1, +- 2, + 3 + ], + "update": [ + 1, +- 2, ++ 22, + 3 + ] + } diff --git a/testdata/base_example_mianxiang.txtar b/testdata/base_example_mianxiang.txtar new file mode 100644 index 0000000..f46f44c --- /dev/null +++ b/testdata/base_example_mianxiang.txtar @@ -0,0 +1,96 @@ +{ + "patchLib": "mianxiang" +} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- after.json -- +{ + "a": 1, + "a1": { + "1": [ + 1, + 2, + 3, + true + ] + }, + "g": 14, + "h": [ + 1, + 2, + 3 + ], + "b": { + "c": 3 + }, + "d": 4, + "f": [ + 5, + 7, + 8, + 9, + 10 + ], + "j": [ + true, + false + ] +} +-- diff.json -- + { + "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, + "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 ++ "c": 3 + }, + "d": 4, +- "e": null, + "f": [ + 5, +- 6, + 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], +- "j": { +- "a": 1 + } ++ "j": [ ++ true, ++ false + ] + } diff --git a/testdata/generated/array.txtar b/testdata/generated/array.txtar new file mode 100644 index 0000000..b801b63 --- /dev/null +++ b/testdata/generated/array.txtar @@ -0,0 +1,127 @@ +{} +-- before.json -- +{ + "append": [1, 2, 3], + "insert": [1, 3], + "multi_change": [5, 6, 7], + "prepend": [1, 2, 3], + "remove": [1, 2, 3], + "update": [1, 2, 3] +} +-- patch.json -- +[ + { + "value": 4, + "op": "add", + "path": "/append/-" + }, + { + "value": 2, + "op": "replace", + "path": "/insert/1" + }, + { + "value": 3, + "op": "add", + "path": "/insert/-" + }, + { + "value": 7, + "op": "replace", + "path": "/multi_change/1" + }, + { + "value": 8, + "op": "replace", + "path": "/multi_change/2" + }, + { + "value": 9, + "op": "add", + "path": "/multi_change/-" + }, + { + "value": 10, + "op": "add", + "path": "/multi_change/-" + }, + { + "value": 0, + "op": "replace", + "path": "/prepend/0" + }, + { + "value": 1, + "op": "replace", + "path": "/prepend/1" + }, + { + "value": 2, + "op": "replace", + "path": "/prepend/2" + }, + { + "value": 3, + "op": "add", + "path": "/prepend/-" + }, + { + "op": "remove", + "path": "/remove/2" + }, + { + "value": 3, + "op": "replace", + "path": "/remove/1" + }, + { + "value": 22, + "op": "replace", + "path": "/update/1" + } +] +-- diff.json -- + { + "append": [ + 1, + 2, + 3, ++ 4 + ], + "insert": [ + 1, +- 3, ++ 2, ++ 3 + ], + "multi_change": [ + 5, +- 6, ++ 7, +- 7, ++ 8, ++ 9, ++ 10 + ], + "prepend": [ +- 1, ++ 0, +- 2, ++ 1, +- 3, ++ 2, ++ 3 + ], + "remove": [ + 1, +- 2, ++ 3, +- 3 + ], + "update": [ + 1, +- 2, ++ 22, + 3 + ] + } diff --git a/testdata/generated/array_mianxiang.txtar b/testdata/generated/array_mianxiang.txtar new file mode 100644 index 0000000..92c12e9 --- /dev/null +++ b/testdata/generated/array_mianxiang.txtar @@ -0,0 +1,51 @@ +{} +-- before.json -- +{ + "append": [1, 2, 3], + "insert": [1, 3], + "multi_change": [5, 6, 7], + "prepend": [1, 2, 3], + "remove": [1, 2, 3], + "update": [1, 2, 3] +} +-- patch.json -- +[{"op":"replace","path":"/update/1","value":22},{"op":"add","path":"/append/3","value":4},{"op":"add","path":"/insert/1","value":2},{"op":"remove","path":"/multi_change/1"},{"op":"add","path":"/multi_change/2","value":8},{"op":"add","path":"/multi_change/3","value":9},{"op":"add","path":"/multi_change/4","value":10},{"op":"add","path":"/prepend/0","value":0},{"op":"remove","path":"/remove/1"}] +-- diff.json -- + { + "append": [ + 1, + 2, + 3, ++ 4 + ], + "insert": [ + 1, ++ 2, + 3 + ], + "multi_change": [ + 5, +- 6, + 7, ++ 8, ++ 9, ++ 10 + ], + "prepend": [ ++ 0, + 1, + 2, + 3 + ], + "remove": [ + 1, +- 2, + 3 + ], + "update": [ + 1, +- 2, ++ 22, + 3 + ] + } diff --git a/testdata/generated/base_example_mianxiang.txtar b/testdata/generated/base_example_mianxiang.txtar new file mode 100644 index 0000000..1716d58 --- /dev/null +++ b/testdata/generated/base_example_mianxiang.txtar @@ -0,0 +1,63 @@ +{} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- patch.json -- +[{"op":"remove","path":"/f/1"},{"op":"add","path":"/f/2","value":8},{"op":"add","path":"/f/3","value":9},{"op":"add","path":"/f/4","value":10},{"op":"replace","path":"/j","value":[true,false]},{"op":"replace","path":"/b/c","value":3},{"op":"remove","path":"/b/b1"},{"op":"remove","path":"/b/b2"},{"op":"remove","path":"/e"},{"op":"add","path":"/a1","value":{"1":[1,2,3,true]}},{"op":"add","path":"/g","value":14},{"op":"add","path":"/h","value":[1,2,3]}] +-- diff.json -- + { + "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, + "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 ++ "c": 3 + }, + "d": 4, +- "e": null, + "f": [ + 5, +- 6, + 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], +- "j": { +- "a": 1 + } ++ "j": [ ++ true, ++ false + ] + } From 38163fbf36172ef9910f8e27f6c4c2b65d29b6f5 Mon Sep 17 00:00:00 2001 From: Lucas Bremgartner Date: Sat, 1 Jun 2024 19:04:21 +0200 Subject: [PATCH 5/6] Add more test cases fix handling of test operations, handling of root level replace --- cmd/generate_testdata/main.go | 6 +- formatter.go | 11 +- testdata/advanced_mianxiang.txtar | 84 +++++++ testdata/base_example_cameront.txtar.off | 134 +++++++++++ testdata/base_example_herkyl.txtar | 156 ++++++++++++ testdata/base_example_mattbaird.txtar | 134 +++++++++++ testdata/base_example_mianxiang.txtar | 38 +++ testdata/base_example_snorwin.txtar.off | 134 +++++++++++ .../base_example_victorlowther-paranoid.txtar | 141 +++++++++++ testdata/base_example_victorlowther.txtar | 141 +++++++++++ testdata/generated/advanced_mianxiang.txtar | 80 +++++++ testdata/generated/array_mianxiang.txtar | 2 +- testdata/generated/base_example_herkyl.txtar | 160 +++++++++++++ .../generated/base_example_mattbaird.txtar | 172 +++++++++++++ .../generated/base_example_mianxiang.txtar | 40 +++- .../base_example_victorlowther-paranoid.txtar | 225 ++++++++++++++++++ .../base_example_victorlowther.txtar | 183 ++++++++++++++ testdata/generated/null_2_string.txtar | 2 +- testdata/generated/string_2_null.txtar | 2 +- testdata/generated/string_2_string.txtar | 2 +- testdata/null_2_string.txtar | 2 +- testdata/string_2_null.txtar | 2 +- testdata/string_2_string.txtar | 2 +- 23 files changed, 1840 insertions(+), 13 deletions(-) create mode 100644 testdata/advanced_mianxiang.txtar create mode 100644 testdata/base_example_cameront.txtar.off create mode 100644 testdata/base_example_herkyl.txtar create mode 100644 testdata/base_example_mattbaird.txtar create mode 100644 testdata/base_example_snorwin.txtar.off create mode 100644 testdata/base_example_victorlowther-paranoid.txtar create mode 100644 testdata/base_example_victorlowther.txtar create mode 100644 testdata/generated/advanced_mianxiang.txtar create mode 100644 testdata/generated/base_example_herkyl.txtar create mode 100644 testdata/generated/base_example_mattbaird.txtar create mode 100644 testdata/generated/base_example_victorlowther-paranoid.txtar create mode 100644 testdata/generated/base_example_victorlowther.txtar diff --git a/cmd/generate_testdata/main.go b/cmd/generate_testdata/main.go index 373cefc..8413ace 100644 --- a/cmd/generate_testdata/main.go +++ b/cmd/generate_testdata/main.go @@ -147,7 +147,11 @@ func compare(patchLib string, beforeJSON, afterJSON []byte) []byte { case "victorlowther-paranoid": patch, err = victorlowther.Generate(beforeJSON, afterJSON, true) marshal = true - default: // "wI2L" + case "wi2l": + patch, err = wI2L.Compare(before, after) + marshal = true + default: + fmt.Fprintf(os.Stderr, `Unknown patch lib %q, default to "wI2L"`, patchLib) patch, err = wI2L.Compare(before, after) marshal = true } diff --git a/formatter.go b/formatter.go index 520cf7c..1854d2e 100644 --- a/formatter.go +++ b/formatter.go @@ -366,6 +366,8 @@ func (f Formatter) printOp(cfg printOpConfig) { if cfg.withKey { fmt.Fprintf(f.w, "%s%s %s%s%s", cfg.preDiffMarkerIndent, opTypeIndicator, cfg.indent, cfg.key, eol) + } else { + fmt.Fprint(f.w, " ") } if cfg.valueOld != "" { fmt.Fprintf(f.w, "%s %s ", cfg.valueOld, f.c.yellow(f.singleLineReplaceTransitionIndicator)) @@ -616,14 +618,14 @@ func asPatchTestSeries(value any, path jsonpointer.Pointer) jsonpatch.Patch { } func compileDiffPatchSeries(src jsonpatch.Patch, patch jsonpatch.Patch) (jsonpatch.Patch, error) { - deletePath := jsonpointer.Pointer{} + var deletePath *jsonpointer.Pointer res := make(jsonpatch.Patch, 0, len(src)+len(patch)) for opIndex := 0; opIndex < len(src); opIndex++ { op := src[opIndex] - if !deletePath.IsEmpty() && deletePath.IsParentOf(op.Path) { + if deletePath != nil && deletePath.IsParentOf(op.Path) { continue } - deletePath = jsonpointer.Pointer{} + deletePath = nil // Search patch for operation with the same path. // If none is found, keep the operation from the source document. @@ -676,13 +678,14 @@ func compileDiffPatchSeries(src jsonpatch.Patch, patch jsonpatch.Patch) (jsonpat switch patchop.Operation { case jsonpatch.OperationTest: // If the patch operation is a test operation, skip it. + opIndex-- continue case jsonpatch.OperationReplace, jsonpatch.OperationRemove: // If the patch operation is a replace or delete operation, preserve the // old value and we mark all child operations for removal. patchop.OldValue = op.Value - deletePath = op.Path + deletePath = &op.Path } res = append(res, patchop) diff --git a/testdata/advanced_mianxiang.txtar b/testdata/advanced_mianxiang.txtar new file mode 100644 index 0000000..23ab833 --- /dev/null +++ b/testdata/advanced_mianxiang.txtar @@ -0,0 +1,84 @@ +{ + "jsonInJSON": [ + "/array", + "/object" + ], + "patchLib": "mianxiang" +} +-- before.json -- +{ + "array": "[\"foo\",\"bar\"]", + "object": "{\"array_changed\":[\"foo\",\"bar\",\"baz\"],\"array_item_added\":[\"foo\",\"bar\",\"baz\"],\"array_item_removed\":[\"foo\",\"bar\",\"baz\"],\"array_removed\":[\"foo\",\"bar\",\"baz\"],\"array_unchanged\":[\"foo\",\"bar\",\"baz\"],\"number_changed\":10,\"number_removed\":10,\"number_unchanged\":10,\"object_changed\":{\"key\":\"value\"},\"object_removed\":{\"key\":\"value\"},\"object_unchanged\":{\"key\":\"value\"},\"string_changed\":\"bar\",\"string_removed\":\"removed\",\"string_unchanged\":\"foo\"}", + "key": "value" +} +-- after.json -- +{ + "array": "[\"new foo\",\"bar\",\"baz\"]", + "object": "{\"array_changed\":[\"foo2\",\"bar\",\"baz2\"],\"array_item_added\":[\"foo\",\"bar\",\"baz\",\"biz\"],\"array_item_removed\":[\"foo\",\"baz\"],\"array_new\":[\"foo\",\"bar\",\"baz\"],\"array_unchanged\":[\"foo\",\"bar\",\"baz\"],\"number_changed\":14,\"number_new\":14,\"number_unchanged\":10,\"object_changed\":{\"key\":\"new value\"},\"object_new\":{\"key\":\"value\"},\"object_unchanged\":{\"key\":\"value\"},\"string_changed\":\"bar changed\",\"string_new\":\"new\",\"string_unchanged\":\"foo\"}", + "key": "value" +} +-- diff.json -- + { +- "array": "[\"foo\",\"bar\"]", ++ "array": "[\"new foo\",\"bar\",\"baz\"]", + "key": "value", +- "object": "{\"array_changed\":[\"foo\",\"bar\",\"baz\"],\"array_item_added\":[\"foo\",\"bar\",\"baz\"],\"array_item_removed\":[\"foo\",\"bar\",\"baz\"],\"array_removed\":[\"foo\",\"bar\",\"baz\"],\"array_unchanged\":[\"foo\",\"bar\",\"baz\"],\"number_changed\":10,\"number_removed\":10,\"number_unchanged\":10,\"object_changed\":{\"key\":\"value\"},\"object_removed\":{\"key\":\"value\"},\"object_unchanged\":{\"key\":\"value\"},\"string_changed\":\"bar\",\"string_removed\":\"removed\",\"string_unchanged\":\"foo\"}" ++ "object": "{\"array_changed\":[\"foo2\",\"bar\",\"baz2\"],\"array_item_added\":[\"foo\",\"bar\",\"baz\",\"biz\"],\"array_item_removed\":[\"foo\",\"baz\"],\"array_new\":[\"foo\",\"bar\",\"baz\"],\"array_unchanged\":[\"foo\",\"bar\",\"baz\"],\"number_changed\":14,\"number_new\":14,\"number_unchanged\":10,\"object_changed\":{\"key\":\"new value\"},\"object_new\":{\"key\":\"value\"},\"object_unchanged\":{\"key\":\"value\"},\"string_changed\":\"bar changed\",\"string_new\":\"new\",\"string_unchanged\":\"foo\"}" + } +-- diff.tf -- + { + ~ array = jsonencode( + [ + ~ "foo" -> "new foo" + "bar" + + "baz" + ] + ) + ~ object = jsonencode( + { + array_changed = [ + ~ "foo" -> "foo2" + "bar" + ~ "baz" -> "baz2" + ] + array_item_added = [ + "foo" + "bar" + "baz" + + "biz" + ] + array_item_removed = [ + "foo" + - "bar" + "baz" + ] + + array_new = [ + + "foo" + + "bar" + + "baz" + ] + - array_removed = [ + - "foo" + - "bar" + - "baz" + ] + ~ number_changed = 10 -> 14 + + number_new = 14 + - number_removed = 10 + object_changed = { + ~ key = "value" -> "new value" + } + + object_new = { + + key = "value" + } + - object_removed = { + - key = "value" + } + ~ string_changed = "bar" -> "bar changed" + + string_new = "new" + - string_removed = "removed" + # (4 unchanged attribute hidden) + } + ) + # (1 unchanged attribute hidden) + } diff --git a/testdata/base_example_cameront.txtar.off b/testdata/base_example_cameront.txtar.off new file mode 100644 index 0000000..f28cda3 --- /dev/null +++ b/testdata/base_example_cameront.txtar.off @@ -0,0 +1,134 @@ +{ + "patchLib": "cameront" +} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- after.json -- +{ + "a": 1, + "a1": { + "1": [ + 1, + 2, + 3, + true + ] + }, + "g": 14, + "h": [ + 1, + 2, + 3 + ], + "b": { + "c": 3 + }, + "d": 4, + "f": [ + 5, + 7, + 8, + 9, + 10 + ], + "j": [ + true, + false + ] +} +-- diff.json -- + { + "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, + "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 ++ "c": 3 + }, + "d": 4, +- "e": null, + "f": [ + 5, +- 6, + 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], +- "j": { +- "a": 1 + } ++ "j": [ ++ true, ++ false + ] + } +-- diff.tf -- + { + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + b = { + - b1 = "a" + - b2 = "b" + ~ c = 2 -> 3 + } + - e = null + f = [ + 5 + - 6 + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + ~ j = { + - a = 1 + } -> [ + + true + + false + ] + # (2 unchanged attribute hidden) + } diff --git a/testdata/base_example_herkyl.txtar b/testdata/base_example_herkyl.txtar new file mode 100644 index 0000000..d554448 --- /dev/null +++ b/testdata/base_example_herkyl.txtar @@ -0,0 +1,156 @@ +{ + "patchLib": "herkyl" +} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- after.json -- +{ + "a": 1, + "a1": { + "1": [ + 1, + 2, + 3, + true + ] + }, + "g": 14, + "h": [ + 1, + 2, + 3 + ], + "b": { + "c": 3 + }, + "d": 4, + "f": [ + 5, + 7, + 8, + 9, + 10 + ], + "j": [ + true, + false + ] +} +-- diff.json -- +- { +- "a": 1, +- "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 + }, +- "d": 4, +- "e": null, +- "f": [ +- 5, +- 6, +- 7 + ], +- "j": { +- "a": 1 + } + } ++ { ++ "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, ++ "b": { ++ "c": 3 + }, ++ "d": 4, ++ "f": [ ++ 5, ++ 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], ++ "j": [ ++ true, ++ false + ] + } +-- diff.tf -- + { + - a = 1 + - b = { + - b1 = "a" + - b2 = "b" + - c = 2 + } + - d = 4 + - e = null + - f = [ + - 5 + - 6 + - 7 + ] + - j = { + - a = 1 + } + } -> { + + a = 1 + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + + b = { + + c = 3 + } + + d = 4 + + f = [ + + 5 + + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + + j = [ + + true + + false + ] + } diff --git a/testdata/base_example_mattbaird.txtar b/testdata/base_example_mattbaird.txtar new file mode 100644 index 0000000..f6cfb17 --- /dev/null +++ b/testdata/base_example_mattbaird.txtar @@ -0,0 +1,134 @@ +{ + "patchLib": "mattbaird" +} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- after.json -- +{ + "a": 1, + "a1": { + "1": [ + 1, + 2, + 3, + true + ] + }, + "g": 14, + "h": [ + 1, + 2, + 3 + ], + "b": { + "c": 3 + }, + "d": 4, + "f": [ + 5, + 7, + 8, + 9, + 10 + ], + "j": [ + true, + false + ] +} +-- diff.json -- + { + "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, + "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 ++ "c": 3 + }, + "d": 4, +- "e": null, + "f": [ + 5, +- 6, + 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], +- "j": { +- "a": 1 + } ++ "j": [ ++ true, ++ false + ] + } +-- diff.tf -- + { + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + b = { + - b1 = "a" + - b2 = "b" + ~ c = 2 -> 3 + } + - e = null + f = [ + 5 + - 6 + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + ~ j = { + - a = 1 + } -> [ + + true + + false + ] + # (2 unchanged attribute hidden) + } diff --git a/testdata/base_example_mianxiang.txtar b/testdata/base_example_mianxiang.txtar index f46f44c..0e4be3c 100644 --- a/testdata/base_example_mianxiang.txtar +++ b/testdata/base_example_mianxiang.txtar @@ -94,3 +94,41 @@ + false ] } +-- diff.tf -- + { + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + b = { + - b1 = "a" + - b2 = "b" + ~ c = 2 -> 3 + } + - e = null + f = [ + 5 + - 6 + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + ~ j = { + - a = 1 + } -> [ + + true + + false + ] + # (2 unchanged attribute hidden) + } diff --git a/testdata/base_example_snorwin.txtar.off b/testdata/base_example_snorwin.txtar.off new file mode 100644 index 0000000..42b0bbf --- /dev/null +++ b/testdata/base_example_snorwin.txtar.off @@ -0,0 +1,134 @@ +{ + "patchLib": "snorwin" +} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- after.json -- +{ + "a": 1, + "a1": { + "1": [ + 1, + 2, + 3, + true + ] + }, + "g": 14, + "h": [ + 1, + 2, + 3 + ], + "b": { + "c": 3 + }, + "d": 4, + "f": [ + 5, + 7, + 8, + 9, + 10 + ], + "j": [ + true, + false + ] +} +-- diff.json -- + { + "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, + "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 ++ "c": 3 + }, + "d": 4, +- "e": null, + "f": [ + 5, +- 6, + 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], +- "j": { +- "a": 1 + } ++ "j": [ ++ true, ++ false + ] + } +-- diff.tf -- + { + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + b = { + - b1 = "a" + - b2 = "b" + ~ c = 2 -> 3 + } + - e = null + f = [ + 5 + - 6 + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + ~ j = { + - a = 1 + } -> [ + + true + + false + ] + # (2 unchanged attribute hidden) + } diff --git a/testdata/base_example_victorlowther-paranoid.txtar b/testdata/base_example_victorlowther-paranoid.txtar new file mode 100644 index 0000000..39c58bf --- /dev/null +++ b/testdata/base_example_victorlowther-paranoid.txtar @@ -0,0 +1,141 @@ +{ + "patchLib": "victorlowther-paranoid" +} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- after.json -- +{ + "a": 1, + "a1": { + "1": [ + 1, + 2, + 3, + true + ] + }, + "g": 14, + "h": [ + 1, + 2, + 3 + ], + "b": { + "c": 3 + }, + "d": 4, + "f": [ + 5, + 7, + 8, + 9, + 10 + ], + "j": [ + true, + false + ] +} +-- diff.json -- + { + "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, + "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 ++ "c": 3 + }, + "d": 4, +- "e": null, +- "f": [ +- 5, +- 6, +- 7 + ], ++ "f": [ ++ 5, ++ 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], +- "j": { +- "a": 1 + } ++ "j": [ ++ true, ++ false + ] + } +-- diff.tf -- + { + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + b = { + - b1 = "a" + - b2 = "b" + ~ c = 2 -> 3 + } + - e = null + ~ f = [ + - 5 + - 6 + - 7 + ] -> [ + + 5 + + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + ~ j = { + - a = 1 + } -> [ + + true + + false + ] + # (2 unchanged attribute hidden) + } diff --git a/testdata/base_example_victorlowther.txtar b/testdata/base_example_victorlowther.txtar new file mode 100644 index 0000000..4530412 --- /dev/null +++ b/testdata/base_example_victorlowther.txtar @@ -0,0 +1,141 @@ +{ + "patchLib": "victorlowther" +} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- after.json -- +{ + "a": 1, + "a1": { + "1": [ + 1, + 2, + 3, + true + ] + }, + "g": 14, + "h": [ + 1, + 2, + 3 + ], + "b": { + "c": 3 + }, + "d": 4, + "f": [ + 5, + 7, + 8, + 9, + 10 + ], + "j": [ + true, + false + ] +} +-- diff.json -- + { + "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, + "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 ++ "c": 3 + }, + "d": 4, +- "e": null, +- "f": [ +- 5, +- 6, +- 7 + ], ++ "f": [ ++ 5, ++ 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], +- "j": { +- "a": 1 + } ++ "j": [ ++ true, ++ false + ] + } +-- diff.tf -- + { + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + b = { + - b1 = "a" + - b2 = "b" + ~ c = 2 -> 3 + } + - e = null + ~ f = [ + - 5 + - 6 + - 7 + ] -> [ + + 5 + + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + ~ j = { + - a = 1 + } -> [ + + true + + false + ] + # (2 unchanged attribute hidden) + } diff --git a/testdata/generated/advanced_mianxiang.txtar b/testdata/generated/advanced_mianxiang.txtar new file mode 100644 index 0000000..dfe2c1d --- /dev/null +++ b/testdata/generated/advanced_mianxiang.txtar @@ -0,0 +1,80 @@ +{} +-- before.json -- +{ + "array": "[\"foo\",\"bar\"]", + "object": "{\"array_changed\":[\"foo\",\"bar\",\"baz\"],\"array_item_added\":[\"foo\",\"bar\",\"baz\"],\"array_item_removed\":[\"foo\",\"bar\",\"baz\"],\"array_removed\":[\"foo\",\"bar\",\"baz\"],\"array_unchanged\":[\"foo\",\"bar\",\"baz\"],\"number_changed\":10,\"number_removed\":10,\"number_unchanged\":10,\"object_changed\":{\"key\":\"value\"},\"object_removed\":{\"key\":\"value\"},\"object_unchanged\":{\"key\":\"value\"},\"string_changed\":\"bar\",\"string_removed\":\"removed\",\"string_unchanged\":\"foo\"}", + "key": "value" +} +-- patch.json -- +[{"op":"replace","path":"/array","value":"[\"new foo\",\"bar\",\"baz\"]"},{"op":"replace","path":"/object","value":"{\"array_changed\":[\"foo2\",\"bar\",\"baz2\"],\"array_item_added\":[\"foo\",\"bar\",\"baz\",\"biz\"],\"array_item_removed\":[\"foo\",\"baz\"],\"array_new\":[\"foo\",\"bar\",\"baz\"],\"array_unchanged\":[\"foo\",\"bar\",\"baz\"],\"number_changed\":14,\"number_new\":14,\"number_unchanged\":10,\"object_changed\":{\"key\":\"new value\"},\"object_new\":{\"key\":\"value\"},\"object_unchanged\":{\"key\":\"value\"},\"string_changed\":\"bar changed\",\"string_new\":\"new\",\"string_unchanged\":\"foo\"}"}] +-- diff.json -- + { +- "array": "[\"foo\",\"bar\"]", ++ "array": "[\"new foo\",\"bar\",\"baz\"]", + "key": "value", +- "object": "{\"array_changed\":[\"foo\",\"bar\",\"baz\"],\"array_item_added\":[\"foo\",\"bar\",\"baz\"],\"array_item_removed\":[\"foo\",\"bar\",\"baz\"],\"array_removed\":[\"foo\",\"bar\",\"baz\"],\"array_unchanged\":[\"foo\",\"bar\",\"baz\"],\"number_changed\":10,\"number_removed\":10,\"number_unchanged\":10,\"object_changed\":{\"key\":\"value\"},\"object_removed\":{\"key\":\"value\"},\"object_unchanged\":{\"key\":\"value\"},\"string_changed\":\"bar\",\"string_removed\":\"removed\",\"string_unchanged\":\"foo\"}" ++ "object": "{\"array_changed\":[\"foo2\",\"bar\",\"baz2\"],\"array_item_added\":[\"foo\",\"bar\",\"baz\",\"biz\"],\"array_item_removed\":[\"foo\",\"baz\"],\"array_new\":[\"foo\",\"bar\",\"baz\"],\"array_unchanged\":[\"foo\",\"bar\",\"baz\"],\"number_changed\":14,\"number_new\":14,\"number_unchanged\":10,\"object_changed\":{\"key\":\"new value\"},\"object_new\":{\"key\":\"value\"},\"object_unchanged\":{\"key\":\"value\"},\"string_changed\":\"bar changed\",\"string_new\":\"new\",\"string_unchanged\":\"foo\"}" + } +-- diff.tf -- + { + ~ array = jsonencode( + [ + ~ "foo" -> "new foo" + "bar" + + "baz" + ] + ) + ~ object = jsonencode( + { + array_changed = [ + ~ "foo" -> "foo2" + "bar" + ~ "baz" -> "baz2" + ] + array_item_added = [ + "foo" + "bar" + "baz" + + "biz" + ] + array_item_removed = [ + "foo" + - "bar" + "baz" + ] + + array_new = [ + + "foo" + + "bar" + + "baz" + ] + - array_removed = [ + - "foo" + - "bar" + - "baz" + ] + ~ number_changed = 10 -> 14 + + number_new = 14 + - number_removed = 10 + object_changed = { + ~ key = "value" -> "new value" + } + + object_new = { + + key = "value" + } + - object_removed = { + - key = "value" + } + ~ string_changed = "bar" -> "bar changed" + + string_new = "new" + - string_removed = "removed" + # (4 unchanged attribute hidden) + } + ) + # (1 unchanged attribute hidden) + } +-- jsonInJSON.0.json -- +[{"op":"replace","path":"/0","value":"new foo"},{"op":"add","path":"/2","value":"baz"}] + +-- jsonInJSON.1.json -- +[{"op":"remove","path":"/object_removed"},{"op":"remove","path":"/array_item_removed/1"},{"op":"remove","path":"/array_removed"},{"op":"replace","path":"/object_changed/key","value":"new value"},{"op":"replace","path":"/number_changed","value":14},{"op":"remove","path":"/number_removed"},{"op":"replace","path":"/string_changed","value":"bar changed"},{"op":"remove","path":"/string_removed"},{"op":"replace","path":"/array_changed/0","value":"foo2"},{"op":"replace","path":"/array_changed/2","value":"baz2"},{"op":"add","path":"/array_item_added/3","value":"biz"},{"op":"add","path":"/number_new","value":14},{"op":"add","path":"/string_new","value":"new"},{"op":"add","path":"/object_new","value":{"key":"value"}},{"op":"add","path":"/array_new","value":["foo","bar","baz"]}] + diff --git a/testdata/generated/array_mianxiang.txtar b/testdata/generated/array_mianxiang.txtar index 92c12e9..5b24a2c 100644 --- a/testdata/generated/array_mianxiang.txtar +++ b/testdata/generated/array_mianxiang.txtar @@ -9,7 +9,7 @@ "update": [1, 2, 3] } -- patch.json -- -[{"op":"replace","path":"/update/1","value":22},{"op":"add","path":"/append/3","value":4},{"op":"add","path":"/insert/1","value":2},{"op":"remove","path":"/multi_change/1"},{"op":"add","path":"/multi_change/2","value":8},{"op":"add","path":"/multi_change/3","value":9},{"op":"add","path":"/multi_change/4","value":10},{"op":"add","path":"/prepend/0","value":0},{"op":"remove","path":"/remove/1"}] +[{"op":"remove","path":"/multi_change/1"},{"op":"add","path":"/multi_change/2","value":8},{"op":"add","path":"/multi_change/3","value":9},{"op":"add","path":"/multi_change/4","value":10},{"op":"add","path":"/prepend/0","value":0},{"op":"remove","path":"/remove/1"},{"op":"replace","path":"/update/1","value":22},{"op":"add","path":"/append/3","value":4},{"op":"add","path":"/insert/1","value":2}] -- diff.json -- { "append": [ diff --git a/testdata/generated/base_example_herkyl.txtar b/testdata/generated/base_example_herkyl.txtar new file mode 100644 index 0000000..9007662 --- /dev/null +++ b/testdata/generated/base_example_herkyl.txtar @@ -0,0 +1,160 @@ +{} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- patch.json -- +[ + { + "op": "replace", + "path": "", + "value": { + "a": 1, + "a1": { + "1": [ + 1, + 2, + 3, + true + ] + }, + "b": { + "c": 3 + }, + "d": 4, + "f": [ + 5, + 7, + 8, + 9, + 10 + ], + "g": 14, + "h": [ + 1, + 2, + 3 + ], + "j": [ + true, + false + ] + } + } +] +-- diff.json -- +- { +- "a": 1, +- "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 + }, +- "d": 4, +- "e": null, +- "f": [ +- 5, +- 6, +- 7 + ], +- "j": { +- "a": 1 + } + } ++ { ++ "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, ++ "b": { ++ "c": 3 + }, ++ "d": 4, ++ "f": [ ++ 5, ++ 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], ++ "j": [ ++ true, ++ false + ] + } +-- diff.tf -- + { + - a = 1 + - b = { + - b1 = "a" + - b2 = "b" + - c = 2 + } + - d = 4 + - e = null + - f = [ + - 5 + - 6 + - 7 + ] + - j = { + - a = 1 + } + } -> { + + a = 1 + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + + b = { + + c = 3 + } + + d = 4 + + f = [ + + 5 + + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + + j = [ + + true + + false + ] + } diff --git a/testdata/generated/base_example_mattbaird.txtar b/testdata/generated/base_example_mattbaird.txtar new file mode 100644 index 0000000..ad18e01 --- /dev/null +++ b/testdata/generated/base_example_mattbaird.txtar @@ -0,0 +1,172 @@ +{} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- patch.json -- +[ + { + "op": "remove", + "path": "/f/1" + }, + { + "op": "add", + "path": "/f/2", + "value": 8 + }, + { + "op": "add", + "path": "/f/3", + "value": 9 + }, + { + "op": "add", + "path": "/f/4", + "value": 10 + }, + { + "op": "replace", + "path": "/j", + "value": [ + true, + false + ] + }, + { + "op": "add", + "path": "/a1", + "value": { + "1": [ + 1, + 2, + 3, + true + ] + } + }, + { + "op": "add", + "path": "/g", + "value": 14 + }, + { + "op": "add", + "path": "/h", + "value": [ + 1, + 2, + 3 + ] + }, + { + "op": "replace", + "path": "/b/c", + "value": 3 + }, + { + "op": "remove", + "path": "/b/b1" + }, + { + "op": "remove", + "path": "/b/b2" + }, + { + "op": "remove", + "path": "/e" + } +] +-- diff.json -- + { + "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, + "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 ++ "c": 3 + }, + "d": 4, +- "e": null, + "f": [ + 5, +- 6, + 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], +- "j": { +- "a": 1 + } ++ "j": [ ++ true, ++ false + ] + } +-- diff.tf -- + { + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + b = { + - b1 = "a" + - b2 = "b" + ~ c = 2 -> 3 + } + - e = null + f = [ + 5 + - 6 + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + ~ j = { + - a = 1 + } -> [ + + true + + false + ] + # (2 unchanged attribute hidden) + } diff --git a/testdata/generated/base_example_mianxiang.txtar b/testdata/generated/base_example_mianxiang.txtar index 1716d58..c5b535f 100644 --- a/testdata/generated/base_example_mianxiang.txtar +++ b/testdata/generated/base_example_mianxiang.txtar @@ -19,7 +19,7 @@ } } -- patch.json -- -[{"op":"remove","path":"/f/1"},{"op":"add","path":"/f/2","value":8},{"op":"add","path":"/f/3","value":9},{"op":"add","path":"/f/4","value":10},{"op":"replace","path":"/j","value":[true,false]},{"op":"replace","path":"/b/c","value":3},{"op":"remove","path":"/b/b1"},{"op":"remove","path":"/b/b2"},{"op":"remove","path":"/e"},{"op":"add","path":"/a1","value":{"1":[1,2,3,true]}},{"op":"add","path":"/g","value":14},{"op":"add","path":"/h","value":[1,2,3]}] +[{"op":"remove","path":"/e"},{"op":"remove","path":"/f/1"},{"op":"add","path":"/f/2","value":8},{"op":"add","path":"/f/3","value":9},{"op":"add","path":"/f/4","value":10},{"op":"replace","path":"/j","value":[true,false]},{"op":"remove","path":"/b/b2"},{"op":"replace","path":"/b/c","value":3},{"op":"remove","path":"/b/b1"},{"op":"add","path":"/a1","value":{"1":[1,2,3,true]}},{"op":"add","path":"/g","value":14},{"op":"add","path":"/h","value":[1,2,3]}] -- diff.json -- { "a": 1, @@ -61,3 +61,41 @@ + false ] } +-- diff.tf -- + { + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + b = { + - b1 = "a" + - b2 = "b" + ~ c = 2 -> 3 + } + - e = null + f = [ + 5 + - 6 + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + ~ j = { + - a = 1 + } -> [ + + true + + false + ] + # (2 unchanged attribute hidden) + } diff --git a/testdata/generated/base_example_victorlowther-paranoid.txtar b/testdata/generated/base_example_victorlowther-paranoid.txtar new file mode 100644 index 0000000..bb6254f --- /dev/null +++ b/testdata/generated/base_example_victorlowther-paranoid.txtar @@ -0,0 +1,225 @@ +{} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- patch.json -- +[ + { + "op": "test", + "path": "/b/c", + "from": "", + "value": 2 + }, + { + "op": "replace", + "path": "/b/c", + "from": "", + "value": 3 + }, + { + "op": "test", + "path": "/b/b1", + "from": "", + "value": "a" + }, + { + "op": "remove", + "path": "/b/b1", + "from": "", + "value": null + }, + { + "op": "test", + "path": "/b/b2", + "from": "", + "value": "b" + }, + { + "op": "remove", + "path": "/b/b2", + "from": "", + "value": null + }, + { + "op": "test", + "path": "/e", + "from": "", + "value": null + }, + { + "op": "remove", + "path": "/e", + "from": "", + "value": null + }, + { + "op": "test", + "path": "/f", + "from": "", + "value": [ + 5, + 6, + 7 + ] + }, + { + "op": "replace", + "path": "/f", + "from": "", + "value": [ + 5, + 7, + 8, + 9, + 10 + ] + }, + { + "op": "test", + "path": "/j", + "from": "", + "value": { + "a": 1 + } + }, + { + "op": "replace", + "path": "/j", + "from": "", + "value": [ + true, + false + ] + }, + { + "op": "add", + "path": "/h", + "from": "", + "value": [ + 1, + 2, + 3 + ] + }, + { + "op": "add", + "path": "/a1", + "from": "", + "value": { + "1": [ + 1, + 2, + 3, + true + ] + } + }, + { + "op": "add", + "path": "/g", + "from": "", + "value": 14 + } +] +-- diff.json -- + { + "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, + "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 ++ "c": 3 + }, + "d": 4, +- "e": null, +- "f": [ +- 5, +- 6, +- 7 + ], ++ "f": [ ++ 5, ++ 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], +- "j": { +- "a": 1 + } ++ "j": [ ++ true, ++ false + ] + } +-- diff.tf -- + { + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + b = { + - b1 = "a" + - b2 = "b" + ~ c = 2 -> 3 + } + - e = null + ~ f = [ + - 5 + - 6 + - 7 + ] -> [ + + 5 + + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + ~ j = { + - a = 1 + } -> [ + + true + + false + ] + # (2 unchanged attribute hidden) + } diff --git a/testdata/generated/base_example_victorlowther.txtar b/testdata/generated/base_example_victorlowther.txtar new file mode 100644 index 0000000..34982a4 --- /dev/null +++ b/testdata/generated/base_example_victorlowther.txtar @@ -0,0 +1,183 @@ +{} +-- before.json -- +{ + "a": 1, + "b": { + "c": 2, + "b1": "a", + "b2": "b" + }, + "d": 4, + "e": null, + "f": [ + 5, + 6, + 7 + ], + "j": { + "a": 1 + } +} +-- patch.json -- +[ + { + "op": "remove", + "path": "/e", + "from": "", + "value": null + }, + { + "op": "replace", + "path": "/f", + "from": "", + "value": [ + 5, + 7, + 8, + 9, + 10 + ] + }, + { + "op": "replace", + "path": "/j", + "from": "", + "value": [ + true, + false + ] + }, + { + "op": "replace", + "path": "/b/c", + "from": "", + "value": 3 + }, + { + "op": "remove", + "path": "/b/b1", + "from": "", + "value": null + }, + { + "op": "remove", + "path": "/b/b2", + "from": "", + "value": null + }, + { + "op": "add", + "path": "/g", + "from": "", + "value": 14 + }, + { + "op": "add", + "path": "/h", + "from": "", + "value": [ + 1, + 2, + 3 + ] + }, + { + "op": "add", + "path": "/a1", + "from": "", + "value": { + "1": [ + 1, + 2, + 3, + true + ] + } + } +] +-- diff.json -- + { + "a": 1, ++ "a1": { ++ "1": [ ++ 1, ++ 2, ++ 3, ++ true + ] + }, + "b": { +- "b1": "a", +- "b2": "b", +- "c": 2 ++ "c": 3 + }, + "d": 4, +- "e": null, +- "f": [ +- 5, +- 6, +- 7 + ], ++ "f": [ ++ 5, ++ 7, ++ 8, ++ 9, ++ 10 + ], ++ "g": 14, ++ "h": [ ++ 1, ++ 2, ++ 3 + ], +- "j": { +- "a": 1 + } ++ "j": [ ++ true, ++ false + ] + } +-- diff.tf -- + { + + a1 = { + + 1 = [ + + 1 + + 2 + + 3 + + true + ] + } + b = { + - b1 = "a" + - b2 = "b" + ~ c = 2 -> 3 + } + - e = null + ~ f = [ + - 5 + - 6 + - 7 + ] -> [ + + 5 + + 7 + + 8 + + 9 + + 10 + ] + + g = 14 + + h = [ + + 1 + + 2 + + 3 + ] + ~ j = { + - a = 1 + } -> [ + + true + + false + ] + # (2 unchanged attribute hidden) + } diff --git a/testdata/generated/null_2_string.txtar b/testdata/generated/null_2_string.txtar index d416c31..2913647 100644 --- a/testdata/generated/null_2_string.txtar +++ b/testdata/generated/null_2_string.txtar @@ -12,4 +12,4 @@ null -- diff.json -- + "foobar" -- diff.tf -- -"foobar" + "foobar" diff --git a/testdata/generated/string_2_null.txtar b/testdata/generated/string_2_null.txtar index 61b7d07..f8982b8 100644 --- a/testdata/generated/string_2_null.txtar +++ b/testdata/generated/string_2_null.txtar @@ -12,4 +12,4 @@ -- diff.json -- - "foobar" -- diff.tf -- -"foobar" + "foobar" diff --git a/testdata/generated/string_2_string.txtar b/testdata/generated/string_2_string.txtar index 0e98cb4..37786c5 100644 --- a/testdata/generated/string_2_string.txtar +++ b/testdata/generated/string_2_string.txtar @@ -13,4 +13,4 @@ - "" + "" -- diff.tf -- -"" -> "" + "" -> "" diff --git a/testdata/null_2_string.txtar b/testdata/null_2_string.txtar index 06344b1..7dae19a 100644 --- a/testdata/null_2_string.txtar +++ b/testdata/null_2_string.txtar @@ -5,4 +5,4 @@ null -- diff.json -- + "foobar" -- diff.tf -- -"foobar" + "foobar" diff --git a/testdata/string_2_null.txtar b/testdata/string_2_null.txtar index 4320b35..2fdf807 100644 --- a/testdata/string_2_null.txtar +++ b/testdata/string_2_null.txtar @@ -5,4 +5,4 @@ null -- diff.json -- - "foobar" -- diff.tf -- -"foobar" + "foobar" diff --git a/testdata/string_2_string.txtar b/testdata/string_2_string.txtar index 8dba40a..6b86b06 100644 --- a/testdata/string_2_string.txtar +++ b/testdata/string_2_string.txtar @@ -6,4 +6,4 @@ - "" + "" -- diff.tf -- -"" -> "" + "" -> "" From b8fcf94ba0952acdcefe8e144adf8d5d6b1c73eb Mon Sep 17 00:00:00 2001 From: Lucas Bremgartner Date: Sat, 1 Jun 2024 21:12:15 +0200 Subject: [PATCH 6/6] Cleanup --- cmd/go.mod | 6 ++---- cmd/go.sum | 23 +++++++++++++++++++++++ formatter_internal_test.go | 1 - go.mod | 2 +- go.work | 4 +--- go.work.sum | 10 ++++++++++ 6 files changed, 37 insertions(+), 9 deletions(-) diff --git a/cmd/go.mod b/cmd/go.mod index 62d1e17..1386f29 100644 --- a/cmd/go.mod +++ b/cmd/go.mod @@ -1,12 +1,11 @@ module github.com/breml/jsondiffprinter/cmd -go 1.22 - -toolchain go1.22.3 +go 1.22.3 require ( github.com/breml/jsondiffprinter v0.0.5 github.com/qri-io/jsonpointer v0.1.1 + github.com/snorwin/jsonpatch v1.5.0 github.com/wI2L/jsondiff v0.5.2 golang.org/x/tools v0.21.0 ) @@ -15,7 +14,6 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/evanphx/json-patch v0.5.2 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/snorwin/jsonpatch v1.5.0 // indirect github.com/stretchr/testify v1.9.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect ) diff --git a/cmd/go.sum b/cmd/go.sum index 34f9a83..a49ed10 100644 --- a/cmd/go.sum +++ b/cmd/go.sum @@ -8,11 +8,27 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/go-faker/faker/v4 v4.4.1 h1:LY1jDgjVkBZWIhATCt+gkl0x9i/7wC61gZx73GTFb+Q= +github.com/go-faker/faker/v4 v4.4.1/go.mod h1:HRLrjis+tYsbFtIHufEPTAIzcZiRu0rS9EYl2Ccwme4= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/herkyl/patchwerk v0.0.0-20190629103337-f0ea77068152 h1:GITUy7r2Eijl7u/Xe5AOs3HBV3Gt/3+l0j2bTh2UO5Y= github.com/herkyl/patchwerk v0.0.0-20190629103337-f0ea77068152/go.mod h1:bRtCxY0f88xmUw+Y0Xfl/uGaCWMUy04wUGSKbnQdsJs= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38 h1:hQWBtNqRYrI7CWIaUSXXtNKR90KzcUA5uiuxFVWw7sU= github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= +github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= +github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= +github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= +github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -33,11 +49,18 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/wI2L/jsondiff v0.5.2 h1:f68drsfk/Xgvt3BpLVDlGkQzOC4o+qUCl9jtGr0sbfE= github.com/wI2L/jsondiff v0.5.2/go.mod h1:96+qu+Fhb323v//55RjkiTWYaGkiNWUqRV/w670bTAE= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/formatter_internal_test.go b/formatter_internal_test.go index e561159..dda7b4e 100644 --- a/formatter_internal_test.go +++ b/formatter_internal_test.go @@ -194,7 +194,6 @@ func Test_compileDiffPatchSeries(t *testing.T) { t.Run(tc.name, func(t *testing.T) { got, err := compileDiffPatchSeries(tc.src, tc.patch) tc.assertErr(t, err) - // require.EqualStringWithTabwriter(t, fmt.Sprintf("%#v", tc.want), fmt.Sprintf("%#v", got)) require.Equal(t, tc.want, got) }) } diff --git a/go.mod b/go.mod index 681c5a5..1752512 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/breml/jsondiffprinter -go 1.21.7 +go 1.22.3 require golang.org/x/tools v0.21.0 diff --git a/go.work b/go.work index 058956c..91756f3 100644 --- a/go.work +++ b/go.work @@ -1,6 +1,4 @@ -go 1.22 - -toolchain go1.22.3 +go 1.22.3 use ( . diff --git a/go.work.sum b/go.work.sum index 45e93c6..778bba4 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,18 +1,28 @@ +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/go-faker/faker/v4 v4.4.1 h1:LY1jDgjVkBZWIhATCt+gkl0x9i/7wC61gZx73GTFb+Q= github.com/go-faker/faker/v4 v4.4.1/go.mod h1:HRLrjis+tYsbFtIHufEPTAIzcZiRu0rS9EYl2Ccwme4= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= +github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=