Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Side by Side Diff: milo/appengine/job_source/swarming/html_data.go

Issue 2949783002: [milo] appengine/* -> * (Closed)
Patch Set: rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 swarming
6
7 import (
8 "encoding/json"
9 "fmt"
10 "io/ioutil"
11 "path/filepath"
12 "sort"
13 "strings"
14 "time"
15
16 "github.com/golang/protobuf/proto"
17 "github.com/luci/gae/impl/memory"
18 "golang.org/x/net/context"
19 "google.golang.org/grpc"
20
21 swarming "github.com/luci/luci-go/common/api/swarming/swarming/v1"
22 "github.com/luci/luci-go/common/clock/testclock"
23 memcfg "github.com/luci/luci-go/common/config/impl/memory"
24 "github.com/luci/luci-go/common/errors"
25 miloProto "github.com/luci/luci-go/common/proto/milo"
26 "github.com/luci/luci-go/logdog/api/endpoints/coordinator/logs/v1"
27 "github.com/luci/luci-go/logdog/api/logpb"
28 "github.com/luci/luci-go/logdog/client/coordinator"
29 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/testconfig "
30 "github.com/luci/luci-go/milo/api/resp"
31 "github.com/luci/luci-go/milo/appengine/common"
32 "github.com/luci/luci-go/milo/appengine/common/model"
33 "github.com/luci/luci-go/server/auth"
34 "github.com/luci/luci-go/server/auth/authtest"
35 "github.com/luci/luci-go/server/templates"
36 )
37
38 type testCase struct {
39 name string
40
41 swarmingRelDir string
42
43 swarmResult string
44 swarmOutput string
45 annotations string
46 }
47
48 func getTestCases(swarmingRelDir string) []*testCase {
49 testCases := make(map[string]*testCase)
50
51 // References "milo/appengine/job_source/swarming/testdata".
52 testdata := filepath.Join(swarmingRelDir, "testdata")
53 f, err := ioutil.ReadDir(testdata)
54 if err != nil {
55 panic(err)
56 }
57 for _, fi := range f {
58 fileName := fi.Name()
59 parts := strings.SplitN(fileName, ".", 2)
60
61 name := parts[0]
62 tc := testCases[name]
63 if tc == nil {
64 tc = &testCase{name: name}
65 testCases[name] = tc
66 }
67 tc.swarmingRelDir = swarmingRelDir
68
69 switch {
70 case len(parts) == 1:
71 tc.swarmOutput = fileName
72 case parts[1] == "swarm":
73 tc.swarmResult = fileName
74 case parts[1] == "pb.txt":
75 tc.annotations = fileName
76 }
77 }
78
79 // Order test cases by name.
80 names := make([]string, 0, len(testCases))
81 for name := range testCases {
82 names = append(names, name)
83 }
84 sort.Strings(names)
85
86 results := make([]*testCase, len(names))
87 for i, name := range names {
88 results[i] = testCases[name]
89 }
90
91 return results
92 }
93
94 func (tc *testCase) getContent(name string) []byte {
95 if name == "" {
96 return nil
97 }
98
99 // ../swarming below assumes that
100 // - this code is not executed by tests outside of this dir
101 // - this dir is a sibling of frontend dir
102 path := filepath.Join(tc.swarmingRelDir, "testdata", name)
103 data, err := ioutil.ReadFile(path)
104 if err != nil {
105 panic(fmt.Errorf("failed to read [%s]: %s", path, err))
106 }
107 return data
108 }
109
110 func (tc *testCase) getSwarmingResult() *swarming.SwarmingRpcsTaskResult {
111 var sr swarming.SwarmingRpcsTaskResult
112 data := tc.getContent(tc.swarmResult)
113 if err := json.Unmarshal(data, &sr); err != nil {
114 panic(fmt.Errorf("failed to unmarshal [%s]: %s", tc.swarmResult, err))
115 }
116 return &sr
117 }
118
119 func (tc *testCase) getSwarmingOutput() string {
120 return string(tc.getContent(tc.swarmOutput))
121 }
122
123 func (tc *testCase) getAnnotation() *miloProto.Step {
124 var step miloProto.Step
125 data := tc.getContent(tc.annotations)
126 if len(data) == 0 {
127 return nil
128 }
129
130 if err := proto.UnmarshalText(string(data), &step); err != nil {
131 panic(fmt.Errorf("failed to unmarshal text protobuf [%s]: %s", t c.annotations, err))
132 }
133 return &step
134 }
135
136 type debugSwarmingService struct {
137 tc *testCase
138 }
139
140 func (svc debugSwarmingService) getHost() string { return "example.com" }
141
142 func (svc debugSwarmingService) getSwarmingResult(c context.Context, taskID stri ng) (
143 *swarming.SwarmingRpcsTaskResult, error) {
144
145 return svc.tc.getSwarmingResult(), nil
146 }
147
148 func (svc debugSwarmingService) getSwarmingRequest(c context.Context, taskID str ing) (
149 *swarming.SwarmingRpcsTaskRequest, error) {
150
151 return nil, errors.New("not implemented")
152 }
153
154 func (svc debugSwarmingService) getTaskOutput(c context.Context, taskID string) (string, error) {
155 return svc.tc.getSwarmingOutput(), nil
156 }
157
158 // LogTestData returns sample test data for log pages.
159 func LogTestData() []common.TestBundle {
160 return []common.TestBundle{
161 {
162 Description: "Basic log",
163 Data: templates.Args{
164 "Log": "This is the log",
165 "Closed": true,
166 },
167 },
168 }
169 }
170
171 // testLogDogClient is a minimal functional LogsClient implementation.
172 //
173 // It retains its latest input parameter and returns its configured err (if not
174 // nil) or resp.
175 type testLogDogClient struct {
176 logdog.LogsClient
177
178 req interface{}
179 resp interface{}
180 err error
181 }
182
183 func (tc *testLogDogClient) Tail(ctx context.Context, in *logdog.TailRequest, op ts ...grpc.CallOption) (
184 *logdog.GetResponse, error) {
185
186 tc.req = in
187 if tc.err != nil {
188 return nil, tc.err
189 }
190 if tc.resp == nil {
191 return nil, coordinator.ErrNoSuchStream
192 }
193 return tc.resp.(*logdog.GetResponse), nil
194 }
195
196 func logDogClientFunc(tc *testCase) func(context.Context, string) (*coordinator. Client, error) {
197 anno := tc.getAnnotation()
198 var resp interface{}
199 if anno != nil {
200 resp = datagramGetResponse("testproject", "foo/bar", tc.getAnnot ation())
201 }
202
203 return func(c context.Context, host string) (*coordinator.Client, error) {
204 return &coordinator.Client{
205 Host: host,
206 C: &testLogDogClient{
207 resp: resp,
208 },
209 }, nil
210 }
211 }
212
213 func datagramGetResponse(project, prefix string, msg proto.Message) *logdog.GetR esponse {
214 data, err := proto.Marshal(msg)
215 if err != nil {
216 panic(err)
217 }
218 return &logdog.GetResponse{
219 Project: project,
220 Desc: &logpb.LogStreamDescriptor{
221 Prefix: prefix,
222 ContentType: miloProto.ContentTypeAnnotations,
223 StreamType: logpb.StreamType_DATAGRAM,
224 },
225 State: &logdog.LogStreamState{},
226 Logs: []*logpb.LogEntry{
227 {
228 Content: &logpb.LogEntry_Datagram{
229 Datagram: &logpb.Datagram{
230 Data: data,
231 },
232 },
233 },
234 },
235 }
236 }
237
238 // BuildTestData returns sample test data for swarming build pages.
239 func BuildTestData(swarmingRelDir string) []common.TestBundle {
240 basic := resp.MiloBuild{
241 Summary: resp.BuildComponent{
242 Label: "Test swarming build",
243 Status: model.Success,
244 Started: time.Date(2016, 1, 2, 15, 4, 5, 999999999, tim e.UTC),
245 Finished: time.Date(2016, 1, 2, 15, 4, 6, 999999999, tim e.UTC),
246 Duration: time.Second,
247 },
248 }
249 results := []common.TestBundle{
250 {
251 Description: "Basic successful build",
252 Data: templates.Args{"Build": basic},
253 },
254 }
255 c := context.Background()
256 c = memory.UseWithAppID(c, "dev~luci-milo")
257 c = testconfig.WithCommonClient(c, memcfg.New(aclConfgs))
258 c = auth.WithState(c, &authtest.FakeState{
259 Identity: "user:alicebob@google.com",
260 IdentityGroups: []string{"all", "googlers"},
261 })
262 c, _ = testclock.UseTime(c, time.Date(2016, time.March, 14, 11, 0, 0, 0, time.UTC))
263
264 for _, tc := range getTestCases(swarmingRelDir) {
265 svc := debugSwarmingService{tc}
266 bl := buildLoader{
267 logDogClientFunc: logDogClientFunc(tc),
268 }
269
270 build, err := bl.swarmingBuildImpl(c, svc, "foo", tc.name)
271 if err != nil {
272 panic(fmt.Errorf("Error while processing %s: %s", tc.nam e, err))
273 }
274 results = append(results, common.TestBundle{
275 Description: tc.name,
276 Data: templates.Args{"Build": build},
277 })
278 }
279 return results
280 }
281
282 var secretProjectCfg = `
283 name: "secret"
284 access: "group:googlers"
285 `
286
287 var publicProjectCfg = `
288 name: "opensource"
289 access: "group:all"
290 `
291
292 var aclConfgs = map[string]memcfg.ConfigSet{
293 "projects/secret": {
294 "project.cfg": secretProjectCfg,
295 },
296 "projects/opensource": {
297 "project.cfg": publicProjectCfg,
298 },
299 }
OLDNEW
« no previous file with comments | « milo/appengine/job_source/swarming/html.go ('k') | milo/appengine/job_source/swarming/html_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698