More tests
This commit is contained in:
parent
69dbfa9f66
commit
1e79cd1d46
@ -34,6 +34,7 @@ func buildRuleIndex(rules []*Rule) (index *ruleIndex) {
|
||||
return index
|
||||
}
|
||||
|
||||
// add adds a new Rule to the index
|
||||
func (index *ruleIndex) add(rules ...*Rule) {
|
||||
if index.children == nil {
|
||||
index.children = make(map[uint64]*ruleIndexNode, len(rules)/2)
|
||||
@ -71,62 +72,12 @@ func (index *ruleIndex) add(rules ...*Rule) {
|
||||
}
|
||||
}
|
||||
|
||||
func (index *ruleIndex) remove(role uint64, resource string, ops ...string) {
|
||||
if _, ok := index.children[role]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
auxOps := ops
|
||||
|
||||
if len(auxOps) == 0 {
|
||||
for op := range index.children[role].children {
|
||||
auxOps = append(auxOps, op)
|
||||
}
|
||||
}
|
||||
|
||||
for _, op := range auxOps {
|
||||
bits := append([]string{op}, strings.Split(resource, "/")...)
|
||||
index.removeRec(index.children[role], bits)
|
||||
|
||||
// Finishing touch cleanup
|
||||
if len(index.children[role].children[op].children) == 0 {
|
||||
delete(index.children[role].children, op)
|
||||
}
|
||||
if len(index.children[role].children) == 0 {
|
||||
delete(index.children, role)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (index *ruleIndex) removeRec(n *ruleIndexNode, bits []string) {
|
||||
// Recursive in; decrement counters
|
||||
n.count--
|
||||
|
||||
if len(bits) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
n = n.children[bits[0]]
|
||||
index.removeRec(n, bits[1:])
|
||||
|
||||
// Recursive out; yoink out obsolete štuff
|
||||
if len(bits) == 1 {
|
||||
if len(n.children) > 0 {
|
||||
n.children[bits[0]].isLeaf = false
|
||||
n.children[bits[0]].rule = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if n.children[bits[1]].count == 0 {
|
||||
delete(n.children, bits[1])
|
||||
}
|
||||
}
|
||||
|
||||
// has checks if the rule is already in there
|
||||
func (t *ruleIndex) has(r *Rule) bool {
|
||||
return len(t.collect(true, r.RoleID, r.Operation, r.Resource)) > 0
|
||||
}
|
||||
|
||||
// get returns the matching rules
|
||||
func (t *ruleIndex) get(role uint64, op, res string) (out []*Rule) {
|
||||
return t.collect(false, role, op, res)
|
||||
}
|
||||
|
||||
@ -9,11 +9,10 @@ import (
|
||||
|
||||
func TestIndexBuild(t *testing.T) {
|
||||
tcc := []struct {
|
||||
name string
|
||||
in []*Rule
|
||||
remove []*Rule
|
||||
add []*Rule
|
||||
out []int
|
||||
name string
|
||||
in []*Rule
|
||||
add []*Rule
|
||||
out []int
|
||||
|
||||
role uint64
|
||||
op string
|
||||
@ -120,126 +119,6 @@ func TestIndexBuild(t *testing.T) {
|
||||
role: 1,
|
||||
op: "read",
|
||||
res: "a:b/c/d",
|
||||
}, {
|
||||
name: "removing the only element",
|
||||
in: []*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}},
|
||||
remove: []*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}},
|
||||
out: nil,
|
||||
|
||||
role: 1,
|
||||
op: "write",
|
||||
res: "a:b/c/d",
|
||||
},
|
||||
{
|
||||
name: "removing twice added thing",
|
||||
in: []*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}, {
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}},
|
||||
remove: []*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}},
|
||||
|
||||
out: nil,
|
||||
|
||||
role: 1,
|
||||
op: "write",
|
||||
res: "a:b/c/d",
|
||||
},
|
||||
{
|
||||
name: "two elements with no common root",
|
||||
in: []*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}, {
|
||||
RoleID: 2,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}},
|
||||
remove: []*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}},
|
||||
out: nil,
|
||||
|
||||
role: 1,
|
||||
op: "write",
|
||||
res: "a:b/c/d",
|
||||
},
|
||||
{
|
||||
name: "two elements with common root (get removed)",
|
||||
in: []*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}, {
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/e",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}},
|
||||
remove: []*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}},
|
||||
out: nil,
|
||||
|
||||
role: 1,
|
||||
op: "write",
|
||||
res: "a:b/c/d",
|
||||
},
|
||||
{
|
||||
name: "two elements with common root (get not removed)",
|
||||
in: []*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}, {
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/e",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}},
|
||||
remove: []*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/d",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}},
|
||||
out: []int{1},
|
||||
|
||||
role: 1,
|
||||
op: "write",
|
||||
res: "a:b/c/e",
|
||||
},
|
||||
{
|
||||
name: "add new element",
|
||||
@ -266,13 +145,12 @@ func TestIndexBuild(t *testing.T) {
|
||||
for _, tc := range tcc {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ix := buildRuleIndex(tc.in)
|
||||
ix.remove(tc.remove...)
|
||||
ix.add(tc.add...)
|
||||
|
||||
out := RuleSet(ix.get(tc.role, tc.op, tc.res))
|
||||
sort.Sort(out)
|
||||
|
||||
want := RuleSet(graby(append(tc.in, tc.add...), tc.out))
|
||||
want := RuleSet(grabIndexMatches(append(tc.in, tc.add...), tc.out))
|
||||
sort.Sort(want)
|
||||
|
||||
require.Len(t, out, len(want))
|
||||
@ -281,10 +159,32 @@ func TestIndexBuild(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func graby(rr []*Rule, want []int) (out []*Rule) {
|
||||
func TestIndexHas(t *testing.T) {
|
||||
ix := buildRuleIndex([]*Rule{{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/x",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}})
|
||||
|
||||
require.True(t, ix.has(&Rule{
|
||||
RoleID: 1,
|
||||
Resource: "a:b/c/x",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}))
|
||||
|
||||
require.False(t, ix.has(&Rule{
|
||||
RoleID: 2,
|
||||
Resource: "a:b/c/x",
|
||||
Operation: "write",
|
||||
Access: Allow,
|
||||
}))
|
||||
}
|
||||
|
||||
func grabIndexMatches(rr []*Rule, want []int) (out []*Rule) {
|
||||
out = make([]*Rule, 0, len(want))
|
||||
|
||||
for _, w := range want {
|
||||
@ -294,14 +194,14 @@ func graby(rr []*Rule, want []int) (out []*Rule) {
|
||||
return
|
||||
}
|
||||
|
||||
// goos: linux
|
||||
// goarch: amd64
|
||||
// goos: darwin
|
||||
// goarch: arm64
|
||||
// pkg: github.com/cortezaproject/corteza/server/pkg/rbac
|
||||
// cpu: Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
|
||||
// BenchmarkIndexBuild_100-12 10000 102361 ns/op 88064 B/op 1271 allocs/op
|
||||
// BenchmarkIndexBuild_1000-12 1149 1024872 ns/op 755375 B/op 11183 allocs/op
|
||||
// BenchmarkIndexBuild_10000-12 128 8986248 ns/op 4406477 B/op 82453 allocs/op
|
||||
// BenchmarkIndexBuild_100000-12 14 81871407 ns/op 20627785 B/op 543568 allocs/op
|
||||
// cpu: Apple M3 Pro
|
||||
// BenchmarkIndexBuild_100-12 26077 43467 ns/op 94785 B/op 1119 allocs/op
|
||||
// BenchmarkIndexBuild_1000-12 2316 505664 ns/op 939447 B/op 10219 allocs/op
|
||||
// BenchmarkIndexBuild_10000-12 228 5301265 ns/op 9008425 B/op 98033 allocs/op
|
||||
// BenchmarkIndexBuild_100000-12 19 68454059 ns/op 70832448 B/op 843270 allocs/op
|
||||
func benchmarkIndexBuild(b *testing.B, rules []*Rule) {
|
||||
b.ResetTimer()
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user