| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. |
| 4 |
| 5 package buildbot |
| 6 |
| 7 import ( |
| 8 "testing" |
| 9 |
| 10 miloProto "github.com/luci/luci-go/common/proto/milo" |
| 11 "github.com/luci/luci-go/logdog/api/endpoints/coordinator/logs/v1" |
| 12 "github.com/luci/luci-go/logdog/api/logpb" |
| 13 "github.com/luci/luci-go/logdog/client/coordinator" |
| 14 milo "github.com/luci/luci-go/milo/api/proto" |
| 15 |
| 16 "github.com/luci/gae/impl/memory" |
| 17 ds "github.com/luci/gae/service/datastore" |
| 18 |
| 19 "github.com/golang/protobuf/proto" |
| 20 "golang.org/x/net/context" |
| 21 "google.golang.org/grpc" |
| 22 |
| 23 . "github.com/luci/luci-go/common/testing/assertions" |
| 24 . "github.com/smartystreets/goconvey/convey" |
| 25 ) |
| 26 |
| 27 // testLogDogClient is a minimal functional LogsClient implementation. |
| 28 // |
| 29 // It retains its latest input parameter and returns its configured err (if not |
| 30 // nil) or resp. |
| 31 type testLogDogClient struct { |
| 32 logdog.LogsClient |
| 33 |
| 34 req []interface{} |
| 35 resp []interface{} |
| 36 err error |
| 37 } |
| 38 |
| 39 func (tc *testLogDogClient) popResp() (resp interface{}) { |
| 40 resp, tc.resp = tc.resp[0], tc.resp[1:] |
| 41 return |
| 42 } |
| 43 |
| 44 func (tc *testLogDogClient) Tail(ctx context.Context, in *logdog.TailRequest, op
ts ...grpc.CallOption) ( |
| 45 *logdog.GetResponse, error) { |
| 46 |
| 47 tc.req = append(tc.req, in) |
| 48 if tc.err != nil { |
| 49 return nil, tc.err |
| 50 } |
| 51 return tc.popResp().(*logdog.GetResponse), nil |
| 52 } |
| 53 |
| 54 // Query returns log stream paths that match the requested query. |
| 55 func (tc *testLogDogClient) Query(ctx context.Context, in *logdog.QueryRequest,
opts ...grpc.CallOption) ( |
| 56 *logdog.QueryResponse, error) { |
| 57 |
| 58 tc.req = append(tc.req, in) |
| 59 if tc.err != nil { |
| 60 return nil, tc.err |
| 61 } |
| 62 return tc.popResp().(*logdog.QueryResponse), nil |
| 63 } |
| 64 |
| 65 func datagramGetResponse(project, prefix string, msg proto.Message) *logdog.GetR
esponse { |
| 66 data, err := proto.Marshal(msg) |
| 67 if err != nil { |
| 68 panic(err) |
| 69 } |
| 70 return &logdog.GetResponse{ |
| 71 Project: project, |
| 72 Desc: &logpb.LogStreamDescriptor{ |
| 73 Prefix: prefix, |
| 74 ContentType: miloProto.ContentTypeAnnotations, |
| 75 StreamType: logpb.StreamType_DATAGRAM, |
| 76 }, |
| 77 State: &logdog.LogStreamState{}, |
| 78 Logs: []*logpb.LogEntry{ |
| 79 { |
| 80 Content: &logpb.LogEntry_Datagram{ |
| 81 Datagram: &logpb.Datagram{ |
| 82 Data: data, |
| 83 }, |
| 84 }, |
| 85 }, |
| 86 }, |
| 87 } |
| 88 } |
| 89 |
| 90 func TestBuildInfo(t *testing.T) { |
| 91 t.Parallel() |
| 92 |
| 93 Convey("A testing BuildInfoProvider", t, func() { |
| 94 c := context.Background() |
| 95 c = memory.Use(c) |
| 96 |
| 97 testClient := testLogDogClient{} |
| 98 bip := BuildInfoProvider{ |
| 99 LogdogClientFunc: func(context.Context) (*coordinator.Cl
ient, error) { |
| 100 return &coordinator.Client{ |
| 101 C: &testClient, |
| 102 Host: "example.com", |
| 103 }, nil |
| 104 }, |
| 105 } |
| 106 |
| 107 build := buildbotBuild{ |
| 108 Master: "foo master", |
| 109 Buildername: "bar builder", |
| 110 Number: 1337, |
| 111 Properties: []*buildbotProperty{ |
| 112 {Name: "foo", Value: "build-foo"}, |
| 113 {Name: "bar", Value: "build-bar"}, |
| 114 }, |
| 115 } |
| 116 |
| 117 logdogStep := miloProto.Step{ |
| 118 Command: &miloProto.Step_Command{ |
| 119 CommandLine: []string{"foo", "bar", "baz"}, |
| 120 }, |
| 121 Text: []string{"test step"}, |
| 122 Property: []*miloProto.Step_Property{ |
| 123 {Name: "bar", Value: "log-bar"}, |
| 124 }, |
| 125 } |
| 126 |
| 127 biReq := milo.BuildInfoRequest{ |
| 128 Build: &milo.BuildInfoRequest_Buildbot{ |
| 129 Buildbot: &milo.BuildInfoRequest_BuildBot{ |
| 130 MasterName: "foo master", |
| 131 BuilderName: "bar builder", |
| 132 BuildNumber: 1337, |
| 133 }, |
| 134 }, |
| 135 } |
| 136 |
| 137 Convey("Can load a BuildBot build by tag.", func() { |
| 138 build.Properties = append(build.Properties, []*buildbotP
roperty{ |
| 139 {Name: "logdog_prefix", Value: "foo/bar"}, |
| 140 {Name: "logdog_project", Value: "testproject"}, |
| 141 }...) |
| 142 So(ds.Put(c, &build), ShouldBeNil) |
| 143 testClient.resp = []interface{}{ |
| 144 datagramGetResponse("testproject", "foo/bar", &l
ogdogStep), |
| 145 } |
| 146 |
| 147 resp, err := bip.GetBuildInfo(c, biReq.GetBuildbot(), ""
) |
| 148 So(err, ShouldBeNil) |
| 149 So(testClient.req, ShouldResemble, []interface{}{ |
| 150 &logdog.TailRequest{ |
| 151 Project: "testproject", |
| 152 Path: "foo/bar/+/annotations", |
| 153 State: true, |
| 154 }, |
| 155 }) |
| 156 So(resp, ShouldResemble, &milo.BuildInfoResponse{ |
| 157 Project: "testproject", |
| 158 Step: &miloProto.Step{ |
| 159 Command: &miloProto.Step_Command{ |
| 160 CommandLine: []string{"foo", "ba
r", "baz"}, |
| 161 }, |
| 162 Text: []string{"test step"}, |
| 163 Property: []*miloProto.Step_Property{ |
| 164 {Name: "bar", Value: "log-bar"}, |
| 165 {Name: "foo", Value: "build-foo"
}, |
| 166 {Name: "logdog_prefix", Value: "
foo/bar"}, |
| 167 {Name: "logdog_project", Value:
"testproject"}, |
| 168 }, |
| 169 }, |
| 170 AnnotationStream: &miloProto.LogdogStream{ |
| 171 Server: "example.com", |
| 172 Prefix: "foo/bar", |
| 173 Name: "annotations", |
| 174 }, |
| 175 }) |
| 176 }) |
| 177 |
| 178 Convey("Fails to load a BuildBot build by query if no project hi
nt is provided.", func() { |
| 179 So(ds.Put(c, &build), ShouldBeNil) |
| 180 |
| 181 _, err := bip.GetBuildInfo(c, biReq.GetBuildbot(), "") |
| 182 So(err, ShouldErrLike, "annotation stream not found") |
| 183 }) |
| 184 |
| 185 Convey("Can load a BuildBot build by query with a project hint."
, func() { |
| 186 So(ds.Put(c, &build), ShouldBeNil) |
| 187 testClient.resp = []interface{}{ |
| 188 &logdog.QueryResponse{ |
| 189 Streams: []*logdog.QueryResponse_Stream{ |
| 190 { |
| 191 Path: "foo/bar/+/annota
tions", |
| 192 State: &logdog.LogStream
State{}, |
| 193 Desc: &logpb.LogStreamD
escriptor{}, |
| 194 }, |
| 195 { |
| 196 Path: "other/ignore/+/me
", |
| 197 }, |
| 198 }, |
| 199 }, |
| 200 datagramGetResponse("testproject", "foo/bar/+/an
notations", &logdogStep), |
| 201 } |
| 202 |
| 203 resp, err := bip.GetBuildInfo(c, biReq.GetBuildbot(), "t
estproject") |
| 204 So(err, ShouldBeNil) |
| 205 So(testClient.req, ShouldResemble, []interface{}{ |
| 206 &logdog.QueryRequest{ |
| 207 Project: "testproject", |
| 208 ContentType: miloProto.ContentTypeAnnota
tions, |
| 209 Tags: map[string]string{ |
| 210 "buildbot.master": "foo mas
ter", |
| 211 "buildbot.builder": "bar bui
lder", |
| 212 "buildbot.buildnumber": "1337", |
| 213 }, |
| 214 }, |
| 215 &logdog.TailRequest{ |
| 216 Project: "testproject", |
| 217 Path: "foo/bar/+/annotations", |
| 218 State: true, |
| 219 }, |
| 220 }) |
| 221 |
| 222 So(resp, ShouldResemble, &milo.BuildInfoResponse{ |
| 223 Project: "testproject", |
| 224 Step: &miloProto.Step{ |
| 225 Command: &miloProto.Step_Command{ |
| 226 CommandLine: []string{"foo", "ba
r", "baz"}, |
| 227 }, |
| 228 Text: []string{"test step"}, |
| 229 Property: []*miloProto.Step_Property{ |
| 230 {Name: "bar", Value: "log-bar"}, |
| 231 {Name: "foo", Value: "build-foo"
}, |
| 232 }, |
| 233 }, |
| 234 AnnotationStream: &miloProto.LogdogStream{ |
| 235 Server: "example.com", |
| 236 Prefix: "foo/bar", |
| 237 Name: "annotations", |
| 238 }, |
| 239 }) |
| 240 }) |
| 241 |
| 242 Convey("Can load a BuildBot build by inferred name.", func() { |
| 243 So(ds.Put(c, &build), ShouldBeNil) |
| 244 testClient.resp = []interface{}{ |
| 245 &logdog.QueryResponse{}, |
| 246 datagramGetResponse("testproject", "foo/bar/+/an
notations", &logdogStep), |
| 247 } |
| 248 |
| 249 resp, err := bip.GetBuildInfo(c, biReq.GetBuildbot(), "t
estproject") |
| 250 So(err, ShouldBeNil) |
| 251 So(testClient.req, ShouldResemble, []interface{}{ |
| 252 &logdog.QueryRequest{ |
| 253 Project: "testproject", |
| 254 ContentType: miloProto.ContentTypeAnnota
tions, |
| 255 Tags: map[string]string{ |
| 256 "buildbot.master": "foo mas
ter", |
| 257 "buildbot.builder": "bar bui
lder", |
| 258 "buildbot.buildnumber": "1337", |
| 259 }, |
| 260 }, |
| 261 &logdog.TailRequest{ |
| 262 Project: "testproject", |
| 263 Path: "bb/foo_master/bar_builder/1337
/+/annotations", |
| 264 State: true, |
| 265 }, |
| 266 }) |
| 267 |
| 268 So(resp, ShouldResemble, &milo.BuildInfoResponse{ |
| 269 Project: "testproject", |
| 270 Step: &miloProto.Step{ |
| 271 Command: &miloProto.Step_Command{ |
| 272 CommandLine: []string{"foo", "ba
r", "baz"}, |
| 273 }, |
| 274 Text: []string{"test step"}, |
| 275 Property: []*miloProto.Step_Property{ |
| 276 {Name: "bar", Value: "log-bar"}, |
| 277 {Name: "foo", Value: "build-foo"
}, |
| 278 }, |
| 279 }, |
| 280 AnnotationStream: &miloProto.LogdogStream{ |
| 281 Server: "example.com", |
| 282 Prefix: "bb/foo_master/bar_builder/1337"
, |
| 283 Name: "annotations", |
| 284 }, |
| 285 }) |
| 286 }) |
| 287 }) |
| 288 } |
| OLD | NEW |