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

Side by Side Diff: scheduler/appengine/apiservers/scheduler_test.go

Issue 2948163002: scheduler: add GetJobInvocations api. (Closed)
Patch Set: grpc.error 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
« no previous file with comments | « scheduler/appengine/apiservers/scheduler.go ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The LUCI Authors. All rights reserved. 1 // Copyright 2017 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package apiservers 5 package apiservers
6 6
7 import ( 7 import (
8 "fmt"
8 "testing" 9 "testing"
10 "time"
11
12 "google.golang.org/grpc/codes"
13 "google.golang.org/grpc/status"
9 14
10 "golang.org/x/net/context" 15 "golang.org/x/net/context"
11 16
12 "github.com/golang/protobuf/proto" 17 "github.com/golang/protobuf/proto"
13 "github.com/luci/luci-go/appengine/gaetesting" 18 "github.com/luci/luci-go/appengine/gaetesting"
14 "github.com/luci/luci-go/server/auth/identity" 19 "github.com/luci/luci-go/server/auth/identity"
15 20
16 scheduler "github.com/luci/luci-go/scheduler/api/scheduler/v1" 21 scheduler "github.com/luci/luci-go/scheduler/api/scheduler/v1"
17 "github.com/luci/luci-go/scheduler/appengine/catalog" 22 "github.com/luci/luci-go/scheduler/appengine/catalog"
18 "github.com/luci/luci-go/scheduler/appengine/engine" 23 "github.com/luci/luci-go/scheduler/appengine/engine"
19 "github.com/luci/luci-go/scheduler/appengine/messages" 24 "github.com/luci/luci-go/scheduler/appengine/messages"
25 "github.com/luci/luci-go/scheduler/appengine/task"
20 "github.com/luci/luci-go/scheduler/appengine/task/urlfetch" 26 "github.com/luci/luci-go/scheduler/appengine/task/urlfetch"
21 27
22 . "github.com/smartystreets/goconvey/convey" 28 . "github.com/smartystreets/goconvey/convey"
23 ) 29 )
24 30
25 func TestGetJobsApi(t *testing.T) { 31 func TestGetJobsApi(t *testing.T) {
26 t.Parallel() 32 t.Parallel()
27 33
28 Convey("Scheduler GetJobs API works", t, func() { 34 Convey("Scheduler GetJobs API works", t, func() {
29 ctx := gaetesting.TestingContext() 35 ctx := gaetesting.TestingContext()
30 fakeEng, catalog := newTestEngine() 36 fakeEng, catalog := newTestEngine()
31 » » So(catalog.RegisterTaskManager(&urlfetch.TaskManager{}), ShouldB eNil) 37 » » fakeTaskBlob, err := registerUrlFetcher(catalog)
32 38 » » So(err, ShouldBeNil)
33 ss := SchedulerServer{fakeEng, catalog} 39 ss := SchedulerServer{fakeEng, catalog}
34 taskBlob, err := proto.Marshal(&messages.TaskDefWrapper{
35 UrlFetch: &messages.UrlFetchTask{Url: "http://example.co m/path"},
36 })
37 So(err, ShouldBeNil)
38 40
39 Convey("Empty", func() { 41 Convey("Empty", func() {
40 fakeEng.getAllJobs = func() ([]*engine.Job, error) { ret urn []*engine.Job{}, nil } 42 fakeEng.getAllJobs = func() ([]*engine.Job, error) { ret urn []*engine.Job{}, nil }
41 reply, err := ss.GetJobs(ctx, nil) 43 reply, err := ss.GetJobs(ctx, nil)
42 So(err, ShouldBeNil) 44 So(err, ShouldBeNil)
43 So(len(reply.GetJobs()), ShouldEqual, 0) 45 So(len(reply.GetJobs()), ShouldEqual, 0)
44 }) 46 })
45 47
46 Convey("All Projects", func() { 48 Convey("All Projects", func() {
47 fakeEng.getAllJobs = func() ([]*engine.Job, error) { 49 fakeEng.getAllJobs = func() ([]*engine.Job, error) {
48 return []*engine.Job{ 50 return []*engine.Job{
49 { 51 {
50 JobID: "bar/foo", 52 JobID: "bar/foo",
51 ProjectID: "bar", 53 ProjectID: "bar",
52 Schedule: "0 * * * * * *", 54 Schedule: "0 * * * * * *",
53 State: engine.JobState{State : engine.JobStateRunning}, 55 State: engine.JobState{State : engine.JobStateRunning},
54 » » » » » » Task: taskBlob, 56 » » » » » » Task: fakeTaskBlob,
55 }, 57 },
56 { 58 {
57 JobID: "baz/faz", 59 JobID: "baz/faz",
58 Paused: true, 60 Paused: true,
59 ProjectID: "baz", 61 ProjectID: "baz",
60 Schedule: "with 1m interval", 62 Schedule: "with 1m interval",
61 State: engine.JobState{State : engine.JobStateSuspended}, 63 State: engine.JobState{State : engine.JobStateSuspended},
62 » » » » » » Task: taskBlob, 64 » » » » » » Task: fakeTaskBlob,
63 }, 65 },
64 }, nil 66 }, nil
65 } 67 }
66 reply, err := ss.GetJobs(ctx, nil) 68 reply, err := ss.GetJobs(ctx, nil)
67 So(err, ShouldBeNil) 69 So(err, ShouldBeNil)
68 So(reply.GetJobs(), ShouldResemble, []*scheduler.Job{ 70 So(reply.GetJobs(), ShouldResemble, []*scheduler.Job{
69 { 71 {
70 Name: "foo", 72 Name: "foo",
71 Project: "bar", 73 Project: "bar",
72 Schedule: "0 * * * * * *", 74 Schedule: "0 * * * * * *",
(...skipping 10 matching lines...) Expand all
83 85
84 Convey("One Project", func() { 86 Convey("One Project", func() {
85 fakeEng.getProjectJobs = func(projectID string) ([]*engi ne.Job, error) { 87 fakeEng.getProjectJobs = func(projectID string) ([]*engi ne.Job, error) {
86 So(projectID, ShouldEqual, "bar") 88 So(projectID, ShouldEqual, "bar")
87 return []*engine.Job{ 89 return []*engine.Job{
88 { 90 {
89 JobID: "bar/foo", 91 JobID: "bar/foo",
90 ProjectID: "bar", 92 ProjectID: "bar",
91 Schedule: "0 * * * * * *", 93 Schedule: "0 * * * * * *",
92 State: engine.JobState{State : engine.JobStateRunning}, 94 State: engine.JobState{State : engine.JobStateRunning},
93 » » » » » » Task: taskBlob, 95 » » » » » » Task: fakeTaskBlob,
94 }, 96 },
95 }, nil 97 }, nil
96 } 98 }
97 reply, err := ss.GetJobs(ctx, &scheduler.JobsRequest{Pro ject: "bar"}) 99 reply, err := ss.GetJobs(ctx, &scheduler.JobsRequest{Pro ject: "bar"})
98 So(err, ShouldBeNil) 100 So(err, ShouldBeNil)
99 So(reply.GetJobs(), ShouldResemble, []*scheduler.Job{ 101 So(reply.GetJobs(), ShouldResemble, []*scheduler.Job{
100 { 102 {
101 Name: "foo", 103 Name: "foo",
102 Project: "bar", 104 Project: "bar",
103 Schedule: "0 * * * * * *", 105 Schedule: "0 * * * * * *",
104 State: &scheduler.JobState{UiStatus: "RUNNING"}, 106 State: &scheduler.JobState{UiStatus: "RUNNING"},
105 }, 107 },
106 }) 108 })
107 }) 109 })
108 }) 110 })
109 } 111 }
110 112
113 func TestGetInvocationsApi(t *testing.T) {
114 t.Parallel()
115
116 Convey("Scheduler GetInvocations API works", t, func() {
117 ctx := gaetesting.TestingContext()
118 fakeEng, catalog := newTestEngine()
119 _, err := registerUrlFetcher(catalog)
120 So(err, ShouldBeNil)
121 ss := SchedulerServer{fakeEng, catalog}
122
123 Convey("Job not found", func() {
124 fakeEng.getJob = func(JobID string) (*engine.Job, error) { return nil, nil }
125 _, err := ss.GetInvocations(ctx, &scheduler.InvocationsR equest{Project: "not", Job: "exists"})
126 s, ok := status.FromError(err)
127 So(ok, ShouldBeTrue)
128 So(s.Code(), ShouldEqual, codes.NotFound)
129 })
130
131 Convey("DS error", func() {
132 fakeEng.getJob = func(JobID string) (*engine.Job, error) { return nil, fmt.Errorf("ds error") }
133 _, err := ss.GetInvocations(ctx, &scheduler.InvocationsR equest{Project: "proj", Job: "job"})
134 s, ok := status.FromError(err)
135 So(ok, ShouldBeTrue)
136 So(s.Code(), ShouldEqual, codes.Internal)
137 })
138
139 fakeEng.getJob = func(JobID string) (*engine.Job, error) {
140 return &engine.Job{JobID: "proj/job", ProjectID: "proj"} , nil
141 }
142
143 Convey("Emtpy with huge pagesize", func() {
144 fakeEng.listInvocations = func(pageSize int, cursor stri ng) ([]*engine.Invocation, string, error) {
145 So(pageSize, ShouldEqual, 50)
146 So(cursor, ShouldEqual, "")
147 return nil, "", nil
148 }
149 r, err := ss.GetInvocations(ctx, &scheduler.InvocationsR equest{Project: "proj", Job: "job", PageSize: 1e9})
150 So(err, ShouldBeNil)
151 So(r.GetNextCursor(), ShouldEqual, "")
152 So(r.GetInvocations(), ShouldBeEmpty)
153 })
154
155 Convey("Some with custom pagesize and cursor", func() {
156 started := time.Unix(123123123, 0).UTC()
157 finished := time.Unix(321321321, 0).UTC()
158 fakeEng.listInvocations = func(pageSize int, cursor stri ng) ([]*engine.Invocation, string, error) {
159 So(pageSize, ShouldEqual, 5)
160 So(cursor, ShouldEqual, "cursor")
161 return []*engine.Invocation{
162 {ID: 12, Revision: "deadbeef", Status: t ask.StatusRunning, Started: started,
163 TriggeredBy: identity.Identity(" user:bot@example.com")},
164 {ID: 13, Revision: "deadbeef", Status: t ask.StatusAborted, Started: started, Finished: finished,
165 ViewURL: "https://example.com/13 "},
166 }, "next", nil
167 }
168 r, err := ss.GetInvocations(ctx, &scheduler.InvocationsR equest{
169 Project: "proj", Job: "job", PageSize: 5, Cursor : "cursor"})
170 So(err, ShouldBeNil)
171 So(r.GetNextCursor(), ShouldEqual, "next")
172 So(r.GetInvocations(), ShouldResemble, []*scheduler.Invo cation{
173 {
174 Project: "proj", Job: "job", ConfigRevis ion: "deadbeef",
175 Id: 12, Final: false, Status: "RUNNING",
176 StartedTs: started.UnixNano() / 1000,
177 TriggeredBy: "user:bot@example.com",
178 },
179 {
180 Project: "proj", Job: "job", ConfigRevis ion: "deadbeef",
181 Id: 13, Final: true, Status: "ABORTED",
182 StartedTs: started.UnixNano() / 1000, Fi nishedTs: finished.UnixNano() / 1000,
183 ViewUrl: "https://example.com/13",
184 },
185 })
186 })
187
188 })
189 }
190
111 //// 191 ////
112 192
193 func registerUrlFetcher(cat catalog.Catalog) ([]byte, error) {
194 if err := cat.RegisterTaskManager(&urlfetch.TaskManager{}); err != nil {
195 return nil, err
196 }
197 return proto.Marshal(&messages.TaskDefWrapper{
198 UrlFetch: &messages.UrlFetchTask{Url: "http://example.com/path"} ,
199 })
200 }
201
113 func newTestEngine() (*fakeEngine, catalog.Catalog) { 202 func newTestEngine() (*fakeEngine, catalog.Catalog) {
114 cat := catalog.New("scheduler.cfg") 203 cat := catalog.New("scheduler.cfg")
115 return &fakeEngine{}, cat 204 return &fakeEngine{}, cat
116 } 205 }
117 206
118 type fakeEngine struct { 207 type fakeEngine struct {
119 » getAllJobs func() ([]*engine.Job, error) 208 » getAllJobs func() ([]*engine.Job, error)
120 » getProjectJobs func(projectID string) ([]*engine.Job, error) 209 » getProjectJobs func(projectID string) ([]*engine.Job, error)
210 » getJob func(jobID string) (*engine.Job, error)
211 » listInvocations func(pageSize int, cursor string) ([]*engine.Invocation, string, error)
121 } 212 }
122 213
123 func (f *fakeEngine) GetAllProjects(c context.Context) ([]string, error) { 214 func (f *fakeEngine) GetAllProjects(c context.Context) ([]string, error) {
124 panic("not implemented") 215 panic("not implemented")
125 } 216 }
126 217
127 func (f *fakeEngine) GetAllJobs(c context.Context) ([]*engine.Job, error) { 218 func (f *fakeEngine) GetAllJobs(c context.Context) ([]*engine.Job, error) {
128 return f.getAllJobs() 219 return f.getAllJobs()
129 } 220 }
130 221
131 func (f *fakeEngine) GetProjectJobs(c context.Context, projectID string) ([]*eng ine.Job, error) { 222 func (f *fakeEngine) GetProjectJobs(c context.Context, projectID string) ([]*eng ine.Job, error) {
132 return f.getProjectJobs(projectID) 223 return f.getProjectJobs(projectID)
133 } 224 }
134 225
135 func (f *fakeEngine) GetJob(c context.Context, jobID string) (*engine.Job, error ) { 226 func (f *fakeEngine) GetJob(c context.Context, jobID string) (*engine.Job, error ) {
136 » panic("not implemented") 227 » return f.getJob(jobID)
137 } 228 }
138 229
139 func (f *fakeEngine) ListInvocations(c context.Context, jobID string, pageSize i nt, cursor string) ([]*engine.Invocation, string, error) { 230 func (f *fakeEngine) ListInvocations(c context.Context, jobID string, pageSize i nt, cursor string) ([]*engine.Invocation, string, error) {
140 » panic("not implemented") 231 » return f.listInvocations(pageSize, cursor)
141 } 232 }
142 233
143 func (f *fakeEngine) GetInvocation(c context.Context, jobID string, invID int64) (*engine.Invocation, error) { 234 func (f *fakeEngine) GetInvocation(c context.Context, jobID string, invID int64) (*engine.Invocation, error) {
144 panic("not implemented") 235 panic("not implemented")
145 } 236 }
146 237
147 func (f *fakeEngine) GetInvocationsByNonce(c context.Context, invNonce int64) ([ ]*engine.Invocation, error) { 238 func (f *fakeEngine) GetInvocationsByNonce(c context.Context, invNonce int64) ([ ]*engine.Invocation, error) {
148 panic("not implemented") 239 panic("not implemented")
149 } 240 }
150 241
(...skipping 29 matching lines...) Expand all
180 panic("not implemented") 271 panic("not implemented")
181 } 272 }
182 273
183 func (f *fakeEngine) AbortInvocation(c context.Context, jobID string, invID int6 4, who identity.Identity) error { 274 func (f *fakeEngine) AbortInvocation(c context.Context, jobID string, invID int6 4, who identity.Identity) error {
184 panic("not implemented") 275 panic("not implemented")
185 } 276 }
186 277
187 func (f *fakeEngine) AbortJob(c context.Context, jobID string, who identity.Iden tity) error { 278 func (f *fakeEngine) AbortJob(c context.Context, jobID string, who identity.Iden tity) error {
188 panic("not implemented") 279 panic("not implemented")
189 } 280 }
OLDNEW
« no previous file with comments | « scheduler/appengine/apiservers/scheduler.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698