diff options
| author | tarasmadan <89859571+tarasmadan@users.noreply.github.com> | 2021-10-25 12:45:20 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-25 12:45:20 +0200 |
| commit | 78e5f70a82a166b5b31c67eeed2563d754a478d2 (patch) | |
| tree | 65cb5029ae0be6e5292519e86b18c5e6fa23cd42 | |
| parent | 4f0000ee28dffdfa5be45c94f77c16ec68994384 (diff) | |
dashboard/app: return JSON data for the /bug requests with "&json=1" (#2823)
| -rw-r--r-- | dashboard/app/getjson_test.go | 65 | ||||
| -rw-r--r-- | dashboard/app/main.go | 19 | ||||
| -rw-r--r-- | dashboard/app/public_json_api.go | 43 |
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 + }}, + } +} |
