blob: 8c6019023bbb0b815a9fde1fdae343914c14d214 [file] [log] [blame]
Tilak Sharma13329d92014-07-14 12:25:28 -07001package testing
Tilak Sharma48202342014-05-13 23:49:49 -07002
3import (
Tilak Sharma13329d92014-07-14 12:25:28 -07004 "io"
5 "runtime"
Tilak Sharma48202342014-05-13 23:49:49 -07006 "sync"
Tilak Sharmadfba8ac2014-06-18 13:49:32 -07007 "testing"
Tilak Sharma48202342014-05-13 23:49:49 -07008
Tilak Sharma86571322014-06-11 14:15:07 -07009 "veyron/services/store/raw"
10
Matt Rosencrantz137b8d22014-08-18 09:56:15 -070011 "veyron2/context"
Tilak Sharma48202342014-05-13 23:49:49 -070012 "veyron2/ipc"
Andres Erbsencdeacfe2014-06-11 14:55:16 -070013 "veyron2/naming"
Matt Rosencrantz137b8d22014-08-18 09:56:15 -070014 "veyron2/rt"
Tilak Sharma48202342014-05-13 23:49:49 -070015 "veyron2/security"
16 "veyron2/services/watch"
Robin Thellende9714902014-08-21 15:01:10 -070017 "veyron2/services/watch/types"
Tilak Sharmadfba8ac2014-06-18 13:49:32 -070018 "veyron2/storage"
Tilak Sharma48202342014-05-13 23:49:49 -070019)
20
Matt Rosencrantz137b8d22014-08-18 09:56:15 -070021// FakeServerContext implements ipc.ServerContext.
22type FakeServerContext struct {
23 context.T
24 cancel context.CancelFunc
25 id security.PublicID
Tilak Sharma48202342014-05-13 23:49:49 -070026}
27
Matt Rosencrantz137b8d22014-08-18 09:56:15 -070028func NewFakeServerContext(id security.PublicID) *FakeServerContext {
29 ctx, cancel := rt.R().NewContext().WithCancel()
30
31 return &FakeServerContext{
32 T: ctx,
33 cancel: cancel,
34 id: id,
Tilak Sharma48202342014-05-13 23:49:49 -070035 }
36}
37
Matt Rosencrantz137b8d22014-08-18 09:56:15 -070038func (*FakeServerContext) Server() ipc.Server { return nil }
39func (*FakeServerContext) Method() string { return "" }
40func (*FakeServerContext) Name() string { return "" }
41func (*FakeServerContext) Suffix() string { return "" }
42func (*FakeServerContext) Label() (l security.Label) { return }
43func (*FakeServerContext) CaveatDischarges() security.CaveatDischargeMap { return nil }
44func (ctx *FakeServerContext) LocalID() security.PublicID { return ctx.id }
45func (ctx *FakeServerContext) RemoteID() security.PublicID { return ctx.id }
46func (*FakeServerContext) Blessing() security.PublicID { return nil }
47func (*FakeServerContext) LocalEndpoint() naming.Endpoint { return nil }
48func (*FakeServerContext) RemoteEndpoint() naming.Endpoint { return nil }
49func (ctx *FakeServerContext) Cancel() { ctx.cancel() }
Tilak Sharma48202342014-05-13 23:49:49 -070050
Tilak Sharma13329d92014-07-14 12:25:28 -070051// Utilities for PutMutations.
52
53// storeServicePutMutationsStream implements raw.StoreServicePutMutationsStream
54type storeServicePutMutationsStream struct {
Shyam Jayaramanc4aed6e2014-07-22 14:25:06 -070055 mus <-chan raw.Mutation
56 value raw.Mutation
Tilak Sharma13329d92014-07-14 12:25:28 -070057}
58
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -070059func (s *storeServicePutMutationsStream) RecvStream() interface {
60 Advance() bool
61 Value() raw.Mutation
62 Err() error
63} {
64 return s
65}
66
Shyam Jayaramanc4aed6e2014-07-22 14:25:06 -070067func (s *storeServicePutMutationsStream) Advance() bool {
68 var ok bool
69 s.value, ok = <-s.mus
70 return ok
71}
72
73func (s *storeServicePutMutationsStream) Value() raw.Mutation {
74 return s.value
75}
76
77func (s *storeServicePutMutationsStream) Err() error {
78 return nil
Tilak Sharma13329d92014-07-14 12:25:28 -070079}
80
81// storePutMutationsStream implements raw.StorePutMutationsStream
82type storePutMutationsStream struct {
Tilak Sharma13329d92014-07-14 12:25:28 -070083 closed bool
84 mus chan<- raw.Mutation
Tilak Sharma13329d92014-07-14 12:25:28 -070085}
86
87func (s *storePutMutationsStream) Send(mu raw.Mutation) error {
88 s.mus <- mu
89 return nil
90}
91
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -070092func (s *storePutMutationsStream) Close() error {
Tilak Sharma13329d92014-07-14 12:25:28 -070093 if !s.closed {
94 s.closed = true
95 close(s.mus)
96 }
97 return nil
98}
99
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700100type storePutMutationsCall struct {
101 ctx ipc.ServerContext
102 stream storePutMutationsStream
103 err <-chan error
104}
105
106func (s *storePutMutationsCall) SendStream() interface {
107 Send(mu raw.Mutation) error
108 Close() error
109} {
110 return &s.stream
111}
112
113func (s *storePutMutationsCall) Finish() error {
114 s.stream.Close()
Tilak Sharma13329d92014-07-14 12:25:28 -0700115 return <-s.err
116}
117
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700118func (s *storePutMutationsCall) Cancel() {
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700119 s.ctx.(*FakeServerContext).Cancel()
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700120 s.stream.Close()
Tilak Sharma13329d92014-07-14 12:25:28 -0700121}
122
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700123func PutMutations(id security.PublicID, putMutationsFn func(ipc.ServerContext, raw.StoreServicePutMutationsStream) error) raw.StorePutMutationsCall {
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700124 ctx := NewFakeServerContext(id)
Tilak Sharma13329d92014-07-14 12:25:28 -0700125 mus := make(chan raw.Mutation)
126 err := make(chan error)
127 go func() {
Shyam Jayaramanc4aed6e2014-07-22 14:25:06 -0700128 err <- putMutationsFn(ctx, &storeServicePutMutationsStream{mus: mus})
Tilak Sharma13329d92014-07-14 12:25:28 -0700129 close(err)
130 }()
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700131 return &storePutMutationsCall{
Tilak Sharma13329d92014-07-14 12:25:28 -0700132 ctx: ctx,
Tilak Sharma13329d92014-07-14 12:25:28 -0700133 err: err,
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700134 stream: storePutMutationsStream{
135 mus: mus,
136 },
Tilak Sharma13329d92014-07-14 12:25:28 -0700137 }
138}
139
140func PutMutationsBatch(t *testing.T, id security.PublicID, putMutationsFn func(ipc.ServerContext, raw.StoreServicePutMutationsStream) error, mus []raw.Mutation) {
141 storePutMutationsStream := PutMutations(id, putMutationsFn)
142 for _, mu := range mus {
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700143 storePutMutationsStream.SendStream().Send(mu)
Tilak Sharma13329d92014-07-14 12:25:28 -0700144 }
145 if err := storePutMutationsStream.Finish(); err != nil {
146 _, file, line, _ := runtime.Caller(1)
147 t.Errorf("%s(%d): can't put mutations %s: %s", file, line, mus, err)
148 }
149}
150
151// Utilities for Watch.
152
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700153// watcherServiceWatchStreamSender implements watch.WatcherServiceWatchStreamSender
154type watcherServiceWatchStreamSender struct {
Tilak Sharma48202342014-05-13 23:49:49 -0700155 mu *sync.Mutex
156 ctx ipc.ServerContext
Robin Thellende9714902014-08-21 15:01:10 -0700157 output chan<- types.ChangeBatch
Tilak Sharma48202342014-05-13 23:49:49 -0700158}
159
Robin Thellende9714902014-08-21 15:01:10 -0700160func (s *watcherServiceWatchStreamSender) Send(cb types.ChangeBatch) error {
Tilak Sharma48202342014-05-13 23:49:49 -0700161 s.mu.Lock()
162 defer s.mu.Unlock()
163 select {
164 case s.output <- cb:
165 return nil
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700166 case <-s.ctx.Done():
Tilak Sharma13329d92014-07-14 12:25:28 -0700167 return io.EOF
Tilak Sharma48202342014-05-13 23:49:49 -0700168 }
169}
170
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700171// watcherServiceWatchStream implements watch.WatcherServiceWatchStream
172type watcherServiceWatchStream struct {
173 watcherServiceWatchStreamSender
174}
175
176func (s *watcherServiceWatchStream) SendStream() interface {
Robin Thellende9714902014-08-21 15:01:10 -0700177 Send(cb types.ChangeBatch) error
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700178} {
179 return s
180}
181func (*watcherServiceWatchStream) Cancel() {}
182
Tilak Sharma48202342014-05-13 23:49:49 -0700183// watcherWatchStream implements watch.WatcherWatchStream.
184type watcherWatchStream struct {
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700185 ctx *FakeServerContext
Robin Thellende9714902014-08-21 15:01:10 -0700186 value types.ChangeBatch
187 input <-chan types.ChangeBatch
Tilak Sharma48202342014-05-13 23:49:49 -0700188 err <-chan error
189}
190
Shyam Jayaramanc4aed6e2014-07-22 14:25:06 -0700191func (s *watcherWatchStream) Advance() bool {
192 var ok bool
193 s.value, ok = <-s.input
194 return ok
195}
196
Robin Thellende9714902014-08-21 15:01:10 -0700197func (s *watcherWatchStream) Value() types.ChangeBatch {
Shyam Jayaramanc4aed6e2014-07-22 14:25:06 -0700198 return s.value
199}
200
201func (*watcherWatchStream) Err() error {
202 return nil
Tilak Sharma48202342014-05-13 23:49:49 -0700203}
204
205func (s *watcherWatchStream) Finish() error {
206 <-s.input
207 return <-s.err
208}
209
210func (s *watcherWatchStream) Cancel() {
211 s.ctx.Cancel()
212}
213
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700214func (s *watcherWatchStream) RecvStream() interface {
215 Advance() bool
Robin Thellende9714902014-08-21 15:01:10 -0700216 Value() types.ChangeBatch
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700217 Err() error
218} {
219 return s
220}
221
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700222func watchImpl(id security.PublicID, watchFn func(ipc.ServerContext, *watcherServiceWatchStream) error) *watcherWatchStream {
Tilak Sharma48202342014-05-13 23:49:49 -0700223 mu := &sync.Mutex{}
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700224 ctx := NewFakeServerContext(id)
Robin Thellende9714902014-08-21 15:01:10 -0700225 c := make(chan types.ChangeBatch, 1)
Tilak Sharma48202342014-05-13 23:49:49 -0700226 errc := make(chan error, 1)
227 go func() {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700228 stream := &watcherServiceWatchStream{
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700229 watcherServiceWatchStreamSender{
230 mu: mu,
231 ctx: ctx,
232 output: c,
233 },
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700234 }
235 err := watchFn(ctx, stream)
Tilak Sharma48202342014-05-13 23:49:49 -0700236 mu.Lock()
237 defer mu.Unlock()
238 ctx.Cancel()
239 close(c)
240 errc <- err
241 close(errc)
242 }()
243 return &watcherWatchStream{
244 ctx: ctx,
245 input: c,
246 err: errc,
247 }
248}
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700249
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700250func WatchRaw(id security.PublicID, watchFn func(ipc.ServerContext, raw.Request, raw.StoreServiceWatchStream) error, req raw.Request) raw.StoreWatchCall {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700251 return watchImpl(id, func(ctx ipc.ServerContext, stream *watcherServiceWatchStream) error {
252 return watchFn(ctx, req, stream)
253 })
254}
255
Robin Thellende9714902014-08-21 15:01:10 -0700256func WatchGlob(id security.PublicID, watchFn func(ipc.ServerContext, types.GlobRequest, watch.GlobWatcherServiceWatchGlobStream) error, req types.GlobRequest) watch.GlobWatcherWatchGlobCall {
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700257 return watchImpl(id, func(ctx ipc.ServerContext, iterator *watcherServiceWatchStream) error {
258 return watchFn(ctx, req, iterator)
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700259 })
260}
261
Robin Thellende9714902014-08-21 15:01:10 -0700262func WatchGlobOnPath(id security.PublicID, watchFn func(ipc.ServerContext, storage.PathName, types.GlobRequest, watch.GlobWatcherServiceWatchGlobStream) error, path storage.PathName, req types.GlobRequest) watch.GlobWatcherWatchGlobCall {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700263 return watchImpl(id, func(ctx ipc.ServerContext, stream *watcherServiceWatchStream) error {
264 return watchFn(ctx, path, req, stream)
265 })
266}
267
Robin Thellende9714902014-08-21 15:01:10 -0700268func ExpectInitialStateSkipped(t *testing.T, change types.Change) {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700269 if change.Name != "" {
270 t.Fatalf("Expect Name to be \"\" but was: %v", change.Name)
271 }
Robin Thellende9714902014-08-21 15:01:10 -0700272 if change.State != types.InitialStateSkipped {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700273 t.Fatalf("Expect State to be InitialStateSkipped but was: %v", change.State)
274 }
275 if len(change.ResumeMarker) != 0 {
276 t.Fatalf("Expect no ResumeMarker but was: %v", change.ResumeMarker)
277 }
278}
279
Robin Thellende9714902014-08-21 15:01:10 -0700280func ExpectEntryExists(t *testing.T, changes []types.Change, name string, id storage.ID, value string) {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700281 change := findEntry(t, changes, name)
Robin Thellende9714902014-08-21 15:01:10 -0700282 if change.State != types.Exists {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700283 t.Fatalf("Expected name to exist: %v", name)
284 }
285 cv, ok := change.Value.(*storage.Entry)
286 if !ok {
287 t.Fatal("Expected an Entry")
288 }
289 if cv.Stat.ID != id {
290 t.Fatalf("Expected ID to be %v, but was: %v", id, cv.Stat.ID)
291 }
292 if cv.Value != value {
293 t.Fatalf("Expected Value to be %v, but was: %v", value, cv.Value)
294 }
295}
296
Robin Thellende9714902014-08-21 15:01:10 -0700297func ExpectEntryDoesNotExist(t *testing.T, changes []types.Change, name string) {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700298 change := findEntry(t, changes, name)
Robin Thellende9714902014-08-21 15:01:10 -0700299 if change.State != types.DoesNotExist {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700300 t.Fatalf("Expected name to not exist: %v", name)
301 }
302 if change.Value != nil {
303 t.Fatal("Expected entry to be nil")
304 }
305}
306
Robin Thellende9714902014-08-21 15:01:10 -0700307func ExpectServiceEntryExists(t *testing.T, changes []types.Change, name string, id storage.ID, value string) {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700308 change := findEntry(t, changes, name)
Robin Thellende9714902014-08-21 15:01:10 -0700309 if change.State != types.Exists {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700310 t.Fatalf("Expected name to exist: %v", name)
311 }
Ken Ashcraftb8ddc352014-08-01 15:11:57 -0700312 cv, ok := change.Value.(*storage.Entry)
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700313 if !ok {
314 t.Fatal("Expected a service Entry")
315 }
316 if cv.Stat.ID != id {
317 t.Fatalf("Expected ID to be %v, but was: %v", id, cv.Stat.ID)
318 }
319 if cv.Value != value {
320 t.Fatalf("Expected Value to be %v, but was: %v", value, cv.Value)
321 }
322}
323
Robin Thellende9714902014-08-21 15:01:10 -0700324func ExpectServiceEntryDoesNotExist(t *testing.T, changes []types.Change, name string) {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700325 change := findEntry(t, changes, name)
Robin Thellende9714902014-08-21 15:01:10 -0700326 if change.State != types.DoesNotExist {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700327 t.Fatalf("Expected name to not exist: %v", name)
328 }
329 if change.Value != nil {
330 t.Fatal("Expected entry to be nil")
331 }
332}
333
Robin Thellende9714902014-08-21 15:01:10 -0700334func findEntry(t *testing.T, changes []types.Change, name string) types.Change {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700335 for _, change := range changes {
336 if change.Name == name {
337 return change
338 }
339 }
340 t.Fatalf("Expected a change for name: %v", name)
341 panic("Should not reach here")
342}
343
344var (
Ken Ashcraftc79f0c02014-08-26 13:11:43 -0700345 EmptyDir = []raw.DEntry{}
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700346)
347
Ken Ashcraftc79f0c02014-08-26 13:11:43 -0700348func DirOf(name string, id storage.ID) []raw.DEntry {
349 return []raw.DEntry{raw.DEntry{
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700350 Name: name,
351 ID: id,
352 }}
353}
354
Ken Ashcraftc79f0c02014-08-26 13:11:43 -0700355func ExpectMutationExists(t *testing.T, changes []types.Change, id storage.ID, pre, post raw.Version, isRoot bool, value string, dir []raw.DEntry) {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700356 change := findMutation(t, changes, id)
Robin Thellende9714902014-08-21 15:01:10 -0700357 if change.State != types.Exists {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700358 t.Fatalf("Expected id to exist: %v", id)
359 }
360 cv := change.Value.(*raw.Mutation)
361 if cv.PriorVersion != pre {
362 t.Fatalf("Expected PriorVersion to be %v, but was: %v", pre, cv.PriorVersion)
363 }
364 if cv.Version != post {
365 t.Fatalf("Expected Version to be %v, but was: %v", post, cv.Version)
366 }
367 if cv.IsRoot != isRoot {
368 t.Fatalf("Expected IsRoot to be: %v, but was: %v", isRoot, cv.IsRoot)
369 }
370 if cv.Value != value {
371 t.Fatalf("Expected Value to be: %v, but was: %v", value, cv.Value)
372 }
373 expectDirEquals(t, cv.Dir, dir)
374}
375
Ken Ashcraft530d3c52014-08-26 10:21:47 -0700376func ExpectMutationDoesNotExist(t *testing.T, changes []types.Change, id storage.ID, pre raw.Version, isRoot bool) {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700377 change := findMutation(t, changes, id)
Robin Thellende9714902014-08-21 15:01:10 -0700378 if change.State != types.DoesNotExist {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700379 t.Fatalf("Expected id to not exist: %v", id)
380 }
381 cv := change.Value.(*raw.Mutation)
382 if cv.PriorVersion != pre {
383 t.Fatalf("Expected PriorVersion to be %v, but was: %v", pre, cv.PriorVersion)
384 }
Ken Ashcraft530d3c52014-08-26 10:21:47 -0700385 if cv.Version != raw.NoVersion {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700386 t.Fatalf("Expected Version to be NoVersion, but was: %v", cv.Version)
387 }
388 if cv.IsRoot != isRoot {
389 t.Fatalf("Expected IsRoot to be: %v, but was: %v", isRoot, cv.IsRoot)
390 }
391 if cv.Value != nil {
392 t.Fatal("Expected Value to be nil")
393 }
394 if cv.Dir != nil {
395 t.Fatal("Expected Dir to be nil")
396 }
397}
398
Robin Thellende9714902014-08-21 15:01:10 -0700399func ExpectMutationExistsNoVersionCheck(t *testing.T, changes []types.Change, id storage.ID, value string) {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700400 change := findMutation(t, changes, id)
Robin Thellende9714902014-08-21 15:01:10 -0700401 if change.State != types.Exists {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700402 t.Fatalf("Expected id to exist: %v", id)
403 }
404 cv := change.Value.(*raw.Mutation)
405 if cv.Value != value {
406 t.Fatalf("Expected Value to be: %v, but was: %v", value, cv.Value)
407 }
408}
409
Robin Thellende9714902014-08-21 15:01:10 -0700410func ExpectMutationDoesNotExistNoVersionCheck(t *testing.T, changes []types.Change, id storage.ID) {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700411 change := findMutation(t, changes, id)
Robin Thellende9714902014-08-21 15:01:10 -0700412 if change.State != types.DoesNotExist {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700413 t.Fatalf("Expected id to not exist: %v", id)
414 }
415}
416
Robin Thellende9714902014-08-21 15:01:10 -0700417func findMutation(t *testing.T, changes []types.Change, id storage.ID) types.Change {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700418 for _, change := range changes {
419 cv, ok := change.Value.(*raw.Mutation)
420 if !ok {
421 t.Fatal("Expected a Mutation")
422 }
423 if cv.ID == id {
424 return change
425 }
426 }
427 t.Fatalf("Expected a change for id: %v", id)
428 panic("Should not reach here")
429}
430
Ken Ashcraftc79f0c02014-08-26 13:11:43 -0700431func expectDirEquals(t *testing.T, actual, expected []raw.DEntry) {
Tilak Sharmadfba8ac2014-06-18 13:49:32 -0700432 if len(actual) != len(expected) {
433 t.Fatalf("Expected Dir to have %v refs, but had %v", len(expected), len(actual))
434 }
435 for i, e := range expected {
436 a := actual[i]
437 if a != e {
438 t.Fatalf("Expected Dir entry %v to be %v, but was %v", i, e, a)
439 }
440 }
441}