go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/logdog/appengine/coordinator/endpoints/services/archiveStream_test.go (about) 1 // Copyright 2015 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 services 16 17 import ( 18 "errors" 19 "testing" 20 "time" 21 22 "go.chromium.org/luci/gae/filter/featureBreaker" 23 ds "go.chromium.org/luci/gae/service/datastore" 24 logdog "go.chromium.org/luci/logdog/api/endpoints/coordinator/services/v1" 25 "go.chromium.org/luci/logdog/appengine/coordinator" 26 ct "go.chromium.org/luci/logdog/appengine/coordinator/coordinatorTest" 27 28 . "github.com/smartystreets/goconvey/convey" 29 . "go.chromium.org/luci/common/testing/assertions" 30 ) 31 32 func TestArchiveStream(t *testing.T) { 33 t.Parallel() 34 35 Convey(`With a testing configuration`, t, func() { 36 c, env := ct.Install() 37 38 svr := New(ServerSettings{NumQueues: 2}) 39 40 // Register a testing log stream with an archive tasked. 41 env.AddProject(c, "proj-foo") 42 tls := ct.MakeStream(c, "proj-foo", "some-realm", "testing/+/foo") 43 tls.State.ArchivalKey = []byte("archival key") 44 So(tls.State.ArchivalState(), ShouldEqual, coordinator.ArchiveTasked) 45 if err := tls.Put(c); err != nil { 46 panic(err) 47 } 48 49 // Advance the clock to differentiate updates from new stream. 50 env.Clock.Add(time.Hour) 51 now := ds.RoundTime(env.Clock.Now().UTC()) 52 53 req := &logdog.ArchiveStreamRequest{ 54 Project: string(tls.Project), 55 Id: string(tls.Stream.ID), 56 TerminalIndex: 13, 57 LogEntryCount: 14, 58 StreamUrl: "gs://fake.stream", 59 StreamSize: 10, 60 IndexUrl: "gs://fake.index", 61 IndexSize: 20, 62 } 63 64 Convey(`Returns Forbidden error if not a service.`, func() { 65 _, err := svr.ArchiveStream(c, req) 66 So(err, ShouldBeRPCPermissionDenied) 67 }) 68 69 Convey(`When logged in as a service`, func() { 70 env.ActAsService() 71 72 Convey(`Will mark the stream as archived.`, func() { 73 _, err := svr.ArchiveStream(c, req) 74 So(err, ShouldBeNil) 75 76 So(tls.Get(c), ShouldBeNil) 77 So(tls.State.Terminated(), ShouldBeTrue) 78 So(tls.State.ArchivalState(), ShouldEqual, coordinator.ArchivedComplete) 79 80 So(tls.State.Updated, ShouldResemble, now) 81 So(tls.State.ArchivalKey, ShouldBeNil) 82 So(tls.State.TerminatedTime, ShouldResemble, now) 83 So(tls.State.ArchivedTime, ShouldResemble, now) 84 So(tls.State.TerminalIndex, ShouldEqual, 13) 85 So(tls.State.ArchiveLogEntryCount, ShouldEqual, 14) 86 So(tls.State.ArchiveStreamURL, ShouldEqual, "gs://fake.stream") 87 So(tls.State.ArchiveStreamSize, ShouldEqual, 10) 88 So(tls.State.ArchiveIndexURL, ShouldEqual, "gs://fake.index") 89 So(tls.State.ArchiveIndexSize, ShouldEqual, 20) 90 }) 91 92 Convey(`Will mark the stream as partially archived if not complete.`, func() { 93 req.LogEntryCount = 13 94 95 _, err := svr.ArchiveStream(c, req) 96 So(err, ShouldBeNil) 97 98 So(tls.Get(c), ShouldBeNil) 99 So(tls.State.Terminated(), ShouldBeTrue) 100 So(tls.State.ArchivalState(), ShouldEqual, coordinator.ArchivedPartial) 101 102 So(tls.State.Updated, ShouldResemble, now) 103 So(tls.State.ArchivalKey, ShouldBeNil) 104 So(tls.State.TerminatedTime, ShouldResemble, now) 105 So(tls.State.ArchivedTime, ShouldResemble, now) 106 So(tls.State.TerminalIndex, ShouldEqual, 13) 107 So(tls.State.ArchiveLogEntryCount, ShouldEqual, 13) 108 So(tls.State.ArchiveStreamURL, ShouldEqual, "gs://fake.stream") 109 So(tls.State.ArchiveStreamSize, ShouldEqual, 10) 110 So(tls.State.ArchiveIndexURL, ShouldEqual, "gs://fake.index") 111 So(tls.State.ArchiveIndexSize, ShouldEqual, 20) 112 }) 113 114 Convey(`Will refuse to process an invalid stream hash.`, func() { 115 req.Id = "!!!invalid!!!" 116 _, err := svr.ArchiveStream(c, req) 117 So(err, ShouldBeRPCInvalidArgument, "Invalid ID") 118 }) 119 120 Convey(`If index URL is missing, will refuse to mark the stream archived.`, func() { 121 req.IndexUrl = "" 122 123 _, err := svr.ArchiveStream(c, req) 124 So(err, ShouldBeRPCInvalidArgument) 125 }) 126 127 Convey(`If stream URL is missing, will refuse to mark the stream archived.`, func() { 128 req.StreamUrl = "" 129 130 _, err := svr.ArchiveStream(c, req) 131 So(err, ShouldBeRPCInvalidArgument) 132 }) 133 134 Convey(`If stream is already archived, will not update and return success.`, func() { 135 tls.State.TerminalIndex = 1337 136 tls.State.ArchiveLogEntryCount = 42 137 tls.State.ArchivedTime = now 138 tls.State.TerminatedTime = now 139 140 So(tls.State.Terminated(), ShouldBeTrue) 141 So(tls.State.ArchivalState(), ShouldEqual, coordinator.ArchivedPartial) 142 So(tls.Put(c), ShouldBeNil) 143 144 _, err := svr.ArchiveStream(c, req) 145 So(err, ShouldBeNil) 146 147 tls.State.TerminalIndex = -1 // To make sure it reloaded. 148 So(tls.Get(c), ShouldBeNil) 149 So(tls.State.Terminated(), ShouldBeTrue) 150 So(tls.State.ArchivalState(), ShouldEqual, coordinator.ArchivedPartial) 151 152 So(tls.State.TerminalIndex, ShouldEqual, 1337) 153 So(tls.State.ArchiveLogEntryCount, ShouldEqual, 42) 154 }) 155 156 Convey(`If the archive has failed, it is archived as an empty stream.`, func() { 157 req.Error = "archive error" 158 159 _, err := svr.ArchiveStream(c, req) 160 So(err, ShouldBeNil) 161 So(tls.Get(c), ShouldBeNil) 162 So(tls.State.ArchivalState(), ShouldEqual, coordinator.ArchivedComplete) 163 164 So(tls.State.ArchivalKey, ShouldBeNil) 165 So(tls.State.TerminalIndex, ShouldEqual, -1) 166 So(tls.State.ArchiveLogEntryCount, ShouldEqual, 0) 167 }) 168 169 Convey(`When datastore Get fails, returns internal error.`, func() { 170 c, fb := featureBreaker.FilterRDS(c, nil) 171 fb.BreakFeatures(errors.New("test error"), "GetMulti") 172 173 _, err := svr.ArchiveStream(c, req) 174 So(err, ShouldBeRPCInternal) 175 }) 176 177 Convey(`When datastore Put fails, returns internal error.`, func() { 178 c, fb := featureBreaker.FilterRDS(c, nil) 179 fb.BreakFeatures(errors.New("test error"), "PutMulti") 180 181 _, err := svr.ArchiveStream(c, req) 182 So(err, ShouldBeRPCInternal) 183 }) 184 }) 185 }) 186 }