aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortarasmadan <89859571+tarasmadan@users.noreply.github.com>2021-10-25 12:45:20 +0200
committerGitHub <noreply@github.com>2021-10-25 12:45:20 +0200
commit78e5f70a82a166b5b31c67eeed2563d754a478d2 (patch)
tree65cb5029ae0be6e5292519e86b18c5e6fa23cd42
parent4f0000ee28dffdfa5be45c94f77c16ec68994384 (diff)
dashboard/app: return JSON data for the /bug requests with "&json=1" (#2823)
-rw-r--r--dashboard/app/getjson_test.go65
-rw-r--r--dashboard/app/main.go19
-rw-r--r--dashboard/app/public_json_api.go43
3 files changed, 127 insertions, 0 deletions
diff --git a/dashboard/app/getjson_test.go b/dashboard/app/getjson_test.go
new file mode 100644
index 000000000..86536e9df
--- /dev/null
+++ b/dashboard/app/getjson_test.go
@@ -0,0 +1,65 @@
+// Copyright 2021 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"
+ "encoding/json"
+ "fmt"
+ "testing"
+)
+
+func TestJSONAPIIntegration(t *testing.T) {
+ sampleCrashDescr := []byte(`{
+ "version":1,
+ "title":"title1",
+ "crashes":[{
+ "kernel-config":"/text?tag=KernelConfig\u0026x=a989f27ebc47e2dc",
+ "kernel-source-commit":"1111111111111111111111111111111111111111",
+ "syzkaller-git":"https://github.com/google/syzkaller/commits/syzkaller_commit1",
+ "syzkaller-commit":"syzkaller_commit1"
+ }]
+ }`)
+
+ sampleCrashWithReproDescr := []byte(`{
+ "version":1,
+ "title":"title2",
+ "crashes":[{
+ "syz-reproducer":"/text?tag=ReproSyz\u0026x=13000000000000",
+ "c-reproducer":"/text?tag=ReproC\u0026x=17000000000000",
+ "kernel-config":"/text?tag=KernelConfig\u0026x=a989f27ebc47e2dc",
+ "kernel-source-commit":"1111111111111111111111111111111111111111",
+ "syzkaller-git":"https://github.com/google/syzkaller/commits/syzkaller_commit1",
+ "syzkaller-commit":"syzkaller_commit1"
+ }]
+ }`)
+
+ c := NewCtx(t)
+ defer c.Close()
+
+ c.makeClient(client1, password1, false)
+
+ build := testBuild(1)
+ c.client.UploadBuild(build)
+
+ crash1 := testCrash(build, 1)
+ c.client.ReportCrash(crash1)
+ bugReport1 := c.client.pollBug()
+ checkBugPageJSONIs(c, bugReport1.ID, sampleCrashDescr)
+
+ crash2 := testCrashWithRepro(build, 2)
+ c.client.ReportCrash(crash2)
+ bugReport2 := c.client.pollBug()
+ checkBugPageJSONIs(c, bugReport2.ID, sampleCrashWithReproDescr)
+}
+
+func checkBugPageJSONIs(c *Ctx, ID string, expectedContent []byte) {
+ url := fmt.Sprintf("/bug?extid=%v&json=1", ID)
+ actualContent, _ := c.client.httpRequest("GET", url, "", AccessAdmin)
+
+ var minExpectedContent bytes.Buffer
+ json.Compact(&minExpectedContent, expectedContent)
+
+ c.expectEQ(string(actualContent), minExpectedContent.String())
+}
diff --git a/dashboard/app/main.go b/dashboard/app/main.go
index b7d2ed69f..bef434663 100644
--- a/dashboard/app/main.go
+++ b/dashboard/app/main.go
@@ -5,6 +5,7 @@ package main
import (
"bytes"
+ "encoding/json"
"fmt"
"net/http"
"sort"
@@ -433,9 +434,27 @@ func handleBug(c context.Context, w http.ResponseWriter, r *http.Request) error
}
}
}
+
+ if isJSONRequested(r) {
+ return writeJSONVersionOf(w, data)
+ }
+
return serveTemplate(w, "bug.html", data)
}
+func isJSONRequested(request *http.Request) bool {
+ return request.FormValue("json") == "1"
+}
+
+func writeJSONVersionOf(writer http.ResponseWriter, bugPage *uiBugPage) error {
+ data, err := json.Marshal(GetExtAPIDescrForBugPage(bugPage))
+ if err != nil {
+ return err
+ }
+ _, err = writer.Write(data)
+ return err
+}
+
func findBugByID(c context.Context, r *http.Request) (*Bug, error) {
if id := r.FormValue("id"); id != "" {
bug := new(Bug)
diff --git a/dashboard/app/public_json_api.go b/dashboard/app/public_json_api.go
new file mode 100644
index 000000000..f2220eee6
--- /dev/null
+++ b/dashboard/app/public_json_api.go
@@ -0,0 +1,43 @@
+// Copyright 2021 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
+
+// publicApiBugDescription is used to serve the /bug HTTP requests
+// and provide JSON description of the BUG. Backward compatible.
+type PublicAPIBugDescription struct {
+ Version int `json:"version"`
+ Title string `json:"title,omitempty"`
+ Crashes []PublicAPICrashDescription `json:"crashes,omitempty"`
+}
+
+type PublicAPICrashDescription struct {
+ SyzReproducer string `json:"syz-reproducer,omitempty"`
+ CReproducer string `json:"c-reproducer,omitempty"`
+ KernelConfig string `json:"kernel-config,omitempty"`
+ KernelSourceGit string `json:"kernel-source-git,omitempty"`
+ KernelSourceCommit string `json:"kernel-source-commit,omitempty"`
+ SyzkallerGit string `json:"syzkaller-git,omitempty"`
+ SyzkallerCommit string `json:"syzkaller-commit,omitempty"`
+ CompilerDescription string `json:"compiler-description,omitempty"`
+ Architecture string `json:"architecture,omitempty"`
+}
+
+func GetExtAPIDescrForBugPage(bugPage *uiBugPage) *PublicAPIBugDescription {
+ crash := bugPage.Crashes.Crashes[0]
+ return &PublicAPIBugDescription{
+ Version: 1,
+ Title: bugPage.Bug.Title,
+ Crashes: []PublicAPICrashDescription{{
+ SyzReproducer: crash.ReproSyzLink,
+ CReproducer: crash.ReproCLink,
+ KernelConfig: crash.KernelConfigLink,
+ KernelSourceGit: crash.KernelCommitLink,
+ KernelSourceCommit: crash.KernelCommit,
+ SyzkallerGit: crash.SyzkallerCommitLink,
+ SyzkallerCommit: crash.SyzkallerCommit,
+ // TODO: add the CompilerDescription
+ // TODO: add the Architecture
+ }},
+ }
+}