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("Load an invalid build", func() { | |
138 _, err := bip.GetBuildInfo(c, | |
139 &milo.BuildInfoRequest_BuildBot{ | |
140 MasterName: "foo master", | |
141 BuilderName: "bar builder", | |
142 BuildNumber: 1334, | |
143 }, "") | |
144 So(err.Error(), ShouldResemble, "rpc error: code = Unaut
henticated desc = ") | |
145 }) | |
146 | |
147 Convey("Can load a BuildBot build by log location.", func() { | |
148 build.Properties = append(build.Properties, []*buildbotP
roperty{ | |
149 {Name: "log_location", Value: "logdog://example.
com/testproject/foo/bar/+/baz/annotations"}, | |
150 }...) | |
151 So(ds.Put(c, &build), ShouldBeNil) | |
152 testClient.resp = []interface{}{ | |
153 datagramGetResponse("testproject", "foo/bar", &l
ogdogStep), | |
154 } | |
155 | |
156 resp, err := bip.GetBuildInfo(c, biReq.GetBuildbot(), ""
) | |
157 So(err, ShouldBeNil) | |
158 So(testClient.req, ShouldResemble, []interface{}{ | |
159 &logdog.TailRequest{ | |
160 Project: "testproject", | |
161 Path: "foo/bar/+/baz/annotations", | |
162 State: true, | |
163 }, | |
164 }) | |
165 So(resp, ShouldResemble, &milo.BuildInfoResponse{ | |
166 Project: "testproject", | |
167 Step: &miloProto.Step{ | |
168 Command: &miloProto.Step_Command{ | |
169 CommandLine: []string{"foo", "ba
r", "baz"}, | |
170 }, | |
171 Text: []string{"test step"}, | |
172 Property: []*miloProto.Step_Property{ | |
173 {Name: "bar", Value: "log-bar"}, | |
174 {Name: "foo", Value: "build-foo"
}, | |
175 {Name: "log_location", Value: "l
ogdog://example.com/testproject/foo/bar/+/baz/annotations"}, | |
176 }, | |
177 }, | |
178 AnnotationStream: &miloProto.LogdogStream{ | |
179 Server: "example.com", | |
180 Prefix: "foo/bar", | |
181 Name: "baz/annotations", | |
182 }, | |
183 }) | |
184 }) | |
185 | |
186 Convey("Can load a BuildBot build by annotation URL.", func() { | |
187 build.Properties = append(build.Properties, []*buildbotP
roperty{ | |
188 {Name: "log_location", Value: "protocol://not/a/
logdog/url"}, | |
189 {Name: "logdog_annotation_url", Value: "logdog:/
/example.com/testproject/foo/bar/+/baz/annotations"}, | |
190 }...) | |
191 So(ds.Put(c, &build), ShouldBeNil) | |
192 testClient.resp = []interface{}{ | |
193 datagramGetResponse("testproject", "foo/bar", &l
ogdogStep), | |
194 } | |
195 | |
196 resp, err := bip.GetBuildInfo(c, biReq.GetBuildbot(), ""
) | |
197 So(err, ShouldBeNil) | |
198 So(testClient.req, ShouldResemble, []interface{}{ | |
199 &logdog.TailRequest{ | |
200 Project: "testproject", | |
201 Path: "foo/bar/+/baz/annotations", | |
202 State: true, | |
203 }, | |
204 }) | |
205 So(resp, ShouldResemble, &milo.BuildInfoResponse{ | |
206 Project: "testproject", | |
207 Step: &miloProto.Step{ | |
208 Command: &miloProto.Step_Command{ | |
209 CommandLine: []string{"foo", "ba
r", "baz"}, | |
210 }, | |
211 Text: []string{"test step"}, | |
212 Property: []*miloProto.Step_Property{ | |
213 {Name: "bar", Value: "log-bar"}, | |
214 {Name: "foo", Value: "build-foo"
}, | |
215 {Name: "log_location", Value: "p
rotocol://not/a/logdog/url"}, | |
216 {Name: "logdog_annotation_url",
Value: "logdog://example.com/testproject/foo/bar/+/baz/annotations"}, | |
217 }, | |
218 }, | |
219 AnnotationStream: &miloProto.LogdogStream{ | |
220 Server: "example.com", | |
221 Prefix: "foo/bar", | |
222 Name: "baz/annotations", | |
223 }, | |
224 }) | |
225 }) | |
226 | |
227 Convey("Can load a BuildBot build by tag.", func() { | |
228 build.Properties = append(build.Properties, []*buildbotP
roperty{ | |
229 {Name: "logdog_prefix", Value: "foo/bar"}, | |
230 {Name: "logdog_project", Value: "testproject"}, | |
231 }...) | |
232 So(ds.Put(c, &build), ShouldBeNil) | |
233 testClient.resp = []interface{}{ | |
234 datagramGetResponse("testproject", "foo/bar", &l
ogdogStep), | |
235 } | |
236 | |
237 resp, err := bip.GetBuildInfo(c, biReq.GetBuildbot(), ""
) | |
238 So(err, ShouldBeNil) | |
239 So(testClient.req, ShouldResemble, []interface{}{ | |
240 &logdog.TailRequest{ | |
241 Project: "testproject", | |
242 Path: "foo/bar/+/annotations", | |
243 State: true, | |
244 }, | |
245 }) | |
246 So(resp, ShouldResemble, &milo.BuildInfoResponse{ | |
247 Project: "testproject", | |
248 Step: &miloProto.Step{ | |
249 Command: &miloProto.Step_Command{ | |
250 CommandLine: []string{"foo", "ba
r", "baz"}, | |
251 }, | |
252 Text: []string{"test step"}, | |
253 Property: []*miloProto.Step_Property{ | |
254 {Name: "bar", Value: "log-bar"}, | |
255 {Name: "foo", Value: "build-foo"
}, | |
256 {Name: "logdog_prefix", Value: "
foo/bar"}, | |
257 {Name: "logdog_project", Value:
"testproject"}, | |
258 }, | |
259 }, | |
260 AnnotationStream: &miloProto.LogdogStream{ | |
261 Server: "example.com", | |
262 Prefix: "foo/bar", | |
263 Name: "annotations", | |
264 }, | |
265 }) | |
266 }) | |
267 | |
268 Convey("Fails to load a BuildBot build by query if no project hi
nt is provided.", func() { | |
269 So(ds.Put(c, &build), ShouldBeNil) | |
270 | |
271 _, err := bip.GetBuildInfo(c, biReq.GetBuildbot(), "") | |
272 So(err, ShouldErrLike, "annotation stream not found") | |
273 }) | |
274 | |
275 Convey("Can load a BuildBot build by query with a project hint."
, func() { | |
276 So(ds.Put(c, &build), ShouldBeNil) | |
277 testClient.resp = []interface{}{ | |
278 &logdog.QueryResponse{ | |
279 Streams: []*logdog.QueryResponse_Stream{ | |
280 { | |
281 Path: "foo/bar/+/annotat
ions", | |
282 }, | |
283 { | |
284 Path: "other/ignore/+/me
", | |
285 }, | |
286 }, | |
287 }, | |
288 datagramGetResponse("testproject", "foo/bar/+/an
notations", &logdogStep), | |
289 } | |
290 | |
291 resp, err := bip.GetBuildInfo(c, biReq.GetBuildbot(), "t
estproject") | |
292 So(err, ShouldBeNil) | |
293 So(testClient.req, ShouldResemble, []interface{}{ | |
294 &logdog.QueryRequest{ | |
295 Project: "testproject", | |
296 ContentType: miloProto.ContentTypeAnnota
tions, | |
297 Tags: map[string]string{ | |
298 "buildbot.master": "foo mas
ter", | |
299 "buildbot.builder": "bar bui
lder", | |
300 "buildbot.buildnumber": "1337", | |
301 }, | |
302 }, | |
303 &logdog.TailRequest{ | |
304 Project: "testproject", | |
305 Path: "foo/bar/+/annotations", | |
306 State: true, | |
307 }, | |
308 }) | |
309 | |
310 So(resp, ShouldResemble, &milo.BuildInfoResponse{ | |
311 Project: "testproject", | |
312 Step: &miloProto.Step{ | |
313 Command: &miloProto.Step_Command{ | |
314 CommandLine: []string{"foo", "ba
r", "baz"}, | |
315 }, | |
316 Text: []string{"test step"}, | |
317 Property: []*miloProto.Step_Property{ | |
318 {Name: "bar", Value: "log-bar"}, | |
319 {Name: "foo", Value: "build-foo"
}, | |
320 }, | |
321 }, | |
322 AnnotationStream: &miloProto.LogdogStream{ | |
323 Server: "example.com", | |
324 Prefix: "foo/bar", | |
325 Name: "annotations", | |
326 }, | |
327 }) | |
328 }) | |
329 | |
330 Convey("Can load a BuildBot build by inferred name.", func() { | |
331 So(ds.Put(c, &build), ShouldBeNil) | |
332 testClient.resp = []interface{}{ | |
333 &logdog.QueryResponse{}, | |
334 datagramGetResponse("testproject", "foo/bar/+/an
notations", &logdogStep), | |
335 } | |
336 | |
337 resp, err := bip.GetBuildInfo(c, biReq.GetBuildbot(), "t
estproject") | |
338 So(err, ShouldBeNil) | |
339 So(testClient.req, ShouldResemble, []interface{}{ | |
340 &logdog.QueryRequest{ | |
341 Project: "testproject", | |
342 ContentType: miloProto.ContentTypeAnnota
tions, | |
343 Tags: map[string]string{ | |
344 "buildbot.master": "foo mas
ter", | |
345 "buildbot.builder": "bar bui
lder", | |
346 "buildbot.buildnumber": "1337", | |
347 }, | |
348 }, | |
349 &logdog.TailRequest{ | |
350 Project: "testproject", | |
351 Path: "bb/foo_master/bar_builder/1337
/+/annotations", | |
352 State: true, | |
353 }, | |
354 }) | |
355 | |
356 So(resp, ShouldResemble, &milo.BuildInfoResponse{ | |
357 Project: "testproject", | |
358 Step: &miloProto.Step{ | |
359 Command: &miloProto.Step_Command{ | |
360 CommandLine: []string{"foo", "ba
r", "baz"}, | |
361 }, | |
362 Text: []string{"test step"}, | |
363 Property: []*miloProto.Step_Property{ | |
364 {Name: "bar", Value: "log-bar"}, | |
365 {Name: "foo", Value: "build-foo"
}, | |
366 }, | |
367 }, | |
368 AnnotationStream: &miloProto.LogdogStream{ | |
369 Server: "example.com", | |
370 Prefix: "bb/foo_master/bar_builder/1337"
, | |
371 Name: "annotations", | |
372 }, | |
373 }) | |
374 }) | |
375 }) | |
376 } | |
OLD | NEW |