diff options
| -rw-r--r-- | pkg/config/merge.go | 15 | ||||
| -rw-r--r-- | pkg/config/merge_test.go | 49 | ||||
| -rw-r--r-- | tools/syz-testbed/checkout.go | 6 | ||||
| -rw-r--r-- | tools/syz-testbed/instance.go | 17 | ||||
| -rw-r--r-- | tools/syz-testbed/testbed.go | 14 |
5 files changed, 77 insertions, 24 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) } diff --git a/tools/syz-testbed/checkout.go b/tools/syz-testbed/checkout.go index 91508ff99..3a4265013 100644 --- a/tools/syz-testbed/checkout.go +++ b/tools/syz-testbed/checkout.go @@ -4,13 +4,13 @@ package main import ( + "encoding/json" "fmt" "log" "path/filepath" "time" syz_instance "github.com/google/syzkaller/pkg/instance" - "github.com/google/syzkaller/pkg/mgrconfig" "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/pkg/vcs" ) @@ -18,7 +18,7 @@ import ( type Checkout struct { Path string Name string - ManagerConfig *mgrconfig.Config + ManagerConfig json.RawMessage Running []*Instance Completed []*RunResult } @@ -35,7 +35,7 @@ func (checkout *Checkout) ArchiveRunning() error { return nil } -func (ctx *TestbedContext) NewCheckout(config *CheckoutConfig, mgrConfig *mgrconfig.Config) (*Checkout, error) { +func (ctx *TestbedContext) NewCheckout(config *CheckoutConfig, mgrConfig json.RawMessage) (*Checkout, error) { checkout := &Checkout{ Name: config.Name, Path: filepath.Join(ctx.Config.Workdir, "checkouts", config.Name), diff --git a/tools/syz-testbed/instance.go b/tools/syz-testbed/instance.go index 6601a2c4a..bd25d55eb 100644 --- a/tools/syz-testbed/instance.go +++ b/tools/syz-testbed/instance.go @@ -20,7 +20,6 @@ type Instance struct { Workdir string BenchFile string LogFile string - HTTP string ExecCommand string ExecCommandArgs []string stopChannel chan bool @@ -111,11 +110,16 @@ func (ctx *TestbedContext) NewInstance(checkout *Checkout, mgrName string) (*Ins } log.Printf("[%s] Generating syz-manager config", name) - managerCfg := *checkout.ManagerConfig - managerCfg.Name = mgrName - managerCfg.Workdir = workdir - managerCfg.Syzkaller = checkout.Path - err = config.SaveFile(managerCfgPath, managerCfg) + managerCfg, err := config.PatchJSON(checkout.ManagerConfig, map[string]interface{}{ + "name": mgrName, + "workdir": workdir, + "syzkaller": checkout.Path, + }) + if err != nil { + return nil, fmt.Errorf("failed to patch mgr config") + } + + err = osutil.WriteFile(managerCfgPath, managerCfg) if err != nil { return nil, fmt.Errorf("failed to save manager config to %s: %s", managerCfgPath, err) } @@ -125,7 +129,6 @@ func (ctx *TestbedContext) NewInstance(checkout *Checkout, mgrName string) (*Ins Workdir: workdir, BenchFile: bench, LogFile: logFile, - HTTP: managerCfg.HTTP, ExecCommand: filepath.Join(checkout.Path, "bin", "syz-manager"), ExecCommandArgs: []string{"-config", managerCfgPath, "-bench", bench}, stopChannel: make(chan bool, 1), diff --git a/tools/syz-testbed/testbed.go b/tools/syz-testbed/testbed.go index 12884d0a4..f83d1dfa9 100644 --- a/tools/syz-testbed/testbed.go +++ b/tools/syz-testbed/testbed.go @@ -19,7 +19,6 @@ import ( "time" "github.com/google/syzkaller/pkg/config" - "github.com/google/syzkaller/pkg/mgrconfig" "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/pkg/tool" "github.com/google/syzkaller/pkg/vcs" @@ -107,18 +106,15 @@ func main() { ctx.Loop(shutdown) } -func (ctx *TestbedContext) MakeMgrConfig(base, patch json.RawMessage) *mgrconfig.Config { - mergedConfig, err := config.MergeJSONData(base, patch) +func (ctx *TestbedContext) MakeMgrConfig(base, patch json.RawMessage) json.RawMessage { + mgrCfg, err := config.MergeJSONs(base, patch) if err != nil { tool.Failf("failed to apply a patch to the base manager config: %s", err) } - mgrCfg, err := mgrconfig.LoadPartialData(mergedConfig) + // We don't care much about the specific ports of syz-managers. + mgrCfg, err = config.PatchJSON(mgrCfg, map[string]interface{}{"HTTP": ":0"}) if err != nil { - tool.Failf("failed to parse base manager config: %s", err) - } - if mgrCfg.HTTP == "" { - // Actually, we don't care much about the specific ports of syz-managers. - mgrCfg.HTTP = ":0" + tool.Failf("failed to assign empty HTTP value: %s", err) } return mgrCfg } |
