go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/analysis/app/commitverifier_test.go (about) 1 // Copyright 2022 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package app 16 17 import ( 18 "context" 19 "fmt" 20 "io" 21 "net/http" 22 "net/http/httptest" 23 "testing" 24 25 "google.golang.org/protobuf/encoding/protojson" 26 27 "go.chromium.org/luci/common/tsmon" 28 cvv1 "go.chromium.org/luci/cv/api/v1" 29 "go.chromium.org/luci/server/router" 30 31 _ "go.chromium.org/luci/analysis/internal/services/resultingester" // Needed to ensure task class is registered. 32 33 . "github.com/smartystreets/goconvey/convey" 34 . "go.chromium.org/luci/common/testing/assertions" 35 ) 36 37 func TestCVRunHandler(t *testing.T) { 38 Convey(`Test CVRunHandler`, t, func() { 39 ctx, _ := tsmon.WithDummyInMemory(context.Background()) 40 41 rID := "id_full_run" 42 fullRunID := fullRunID("cvproject", rID) 43 44 h := &CVRunHandler{} 45 rsp := httptest.NewRecorder() 46 rctx := &router.Context{ 47 Writer: rsp, 48 } 49 Convey(`Valid message`, func() { 50 message := &cvv1.PubSubRun{ 51 Id: fullRunID, 52 Status: cvv1.Run_SUCCEEDED, 53 Hostname: "cvhost", 54 } 55 56 called := false 57 var processed bool 58 h.handleCVRun = func(ctx context.Context, psRun *cvv1.PubSubRun) (project string, wasProcessed bool, err error) { 59 So(called, ShouldBeFalse) 60 So(psRun, ShouldResembleProto, message) 61 62 called = true 63 return "cvproject", processed, nil 64 } 65 66 Convey(`Processed`, func() { 67 processed = true 68 69 rctx.Request = (&http.Request{Body: makeCVRunReq(message)}).WithContext(ctx) 70 h.Handle(rctx) 71 So(rsp.Code, ShouldEqual, http.StatusOK) 72 So(cvRunCounter.Get(ctx, "cvproject", "success"), ShouldEqual, 1) 73 }) 74 Convey(`Not processed`, func() { 75 processed = false 76 77 rctx.Request = (&http.Request{Body: makeCVRunReq(message)}).WithContext(ctx) 78 h.Handle(rctx) 79 So(rsp.Code, ShouldEqual, http.StatusNoContent) 80 So(cvRunCounter.Get(ctx, "cvproject", "ignored"), ShouldEqual, 1) 81 }) 82 }) 83 Convey(`Invalid data`, func() { 84 h.handleCVRun = func(ctx context.Context, psRun *cvv1.PubSubRun) (project string, wasProcessed bool, err error) { 85 panic("Should not be reached.") 86 } 87 88 rctx.Request = (&http.Request{Body: makeReq([]byte("Hello"), nil)}).WithContext(ctx) 89 h.Handle(rctx) 90 So(rsp.Code, ShouldEqual, http.StatusAccepted) 91 So(cvRunCounter.Get(ctx, "unknown", "permanent-failure"), ShouldEqual, 1) 92 }) 93 }) 94 } 95 96 func makeCVRunReq(message *cvv1.PubSubRun) io.ReadCloser { 97 blob, _ := protojson.Marshal(message) 98 return makeReq(blob, nil) 99 } 100 101 func fullRunID(project, runID string) string { 102 return fmt.Sprintf("projects/%s/runs/%s", project, runID) 103 }