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

This commit is contained in:
upstream-mirror
2026-09-18 01:22:23 +05:00
commit 7e385fc126
8391 changed files with 1766236 additions and 0 deletions

View 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)
}
}