github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/syz-cluster/pkg/controller/api_test.go (about) 1 // Copyright 2024 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package controller 5 6 import ( 7 "bytes" 8 "testing" 9 "time" 10 11 "github.com/google/syzkaller/syz-cluster/pkg/api" 12 "github.com/google/syzkaller/syz-cluster/pkg/app" 13 "github.com/google/syzkaller/syz-cluster/pkg/db" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestAPIGetSeries(t *testing.T) { 19 env, ctx := app.TestEnvironment(t) 20 client := TestServer(t, env) 21 ids := UploadTestSeries(t, ctx, client, testSeries) 22 23 ret, err := client.GetSessionSeries(ctx, ids.SessionID) 24 assert.NoError(t, err) 25 ret.ID = "" 26 assert.Equal(t, testSeries, ret) 27 28 ret, err = client.GetSeries(ctx, ids.SeriesID) 29 assert.NoError(t, err) 30 ret.ID = "" 31 assert.Equal(t, testSeries, ret) 32 } 33 34 func TestAPISuccessfulBuild(t *testing.T) { 35 env, ctx := app.TestEnvironment(t) 36 client := TestServer(t, env) 37 UploadTestBuild(t, ctx, client, testBuild) 38 info, err := client.LastBuild(ctx, &api.LastBuildReq{ 39 Arch: testBuild.Arch, 40 TreeName: testBuild.TreeName, 41 ConfigName: testBuild.ConfigName, 42 Status: api.BuildSuccess, 43 }) 44 assert.NoError(t, err) 45 assert.Equal(t, testBuild, info) 46 } 47 48 func TestAPISaveFinding(t *testing.T) { 49 env, ctx := app.TestEnvironment(t) 50 client := TestServer(t, env) 51 52 ids := UploadTestSeries(t, ctx, client, testSeries) 53 buildResp := UploadTestBuild(t, ctx, client, testBuild) 54 err := client.UploadTestResult(ctx, &api.TestResult{ 55 SessionID: ids.SessionID, 56 BaseBuildID: buildResp.ID, 57 TestName: "test", 58 Result: api.TestRunning, 59 Log: []byte("some log"), 60 }) 61 assert.NoError(t, err) 62 63 t.Run("not existing test", func(t *testing.T) { 64 err = client.UploadFinding(ctx, &api.NewFinding{ 65 SessionID: ids.SessionID, 66 TestName: "unknown test", 67 }) 68 assert.Error(t, err) 69 }) 70 71 t.Run("must succeed", func(t *testing.T) { 72 finding := &api.NewFinding{ 73 SessionID: ids.SessionID, 74 TestName: "test", 75 Title: "title", 76 Report: []byte("report"), 77 Log: []byte("log"), 78 SyzRepro: []byte("syz repro"), 79 SyzReproOpts: []byte("syz_repro_opts"), 80 } 81 err = client.UploadFinding(ctx, finding) 82 assert.NoError(t, err) 83 // Even if the same finding is reported the second time, it must still not fail. 84 err = client.UploadFinding(ctx, finding) 85 assert.NoError(t, err) 86 }) 87 88 t.Run("add C repro", func(t *testing.T) { 89 finding := &api.NewFinding{ 90 SessionID: ids.SessionID, 91 TestName: "test", 92 Title: "title", 93 Report: []byte("report"), 94 Log: []byte("log"), 95 SyzRepro: []byte("syz repro"), 96 SyzReproOpts: []byte("syz_repro_opts"), 97 CRepro: []byte("C repro"), 98 } 99 err = client.UploadFinding(ctx, finding) 100 assert.NoError(t, err) 101 // Verify that C repro has appeared indeed. 102 findingRepo := db.NewFindingRepository(env.Spanner) 103 findings, err := findingRepo.ListForSession(ctx, ids.SessionID, db.NoLimit) 104 require.NoError(t, err) 105 require.Len(t, findings, 1) 106 assert.NotEmpty(t, findings[0].CReproURI) 107 }) 108 109 t.Run("session stopped", func(t *testing.T) { 110 MarkSessionFinished(t, env, ids.SessionID) 111 finding := &api.NewFinding{ 112 SessionID: ids.SessionID, 113 TestName: "test", 114 Title: "new title", 115 Report: []byte("report"), 116 Log: []byte("log"), 117 SyzRepro: []byte("syz repro"), 118 } 119 err = client.UploadFinding(ctx, finding) 120 assert.ErrorContains(t, err, "session is already finished") 121 }) 122 } 123 124 func TestAPIUploadTestArtifacts(t *testing.T) { 125 env, ctx := app.TestEnvironment(t) 126 client := TestServer(t, env) 127 128 ids := UploadTestSeries(t, ctx, client, testSeries) 129 buildResp := UploadTestBuild(t, ctx, client, testBuild) 130 err := client.UploadTestResult(ctx, &api.TestResult{ 131 SessionID: ids.SessionID, 132 BaseBuildID: buildResp.ID, 133 TestName: "test", 134 Result: api.TestRunning, 135 Log: []byte("some log"), 136 }) 137 assert.NoError(t, err) 138 err = client.UploadTestArtifacts(ctx, ids.SessionID, "test", bytes.NewReader([]byte("artifacts content"))) 139 assert.NoError(t, err) 140 } 141 142 func TestAPIBaseFindings(t *testing.T) { 143 env, ctx := app.TestEnvironment(t) 144 client := TestServer(t, env) 145 buildResp := UploadTestBuild(t, ctx, client, testBuild) 146 147 err := client.UploadBaseFinding(ctx, &api.BaseFindingInfo{ 148 BuildID: buildResp.ID, 149 Title: "title 1", 150 }) 151 assert.NoError(t, err) 152 153 // Let's upload a different build for the same revision. 154 buildResp2 := UploadTestBuild(t, ctx, client, testBuild) 155 assert.NotEqual(t, buildResp.ID, buildResp2.ID) 156 157 resp, err := client.BaseFindingStatus(ctx, &api.BaseFindingInfo{ 158 BuildID: buildResp2.ID, 159 Title: "title 1", 160 }) 161 assert.NoError(t, err) 162 assert.True(t, resp.Observed) 163 164 t.Run("unseen title", func(t *testing.T) { 165 resp, err := client.BaseFindingStatus(ctx, &api.BaseFindingInfo{ 166 BuildID: buildResp2.ID, 167 Title: "title 2", 168 }) 169 assert.NoError(t, err) 170 assert.False(t, resp.Observed) 171 }) 172 173 t.Run("invalid build id", func(t *testing.T) { 174 _, err := client.BaseFindingStatus(ctx, &api.BaseFindingInfo{ 175 BuildID: "unknown id", 176 Title: "title 1", 177 }) 178 assert.Error(t, err) 179 }) 180 } 181 182 var testSeries = &api.Series{ 183 ExtID: "ext-id", 184 AuthorEmail: "some@email.com", 185 Title: "test series name", 186 Version: 2, 187 PublishedAt: time.Date(2020, time.January, 1, 3, 0, 0, 0, time.UTC), 188 Cc: []string{"email"}, 189 SubjectTags: []string{"tag"}, 190 Patches: []api.SeriesPatch{ 191 { 192 Seq: 1, 193 Body: []byte("first content"), 194 }, 195 { 196 Seq: 2, 197 Body: []byte("second content"), 198 }, 199 }, 200 } 201 202 var testBuild = &api.Build{ 203 Arch: "amd64", 204 TreeName: "mainline", 205 TreeURL: "https://git/tree", 206 ConfigName: "config", 207 CommitHash: "abcd", 208 CommitDate: time.Date(2020, time.January, 1, 3, 0, 0, 0, time.UTC), 209 BuildSuccess: true, 210 }