func (r *rootSuite) TestFindMethodEnsuresTypeMatch(c *gc.C) { srvRoot := apiserver.TestingApiRoot(nil) defer common.Facades.Discard("my-testing-facade", 0) defer common.Facades.Discard("my-testing-facade", 1) defer common.Facades.Discard("my-testing-facade", 2) myBadFacade := func( *state.State, *common.Resources, common.Authorizer, string, ) ( interface{}, error, ) { return &badType{}, nil } myGoodFacade := func( *state.State, *common.Resources, common.Authorizer, string, ) ( interface{}, error, ) { return &testingType{}, nil } myErrFacade := func( *state.State, *common.Resources, common.Authorizer, string, ) ( interface{}, error, ) { return nil, fmt.Errorf("you shall not pass") } expectedType := reflect.TypeOf((*testingType)(nil)) common.RegisterFacade("my-testing-facade", 0, myBadFacade, expectedType) common.RegisterFacade("my-testing-facade", 1, myGoodFacade, expectedType) common.RegisterFacade("my-testing-facade", 2, myErrFacade, expectedType) // Now, myGoodFacade returns the right type, so calling it should work // fine caller, err := srvRoot.FindMethod("my-testing-facade", 1, "Exposed") c.Assert(err, jc.ErrorIsNil) _, err = caller.Call("", reflect.Value{}) c.Check(err, gc.ErrorMatches, "Exposed was bogus") // However, myBadFacade returns the wrong type, so trying to access it // should create an error caller, err = srvRoot.FindMethod("my-testing-facade", 0, "Exposed") c.Assert(err, jc.ErrorIsNil) _, err = caller.Call("", reflect.Value{}) c.Check(err, gc.ErrorMatches, `internal error, my-testing-facade\(0\) claimed to return \*apiserver_test.testingType but returned \*apiserver_test.badType`) // myErrFacade had the permissions change, so calling it returns an // error, but that shouldn't trigger the type checking code. caller, err = srvRoot.FindMethod("my-testing-facade", 2, "Exposed") c.Assert(err, jc.ErrorIsNil) res, err := caller.Call("", reflect.Value{}) c.Check(err, gc.ErrorMatches, `you shall not pass`) c.Check(res.IsValid(), jc.IsFalse) }
func (r *rootSuite) TestFindMethodCacheRaceSafe(c *gc.C) { srvRoot := apiserver.TestingApiRoot(nil) defer common.Facades.Discard("my-counting-facade", 0) var count int64 newIdCounter := func( _ *state.State, _ *common.Resources, _ common.Authorizer, id string, ) (interface{}, error) { count += 1 return &countingType{count: count, id: id}, nil } reflectType := reflect.TypeOf((*countingType)(nil)) common.RegisterFacade("my-counting-facade", 0, newIdCounter, reflectType) caller, err := srvRoot.FindMethod("my-counting-facade", 0, "Count") c.Assert(err, jc.ErrorIsNil) // This is designed to trigger the race detector var wg sync.WaitGroup wg.Add(4) go func() { caller.Call("first", reflect.Value{}); wg.Done() }() go func() { caller.Call("second", reflect.Value{}); wg.Done() }() go func() { caller.Call("first", reflect.Value{}); wg.Done() }() go func() { caller.Call("second", reflect.Value{}); wg.Done() }() wg.Wait() // Once we're done, we should have only instantiated 2 different // objects. If we pass a different Id, we should be at 3 total count. assertCallResult(c, caller, "third", "third3") }
func (r *rootSuite) TestFindMethodCachesFacadesWithId(c *gc.C) { srvRoot := apiserver.TestingApiRoot(nil) defer common.Facades.Discard("my-counting-facade", 0) var count int64 // like newCounter, but also tracks the "id" that was requested for // this counter newIdCounter := func( _ *state.State, _ *common.Resources, _ common.Authorizer, id string, ) (interface{}, error) { count += 1 return &countingType{count: count, id: id}, nil } reflectType := reflect.TypeOf((*countingType)(nil)) common.RegisterFacade("my-counting-facade", 0, newIdCounter, reflectType) // The first time we call FindMethod, it should lookup a facade, and // request a new object. caller, err := srvRoot.FindMethod("my-counting-facade", 0, "Count") c.Assert(err, jc.ErrorIsNil) assertCallResult(c, caller, "orig-id", "orig-id1") // However, if we place another call for a different Id, it should grab // a new object assertCallResult(c, caller, "alt-id", "alt-id2") // Asking for the original object gives us the cached value assertCallResult(c, caller, "orig-id", "orig-id1") // Asking for the original object gives us the cached value assertCallResult(c, caller, "alt-id", "alt-id2") // We get the same results asking for the other method caller, err = srvRoot.FindMethod("my-counting-facade", 0, "AltCount") c.Assert(err, jc.ErrorIsNil) assertCallResult(c, caller, "orig-id", "ALT-orig-id1") assertCallResult(c, caller, "alt-id", "ALT-alt-id2") assertCallResult(c, caller, "third-id", "ALT-third-id3") }
func (s *facadeRegistrySuite) TestRegisterFacadePanicsOnDoubleRegistry(c *gc.C) { var v interface{} doRegister := func() { common.RegisterFacade("myfacade", 0, testFacade, reflect.TypeOf(v)) } doRegister() c.Assert(doRegister, gc.PanicMatches, `object "myfacade\(0\)" already registered`) }
func init() { common.RegisterFacade( "AllWatcher", 0, newClientAllWatcher, reflect.TypeOf((*srvClientAllWatcher)(nil)), ) common.RegisterFacade( "NotifyWatcher", 0, newNotifyWatcher, reflect.TypeOf((*srvNotifyWatcher)(nil)), ) common.RegisterFacade( "StringsWatcher", 0, newStringsWatcher, reflect.TypeOf((*srvStringsWatcher)(nil)), ) common.RegisterFacade( "RelationUnitsWatcher", 0, newRelationUnitsWatcher, reflect.TypeOf((*srvRelationUnitsWatcher)(nil)), ) }
func (s *facadeRegistrySuite) TestRegister(c *gc.C) { common.SanitizeFacades(s) var v interface{} common.RegisterFacade("myfacade", 0, testFacade, reflect.TypeOf(&v).Elem()) f, err := common.Facades.GetFactory("myfacade", 0) c.Assert(err, gc.IsNil) val, err := f(nil, nil, nil, "") c.Assert(err, gc.IsNil) c.Check(val, gc.Equals, "myobject") }
func init() { common.RegisterFacade( "AllWatcher", 0, newClientAllWatcher, reflect.TypeOf((*srvClientAllWatcher)(nil)), ) common.RegisterFacade( "NotifyWatcher", 0, newNotifyWatcher, reflect.TypeOf((*srvNotifyWatcher)(nil)), ) common.RegisterFacade( "StringsWatcher", 0, newStringsWatcher, reflect.TypeOf((*srvStringsWatcher)(nil)), ) common.RegisterFacade( "RelationUnitsWatcher", 0, newRelationUnitsWatcher, reflect.TypeOf((*srvRelationUnitsWatcher)(nil)), ) common.RegisterFacade( "VolumeAttachmentsWatcher", 1, newVolumeAttachmentsWatcher, reflect.TypeOf((*srvMachineStorageIdsWatcher)(nil)), ) common.RegisterFacade( "FilesystemAttachmentsWatcher", 1, newFilesystemAttachmentsWatcher, reflect.TypeOf((*srvMachineStorageIdsWatcher)(nil)), ) }
func init() { common.RegisterFacade( "AllWatcher", 1, NewAllWatcher, reflect.TypeOf((*SrvAllWatcher)(nil)), ) // Note: AllModelWatcher uses the same infrastructure as AllWatcher // but they are get under separate names as it possible the may // diverge in the future (especially in terms of authorisation // checks). common.RegisterFacade( "AllModelWatcher", 2, NewAllWatcher, reflect.TypeOf((*SrvAllWatcher)(nil)), ) common.RegisterFacade( "NotifyWatcher", 1, newNotifyWatcher, reflect.TypeOf((*srvNotifyWatcher)(nil)), ) common.RegisterFacade( "StringsWatcher", 1, newStringsWatcher, reflect.TypeOf((*srvStringsWatcher)(nil)), ) common.RegisterFacade( "RelationUnitsWatcher", 1, newRelationUnitsWatcher, reflect.TypeOf((*srvRelationUnitsWatcher)(nil)), ) common.RegisterFacade( "VolumeAttachmentsWatcher", 2, newVolumeAttachmentsWatcher, reflect.TypeOf((*srvMachineStorageIdsWatcher)(nil)), ) common.RegisterFacade( "FilesystemAttachmentsWatcher", 2, newFilesystemAttachmentsWatcher, reflect.TypeOf((*srvMachineStorageIdsWatcher)(nil)), ) common.RegisterFacade( "EntityWatcher", 2, newEntitiesWatcher, reflect.TypeOf((*srvEntitiesWatcher)(nil)), ) common.RegisterFacade( "MigrationStatusWatcher", 1, newMigrationStatusWatcher, reflect.TypeOf((*srvMigrationStatusWatcher)(nil)), ) }