diff options
| author | Zubin Mithra <zsm@chromium.org> | 2019-07-30 10:58:08 -0700 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2019-08-01 13:43:22 +0200 |
| commit | 835dffe7e5d185154a9b147476a17b6301ee139e (patch) | |
| tree | 463910ecb9f9a7e54053961b3a402f53176d2261 | |
| parent | c692b5bdabba075211571ae6dfe3453a8193591a (diff) | |
dashboard/app: allow fix bisection results to be visible on web UI
* Modify the dashboard/app/bug.html template to show fix bisection
results.
* Modify handleBug() to fetch and create a uiJob for fix bisection
results.
* Modify loadBisectJob() to fetch jobs based on a specified jobType.
Change all callers to pass in jobType info into loadBisectJob().
* Add TestBugBisectionResults() to ensure bisection results show up as
expected.
| -rw-r--r-- | dashboard/app/bisect_test.go | 103 | ||||
| -rw-r--r-- | dashboard/app/bug.html | 35 | ||||
| -rw-r--r-- | dashboard/app/main.go | 32 | ||||
| -rw-r--r-- | dashboard/app/reporting.go | 12 |
4 files changed, 170 insertions, 12 deletions
diff --git a/dashboard/app/bisect_test.go b/dashboard/app/bisect_test.go index bfeb12be0..3650d65ed 100644 --- a/dashboard/app/bisect_test.go +++ b/dashboard/app/bisect_test.go @@ -6,6 +6,7 @@ package dash import ( + "bytes" "fmt" "strings" "testing" @@ -13,6 +14,7 @@ import ( "github.com/google/syzkaller/dashboard/dashapi" "github.com/google/syzkaller/pkg/email" + db "google.golang.org/appengine/datastore" ) func TestBisectCause(t *testing.T) { @@ -716,3 +718,104 @@ func TestBisectCauseReproSyz2(t *testing.T) { t.Fatalf("report still contains bisection results:\n%v", msg.Body) } } + +// Test that bisection results show up on UI +func TestBugBisectionResults(t *testing.T) { + c := NewCtx(t) + defer c.Close() + + // Upload a crash report + build := testBuild(1) + c.client2.UploadBuild(build) + crash := testCrashWithRepro(build, 1) + c.client2.ReportCrash(crash) + c.client2.pollEmailBug() + + // Receive the JobBisectCause and send cause information + resp := c.client2.pollJobs(build.Manager) + c.client2.expectNE(resp.ID, "") + c.client2.expectEQ(resp.Type, dashapi.JobBisectCause) + jobID := resp.ID + done := &dashapi.JobDoneReq{ + ID: jobID, + Build: *build, + Log: []byte("bisectfix log 4"), + CrashTitle: "bisectfix crash title 4", + CrashLog: []byte("bisectfix crash log 4"), + CrashReport: []byte("bisectfix crash report 4"), + Commits: []dashapi.Commit{ + { + Hash: "36e65cb4a0448942ec316b24d60446bbd5cc7827", + Title: "kernel: add a bug", + Author: "author@kernel.org", + AuthorName: "Author Kernelov", + CC: []string{ + "reviewer1@kernel.org", "\"Reviewer2\" <reviewer2@kernel.org>", + // These must be filtered out: + "syzbot@testapp.appspotmail.com", + "syzbot+1234@testapp.appspotmail.com", + "\"syzbot\" <syzbot+1234@testapp.appspotmail.com>", + }, + Date: time.Date(2000, 2, 9, 4, 5, 6, 7, time.UTC), + }, + }, + } + c.expectOK(c.client2.JobDone(done)) + + // Advance time by 30 days and read out any notification emails + { + c.advanceTime(30 * 24 * time.Hour) + msg := c.client2.pollEmailBug() + c.expectTrue(strings.Contains(msg.Body, "syzbot has bisected this bug to:")) + msg = c.client2.pollEmailBug() + c.expectTrue(strings.Contains(msg.Body, "Sending this report upstream.")) + msg = c.client2.pollEmailBug() + c.expectTrue(strings.Contains(msg.Body, "syzbot found the following crash")) + } + + // Receive a JobBisectfix and send fix information. + resp = c.client2.pollJobs(build.Manager) + c.client2.expectNE(resp.ID, "") + c.client2.expectEQ(resp.Type, dashapi.JobBisectFix) + jobID = resp.ID + done = &dashapi.JobDoneReq{ + ID: jobID, + Build: *build, + Log: []byte("bisectfix log 4"), + CrashTitle: "bisectfix crash title 4", + CrashLog: []byte("bisectfix crash log 4"), + CrashReport: []byte("bisectfix crash report 4"), + Commits: []dashapi.Commit{ + { + Hash: "46e65cb4a0448942ec316b24d60446bbd5cc7827", + Title: "kernel: add a fix", + Author: "author@kernel.org", + AuthorName: "Author Kernelov", + CC: []string{ + "reviewer1@kernel.org", "\"Reviewer2\" <reviewer2@kernel.org>", + // These must be filtered out: + "syzbot@testapp.appspotmail.com", + "syzbot+1234@testapp.appspotmail.com", + "\"syzbot\" <syzbot+1234@testapp.appspotmail.com>", + }, + Date: time.Date(2000, 2, 9, 4, 5, 6, 7, time.UTC), + }, + }, + } + c.expectOK(c.client2.JobDone(done)) + + // Fetch bug details + var bugs []*Bug + keys, err := db.NewQuery("Bug").GetAll(c.ctx, &bugs) + c.expectEQ(err, nil) + c.expectEQ(len(bugs), 1) + + // Ensure expected results show up on web UI + url := fmt.Sprintf("/bug?id=%v", keys[0].StringID()) + content, err := c.httpRequest("GET", url, "", AccessAdmin) + c.expectEQ(err, nil) + c.expectTrue(bytes.Contains(content, []byte("Bisection: introduced by"))) + c.expectTrue(bytes.Contains(content, []byte("kernel: add a bug"))) + c.expectTrue(bytes.Contains(content, []byte("Bisection: fixed by"))) + c.expectTrue(bytes.Contains(content, []byte("kernel: add a fix"))) +} diff --git a/dashboard/app/bug.html b/dashboard/app/bug.html index 6bbf30fc7..2efb75a8c 100644 --- a/dashboard/app/bug.html +++ b/dashboard/app/bug.html @@ -60,6 +60,41 @@ Page with details about a single bug. {{optlink $bisect.Crash.KernelConfigLink ".config"}}<br> {{end}} + {{with $bisect := .BisectFix}}<br> + {{if $bisect.ErrorLink}} + <b>Bisection: {{link $bisect.ErrorLink "error"}} + ({{link $bisect.LogLink "bisect log"}})</b><br> + {{else if $bisect.Commit}}{{with $com := $bisect.Commit}} + <b>Bisection: fixed by + ({{link $bisect.LogLink "bisect log"}}):</b><br> + <br><span class="mono"> + commit {{$com.Hash}}<br> + Author: {{$com.Author}}<br> + Date: {{formatKernelTime $com.Date}}<br> + <br> + {{$com.Title}}<br> + </span><br> + {{end}}{{else if $bisect.Commits}}{{with $bisect.Commits}} + <b>Bisection: the fix commit could be any of + ({{link $bisect.LogLink "bisect log"}}):</b><br> + <br><span class="mono"> + {{range $com := $bisect.Commits}} + {{formatTagHash $com.Hash}} {{$com.Title}}<br> + {{end}} + </span><br> + {{end}}{{else}} + <b>Bisection: the bug occurs on the newest tested release + ({{link $bisect.LogLink "bisect log"}})</b><br> + {{end}} + Tree: <span title="{{$bisect.Manager}}">{{$bisect.KernelAlias}}</span><br> + {{if $bisect.CrashLogLink}} + Crash: {{link $bisect.CrashReportLink $bisect.CrashTitle}} ({{link $bisect.CrashLogLink "log"}})<br> + {{end}} + Repro: {{optlink $bisect.Crash.ReproCLink "C"}} + {{optlink $bisect.Crash.ReproSyzLink "syz"}} + {{optlink $bisect.Crash.KernelConfigLink ".config"}}<br> + {{end}} + {{template "bug_list" .DupOf}} {{template "bug_list" .Dups}} {{template "bug_list" .Similar}} diff --git a/dashboard/app/main.go b/dashboard/app/main.go index 4ac85e218..c1e47c6d0 100644 --- a/dashboard/app/main.go +++ b/dashboard/app/main.go @@ -111,6 +111,7 @@ type uiBugPage struct { Now time.Time Bug *uiBug BisectCause *uiJob + BisectFix *uiJob DupOf *uiBugGroup Dups *uiBugGroup Similar *uiBugGroup @@ -360,20 +361,17 @@ func handleBug(c context.Context, w http.ResponseWriter, r *http.Request) error } var bisectCause *uiJob if bug.BisectCause > BisectPending { - job, _, jobKey, _, err := loadBisectJob(c, bug) + bisectCause, err = getUIJob(c, bug, JobBisectCause) if err != nil { return err } - crash := new(Crash) - crashKey := db.NewKey(c, "Crash", "", job.CrashID, bug.key(c)) - if err := db.Get(c, crashKey, crash); err != nil { - return fmt.Errorf("failed to get crash: %v", err) - } - build, err := loadBuild(c, bug.Namespace, crash.BuildID) + } + var bisectFix *uiJob + if bug.BisectFix > BisectPending { + bisectFix, err = getUIJob(c, bug, JobBisectFix) if err != nil { return err } - bisectCause = makeUIJob(job, jobKey, crash, build) } hasMaintainers := false for _, crash := range crashes { @@ -387,6 +385,7 @@ func handleBug(c context.Context, w http.ResponseWriter, r *http.Request) error Now: timeNow(c), Bug: uiBug, BisectCause: bisectCause, + BisectFix: bisectFix, DupOf: dupOf, Dups: dups, Similar: similar, @@ -397,6 +396,23 @@ func handleBug(c context.Context, w http.ResponseWriter, r *http.Request) error return serveTemplate(w, "bug.html", data) } +func getUIJob(c context.Context, bug *Bug, jobType JobType) (*uiJob, error) { + job, _, jobKey, _, err := loadBisectJob(c, bug, jobType) + if err != nil { + return nil, err + } + crash := new(Crash) + crashKey := db.NewKey(c, "Crash", "", job.CrashID, bug.key(c)) + if err := db.Get(c, crashKey, crash); err != nil { + return nil, fmt.Errorf("failed to get crash: %v", err) + } + build, err := loadBuild(c, bug.Namespace, crash.BuildID) + if err != nil { + return nil, err + } + return makeUIJob(job, jobKey, crash, build), nil +} + // handleText serves plain text blobs (crash logs, reports, reproducers, etc). func handleTextImpl(c context.Context, w http.ResponseWriter, r *http.Request, tag string) error { var id int64 diff --git a/dashboard/app/reporting.go b/dashboard/app/reporting.go index 5020219d3..ee36930c5 100644 --- a/dashboard/app/reporting.go +++ b/dashboard/app/reporting.go @@ -303,7 +303,7 @@ func createBugReport(c context.Context, bug *Bug, crash *Crash, crashKey *db.Key var job *Job if bug.BisectCause == BisectYes { // If we have bisection results, report the crash/repro used for bisection. - job1, crash1, _, crashKey1, err := loadBisectJob(c, bug) + job1, crash1, _, crashKey1, err := loadBisectJob(c, bug, JobBisectCause) if err != nil { return nil, err } @@ -422,12 +422,12 @@ func fillBugReport(c context.Context, rep *dashapi.BugReport, bug *Bug, bugRepor return nil } -func loadBisectJob(c context.Context, bug *Bug) (*Job, *Crash, *db.Key, *db.Key, error) { +func loadBisectJob(c context.Context, bug *Bug, jobType JobType) (*Job, *Crash, *db.Key, *db.Key, error) { bugKey := bug.key(c) var jobs []*Job keys, err := db.NewQuery("Job"). Ancestor(bugKey). - Filter("Type=", JobBisectCause). + Filter("Type=", jobType). Filter("Finished>", time.Time{}). Order("-Finished"). Limit(1). @@ -436,7 +436,11 @@ func loadBisectJob(c context.Context, bug *Bug) (*Job, *Crash, *db.Key, *db.Key, return nil, nil, nil, nil, fmt.Errorf("failed to query jobs: %v", err) } if len(jobs) == 0 { - return nil, nil, nil, nil, fmt.Errorf("can't find bisect cause job for bug") + jobStr := map[JobType]string{ + JobBisectCause: "bisect cause", + JobBisectFix: "bisect fix", + } + return nil, nil, nil, nil, fmt.Errorf("can't find %s job for bug", jobStr[jobType]) } job := jobs[0] crash := new(Crash) |
