aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZubin Mithra <zsm@chromium.org>2019-07-30 10:58:08 -0700
committerDmitry Vyukov <dvyukov@google.com>2019-08-01 13:43:22 +0200
commit835dffe7e5d185154a9b147476a17b6301ee139e (patch)
tree463910ecb9f9a7e54053961b3a402f53176d2261
parentc692b5bdabba075211571ae6dfe3453a8193591a (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.go103
-rw-r--r--dashboard/app/bug.html35
-rw-r--r--dashboard/app/main.go32
-rw-r--r--dashboard/app/reporting.go12
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>
+ &nbsp;&nbsp;{{$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}}
+ &nbsp;&nbsp;{{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)