forked from TrueCloudLab/policy-engine
218 lines
6.3 KiB
Go
218 lines
6.3 KiB
Go
|
package inmemory
|
||
|
|
||
|
import (
|
||
|
"testing"
|
||
|
|
||
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||
|
"github.com/stretchr/testify/require"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
resrc = "native:::object/ExYw/*"
|
||
|
chainID = "ingress:ExYw"
|
||
|
nonExistChainId = "ingress:LxGyWyL"
|
||
|
)
|
||
|
|
||
|
func testInmemLocalStorage() *inmemoryLocalStorage {
|
||
|
return NewInmemoryLocalStorage().(*inmemoryLocalStorage)
|
||
|
}
|
||
|
|
||
|
func TestAddOverride(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
|
||
|
inmem.AddOverride(chain.Ingress, resrc, &chain.Chain{
|
||
|
Rules: []chain.Rule{
|
||
|
{
|
||
|
Status: chain.AccessDenied,
|
||
|
Actions: chain.Actions{Names: []string{"native::object::delete"}},
|
||
|
Resources: chain.Resources{Names: []string{"native::object::*"}},
|
||
|
},
|
||
|
},
|
||
|
})
|
||
|
|
||
|
ingressChains, ok := inmem.nameToResourceChains[chain.Ingress]
|
||
|
require.True(t, ok)
|
||
|
resourceChains, ok := ingressChains[resrc]
|
||
|
require.True(t, ok)
|
||
|
require.Len(t, resourceChains, 1)
|
||
|
require.Len(t, resourceChains[0].Rules, 1)
|
||
|
|
||
|
inmem.AddOverride(chain.Ingress, resrc, &chain.Chain{
|
||
|
Rules: []chain.Rule{
|
||
|
{
|
||
|
Status: chain.QuotaLimitReached,
|
||
|
Actions: chain.Actions{Names: []string{"native::object::put"}},
|
||
|
Resources: chain.Resources{Names: []string{"native::object::*"}},
|
||
|
},
|
||
|
{
|
||
|
Status: chain.AccessDenied,
|
||
|
Actions: chain.Actions{Names: []string{"native::object::get"}},
|
||
|
Resources: chain.Resources{Names: []string{"native::object::*"}},
|
||
|
},
|
||
|
},
|
||
|
})
|
||
|
|
||
|
ingressChains, ok = inmem.nameToResourceChains[chain.Ingress]
|
||
|
require.True(t, ok)
|
||
|
resourceChains, ok = ingressChains[resrc]
|
||
|
require.True(t, ok)
|
||
|
require.Len(t, resourceChains, 2)
|
||
|
require.Len(t, resourceChains[1].Rules, 2)
|
||
|
}
|
||
|
|
||
|
func TestRemoveOverride(t *testing.T) {
|
||
|
t.Run("remove from empty storage", func(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
err := inmem.RemoveOverride(chain.Ingress, resrc, chain.ID(chainID))
|
||
|
require.ErrorIs(t, err, engine.ErrChainNameNotFound)
|
||
|
})
|
||
|
|
||
|
t.Run("remove not added chain id", func(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
inmem.AddOverride(chain.Ingress, resrc, &chain.Chain{
|
||
|
ID: chain.ID(chainID),
|
||
|
Rules: []chain.Rule{
|
||
|
{ // Restrict to remove ANY object from the namespace.
|
||
|
Status: chain.AccessDenied,
|
||
|
Actions: chain.Actions{Names: []string{"native::object::delete"}},
|
||
|
Resources: chain.Resources{Names: []string{"native::object::*"}},
|
||
|
},
|
||
|
},
|
||
|
})
|
||
|
|
||
|
err := inmem.RemoveOverride(chain.Ingress, resrc, chain.ID(nonExistChainId))
|
||
|
require.ErrorIs(t, err, engine.ErrChainNotFound)
|
||
|
})
|
||
|
|
||
|
t.Run("remove existing chain id", func(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
inmem.AddOverride(chain.Ingress, resrc, &chain.Chain{
|
||
|
ID: chain.ID(chainID),
|
||
|
Rules: []chain.Rule{
|
||
|
{ // Restrict to remove ANY object from the namespace.
|
||
|
Status: chain.AccessDenied,
|
||
|
Actions: chain.Actions{Names: []string{"native::object::delete"}},
|
||
|
Resources: chain.Resources{Names: []string{"native::object::*"}},
|
||
|
},
|
||
|
},
|
||
|
})
|
||
|
|
||
|
err := inmem.RemoveOverride(chain.Ingress, resrc, chain.ID(chainID))
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
ingressChains, ok := inmem.nameToResourceChains[chain.Ingress]
|
||
|
require.True(t, ok)
|
||
|
require.Len(t, ingressChains, 1)
|
||
|
resourceChains, ok := ingressChains[resrc]
|
||
|
require.True(t, ok)
|
||
|
require.Len(t, resourceChains, 0)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestGetOverride(t *testing.T) {
|
||
|
addChain := &chain.Chain{
|
||
|
ID: chain.ID(chainID),
|
||
|
Rules: []chain.Rule{
|
||
|
{ // Restrict to remove ANY object from the namespace.
|
||
|
Status: chain.AccessDenied,
|
||
|
Actions: chain.Actions{Names: []string{"native::object::delete"}},
|
||
|
Resources: chain.Resources{Names: []string{"native::object::*"}},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
t.Run("get from empty storage", func(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
_, err := inmem.GetOverride(chain.Ingress, resrc, chain.ID(chainID))
|
||
|
require.ErrorIs(t, err, engine.ErrChainNameNotFound)
|
||
|
})
|
||
|
|
||
|
t.Run("get not added chain id", func(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
inmem.AddOverride(chain.Ingress, resrc, addChain)
|
||
|
|
||
|
const nonExistingChainID = "ingress:LxGyWyL"
|
||
|
|
||
|
_, err := inmem.GetOverride(chain.Ingress, resrc, chain.ID(nonExistingChainID))
|
||
|
require.ErrorIs(t, err, engine.ErrChainNotFound)
|
||
|
})
|
||
|
|
||
|
t.Run("get existing chain id", func(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
inmem.AddOverride(chain.Ingress, resrc, addChain)
|
||
|
|
||
|
c, err := inmem.GetOverride(chain.Ingress, resrc, chain.ID(chainID))
|
||
|
require.NoError(t, err)
|
||
|
require.EqualValues(t, *addChain, *c)
|
||
|
})
|
||
|
|
||
|
t.Run("get removed chain id", func(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
inmem.AddOverride(chain.Ingress, resrc, addChain)
|
||
|
|
||
|
err := inmem.RemoveOverride(chain.Ingress, resrc, chain.ID(chainID))
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
_, err = inmem.GetOverride(chain.Ingress, resrc, chain.ID(chainID))
|
||
|
require.ErrorIs(t, err, engine.ErrChainNotFound)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestListOverrides(t *testing.T) {
|
||
|
addChain := &chain.Chain{
|
||
|
ID: chain.ID(chainID),
|
||
|
Rules: []chain.Rule{
|
||
|
{ // Restrict to remove ANY object from the namespace.
|
||
|
Status: chain.AccessDenied,
|
||
|
Actions: chain.Actions{Names: []string{"native::object::delete"}},
|
||
|
Resources: chain.Resources{Names: []string{"native::object::*"}},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
t.Run("list empty storage", func(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
l, _ := inmem.ListOverrides(chain.Ingress, resrc)
|
||
|
require.Len(t, l, 0)
|
||
|
})
|
||
|
|
||
|
t.Run("list with one added resource", func(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
inmem.AddOverride(chain.Ingress, resrc, addChain)
|
||
|
l, _ := inmem.ListOverrides(chain.Ingress, resrc)
|
||
|
require.Len(t, l, 1)
|
||
|
})
|
||
|
|
||
|
t.Run("list after drop", func(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
inmem.AddOverride(chain.Ingress, resrc, addChain)
|
||
|
l, _ := inmem.ListOverrides(chain.Ingress, resrc)
|
||
|
require.Len(t, l, 1)
|
||
|
|
||
|
_ = inmem.DropAllOverrides(chain.Ingress)
|
||
|
l, _ = inmem.ListOverrides(chain.Ingress, resrc)
|
||
|
require.Len(t, l, 0)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestGenerateID(t *testing.T) {
|
||
|
inmem := testInmemLocalStorage()
|
||
|
ids := make([]chain.ID, 0, 100)
|
||
|
for i := 0; i < 100; i++ {
|
||
|
ids = append(ids, inmem.generateChainID(chain.Ingress, resrc))
|
||
|
}
|
||
|
require.False(t, hasDuplicates(ids))
|
||
|
}
|
||
|
|
||
|
func hasDuplicates(ids []chain.ID) bool {
|
||
|
seen := make(map[chain.ID]bool)
|
||
|
for _, id := range ids {
|
||
|
if seen[id] {
|
||
|
return true
|
||
|
}
|
||
|
seen[id] = true
|
||
|
}
|
||
|
return false
|
||
|
}
|