aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/config
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/config')
-rw-r--r--pkg/config/merge.go15
-rw-r--r--pkg/config/merge_test.go49
2 files changed, 59 insertions, 5 deletions
diff --git a/pkg/config/merge.go b/pkg/config/merge.go
index 49a7254de..3d8193c02 100644
--- a/pkg/config/merge.go
+++ b/pkg/config/merge.go
@@ -9,7 +9,7 @@ import (
// Unfortunately, if we want to apply a JSON patch to some configuration, we cannot just unmarshal
// it twice - in that case json.RawMessage objects will be completely replaced, but not merged.
-func MergeJSONData(left, right []byte) ([]byte, error) {
+func MergeJSONs(left, right []byte) ([]byte, error) {
vLeft, err := parseFragment(left)
if err != nil {
return nil, err
@@ -18,8 +18,17 @@ func MergeJSONData(left, right []byte) ([]byte, error) {
if err != nil {
return nil, err
}
- merged := mergeRecursive(vLeft, vRight)
- return json.Marshal(merged)
+ return json.Marshal(mergeRecursive(vLeft, vRight))
+}
+
+// Recursively apply a patch to a raw JSON data.
+// Patch is supposed to be a map, which possibly nests other map objects.
+func PatchJSON(left []byte, patch map[string]interface{}) ([]byte, error) {
+ vLeft, err := parseFragment(left)
+ if err != nil {
+ return nil, err
+ }
+ return json.Marshal(mergeRecursive(vLeft, patch))
}
func parseFragment(input []byte) (parsed interface{}, err error) {
diff --git a/pkg/config/merge_test.go b/pkg/config/merge_test.go
index c5a45754e..6785534f1 100644
--- a/pkg/config/merge_test.go
+++ b/pkg/config/merge_test.go
@@ -10,7 +10,7 @@ import (
"github.com/google/syzkaller/pkg/config"
)
-func TestMergeJSONData(t *testing.T) {
+func TestMergeJSONs(t *testing.T) {
tests := []struct {
left string
right string
@@ -38,7 +38,52 @@ func TestMergeJSONData(t *testing.T) {
},
}
for _, test := range tests {
- res, err := config.MergeJSONData([]byte(test.left), []byte(test.right))
+ res, err := config.MergeJSONs([]byte(test.left), []byte(test.right))
+ if err != nil {
+ t.Errorf("unexpected error: %s", err)
+ }
+ if !bytes.Equal(res, []byte(test.result)) {
+ t.Errorf("expected %s, got %s", test.result, res)
+ }
+ }
+}
+
+func TestPatchJSON(t *testing.T) {
+ tests := []struct {
+ left string
+ patch map[string]interface{}
+ result string
+ }{
+ {
+ `{"a":1,"b":2}`,
+ map[string]interface{}{"b": "string val"},
+ `{"a":1,"b":"string val"}`,
+ },
+ {
+ `{"a":1,"b":2}`,
+ map[string]interface{}{
+ "a": map[string]interface{}{
+ "b": map[string]interface{}{
+ "c": 5,
+ },
+ },
+ },
+ `{"a":{"b":{"c":5}},"b":2}`,
+ },
+ {
+ `{}`,
+ map[string]interface{}{
+ "a": map[string]interface{}{
+ "b": map[string]interface{}{
+ "c": 0,
+ },
+ },
+ },
+ `{"a":{"b":{"c":0}}}`,
+ },
+ }
+ for _, test := range tests {
+ res, err := config.PatchJSON([]byte(test.left), test.patch)
if err != nil {
t.Errorf("unexpected error: %s", err)
}