snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
807
server/pkg/rbac/user_groups_test.go
Normal file
807
server/pkg/rbac/user_groups_test.go
Normal file
@@ -0,0 +1,807 @@
|
||||
package rbac
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGroupMembership(t *testing.T) {
|
||||
svc, err := testPrepState(t)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, svc)
|
||||
|
||||
mm := svc.GroupMembers(id.MustNumID(1))
|
||||
require.Len(t, mm, 2)
|
||||
require.Contains(t, mm, id.MustNumID(101))
|
||||
require.Contains(t, mm, id.MustNumID(102))
|
||||
|
||||
mm = svc.GroupMembers(id.MustNumID(2))
|
||||
require.Len(t, mm, 3)
|
||||
require.Contains(t, mm, id.MustNumID(121))
|
||||
require.Contains(t, mm, id.MustNumID(122))
|
||||
require.Contains(t, mm, id.MustNumID(123))
|
||||
}
|
||||
|
||||
func TestMemberBranch(t *testing.T) {
|
||||
// @todo add some test cases for named paths; they use the same underlying fnc so I'm skipping for now
|
||||
t.Run("unnamed paths", func(t *testing.T) {
|
||||
svc, err := testPrepState(t)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, svc)
|
||||
|
||||
mm, err := svc.MemberBranch(id.MustNumID(102))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, mm, 4)
|
||||
require.Equal(t, id.MustNumID(1), mm[0].id)
|
||||
require.Equal(t, id.MustNumID(2), mm[1].id)
|
||||
require.Equal(t, id.MustNumID(3), mm[2].id)
|
||||
require.Equal(t, id.MustNumID(4), mm[3].id)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsAbove(t *testing.T) {
|
||||
t.Run("unnamed", func(t *testing.T) {
|
||||
svc, err := testPrepState(t)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("yes, child", func(t *testing.T) {
|
||||
require.True(t, svc.IsAbove(id.MustNumID(121), id.MustNumID(101)))
|
||||
})
|
||||
|
||||
t.Run("yes, grandchild", func(t *testing.T) {
|
||||
require.True(t, svc.IsAbove(id.MustNumID(141), id.MustNumID(101)))
|
||||
})
|
||||
|
||||
t.Run("no, same lvl", func(t *testing.T) {
|
||||
require.False(t, svc.IsAbove(id.MustNumID(101), id.MustNumID(102)))
|
||||
})
|
||||
|
||||
t.Run("no, below", func(t *testing.T) {
|
||||
require.False(t, svc.IsAbove(id.MustNumID(101), id.MustNumID(121)))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("named", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
err = svc.AssignGroupMembers(id.MustNumID(101), id.MustNumID(101))
|
||||
require.NoError(t, err)
|
||||
|
||||
//
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPpn(id.MustNumID(101), "a")...)
|
||||
require.NoError(t, err)
|
||||
err = svc.AssignGroupMembers(id.MustNumID(201), id.MustNumID(201))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(202), "c2", mkPpn(id.MustNumID(101), "a", id.MustNumID(101), "b")...)
|
||||
require.NoError(t, err)
|
||||
err = svc.AssignGroupMembers(id.MustNumID(202), id.MustNumID(202))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(203), "c3", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
err = svc.AssignGroupMembers(id.MustNumID(203), id.MustNumID(203))
|
||||
require.NoError(t, err)
|
||||
|
||||
//
|
||||
|
||||
err = svc.AddNode(id.MustNumID(301), "cc1", mkPpn(id.MustNumID(201), "a")...)
|
||||
require.NoError(t, err)
|
||||
err = svc.AssignGroupMembers(id.MustNumID(301), id.MustNumID(301))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(302), "cc2", mkPpn(id.MustNumID(202), "a")...)
|
||||
require.NoError(t, err)
|
||||
err = svc.AssignGroupMembers(id.MustNumID(302), id.MustNumID(302))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(303), "cc3", mkPpn(id.MustNumID(101), "a")...)
|
||||
require.NoError(t, err)
|
||||
err = svc.AssignGroupMembers(id.MustNumID(303), id.MustNumID(303))
|
||||
require.NoError(t, err)
|
||||
|
||||
// ---
|
||||
|
||||
t.Run("yes, child, labeled path", func(t *testing.T) {
|
||||
require.True(t, svc.IsAbove(id.MustNumID(201), id.MustNumID(101), "a"))
|
||||
})
|
||||
|
||||
t.Run("yes, child, has labeled path but looking generic", func(t *testing.T) {
|
||||
require.True(t, svc.IsAbove(id.MustNumID(201), id.MustNumID(101)))
|
||||
})
|
||||
|
||||
t.Run("no, child, wrong labeled path", func(t *testing.T) {
|
||||
require.False(t, svc.IsAbove(id.MustNumID(201), id.MustNumID(101), "b"))
|
||||
})
|
||||
|
||||
t.Run("yes, grandchild, labeled path", func(t *testing.T) {
|
||||
require.True(t, svc.IsAbove(id.MustNumID(302), id.MustNumID(101), "a"))
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestAddGroupRole(t *testing.T) {
|
||||
t.Run("add role", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddGroupRole(id.MustNumID(101), id.MustNumID(991))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, n := svc.findNode(id.MustNumID(101))
|
||||
require.NotNil(t, n)
|
||||
|
||||
require.Len(t, n.roles, 1)
|
||||
require.Equal(t, id.MustNumID(991), n.roles[0])
|
||||
})
|
||||
|
||||
t.Run("add duplicate role", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddGroupRole(id.MustNumID(101), id.MustNumID(991), id.MustNumID(991))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, n := svc.findNode(id.MustNumID(101))
|
||||
require.NotNil(t, n)
|
||||
|
||||
require.Len(t, n.roles, 1)
|
||||
require.Equal(t, id.MustNumID(991), n.roles[0])
|
||||
})
|
||||
|
||||
t.Run("append role", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddGroupRole(id.MustNumID(101), id.MustNumID(991))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddGroupRole(id.MustNumID(101), id.MustNumID(992), id.MustNumID(993))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, n := svc.findNode(id.MustNumID(101))
|
||||
require.NotNil(t, n)
|
||||
|
||||
require.Len(t, n.roles, 3)
|
||||
require.Equal(t, id.MustNumID(991), n.roles[0])
|
||||
require.Equal(t, id.MustNumID(992), n.roles[1])
|
||||
require.Equal(t, id.MustNumID(993), n.roles[2])
|
||||
})
|
||||
}
|
||||
|
||||
func TestRemoveGroupRole(t *testing.T) {
|
||||
t.Run("remove role", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddGroupRole(id.MustNumID(101), id.MustNumID(991))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.RemoveGroupRole(id.MustNumID(101), id.MustNumID(991))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, n := svc.findNode(id.MustNumID(101))
|
||||
require.NotNil(t, n)
|
||||
|
||||
require.Len(t, n.roles, 0)
|
||||
})
|
||||
|
||||
t.Run("remove roles", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddGroupRole(id.MustNumID(101), id.MustNumID(991), id.MustNumID(992), id.MustNumID(993))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.RemoveGroupRole(id.MustNumID(101), id.MustNumID(991), id.MustNumID(993))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, n := svc.findNode(id.MustNumID(101))
|
||||
require.NotNil(t, n)
|
||||
|
||||
require.Len(t, n.roles, 1)
|
||||
require.Equal(t, id.MustNumID(992), n.roles[0])
|
||||
})
|
||||
}
|
||||
|
||||
func TestAddNode(t *testing.T) {
|
||||
t.Run("empty svc", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(1), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
ii := svc.root.inline()
|
||||
|
||||
require.Len(t, ii, 1)
|
||||
require.Equal(t, id.MustNumID(1), ii[0].id)
|
||||
})
|
||||
|
||||
t.Run("add children", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(202), "c2", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(301), "c3", mkPp(id.MustNumID(201))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
// ---
|
||||
|
||||
checkInline(t, svc.root, id.MustNumID(101), id.MustNumID(201), id.MustNumID(202), id.MustNumID(301))
|
||||
|
||||
checkInline(t, svc.branchIndex[id.MustNumID(101)], id.MustNumID(101), id.MustNumID(201), id.MustNumID(202), id.MustNumID(301))
|
||||
checkInline(t, svc.branchIndex[id.MustNumID(201)], id.MustNumID(201), id.MustNumID(301))
|
||||
checkInline(t, svc.branchIndex[id.MustNumID(202)], id.MustNumID(202))
|
||||
checkInline(t, svc.branchIndex[id.MustNumID(301)], id.MustNumID(301))
|
||||
})
|
||||
|
||||
t.Run("check path management", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Add initial stuff
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", GroupNodePath{SelfID: id.MustNumID(101)})
|
||||
require.NoError(t, err)
|
||||
err = svc.AddNode(id.MustNumID(202), "c2", GroupNodePath{SelfID: id.MustNumID(101)})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(301), "cc1", GroupNodePath{SelfID: id.MustNumID(201)})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(101)].parents, 0)
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(101)].children, 2)
|
||||
require.Equal(t, id.MustNumID(201), svc.branchIndex[id.MustNumID(101)].children[0].node.id)
|
||||
require.Equal(t, id.MustNumID(202), svc.branchIndex[id.MustNumID(101)].children[1].node.id)
|
||||
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(201)].parents, 1)
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(201)].children, 1)
|
||||
require.Equal(t, id.MustNumID(301), svc.branchIndex[id.MustNumID(201)].children[0].node.id)
|
||||
require.Equal(t, id.MustNumID(101), svc.branchIndex[id.MustNumID(201)].parents[0].node.id)
|
||||
|
||||
// Change c2 connection
|
||||
|
||||
err = svc.UpdateNode(id.MustNumID(202), "ccc2 edit", GroupNodePath{SelfID: id.MustNumID(301)})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(101)].parents, 0)
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(101)].children, 1)
|
||||
require.Equal(t, id.MustNumID(201), svc.branchIndex[id.MustNumID(101)].children[0].node.id)
|
||||
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(301)].parents, 1)
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(301)].children, 1)
|
||||
require.Equal(t, id.MustNumID(201), svc.branchIndex[id.MustNumID(301)].parents[0].node.id)
|
||||
require.Equal(t, id.MustNumID(202), svc.branchIndex[id.MustNumID(301)].children[0].node.id)
|
||||
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(202)].parents, 1)
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(202)].children, 0)
|
||||
require.Equal(t, id.MustNumID(301), svc.branchIndex[id.MustNumID(202)].parents[0].node.id)
|
||||
|
||||
// Remove c2 node
|
||||
|
||||
err = svc.RemoveNode(id.MustNumID(202))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(301)].parents, 1)
|
||||
require.Len(t, svc.branchIndex[id.MustNumID(301)].children, 0)
|
||||
require.Equal(t, id.MustNumID(201), svc.branchIndex[id.MustNumID(301)].parents[0].node.id)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMultiPath(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
// lvl 2 roots
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(202), "c2", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Multi path child
|
||||
err = svc.AddNode(id.MustNumID(301), "cc1", mkPp(id.MustNumID(201), id.MustNumID(202))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check
|
||||
|
||||
gg := svc.branchIndex[id.MustNumID(201)].inline()
|
||||
require.Len(t, gg, 2)
|
||||
|
||||
require.Equal(t, id.MustNumID(201), gg[0].id)
|
||||
require.Equal(t, id.MustNumID(301), gg[1].id)
|
||||
|
||||
gg = svc.branchIndex[id.MustNumID(202)].inline()
|
||||
require.Len(t, gg, 2)
|
||||
|
||||
require.Equal(t, id.MustNumID(202), gg[0].id)
|
||||
require.Equal(t, id.MustNumID(301), gg[1].id)
|
||||
}
|
||||
|
||||
func TestNamedPaths(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
//
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPpn(id.MustNumID(101), "a")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(202), "c2", mkPpn(id.MustNumID(101), "b")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(203), "c3", mkPpn(id.MustNumID(101), "")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
//
|
||||
|
||||
err = svc.AddNode(id.MustNumID(311), "cc11", mkPpn(id.MustNumID(201), "a", id.MustNumID(201), "b")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(312), "cc12", mkPpn(id.MustNumID(201), "")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(321), "cc21", mkPpn(id.MustNumID(202), "")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(331), "cc31", mkPpn(id.MustNumID(203), "a")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(332), "cc32", mkPpn(id.MustNumID(203), "b")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
//
|
||||
|
||||
err = svc.AddNode(id.MustNumID(401), "ccc01", mkPpn(id.MustNumID(311), "")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(402), "ccc02", mkPpn(id.MustNumID(312), "b")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(403), "ccc03", mkPpn(id.MustNumID(332), "")...)
|
||||
require.NoError(t, err)
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
t.Run("201 any path", func(t *testing.T) {
|
||||
bb := svc.branchIndex[id.MustNumID(201)].inline()
|
||||
require.Len(t, bb, 5)
|
||||
|
||||
require.Equal(t, id.MustNumID(201), bb[0].id)
|
||||
require.Equal(t, id.MustNumID(311), bb[1].id)
|
||||
require.Equal(t, id.MustNumID(312), bb[2].id)
|
||||
require.Equal(t, id.MustNumID(401), bb[3].id)
|
||||
require.Equal(t, id.MustNumID(402), bb[4].id)
|
||||
})
|
||||
|
||||
t.Run("201 a path", func(t *testing.T) {
|
||||
bb := svc.branchIndex[id.MustNumID(201)].inline("a")
|
||||
require.Len(t, bb, 4)
|
||||
|
||||
require.Equal(t, id.MustNumID(201), bb[0].id)
|
||||
require.Equal(t, id.MustNumID(311), bb[1].id)
|
||||
require.Equal(t, id.MustNumID(312), bb[2].id)
|
||||
require.Equal(t, id.MustNumID(401), bb[3].id)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestUpdateNode(t *testing.T) {
|
||||
t.Run("update without move", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.UpdateNode(id.MustNumID(101), "root edited")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, id.MustNumID(101), svc.root.id)
|
||||
require.Equal(t, "root edited", svc.root.handle)
|
||||
})
|
||||
|
||||
t.Run("change parent", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(202), "c2", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(301), "c3", mkPp(id.MustNumID(201))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.UpdateNode(id.MustNumID(301), "c3 edited", mkPp(id.MustNumID(202))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkInline(t, svc.branchIndex[id.MustNumID(201)], id.MustNumID(201))
|
||||
checkInline(t, svc.branchIndex[id.MustNumID(202)], id.MustNumID(202), id.MustNumID(301))
|
||||
})
|
||||
|
||||
t.Run("update non existing node", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.UpdateNode(id.MustNumID(999), "root edited", mkPp(id.MustNumID(0))...)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRemoveNode(t *testing.T) {
|
||||
t.Run("remove leaf node", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.RemoveNode(id.MustNumID(201))
|
||||
require.NoError(t, err)
|
||||
|
||||
checkInline(t, svc.branchIndex[id.MustNumID(101)], id.MustNumID(101))
|
||||
checkInline(t, svc.branchIndex[id.MustNumID(201)])
|
||||
})
|
||||
|
||||
t.Run("can not remove non-lief nodes", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(301), "c2", mkPp(id.MustNumID(201))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.RemoveNode(id.MustNumID(201))
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("can not remove non-existing nodes", func(t *testing.T) {
|
||||
svc, err := mkOrgTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(101), "root")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.AddNode(id.MustNumID(201), "c1", mkPp(id.MustNumID(101))...)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.RemoveNode(id.MustNumID(999))
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAssignGroupMembers(t *testing.T) {
|
||||
t.Run("new", func(t *testing.T) {
|
||||
svc, err := mkOrgTree(
|
||||
GroupMembers{
|
||||
group: &groupNode{
|
||||
id: id.MustNumID(1),
|
||||
handle: "root",
|
||||
},
|
||||
members: nil,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, svc)
|
||||
|
||||
err = svc.AssignGroupMembers(id.MustNumID(1), id.MustNumID(101), id.MustNumID(102))
|
||||
require.NoError(t, err)
|
||||
|
||||
members := svc.GroupMembers(id.MustNumID(1))
|
||||
require.Len(t, members, 2)
|
||||
|
||||
require.Equal(t, id.MustNumID(101), members[0])
|
||||
require.Equal(t, id.MustNumID(102), members[1])
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
svc, err := mkOrgTree(
|
||||
GroupMembers{
|
||||
group: &groupNode{
|
||||
id: id.MustNumID(1),
|
||||
handle: "root",
|
||||
},
|
||||
members: []id.ID{id.MustNumID(991), id.MustNumID(102)},
|
||||
},
|
||||
|
||||
GroupMembers{
|
||||
group: &groupNode{
|
||||
id: id.MustNumID(2),
|
||||
handle: "subgroup",
|
||||
paths: mkPp(id.MustNumID(1)),
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, svc)
|
||||
|
||||
err = svc.AssignGroupMembers(id.MustNumID(2), id.MustNumID(991))
|
||||
require.NoError(t, err)
|
||||
|
||||
members := svc.GroupMembers(id.MustNumID(1))
|
||||
require.Len(t, members, 1)
|
||||
|
||||
require.Equal(t, id.MustNumID(102), members[0])
|
||||
|
||||
members = svc.GroupMembers(id.MustNumID(2))
|
||||
require.Len(t, members, 1)
|
||||
|
||||
require.Equal(t, id.MustNumID(991), members[0])
|
||||
})
|
||||
}
|
||||
|
||||
func TestRemoveGroupMembers(t *testing.T) {
|
||||
svc, err := mkOrgTree(
|
||||
GroupMembers{
|
||||
group: &groupNode{
|
||||
id: id.MustNumID(1),
|
||||
handle: "root",
|
||||
},
|
||||
members: []id.ID{id.MustNumID(101), id.MustNumID(102), id.MustNumID(103)},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, svc)
|
||||
|
||||
err = svc.RemoveGroupMembers(id.MustNumID(1), id.MustNumID(102))
|
||||
require.NoError(t, err)
|
||||
|
||||
members := svc.GroupMembers(id.MustNumID(1))
|
||||
require.Len(t, members, 2)
|
||||
|
||||
require.Equal(t, id.MustNumID(101), members[0])
|
||||
require.Equal(t, id.MustNumID(103), members[1])
|
||||
}
|
||||
|
||||
func TestRebuild(t *testing.T) {
|
||||
svc, err := testPrepState(t)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, svc)
|
||||
|
||||
err = svc.Rebuild(GroupMembers{
|
||||
group: &groupNode{
|
||||
id: id.MustNumID(999),
|
||||
handle: "newRoot",
|
||||
},
|
||||
members: []id.ID{id.MustNumID(991), id.MustNumID(992), id.MustNumID(993)},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
members := svc.GroupMembers(id.MustNumID(1))
|
||||
require.Len(t, members, 0)
|
||||
|
||||
members = svc.GroupMembers(id.MustNumID(999))
|
||||
require.Len(t, members, 3)
|
||||
}
|
||||
|
||||
func TestBuildOrgTree(t *testing.T) {
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
out, _, err := buildOrgTree()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, out)
|
||||
})
|
||||
|
||||
t.Run("just root", func(t *testing.T) {
|
||||
out, _, err := buildOrgTree(&groupNode{id: id.MustNumID(1), handle: "root"})
|
||||
require.NoError(t, err)
|
||||
|
||||
nodes := out.inline()
|
||||
require.Len(t, nodes, 1)
|
||||
require.Equal(t, "root", nodes[0].handle)
|
||||
})
|
||||
|
||||
t.Run("multiple root error", func(t *testing.T) {
|
||||
_, _, err := buildOrgTree(
|
||||
&groupNode{id: id.MustNumID(1), handle: "root1"},
|
||||
&groupNode{id: id.MustNumID(2), handle: "root2"},
|
||||
)
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "multiple root nodes detected")
|
||||
})
|
||||
|
||||
t.Run("missing parent error", func(t *testing.T) {
|
||||
_, _, err := buildOrgTree(
|
||||
&groupNode{id: id.MustNumID(1), handle: "root1"},
|
||||
&groupNode{id: id.MustNumID(2), handle: "child1", paths: mkPp(id.MustNumID(99))},
|
||||
)
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, `node "2" parent "99" not found`)
|
||||
})
|
||||
|
||||
t.Run("build tree", func(t *testing.T) {
|
||||
out, _, err := buildOrgTree(
|
||||
&groupNode{id: id.MustNumID(1), handle: "root"},
|
||||
&groupNode{id: id.MustNumID(2), handle: "child1", paths: mkPp(id.MustNumID(1))},
|
||||
&groupNode{id: id.MustNumID(3), handle: "child2", paths: mkPp(id.MustNumID(1))},
|
||||
&groupNode{id: id.MustNumID(4), handle: "child1_grandchild1", paths: mkPp(id.MustNumID(2))},
|
||||
&groupNode{id: id.MustNumID(5), handle: "child1_grandchild2", paths: mkPp(id.MustNumID(2))},
|
||||
&groupNode{id: id.MustNumID(6), handle: "child2_grandchild1", paths: mkPp(id.MustNumID(3))},
|
||||
&groupNode{id: id.MustNumID(7), handle: "child1_grandchild2_ggrandchild1", paths: mkPp(id.MustNumID(5))},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
nn := out.inline()
|
||||
require.Len(t, nn, 7)
|
||||
require.Equal(t, "root", nn[0].handle)
|
||||
require.Equal(t, "child1", nn[1].handle)
|
||||
require.Equal(t, "child2", nn[2].handle)
|
||||
require.Equal(t, "child1_grandchild1", nn[3].handle)
|
||||
require.Equal(t, "child1_grandchild2", nn[4].handle)
|
||||
require.Equal(t, "child2_grandchild1", nn[5].handle)
|
||||
require.Equal(t, "child1_grandchild2_ggrandchild1", nn[6].handle)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFindNode(t *testing.T) {
|
||||
svc, err := testPrepState(t)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("first", func(t *testing.T) {
|
||||
i, n := svc.findNode(id.MustNumID(1))
|
||||
require.Equal(t, 0, i)
|
||||
require.NotNil(t, n)
|
||||
})
|
||||
|
||||
t.Run("last", func(t *testing.T) {
|
||||
i, n := svc.findNode(id.MustNumID(4))
|
||||
require.Equal(t, 3, i)
|
||||
require.NotNil(t, n)
|
||||
})
|
||||
|
||||
t.Run("middle", func(t *testing.T) {
|
||||
i, n := svc.findNode(id.MustNumID(3))
|
||||
require.Equal(t, 2, i)
|
||||
require.NotNil(t, n)
|
||||
})
|
||||
|
||||
t.Run("not existing", func(t *testing.T) {
|
||||
i, n := svc.findNode(id.MustNumID(999))
|
||||
require.Equal(t, -1, i)
|
||||
require.Nil(t, n)
|
||||
})
|
||||
}
|
||||
|
||||
func testPrepState(t *testing.T) (svc *orgTree, err error) {
|
||||
return mkOrgTree(GroupMembers{
|
||||
group: &groupNode{
|
||||
id: id.MustNumID(1),
|
||||
handle: "root",
|
||||
},
|
||||
members: []id.ID{id.MustNumID(101), id.MustNumID(102)},
|
||||
}, GroupMembers{
|
||||
group: &groupNode{
|
||||
id: id.MustNumID(2),
|
||||
handle: "subgroup1",
|
||||
paths: mkPp(id.MustNumID(1)),
|
||||
},
|
||||
members: []id.ID{id.MustNumID(121), id.MustNumID(122), id.MustNumID(123)},
|
||||
}, GroupMembers{
|
||||
group: &groupNode{
|
||||
id: id.MustNumID(3),
|
||||
handle: "subgroup2",
|
||||
paths: mkPp(id.MustNumID(1)),
|
||||
},
|
||||
members: []id.ID{id.MustNumID(131)},
|
||||
}, GroupMembers{
|
||||
group: &groupNode{
|
||||
id: id.MustNumID(4),
|
||||
handle: "subgroup1_subgroup1",
|
||||
paths: mkPp(id.MustNumID(2)),
|
||||
},
|
||||
members: []id.ID{id.MustNumID(141), id.MustNumID(142)},
|
||||
})
|
||||
}
|
||||
|
||||
func mkPp(ii ...id.ID) []GroupNodePath {
|
||||
out := make([]GroupNodePath, len(ii))
|
||||
for i, x := range ii {
|
||||
out[i] = GroupNodePath{
|
||||
SelfID: x,
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func mkPpn(ii ...any) []GroupNodePath {
|
||||
if len(ii)%2 != 0 {
|
||||
panic("number of things not even")
|
||||
}
|
||||
|
||||
out := make([]GroupNodePath, 0, len(ii))
|
||||
for i := 0; i < len(ii); i += 2 {
|
||||
id := ii[i].(id.ID)
|
||||
label := ii[i+1].(string)
|
||||
|
||||
out = append(out, GroupNodePath{
|
||||
SelfID: id,
|
||||
Name: label,
|
||||
})
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func checkInline(t *testing.T, node *groupNode, ii ...id.ID) {
|
||||
nn := node.inline()
|
||||
require.Len(t, nn, len(ii))
|
||||
|
||||
for i, n := range nn {
|
||||
require.Equal(t, ii[i], n.id)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user