aboutsummaryrefslogtreecommitdiffstats
path: root/syz-cluster/pkg/controller
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2026-02-16 08:48:25 +0000
committerAleksandr Nogikh <nogikh@google.com>2026-03-04 18:19:12 +0000
commit5675edac8a8dd3f3041df8d9ec79f95a42d434fa (patch)
treeeab8686c35dce571b119ddd3468ffc731688ec07 /syz-cluster/pkg/controller
parent12c7ee42182673f63622aadb91d5da1f2eedb8f1 (diff)
syz-cluster: add ListPreviousFindings API
The API call returns an aggregated list of findings in all previous versions of the specified patch series.
Diffstat (limited to 'syz-cluster/pkg/controller')
-rw-r--r--syz-cluster/pkg/controller/api.go14
-rw-r--r--syz-cluster/pkg/controller/api_test.go107
2 files changed, 121 insertions, 0 deletions
diff --git a/syz-cluster/pkg/controller/api.go b/syz-cluster/pkg/controller/api.go
index a9e3058f4..5d6ed247d 100644
--- a/syz-cluster/pkg/controller/api.go
+++ b/syz-cluster/pkg/controller/api.go
@@ -40,6 +40,7 @@ func (c APIServer) Mux() *http.ServeMux {
mux.HandleFunc("/builds/last", c.getLastBuild)
mux.HandleFunc("/builds/upload", c.uploadBuild)
mux.HandleFunc("/findings/upload", c.uploadFinding)
+ mux.HandleFunc("/findings/previous", c.getPreviousFindings)
mux.HandleFunc("/findings/{finding_id}", c.getFinding)
mux.HandleFunc("/series/upload", c.uploadSeries)
mux.HandleFunc("/series/{series_id}", c.getSeries)
@@ -166,6 +167,19 @@ func (c APIServer) uploadFinding(w http.ResponseWriter, r *http.Request) {
api.ReplyJSON[any](w, nil)
}
+func (c APIServer) getPreviousFindings(w http.ResponseWriter, r *http.Request) {
+ req := api.ParseJSON[api.ListPreviousFindingsReq](w, r)
+ if req == nil {
+ return
+ }
+ findings, err := c.findingService.ListPreviousFindings(r.Context(), req)
+ if err != nil {
+ http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
+ return
+ }
+ api.ReplyJSON(w, findings)
+}
+
func (c APIServer) getFinding(w http.ResponseWriter, r *http.Request) {
finding, err := c.findingService.Get(r.Context(), r.PathValue("finding_id"))
if errors.Is(err, service.ErrFindingNotFound) {
diff --git a/syz-cluster/pkg/controller/api_test.go b/syz-cluster/pkg/controller/api_test.go
index ea82b21cb..c31092a05 100644
--- a/syz-cluster/pkg/controller/api_test.go
+++ b/syz-cluster/pkg/controller/api_test.go
@@ -209,6 +209,113 @@ var testBuild = &api.Build{
BuildSuccess: true,
}
+func TestAPIListPreviousFindings(t *testing.T) {
+ env, ctx := app.TestEnvironment(t)
+ client := TestServer(t, env)
+
+ // Setup v1 Series.
+ // It has "Crash in foo" and "Crash in bar".
+ seriesV1 := DummySeries()
+ seriesV1.Version = 1
+ seriesV1.ExtID = "ext-id-1"
+ idsV1 := UploadTestSeries(t, ctx, client, seriesV1)
+
+ buildV1 := DummyBuild()
+ buildV1.ConfigName = "config-1"
+ buildV1Resp := UploadTestBuild(t, ctx, client, buildV1)
+
+ require.NoError(t, client.UploadSessionTest(ctx, &api.SessionTest{
+ SessionID: idsV1.SessionID,
+ TestName: "test",
+ Result: api.TestPassed,
+ PatchedBuildID: buildV1Resp.ID,
+ Log: []byte("log"),
+ }))
+
+ require.NoError(t, client.UploadFinding(ctx, &api.RawFinding{
+ SessionID: idsV1.SessionID,
+ Title: "Crash in foo",
+ TestName: "test",
+ }))
+ require.NoError(t, client.UploadFinding(ctx, &api.RawFinding{
+ SessionID: idsV1.SessionID,
+ Title: "Crash in bar",
+ TestName: "test",
+ }))
+ MarkSessionFinished(t, env, idsV1.SessionID)
+
+ // Setup v2 Series.
+ seriesV2 := DummySeries()
+ seriesV2.Version = 2
+ seriesV2.ExtID = "ext-id-2"
+ idsV2 := UploadTestSeries(t, ctx, client, seriesV2)
+
+ buildV2 := DummyBuild()
+ buildV2.ConfigName = "config-1"
+ buildV2Resp := UploadTestBuild(t, ctx, client, buildV2)
+
+ require.NoError(t, client.UploadSessionTest(ctx, &api.SessionTest{
+ SessionID: idsV2.SessionID,
+ TestName: "test",
+ Result: api.TestPassed,
+ PatchedBuildID: buildV2Resp.ID,
+ Log: []byte("log"),
+ }))
+
+ require.NoError(t, client.UploadFinding(ctx, &api.RawFinding{
+ SessionID: idsV2.SessionID,
+ Title: "Crash in foo",
+ TestName: "test",
+ }))
+ MarkSessionFinished(t, env, idsV2.SessionID)
+
+ // Setup v3 Series.
+ seriesV3 := DummySeries()
+ seriesV3.Version = 3
+ seriesV3.ExtID = "ext-id-3"
+ idsV3 := UploadTestSeries(t, ctx, client, seriesV3)
+
+ list, err := client.ListPreviousFindings(ctx, &api.ListPreviousFindingsReq{
+ SeriesID: idsV3.SeriesID,
+ })
+ require.NoError(t, err)
+ require.Len(t, list, 2)
+
+ finding1, err := client.GetFinding(ctx, list[0])
+ require.NoError(t, err)
+ assert.Equal(t, "Crash in foo", finding1.Title)
+ assert.Equal(t, idsV2.SessionID, finding1.SessionID)
+
+ finding2, err := client.GetFinding(ctx, list[1])
+ require.NoError(t, err)
+ assert.Equal(t, "Crash in bar", finding2.Title)
+ assert.Equal(t, idsV1.SessionID, finding2.SessionID)
+
+ list, err = client.ListPreviousFindings(ctx, &api.ListPreviousFindingsReq{
+ SeriesID: idsV3.SeriesID,
+ Arch: buildV1.Arch,
+ Config: buildV1.ConfigName,
+ })
+ require.NoError(t, err)
+ require.Len(t, list, 2)
+
+ list, err = client.ListPreviousFindings(ctx, &api.ListPreviousFindingsReq{
+ SeriesID: idsV3.SeriesID,
+ Arch: "wrong-arch",
+ Config: buildV1.ConfigName,
+ })
+ require.NoError(t, err)
+ require.Empty(t, list)
+
+ list, err = client.ListPreviousFindings(ctx, &api.ListPreviousFindingsReq{
+ SeriesID: idsV2.SeriesID,
+ Arch: buildV1.Arch,
+ Config: "wrong-config",
+ })
+ require.NoError(t, err)
+ require.Empty(t, list)
+}
+
func TestAPIGetFinding(t *testing.T) {
env, ctx := app.TestEnvironment(t)
client := TestServer(t, env)