From aa3dbd72ed6726be5bf1bec14a2ceaca369a8063 Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Thu, 10 Feb 2022 15:13:03 +0000 Subject: tools/syz-testbed: don't parse configs It's not practical to parse configs from tools/syz-testbed because it limits the tool to using only those configuration options, which are supported by the syzkaller version at the moment of tools/syz-testbed compilation. Operate with manager configs as if they were just some JSON objects. Introduce a PatchJSON method to update their fields in a convenient way. --- pkg/config/merge.go | 15 ++++++++++++--- pkg/config/merge_test.go | 49 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 5 deletions(-) (limited to 'pkg') 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) } -- cgit mrf-deployment