aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/bisect
diff options
context:
space:
mode:
authorZubin Mithra <zsm@chromium.org>2019-10-08 15:57:52 -0700
committerDmitry Vyukov <dvyukov@google.com>2019-10-22 10:09:57 +0200
commita2bdbd8c37841cc507a2ad59f25d90d6467e5858 (patch)
treebc4ad0e738a749c2321b7181e4ea04c5615738e7 /pkg/bisect
parent37dc03de04826cc0d5d1e3699832b0a3113d40af (diff)
pkg/bisect: add initial testing support for cause bisection
(note: incomplete change) Refactor existing code as follows: * Move reusable test utility functions from git_repo_test.go to pkg/vcs/test_util.go and make them exported. * Split Run() into Run()+runImpl(). * Change type of bisect.go:env.inst to `instance.BuilderTester`. Change usage inside syz-testbuild/testbuild.go accordingly. * Move most of linux.PreviousReleaseTags() into vcs/git.go as git.previousReleaseTags(). * Allow build.CompilerIdentity to be mocked. Introduce the following changes: * instance.BuilderTester is an interface with methods BuildSyzkaller() BuildKernel() Test() NewEnv() now returns this interface. * type testEnv implements instance.BuilderTester. * type testBuilder implements builder interface. Add a entry into table inside pkg/build/build.go:getBuilder() to return testBuilder object.
Diffstat (limited to 'pkg/bisect')
-rw-r--r--pkg/bisect/bisect.go27
-rw-r--r--pkg/bisect/bisect_test.go133
2 files changed, 153 insertions, 7 deletions
diff --git a/pkg/bisect/bisect.go b/pkg/bisect/bisect.go
index 78cb58bd4..904be4b53 100644
--- a/pkg/bisect/bisect.go
+++ b/pkg/bisect/bisect.go
@@ -55,7 +55,7 @@ type env struct {
repo vcs.Repo
bisecter vcs.Bisecter
head *vcs.Commit
- inst *instance.Env
+ inst instance.BuilderTester
numTests int
buildTime time.Duration
testTime time.Duration
@@ -85,11 +85,30 @@ func Run(cfg *Config) ([]*vcs.Commit, *report.Report, error) {
if !ok {
return nil, nil, fmt.Errorf("bisection is not implemented for %v", cfg.Manager.TargetOS)
}
+ inst, err := instance.NewEnv(&cfg.Manager)
+ if err != nil {
+ return nil, nil, err
+ }
+ if _, err = repo.CheckoutBranch(cfg.Kernel.Repo, cfg.Kernel.Branch); err != nil {
+ return nil, nil, err
+ }
+
+ return runImpl(cfg, repo, bisecter, inst)
+}
+
+func runImpl(cfg *Config, repo vcs.Repo, bisecter vcs.Bisecter, inst instance.BuilderTester) (
+ []*vcs.Commit, *report.Report, error) {
env := &env{
cfg: cfg,
repo: repo,
bisecter: bisecter,
+ inst: inst,
}
+ head, err := repo.HeadCommit()
+ if err != nil {
+ return nil, nil, err
+ }
+ env.head = head
if cfg.Fix {
env.log("bisecting fixing commit since %v", cfg.Kernel.Commit)
} else {
@@ -135,12 +154,6 @@ func Run(cfg *Config) ([]*vcs.Commit, *report.Report, error) {
func (env *env) bisect() ([]*vcs.Commit, *report.Report, error) {
cfg := env.cfg
var err error
- if env.inst, err = instance.NewEnv(&cfg.Manager); err != nil {
- return nil, nil, err
- }
- if env.head, err = env.repo.CheckoutBranch(cfg.Kernel.Repo, cfg.Kernel.Branch); err != nil {
- return nil, nil, err
- }
if err := build.Clean(cfg.Manager.TargetOS, cfg.Manager.TargetVMArch,
cfg.Manager.Type, cfg.Manager.KernelSrc); err != nil {
return nil, nil, fmt.Errorf("kernel clean failed: %v", err)
diff --git a/pkg/bisect/bisect_test.go b/pkg/bisect/bisect_test.go
new file mode 100644
index 000000000..472fde289
--- /dev/null
+++ b/pkg/bisect/bisect_test.go
@@ -0,0 +1,133 @@
+// Copyright 2019 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 bisect
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strconv"
+ "testing"
+
+ "github.com/google/syzkaller/pkg/build"
+ "github.com/google/syzkaller/pkg/instance"
+ "github.com/google/syzkaller/pkg/mgrconfig"
+ "github.com/google/syzkaller/pkg/report"
+ "github.com/google/syzkaller/pkg/vcs"
+)
+
+// testEnv will implement instance.BuilderTester. This allows us to
+// set bisect.env.inst to a testEnv object.
+type testEnv struct {
+ repo *vcs.TestRepo
+ r vcs.Repo
+ t *testing.T
+ // TODO: add a "fix bool" here so that Test() can return results according to
+ // whether fix/cause bisection is happening.
+}
+
+func (env *testEnv) BuildSyzkaller(repo, commit string) error {
+ return nil
+}
+
+func (env *testEnv) BuildKernel(compilerBin, userspaceDir, cmdlineFile, sysctlFile string,
+ kernelConfig []byte) (string, error) {
+ return "", nil
+}
+
+func (env *testEnv) Test(numVMs int, reproSyz, reproOpts, reproC []byte) ([]error, error) {
+ hc, err := env.r.HeadCommit()
+ if err != nil {
+ env.t.Fatal(err)
+ }
+ // For cause bisection, if newer than or equal to 602, it crashes.
+ // -- 602 is the cause commit.
+ // TODO: for fix bisection(check env.fix), if older than 602, it crashes.
+ // -- 602 is the fix commit.
+ val, err := strconv.Atoi(hc.Title)
+ if err != nil {
+ env.t.Fatalf("invalid commit title: %v", val)
+ }
+ if val >= 602 {
+ var errors []error
+ for i := 0; i < numVMs; i++ {
+ errors = append(errors, &instance.CrashError{
+ Report: &report.Report{
+ Title: fmt.Sprintf("crashes at %v", hc.Title),
+ },
+ })
+ }
+ return errors, nil
+ }
+ var errors []error
+ for i := 0; i < numVMs; i++ {
+ errors = append(errors, nil)
+ }
+ return errors, nil
+}
+
+// TestBisectCause tests that bisection returns the correct cause
+// commit.
+func TestBisectCause(t *testing.T) {
+ t.Parallel()
+ build.CompilerIdentity = func(_ string) (string, error) {
+ return "unused-compiler-identity", nil
+ }
+ baseDir, err := ioutil.TempDir("", "syz-git-test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(baseDir)
+ originRepo := vcs.CreateTestRepo(t, baseDir, "originRepo")
+ for rv := 4; rv < 10; rv++ {
+ for i := 0; i < 6; i++ {
+ originRepo.CommitChange(fmt.Sprintf("%v", rv*100+i))
+ if i == 0 {
+ originRepo.SetTag(fmt.Sprintf("v%v.0", rv))
+ }
+ }
+ }
+ repo := vcs.CloneTestRepo(t, baseDir, "repo", originRepo)
+ r, err := vcs.NewRepo("test", "64", repo.Dir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ head, err := r.HeadCommit()
+ if err != nil {
+ t.Fatal(err)
+ }
+ cfg := &Config{
+ Fix: false,
+ Trace: new(bytes.Buffer),
+ Manager: mgrconfig.Config{
+ TargetOS: "test",
+ TargetVMArch: "64",
+ Type: "qemu",
+ KernelSrc: repo.Dir,
+ },
+ Kernel: KernelConfig{
+ Commit: head.Hash,
+ Repo: originRepo.Dir,
+ },
+ }
+ inst := &testEnv{
+ repo: repo,
+ r: r,
+ t: t,
+ }
+ commits, rep, err := runImpl(cfg, r, r.(vcs.Bisecter), inst)
+ if err != nil {
+ t.Fatalf("returned error: '%v'", err)
+ }
+ if len(commits) != 1 {
+ t.Fatalf("Got %d commits: %v", len(commits), commits)
+ }
+ if commits[0].Title != "602" {
+ t.Fatalf("Expected commit '602' got '%v'", commits[0].Title)
+ }
+ if rep == nil {
+ t.Fatal("returned rep==nil, report should not be empty")
+ }
+}