Beispiel #1
0
func (r *rootSuite) TestFindMethodEnsuresTypeMatch(c *gc.C) {
	srvRoot := apiserver.TestingSrvRoot(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, gc.IsNil)
	_, 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, gc.IsNil)
	_, 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, gc.IsNil)
	res, err := caller.Call("", reflect.Value{})
	c.Check(err, gc.ErrorMatches, `you shall not pass`)
	c.Check(res.IsValid(), jc.IsFalse)
}
Beispiel #2
0
func (r *rootSuite) TestFindMethodCacheRaceSafe(c *gc.C) {
	srvRoot := apiserver.TestingSrvRoot(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, gc.IsNil)
	// 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")
}
Beispiel #3
0
func (r *rootSuite) TestFindMethodCachesFacadesWithId(c *gc.C) {
	srvRoot := apiserver.TestingSrvRoot(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, gc.IsNil)
	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, gc.IsNil)
	assertCallResult(c, caller, "orig-id", "ALT-orig-id1")
	assertCallResult(c, caller, "alt-id", "ALT-alt-id2")
	assertCallResult(c, caller, "third-id", "ALT-third-id3")
}
Beispiel #4
0
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)),
	)
}