github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/apiserver/common/registry_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common_test
     5  
     6  import (
     7  	"reflect"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/apiserver/common"
    14  	"github.com/juju/juju/apiserver/facade"
    15  	"github.com/juju/juju/apiserver/facade/facadetest"
    16  	apiservertesting "github.com/juju/juju/apiserver/testing"
    17  	"github.com/juju/juju/rpc/rpcreflect"
    18  	"github.com/juju/juju/state"
    19  	coretesting "github.com/juju/juju/testing"
    20  )
    21  
    22  type facadeRegistrySuite struct {
    23  	coretesting.BaseSuite
    24  }
    25  
    26  var _ = gc.Suite(&facadeRegistrySuite{})
    27  
    28  func (s *facadeRegistrySuite) TestRegister(c *gc.C) {
    29  	common.SanitizeFacades(s)
    30  	var v interface{}
    31  	common.RegisterFacade("myfacade", 0, testFacade, reflect.TypeOf(&v).Elem())
    32  	f, err := common.Facades.GetFactory("myfacade", 0)
    33  	c.Assert(err, jc.ErrorIsNil)
    34  	val, err := f(nil)
    35  	c.Assert(err, jc.ErrorIsNil)
    36  	c.Check(val, gc.Equals, "myobject")
    37  }
    38  
    39  func (s *facadeRegistrySuite) TestRegisterForFeature(c *gc.C) {
    40  	common.SanitizeFacades(s)
    41  	var v interface{}
    42  	common.RegisterFacadeForFeature("myfacade", 0, testFacade, reflect.TypeOf(&v).Elem(), "magic")
    43  	f, err := common.Facades.GetFactory("myfacade", 0)
    44  	c.Check(err, jc.Satisfies, errors.IsNotFound)
    45  
    46  	s.SetFeatureFlags("magic")
    47  
    48  	f, err = common.Facades.GetFactory("myfacade", 0)
    49  	c.Assert(err, jc.ErrorIsNil)
    50  	val, err := f(nil)
    51  	c.Assert(err, jc.ErrorIsNil)
    52  	c.Check(val, gc.Equals, "myobject")
    53  }
    54  
    55  func (s *facadeRegistrySuite) TestRegisterFacadePanicsOnDoubleRegistry(c *gc.C) {
    56  	var v interface{}
    57  	doRegister := func() {
    58  		common.RegisterFacade("myfacade", 0, testFacade, reflect.TypeOf(v))
    59  	}
    60  	doRegister()
    61  	c.Assert(doRegister, gc.PanicMatches, `object "myfacade\(0\)" already registered`)
    62  }
    63  
    64  func (*facadeRegistrySuite) TestValidateNewFacade(c *gc.C) {
    65  	checkValidateNewFacadeFailsWith(c, nil,
    66  		`cannot wrap nil`)
    67  	checkValidateNewFacadeFailsWith(c, "notafunc",
    68  		`wrong type "string" is not a function`)
    69  	checkValidateNewFacadeFailsWith(c, noArgs,
    70  		`function ".*noArgs" does not take 3 parameters and return 2`)
    71  	checkValidateNewFacadeFailsWith(c, badCountIn,
    72  		`function ".*badCountIn" does not take 3 parameters and return 2`)
    73  	checkValidateNewFacadeFailsWith(c, badCountOut,
    74  		`function ".*badCountOut" does not take 3 parameters and return 2`)
    75  	checkValidateNewFacadeFailsWith(c, wrongIn,
    76  		`function ".*wrongIn" does not have the signature func \(\*state.State, facade.Resources, facade.Authorizer\) \(\*Type, error\)`)
    77  	checkValidateNewFacadeFailsWith(c, wrongOut,
    78  		`function ".*wrongOut" does not have the signature func \(\*state.State, facade.Resources, facade.Authorizer\) \(\*Type, error\)`)
    79  	err := common.ValidateNewFacade(reflect.ValueOf(validFactory))
    80  	c.Assert(err, jc.ErrorIsNil)
    81  }
    82  
    83  func (*facadeRegistrySuite) TestWrapNewFacadeFailure(c *gc.C) {
    84  	_, _, err := common.WrapNewFacade("notafunc")
    85  	c.Check(err, gc.ErrorMatches, `wrong type "string" is not a function`)
    86  }
    87  
    88  func (*facadeRegistrySuite) TestWrapNewFacadeHandlesId(c *gc.C) {
    89  	wrapped, _, err := common.WrapNewFacade(validFactory)
    90  	c.Assert(err, jc.ErrorIsNil)
    91  	val, err := wrapped(facadetest.Context{
    92  		ID_: "badId",
    93  	})
    94  	c.Check(err, gc.ErrorMatches, "id not found")
    95  	c.Check(val, gc.Equals, nil)
    96  }
    97  
    98  func (*facadeRegistrySuite) TestWrapNewFacadeCallsFunc(c *gc.C) {
    99  	wrapped, _, err := common.WrapNewFacade(validFactory)
   100  	c.Assert(err, jc.ErrorIsNil)
   101  	val, err := wrapped(facadetest.Context{})
   102  	c.Assert(err, jc.ErrorIsNil)
   103  	c.Check(*(val.(*int)), gc.Equals, 100)
   104  }
   105  
   106  func (*facadeRegistrySuite) TestWrapNewFacadeCallsWithRightParams(c *gc.C) {
   107  	authorizer := apiservertesting.FakeAuthorizer{}
   108  	resources := common.NewResources()
   109  	testFunc := func(
   110  		st *state.State,
   111  		resources facade.Resources,
   112  		authorizer facade.Authorizer,
   113  	) (*myResult, error) {
   114  		return &myResult{st, resources, authorizer}, nil
   115  	}
   116  	wrapped, facadeType, err := common.WrapNewFacade(testFunc)
   117  	c.Assert(err, jc.ErrorIsNil)
   118  	c.Check(facadeType, gc.Equals, reflect.TypeOf((*myResult)(nil)))
   119  
   120  	val, err := wrapped(facadetest.Context{
   121  		Resources_: resources,
   122  		Auth_:      authorizer,
   123  	})
   124  	c.Assert(err, jc.ErrorIsNil)
   125  	asResult := val.(*myResult)
   126  	c.Check(asResult.st, gc.IsNil)
   127  	c.Check(asResult.resources, gc.Equals, resources)
   128  	c.Check(asResult.auth, gc.Equals, authorizer)
   129  }
   130  
   131  func (s *facadeRegistrySuite) TestRegisterStandardFacade(c *gc.C) {
   132  	common.SanitizeFacades(s)
   133  	common.RegisterStandardFacade("testing", 0, validFactory)
   134  	wrapped, err := common.Facades.GetFactory("testing", 0)
   135  	c.Assert(err, jc.ErrorIsNil)
   136  	val, err := wrapped(facadetest.Context{})
   137  	c.Assert(err, jc.ErrorIsNil)
   138  	c.Check(*(val.(*int)), gc.Equals, 100)
   139  }
   140  
   141  func (s *facadeRegistrySuite) TestRegisterStandardFacadePanic(c *gc.C) {
   142  	common.SanitizeFacades(s)
   143  	c.Assert(
   144  		func() { common.RegisterStandardFacade("badtest", 0, noArgs) },
   145  		gc.PanicMatches,
   146  		`function ".*noArgs" does not take 3 parameters and return 2`)
   147  	_, err := common.Facades.GetFactory("badtest", 0)
   148  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   149  	c.Assert(err, gc.ErrorMatches, `badtest\(0\) not found`)
   150  }
   151  
   152  func (*facadeRegistrySuite) TestDiscardedAPIMethods(c *gc.C) {
   153  	allFacades := common.Facades.List()
   154  	c.Assert(allFacades, gc.Not(gc.HasLen), 0)
   155  	for _, description := range allFacades {
   156  		for _, version := range description.Versions {
   157  			facadeType, err := common.Facades.GetType(description.Name, version)
   158  			c.Assert(err, jc.ErrorIsNil)
   159  			facadeObjType := rpcreflect.ObjTypeOf(facadeType)
   160  			// We must have some methods on every object returned
   161  			// by a root-level method.
   162  			c.Assert(facadeObjType.MethodNames(), gc.Not(gc.HasLen), 0)
   163  			// We don't allow any methods that don't implement
   164  			// an RPC entry point.
   165  			c.Assert(facadeObjType.DiscardedMethods(), gc.HasLen, 0)
   166  		}
   167  	}
   168  }
   169  
   170  func testFacade(facade.Context) (facade.Facade, error) {
   171  	return "myobject", nil
   172  }
   173  
   174  type myResult struct {
   175  	st        *state.State
   176  	resources facade.Resources
   177  	auth      facade.Authorizer
   178  }
   179  
   180  func checkValidateNewFacadeFailsWith(c *gc.C, obj interface{}, errMsg string) {
   181  	err := common.ValidateNewFacade(reflect.ValueOf(obj))
   182  	c.Check(err, gc.NotNil)
   183  	c.Check(err, gc.ErrorMatches, errMsg)
   184  }
   185  
   186  func noArgs() {
   187  }
   188  
   189  func badCountIn(a string) (*int, error) {
   190  	return nil, nil
   191  }
   192  
   193  func badCountOut(a, b, c string) error {
   194  	return nil
   195  }
   196  
   197  func wrongIn(a, b, c string) (*int, error) {
   198  	return nil, nil
   199  }
   200  
   201  func wrongOut(*state.State, facade.Resources, facade.Authorizer) (error, *int) {
   202  	return nil, nil
   203  }
   204  
   205  func validFactory(*state.State, facade.Resources, facade.Authorizer) (*int, error) {
   206  	var i = 100
   207  	return &i, nil
   208  }