aboutsummaryrefslogtreecommitdiffstats
path: root/dashboard
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2022-12-22 11:35:38 +0100
committerAleksandr Nogikh <wp32pw@gmail.com>2023-01-11 13:14:11 +0100
commit96166539c4c242fccd41c7316b7080377dca428b (patch)
treef1d80628667c9daa66d80b6c0f8df7ea5cc72de4 /dashboard
parent48bc529a18de54dddab161d995fc3abd85a670a8 (diff)
dashboard: support the only_manager filter
The manager= filter limits the dashboard output only to the bugs that happened on the specified manager (but not exclusively there). Introduce the only_manager= filter to only show the bugs that happened ONLY on the specified manager.
Diffstat (limited to 'dashboard')
-rw-r--r--dashboard/app/main.go37
-rw-r--r--dashboard/app/main_test.go77
2 files changed, 105 insertions, 9 deletions
diff --git a/dashboard/app/main.go b/dashboard/app/main.go
index a74ee39df..1448796c6 100644
--- a/dashboard/app/main.go
+++ b/dashboard/app/main.go
@@ -299,12 +299,16 @@ func handleMain(c context.Context, w http.ResponseWriter, r *http.Request) error
return err
}
accessLevel := accessLevel(c, r)
- manager := r.FormValue("manager")
+ onlyManager := r.FormValue("only_manager")
+ manager := onlyManager
+ if manager == "" {
+ manager = r.FormValue("manager")
+ }
managers, err := loadManagers(c, accessLevel, hdr.Namespace, manager)
if err != nil {
return err
}
- groups, err := fetchNamespaceBugs(c, accessLevel, hdr.Namespace, manager)
+ groups, err := fetchNamespaceBugs(c, accessLevel, hdr.Namespace, manager, onlyManager != "")
if err != nil {
return err
}
@@ -360,6 +364,8 @@ type TerminalBug struct {
ShowPatch bool
ShowPatched bool
ShowStats bool
+ Manager string
+ OneManager bool
}
func handleTerminalBugList(c context.Context, w http.ResponseWriter, r *http.Request, typ *TerminalBug) error {
@@ -369,16 +375,22 @@ func handleTerminalBugList(c context.Context, w http.ResponseWriter, r *http.Req
return err
}
hdr.Subpage = typ.Subpage
- manager := r.FormValue("manager")
+ onlyManager := r.FormValue("only_manager")
+ if onlyManager != "" {
+ typ.Manager = onlyManager
+ typ.OneManager = true
+ } else {
+ typ.Manager = r.FormValue("manager")
+ }
extraBugs := []*Bug{}
if typ.Status == BugStatusFixed {
// Mix in bugs that have pending fixes.
- extraBugs, err = fetchFixPendingBugs(c, hdr.Namespace, manager)
+ extraBugs, err = fetchFixPendingBugs(c, hdr.Namespace, typ.Manager)
if err != nil {
return err
}
}
- bugs, stats, err := fetchTerminalBugs(c, accessLevel, hdr.Namespace, manager, typ, extraBugs)
+ bugs, stats, err := fetchTerminalBugs(c, accessLevel, hdr.Namespace, typ, extraBugs)
if err != nil {
return err
}
@@ -796,7 +808,8 @@ func fetchFixPendingBugs(c context.Context, ns, manager string) ([]*Bug, error)
return rawBugs, nil
}
-func fetchNamespaceBugs(c context.Context, accessLevel AccessLevel, ns, manager string) ([]*uiBugGroup, error) {
+func fetchNamespaceBugs(c context.Context, accessLevel AccessLevel, ns,
+ manager string, oneManager bool) ([]*uiBugGroup, error) {
bugs, err := loadVisibleBugs(c, accessLevel, ns, manager)
if err != nil {
return nil, err
@@ -820,6 +833,9 @@ func fetchNamespaceBugs(c context.Context, accessLevel AccessLevel, ns, manager
dups = append(dups, bug)
continue
}
+ if oneManager && len(bug.HappenedOn) > 1 {
+ continue
+ }
uiBug := createUIBug(c, bug, state, managers)
if len(uiBug.Commits) != 0 {
// Don't show "fix pending" bugs on the main page.
@@ -914,12 +930,12 @@ func loadVisibleBugs(c context.Context, accessLevel AccessLevel, ns, manager str
}
func fetchTerminalBugs(c context.Context, accessLevel AccessLevel,
- ns, manager string, typ *TerminalBug, extraBugs []*Bug) (*uiBugGroup, *uiBugStats, error) {
+ ns string, typ *TerminalBug, extraBugs []*Bug) (*uiBugGroup, *uiBugStats, error) {
bugs, _, err := loadAllBugs(c, func(query *db.Query) *db.Query {
query = query.Filter("Namespace=", ns).
Filter("Status=", typ.Status)
- if manager != "" {
- query = query.Filter("HappenedOn=", manager)
+ if typ.Manager != "" {
+ query = query.Filter("HappenedOn=", typ.Manager)
}
return query
})
@@ -955,6 +971,9 @@ func fetchTerminalBugs(c context.Context, accessLevel AccessLevel,
if accessLevel < bug.sanitizeAccess(accessLevel) {
continue
}
+ if typ.OneManager && len(bug.HappenedOn) > 1 {
+ continue
+ }
uiBug := createUIBug(c, bug, state, managers)
res.Bugs = append(res.Bugs, uiBug)
stats.Record(bug, &bug.Reporting[uiBug.ReportingIndex])
diff --git a/dashboard/app/main_test.go b/dashboard/app/main_test.go
new file mode 100644
index 000000000..1629bab31
--- /dev/null
+++ b/dashboard/app/main_test.go
@@ -0,0 +1,77 @@
+// Copyright 2023 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 main
+
+import (
+ "bytes"
+ "testing"
+
+ "github.com/google/syzkaller/dashboard/dashapi"
+)
+
+func TestOnlyManagerFilter(t *testing.T) {
+ c := NewCtx(t)
+ defer c.Close()
+
+ client := c.client
+ build1 := testBuild(1)
+ client.UploadBuild(build1)
+ build2 := testBuild(2)
+ client.UploadBuild(build2)
+
+ crash1 := testCrash(build1, 1)
+ crash1.Title = "only the first manager"
+ client.ReportCrash(crash1)
+
+ crash2 := testCrash(build2, 2)
+ crash2.Title = "only the second manager"
+ client.ReportCrash(crash2)
+
+ crashBoth1 := testCrash(build1, 3)
+ crashBoth1.Title = "both managers"
+ client.ReportCrash(crashBoth1)
+
+ crashBoth2 := testCrash(build2, 4)
+ crashBoth2.Title = "both managers"
+ client.ReportCrash(crashBoth2)
+
+ // Make sure all those bugs are present on the main page.
+ reply, err := c.AuthGET(AccessAdmin, "/test1")
+ c.expectOK(err)
+ for _, title := range []string{crash1.Title, crash2.Title, crashBoth1.Title} {
+ if !bytes.Contains(reply, []byte(title)) {
+ t.Fatalf("%#v is not contained on the main page", title)
+ }
+ }
+
+ // Check that filtering on the main page works.
+ reply, err = c.AuthGET(AccessAdmin, "/test1?only_manager="+build1.Manager)
+ c.expectOK(err)
+ for _, title := range []string{crash2.Title, crashBoth1.Title} {
+ if bytes.Contains(reply, []byte(title)) {
+ t.Fatalf("%#v is contained on the main page", title)
+ }
+ }
+ if !bytes.Contains(reply, []byte(crash1.Title)) {
+ t.Fatalf("%#v is not contained on the main page", crash1.Title)
+ }
+
+ // Invalidate all these bugs.
+ polledBugs := client.pollBugs(3)
+ for _, bug := range polledBugs {
+ client.updateBug(bug.ID, dashapi.BugStatusInvalid, "")
+ }
+
+ // Verify that the filtering works on the invalid bugs page.
+ reply, err = c.AuthGET(AccessAdmin, "/test1/invalid?only_manager="+build2.Manager)
+ c.expectOK(err)
+ for _, title := range []string{crash1.Title, crashBoth1.Title} {
+ if bytes.Contains(reply, []byte(title)) {
+ t.Fatalf("%#v is contained on the invalid bugs page", title)
+ }
+ }
+ if !bytes.Contains(reply, []byte(crash2.Title)) {
+ t.Fatalf("%#v is not contained on the invalid bugs page", crash2.Title)
+ }
+}