mirror of https://github.com/poanetwork/quorum.git
Added unit test cases for permissions cache implementation. Refactored permissions code for enabling unit tests with lower cache configuration
This commit is contained in:
parent
5031e5b8ee
commit
f9677c8843
|
@ -117,19 +117,13 @@ var QIP714BlockReached = false
|
|||
var networkAdminRole string
|
||||
var orgAdminRole string
|
||||
|
||||
const defaultOrgMapLimit = 2000
|
||||
const defaultRoleMapLimit = 2500
|
||||
const defaultNodeMapLimit = 1000
|
||||
const defaultAccountMapLimit = 6000
|
||||
|
||||
var (
|
||||
OrgInfoMap = NewOrgCache()
|
||||
NodeInfoMap = NewNodeCache()
|
||||
RoleInfoMap = NewRoleCache()
|
||||
AcctInfoMap = NewAcctCache()
|
||||
OrgInfoMap *OrgCache
|
||||
NodeInfoMap *NodeCache
|
||||
RoleInfoMap *RoleCache
|
||||
AcctInfoMap *AcctCache
|
||||
)
|
||||
|
||||
|
||||
type OrgKey struct {
|
||||
OrgId string
|
||||
}
|
||||
|
@ -141,17 +135,16 @@ type OrgCache struct {
|
|||
populateCacheFunc func(orgId string) *OrgInfo
|
||||
}
|
||||
|
||||
|
||||
func (o *OrgCache) PopulateCacheFunc(cf func(string) *OrgInfo) {
|
||||
o.populateCacheFunc = cf
|
||||
}
|
||||
|
||||
func NewOrgCache() *OrgCache {
|
||||
func NewOrgCache(cacheSize int) *OrgCache {
|
||||
orgCache := OrgCache{evicted: false}
|
||||
onEvictedFunc := func(k interface{}, v interface{}) {
|
||||
orgCache.evicted = true
|
||||
}
|
||||
orgCache.c, _ = lru.NewWithEvict(defaultOrgMapLimit, onEvictedFunc)
|
||||
orgCache.c, _ = lru.NewWithEvict(cacheSize, onEvictedFunc)
|
||||
return &orgCache
|
||||
}
|
||||
|
||||
|
@ -170,12 +163,12 @@ func (r *RoleCache) PopulateCacheFunc(cf func(*RoleKey) *RoleInfo) {
|
|||
r.populateCacheFunc = cf
|
||||
}
|
||||
|
||||
func NewRoleCache() *RoleCache {
|
||||
func NewRoleCache(cacheSize int) *RoleCache {
|
||||
roleCache := RoleCache{evicted: false}
|
||||
onEvictedFunc := func(k interface{}, v interface{}) {
|
||||
roleCache.evicted = true
|
||||
}
|
||||
roleCache.c, _ = lru.NewWithEvict(defaultRoleMapLimit, onEvictedFunc)
|
||||
roleCache.c, _ = lru.NewWithEvict(cacheSize, onEvictedFunc)
|
||||
return &roleCache
|
||||
}
|
||||
|
||||
|
@ -199,13 +192,13 @@ func (n *NodeCache) PopulateCacheFunc(cf func(string) *NodeInfo) {
|
|||
n.populateCacheFunc = cf
|
||||
}
|
||||
|
||||
func NewNodeCache() *NodeCache {
|
||||
func NewNodeCache(cacheSize int) *NodeCache {
|
||||
nodeCache := NodeCache{evicted: false}
|
||||
onEvictedFunc := func(k interface{}, v interface{}) {
|
||||
nodeCache.evicted = true
|
||||
|
||||
}
|
||||
nodeCache.c, _ = lru.NewWithEvict(defaultNodeMapLimit, onEvictedFunc)
|
||||
nodeCache.c, _ = lru.NewWithEvict(cacheSize, onEvictedFunc)
|
||||
return &nodeCache
|
||||
}
|
||||
|
||||
|
@ -223,13 +216,13 @@ func (a *AcctCache) PopulateCacheFunc(cf func(common.Address) *AccountInfo) {
|
|||
a.populateCacheFunc = cf
|
||||
}
|
||||
|
||||
func NewAcctCache() *AcctCache {
|
||||
func NewAcctCache(cacheSize int) *AcctCache {
|
||||
acctCache := AcctCache{evicted: false}
|
||||
onEvictedFunc := func(k interface{}, v interface{}) {
|
||||
acctCache.evicted = true
|
||||
}
|
||||
|
||||
acctCache.c, _ = lru.NewWithEvict(defaultAccountMapLimit, onEvictedFunc)
|
||||
acctCache.c, _ = lru.NewWithEvict(cacheSize, onEvictedFunc)
|
||||
return &acctCache
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,13 @@ const (
|
|||
NodeDelete
|
||||
)
|
||||
|
||||
const (
|
||||
defaultOrgMapLimit = 2000
|
||||
defaultRoleMapLimit = 2500
|
||||
defaultNodeMapLimit = 1000
|
||||
defaultAccountMapLimit = 6000
|
||||
)
|
||||
|
||||
type PermissionCtrl struct {
|
||||
node *node.Node
|
||||
ethClnt bind.ContractBackend
|
||||
|
@ -177,7 +184,7 @@ func (p *PermissionCtrl) AfterStart() error {
|
|||
}
|
||||
|
||||
// populate the initial list of permissioned nodes and account accesses
|
||||
if err := p.populateInitPermissions(); err != nil {
|
||||
if err := p.populateInitPermissions(defaultOrgMapLimit, defaultRoleMapLimit, defaultNodeMapLimit, defaultAccountMapLimit); err != nil {
|
||||
return fmt.Errorf("populateInitPermissions failed: %v", err)
|
||||
}
|
||||
|
||||
|
@ -313,9 +320,6 @@ func (p *PermissionCtrl) monitorQIP714Block() error {
|
|||
// monitors org management related events happening via smart contracts
|
||||
// and updates cache accordingly
|
||||
func (p *PermissionCtrl) manageOrgPermissions() error {
|
||||
// set the cache function
|
||||
types.OrgInfoMap.PopulateCacheFunc(p.populateOrgToCache)
|
||||
|
||||
chPendingApproval := make(chan *pbind.OrgManagerOrgPendingApproval, 1)
|
||||
chOrgApproved := make(chan *pbind.OrgManagerOrgApproved, 1)
|
||||
chOrgSuspended := make(chan *pbind.OrgManagerOrgSuspended, 1)
|
||||
|
@ -374,10 +378,6 @@ func (p *PermissionCtrl) subscribeStopEvent() (chan stopEvent, event.Subscriptio
|
|||
|
||||
// Monitors node management events and updates cache accordingly
|
||||
func (p *PermissionCtrl) manageNodePermissions() error {
|
||||
// populate function to populate cache
|
||||
types.NodeInfoMap.PopulateValidateFunc(p.populateNodeCacheAndValidate)
|
||||
types.NodeInfoMap.PopulateCacheFunc(p.populateNodeCache)
|
||||
|
||||
chNodeApproved := make(chan *pbind.NodeManagerNodeApproved, 1)
|
||||
chNodeProposed := make(chan *pbind.NodeManagerNodeProposed, 1)
|
||||
chNodeDeactivated := make(chan *pbind.NodeManagerNodeDeactivated, 1)
|
||||
|
@ -548,9 +548,6 @@ func (p *PermissionCtrl) updateDisallowedNodes(url string, operation NodeOperati
|
|||
|
||||
// Monitors account access related events and updates the cache accordingly
|
||||
func (p *PermissionCtrl) manageAccountPermissions() error {
|
||||
// set the function for cache population
|
||||
types.AcctInfoMap.PopulateCacheFunc(p.populateAccountToCache)
|
||||
|
||||
chAccessModified := make(chan *pbind.AcctManagerAccountAccessModified)
|
||||
chAccessRevoked := make(chan *pbind.AcctManagerAccountAccessRevoked)
|
||||
chStatusChanged := make(chan *pbind.AcctManagerAccountStatusChanged)
|
||||
|
@ -624,9 +621,25 @@ func (p *PermissionCtrl) disconnectNode(enodeId string) {
|
|||
|
||||
}
|
||||
|
||||
func (p *PermissionCtrl) instantiateCache(orgCacheSize, roleCacheSize, nodeCacheSize, accountCacheSize int){
|
||||
// instantiate the cache objects for permissions
|
||||
types.OrgInfoMap = types.NewOrgCache(orgCacheSize)
|
||||
types.OrgInfoMap.PopulateCacheFunc(p.populateOrgToCache)
|
||||
|
||||
types.RoleInfoMap = types.NewRoleCache(roleCacheSize)
|
||||
types.RoleInfoMap.PopulateCacheFunc(p.populateRoleToCache)
|
||||
|
||||
types.NodeInfoMap = types.NewNodeCache(nodeCacheSize)
|
||||
types.NodeInfoMap.PopulateCacheFunc(p.populateNodeCache)
|
||||
types.NodeInfoMap.PopulateValidateFunc(p.populateNodeCacheAndValidate)
|
||||
|
||||
types.AcctInfoMap = types.NewAcctCache(accountCacheSize)
|
||||
types.AcctInfoMap.PopulateCacheFunc(p.populateAccountToCache)
|
||||
}
|
||||
|
||||
// Thus function checks if the initial network boot up status and if no
|
||||
// populates permissions model with details from permission-config.json
|
||||
func (p *PermissionCtrl) populateInitPermissions() error {
|
||||
func (p *PermissionCtrl) populateInitPermissions(orgCacheSize, roleCacheSize, nodeCacheSize, accountCacheSize int) error {
|
||||
auth := bind.NewKeyedTransactor(p.key)
|
||||
permInterfSession := &pbind.PermInterfaceSession{
|
||||
Contract: p.permInterf,
|
||||
|
@ -641,6 +654,8 @@ func (p *PermissionCtrl) populateInitPermissions() error {
|
|||
},
|
||||
}
|
||||
|
||||
p.instantiateCache(orgCacheSize, roleCacheSize, nodeCacheSize, accountCacheSize)
|
||||
|
||||
networkInitialized, err := permInterfSession.GetNetworkBootStatus()
|
||||
if err != nil {
|
||||
// handle the scenario of no contract code.
|
||||
|
@ -828,9 +843,6 @@ func (p *PermissionCtrl) updateNetworkStatus(permissionsSession *pbind.PermInter
|
|||
|
||||
// monitors role management related events and updated cache
|
||||
func (p *PermissionCtrl) manageRolePermissions() error {
|
||||
// populate function for cache population
|
||||
types.RoleInfoMap.PopulateCacheFunc(p.populateRoleToCache)
|
||||
|
||||
chRoleCreated := make(chan *pbind.RoleManagerRoleCreated, 1)
|
||||
chRoleRevoked := make(chan *pbind.RoleManagerRoleRevoked, 1)
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
|
@ -41,10 +42,16 @@ const (
|
|||
arbitraryOrgAdminRole = "ORG_ADMIN_ROLE"
|
||||
arbitraryNode1 = "enode://ac6b1096ca56b9f6d004b779ae3728bf83f8e22453404cc3cef16a3d9b96608bc67c4b30db88e0a5a6c6390213f7acbe1153ff6d23ce57380104288ae19373ef@127.0.0.1:21000?discport=0&raftport=50401"
|
||||
arbitraryNode2 = "enode://0ba6b9f606a43a95edc6247cdb1c1e105145817be7bcafd6b2c0ba15d58145f0dc1a194f70ba73cd6f4cdd6864edc7687f311254c7555cc32e4d45aeb1b80416@127.0.0.1:21001?discport=0&raftport=50402"
|
||||
arbitraryNode3 = "enode://579f786d4e2830bbcc02815a27e8a9bacccc9605df4dc6f20bcc1a6eb391e7225fff7cb83e5b4ecd1f3a94d8b733803f2f66b7e871961e7b029e22c155c3a778@127.0.0.1:21002?discport=0&raftport=50403"
|
||||
arbitraryNode4 = "enode://3d9ca5956b38557aba991e31cf510d4df641dce9cc26bfeb7de082f0c07abb6ede3a58410c8f249dabeecee4ad3979929ac4c7c496ad20b8cfdd061b7401b4f5@127.0.0.1:21003?discport=0&raftport=50404"
|
||||
arbitraryOrgToAdd = "ORG1"
|
||||
arbitrarySubOrg = "SUB1"
|
||||
arbitrartNewRole1 = "NEW_ROLE_1"
|
||||
arbitrartNewRole2 = "NEW_ROLE_2"
|
||||
orgCacheSize = 4
|
||||
roleCacheSize = 4
|
||||
nodeCacheSize = 2
|
||||
accountCacheSize = 4
|
||||
)
|
||||
|
||||
var ErrAccountsLinked = errors.New("Accounts linked to the role. Cannot be removed")
|
||||
|
@ -201,7 +208,7 @@ func TestPermissionCtrl_PopulateInitPermissions_AfterNetworkIsInitialized(t *tes
|
|||
testObject := typicalPermissionCtrl(t)
|
||||
assert.NoError(t, testObject.AfterStart())
|
||||
|
||||
err := testObject.populateInitPermissions()
|
||||
err := testObject.populateInitPermissions(orgCacheSize, roleCacheSize, nodeCacheSize, accountCacheSize)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
|
@ -241,7 +248,7 @@ func typicalQuorumControlsAPI(t *testing.T) *QuorumControlsAPI {
|
|||
if !assert.NoError(t, pc.AfterStart()) {
|
||||
t.Fail()
|
||||
}
|
||||
if !assert.NoError(t, pc.populateInitPermissions()) {
|
||||
if !assert.NoError(t, pc.populateInitPermissions(orgCacheSize, roleCacheSize, nodeCacheSize, accountCacheSize)) {
|
||||
t.Fail()
|
||||
}
|
||||
return NewQuorumControlsAPI(pc)
|
||||
|
@ -323,9 +330,21 @@ func TestQuorumControlsAPI_OrgAPIs(t *testing.T) {
|
|||
_, err = testObject.AddSubOrg(arbitraryNetworkAdminOrg, "", "", txa)
|
||||
assert.Equal(t, err, errors.New("Invalid input"))
|
||||
|
||||
_, err = testObject.GetOrgDetails(arbitraryOrgToAdd)
|
||||
assert.NoError(t, err)
|
||||
// caching tests - cache size for org is 4. add 4 sub orgs
|
||||
// this will result in cache eviction
|
||||
// get org details after this
|
||||
for i := 0; i < orgCacheSize; i++ {
|
||||
subOrgId:= "TESTSUBORG" + strconv.Itoa(i)
|
||||
_, err = testObject.AddSubOrg(arbitraryNetworkAdminOrg, subOrgId, "", txa)
|
||||
assert.NoError(t, err)
|
||||
types.OrgInfoMap.UpsertOrg(subOrgId, arbitraryNetworkAdminOrg, arbitraryNetworkAdminOrg, big.NewInt(2), types.OrgApproved)
|
||||
}
|
||||
|
||||
assert.Equal(t, orgCacheSize, len(types.OrgInfoMap.GetOrgList()))
|
||||
|
||||
orgDetails, err := testObject.GetOrgDetails(arbitraryNetworkAdminOrg)
|
||||
assert.Equal(t, orgDetails.AcctList[0].AcctId, guardianAddress)
|
||||
assert.Equal(t, orgDetails.RoleList[0].RoleId, arbitraryNetworkAdminRole)
|
||||
}
|
||||
|
||||
func TestQuorumControlsAPI_NodeAPIs(t *testing.T) {
|
||||
|
@ -371,6 +390,20 @@ func TestQuorumControlsAPI_NodeAPIs(t *testing.T) {
|
|||
_, err = testObject.ApproveBlackListedNodeRecovery(arbitraryNetworkAdminOrg, arbitraryNode2, txa)
|
||||
assert.NoError(t, err)
|
||||
types.NodeInfoMap.UpsertNode(arbitraryNetworkAdminOrg, arbitraryNode2, types.NodeApproved)
|
||||
|
||||
// caching tests - cache size for node is 3. add 2 nodes which will
|
||||
// result in node eviction from cache. get evicted node details using api
|
||||
_, err = testObject.AddNode(arbitraryNetworkAdminOrg, arbitraryNode3, txa)
|
||||
assert.NoError(t, err)
|
||||
types.NodeInfoMap.UpsertNode(arbitraryNetworkAdminOrg, arbitraryNode3, types.NodeApproved)
|
||||
|
||||
_, err = testObject.AddNode(arbitraryNetworkAdminOrg, arbitraryNode4, txa)
|
||||
assert.NoError(t, err)
|
||||
types.NodeInfoMap.UpsertNode(arbitraryNetworkAdminOrg, arbitraryNode4, types.NodeApproved)
|
||||
|
||||
assert.Equal(t, nodeCacheSize, len(types.NodeInfoMap.GetNodeList()))
|
||||
nodeInfo := types.NodeInfoMap.GetNodeByUrl(arbitraryNode4)
|
||||
assert.Equal(t,types.NodeApproved, nodeInfo.Status )
|
||||
}
|
||||
|
||||
func TestQuorumControlsAPI_RoleAndAccountsAPIs(t *testing.T) {
|
||||
|
@ -457,6 +490,36 @@ func TestQuorumControlsAPI_RoleAndAccountsAPIs(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
types.AcctInfoMap.UpsertAccount(arbitraryNetworkAdminOrg, arbitrartNewRole2, acct, true, types.AcctActive)
|
||||
|
||||
// check role cache. the cache size is set to 4
|
||||
// insert 4 records and then retrieve the 1st role
|
||||
for i := 0; i < roleCacheSize; i++ {
|
||||
roleId := "TESTROLE" + strconv.Itoa(i)
|
||||
_, err = testObject.AddNewRole(arbitraryNetworkAdminOrg, roleId, uint8(types.FullAccess), false, false, txa)
|
||||
assert.NoError(t, err)
|
||||
types.RoleInfoMap.UpsertRole(arbitraryNetworkAdminOrg, roleId, false, false, types.FullAccess, true)
|
||||
}
|
||||
|
||||
assert.Equal(t, roleCacheSize, len(types.RoleInfoMap.GetRoleList()))
|
||||
roleInfo := types.RoleInfoMap.GetRole(arbitraryNetworkAdminOrg, arbitrartNewRole1)
|
||||
|
||||
assert.Equal(t, roleInfo.RoleId, arbitrartNewRole1)
|
||||
|
||||
// check account cache
|
||||
var AccountArray [4]common.Address
|
||||
AccountArray[0] = common.StringToAddress("0fbdc686b912d7722dc86510934589e0aaf3b55a")
|
||||
AccountArray[1] = common.StringToAddress("9186eb3d20cbd1f5f992a950d808c4495153abd5")
|
||||
AccountArray[2] = common.StringToAddress("0638e1574728b6d862dd5d3a3e0942c3be47d996")
|
||||
AccountArray[3] = common.StringToAddress("ae9bc6cd5145e67fbd1887a5145271fd182f0ee7")
|
||||
|
||||
for i := 0; i < accountCacheSize; i++ {
|
||||
_, err = testObject.AddAccountToOrg(AccountArray[i], arbitraryNetworkAdminOrg, arbitrartNewRole1, txa)
|
||||
assert.NoError(t, err)
|
||||
types.AcctInfoMap.UpsertAccount(arbitraryNetworkAdminOrg, arbitrartNewRole1, AccountArray[i], false, types.AcctActive)
|
||||
}
|
||||
assert.Equal(t, accountCacheSize, len(types.AcctInfoMap.GetAcctList()))
|
||||
|
||||
acctInfo := types.AcctInfoMap.GetAccount(acct)
|
||||
assert.True(t, acctInfo != nil, "account details nil")
|
||||
}
|
||||
|
||||
func getArbitraryAccount() common.Address {
|
||||
|
@ -480,8 +543,8 @@ func typicalPermissionCtrl(t *testing.T) *PermissionCtrl {
|
|||
Accounts: []common.Address{
|
||||
guardianAddress,
|
||||
},
|
||||
SubOrgDepth: big.NewInt(3),
|
||||
SubOrgBreadth: big.NewInt(3),
|
||||
SubOrgDepth: big.NewInt(10),
|
||||
SubOrgBreadth: big.NewInt(10),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -512,7 +575,7 @@ func TestPermissionCtrl_whenUpdateFile(t *testing.T) {
|
|||
testObject := typicalPermissionCtrl(t)
|
||||
assert.NoError(t, testObject.AfterStart())
|
||||
|
||||
err := testObject.populateInitPermissions()
|
||||
err := testObject.populateInitPermissions(orgCacheSize, roleCacheSize, nodeCacheSize, accountCacheSize)
|
||||
assert.NoError(t, err)
|
||||
|
||||
d, _ := ioutil.TempDir("", "qdata")
|
||||
|
|
Loading…
Reference in New Issue