| // Copyright 2016 syzkaller project authors. All rights reserved. |
| // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. |
| |
| package state |
| |
| import ( |
| "fmt" |
| "io/ioutil" |
| "os" |
| "path/filepath" |
| "runtime" |
| "testing" |
| ) |
| |
| func TestState(t *testing.T) { |
| dir, err := ioutil.TempDir("", "syz-hub-state-test") |
| if err != nil { |
| t.Fatalf("failed to create temp dir: %v", err) |
| } |
| defer os.RemoveAll(dir) |
| |
| st, err := Make(dir) |
| if err != nil { |
| t.Fatalf("failed to make state: %v", err) |
| } |
| _, _, err = st.Sync("foo", nil, nil) |
| if err == nil { |
| t.Fatalf("synced with unconnected manager") |
| } |
| calls := []string{"read", "write"} |
| if err := st.Connect("foo", false, calls, nil); err != nil { |
| t.Fatalf("Connect failed: %v", err) |
| } |
| _, _, err = st.Sync("foo", nil, nil) |
| if err != nil { |
| t.Fatalf("Sync failed: %v", err) |
| } |
| } |
| |
| func TestRepro(t *testing.T) { |
| dir, err := ioutil.TempDir("", "syz-hub-state-test") |
| if err != nil { |
| t.Fatalf("failed to create temp dir: %v", err) |
| } |
| defer os.RemoveAll(dir) |
| |
| st, err := Make(dir) |
| if err != nil { |
| t.Fatalf("failed to make state: %v", err) |
| } |
| |
| if err := st.Connect("foo", false, []string{"open", "read", "write"}, nil); err != nil { |
| t.Fatalf("Connect failed: %v", err) |
| } |
| if err := st.Connect("bar", false, []string{"open", "read", "close"}, nil); err != nil { |
| t.Fatalf("Connect failed: %v", err) |
| } |
| checkPendingRepro(t, st, "foo", "") |
| checkPendingRepro(t, st, "bar", "") |
| |
| if err := st.AddRepro("foo", []byte("open()")); err != nil { |
| t.Fatalf("AddRepro failed: %v", err) |
| } |
| checkPendingRepro(t, st, "foo", "") |
| checkPendingRepro(t, st, "bar", "open()") |
| checkPendingRepro(t, st, "bar", "") |
| |
| // This repro is already present. |
| if err := st.AddRepro("bar", []byte("open()")); err != nil { |
| t.Fatalf("AddRepro failed: %v", err) |
| } |
| if err := st.AddRepro("bar", []byte("read()")); err != nil { |
| t.Fatalf("AddRepro failed: %v", err) |
| } |
| if err := st.AddRepro("bar", []byte("open()\nread()")); err != nil { |
| t.Fatalf("AddRepro failed: %v", err) |
| } |
| // This does not satisfy foo's call set. |
| if err := st.AddRepro("bar", []byte("close()")); err != nil { |
| t.Fatalf("AddRepro failed: %v", err) |
| } |
| checkPendingRepro(t, st, "bar", "") |
| |
| // Check how persistence works. |
| st, err = Make(dir) |
| if err != nil { |
| t.Fatalf("failed to make state: %v", err) |
| } |
| if err := st.Connect("foo", false, []string{"open", "read", "write"}, nil); err != nil { |
| t.Fatalf("Connect failed: %v", err) |
| } |
| if err := st.Connect("bar", false, []string{"open", "read", "close"}, nil); err != nil { |
| t.Fatalf("Connect failed: %v", err) |
| } |
| checkPendingRepro(t, st, "bar", "") |
| checkPendingRepro(t, st, "foo", "read()") |
| checkPendingRepro(t, st, "foo", "open()\nread()") |
| checkPendingRepro(t, st, "foo", "") |
| } |
| |
| func checkPendingRepro(t *testing.T, st *State, name, result string) { |
| repro, err := st.PendingRepro(name) |
| if err != nil { |
| t.Fatalf("\n%v: PendingRepro failed: %v", caller(1), err) |
| } |
| if string(repro) != result { |
| t.Fatalf("\n%v: PendingRepro returned %q, want %q", caller(1), string(repro), result) |
| } |
| } |
| |
| func caller(skip int) string { |
| _, file, line, _ := runtime.Caller(skip + 1) |
| return fmt.Sprintf("%v:%v", filepath.Base(file), line) |
| } |