github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/worker/dependency/testing/stub.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package testing 5 6 import ( 7 "reflect" 8 9 "github.com/juju/errors" 10 "github.com/juju/juju/worker/dependency" 11 ) 12 13 // StubResource is used to define the behaviour of a StubGetResource func for a 14 // particular resource name. 15 type StubResource struct { 16 Output interface{} 17 Error error 18 } 19 20 // NewStubResources converts raw into a StubResources by assuming that any non-error 21 // value is intended to be an output. 22 func NewStubResources(raw map[string]interface{}) StubResources { 23 resources := StubResources{} 24 for name, value := range raw { 25 if err, ok := value.(error); ok { 26 resources[name] = StubResource{Error: err} 27 } else { 28 resources[name] = StubResource{Output: value} 29 } 30 } 31 return resources 32 } 33 34 // StubResources defines the complete behaviour of a StubGetResource func. 35 type StubResources map[string]StubResource 36 37 // Context returns a dependency.Context that never aborts, backed by resources. 38 func (resources StubResources) Context() dependency.Context { 39 return &Context{ 40 resources: resources, 41 } 42 } 43 44 // StubContext returns a Context backed by abort and resources derived from raw. 45 func StubContext(abort <-chan struct{}, raw map[string]interface{}) *Context { 46 return &Context{ 47 abort: abort, 48 resources: NewStubResources(raw), 49 } 50 } 51 52 // Context implements dependency.Context for convenient testing of dependency.StartFuncs. 53 type Context struct { 54 abort <-chan struct{} 55 resources StubResources 56 } 57 58 // Abort is part of the dependency.Context interface. 59 func (ctx *Context) Abort() <-chan struct{} { 60 return ctx.abort 61 } 62 63 // Get is part of the dependency.Context interface. 64 func (ctx *Context) Get(name string, outPtr interface{}) error { 65 resource, found := ctx.resources[name] 66 if !found { 67 return errors.Errorf("unexpected resource name: %s", name) 68 } else if resource.Error != nil { 69 return resource.Error 70 } 71 if outPtr != nil { 72 outPtrV := reflect.ValueOf(outPtr) 73 if outPtrV.Kind() != reflect.Ptr { 74 return errors.Errorf("outPtr should be a pointer; is %#v", outPtr) 75 } 76 outV := outPtrV.Elem() 77 outT := outV.Type() 78 setV := reflect.ValueOf(resource.Output) 79 setT := setV.Type() 80 if !setT.ConvertibleTo(outT) { 81 return errors.Errorf("cannot set %#v into %T", resource.Output, outPtr) 82 } 83 outV.Set(setV.Convert(outT)) 84 } 85 return nil 86 }