app-cloudep-permission-server/pkg/usecase/permission_tree_test.go

360 lines
8.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package usecase
import (
"sync"
"testing"
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain/permission"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// TestGeneratePermissionTree 測試 GeneratePermissionTree 函數的建立樹功能
func TestGeneratePermissionTree(t *testing.T) {
// 準備測試資料
// p1 為根節點Parent 為空)
p1ID := primitive.NewObjectID()
p1 := entity.Permission{
ID: p1ID,
Parent: "",
Name: "A",
}
// p2 的父節點為 p1
p2ID := primitive.NewObjectID()
p2 := entity.Permission{
ID: p2ID,
Parent: p1ID.Hex(),
Name: "B",
}
// p3 為另一個根節點Parent 為空)
p3ID := primitive.NewObjectID()
p3 := entity.Permission{
ID: p3ID,
Parent: "",
Name: "C",
}
// p4 的 Parent 填寫一個不存在的 id預期會掛在 dummy root 下
p4ID := primitive.NewObjectID()
p4 := entity.Permission{
ID: p4ID,
Parent: "nonexistent",
Name: "D",
}
permissions := []entity.Permission{p1, p2, p3, p4}
// 建立樹
tree := GeneratePermissionTree(permissions)
// 驗證 dummy root 下的子節點
// 預期 p1、p3、p4 均掛在 dummy root 下
if len(tree.root.Children) != 3 {
t.Errorf("expected 3 children under dummy root, got %d", len(tree.root.Children))
}
// 驗證 p1 的節點是否正確
nodeP1, ok := tree.nodes[p1ID.Hex()]
if !ok {
t.Errorf("node for permission A (p1) not found")
} else {
// p1 應該有一個子節點 p2
if len(nodeP1.Children) != 1 {
t.Errorf("expected node A to have 1 child, got %d", len(nodeP1.Children))
} else {
if nodeP1.Children[0].Data.ID != p2ID {
t.Errorf("expected node A child to be permission B (p2), got %v", nodeP1.Children[0].Data.ID.Hex())
}
}
}
// 驗證 tree.names 的對應關係
checkNames := []struct {
name string
expectedID string
}{
{"A", p1ID.Hex()},
{"B", p2ID.Hex()},
{"C", p3ID.Hex()},
{"D", p4ID.Hex()},
}
for _, cn := range checkNames {
ids, ok := tree.names[cn.name]
if !ok {
t.Errorf("name mapping for %s not found", cn.name)
continue
}
if len(ids) != 1 || ids[0] != cn.expectedID {
t.Errorf("expected name mapping for %s to be [%s], got %v", cn.name, cn.expectedID, ids)
}
}
}
func TestGetNode(t *testing.T) {
// 建立一個測試用的 PermissionTree
tree := &PermissionTree{
nodes: make(map[string]*PermissionNode),
names: make(map[string][]string),
}
id := primitive.NewObjectID()
// 建立一個測試節點ID 為 "testID"
perm := entity.Permission{
ID: id,
Name: "Test Permission",
}
node := &PermissionNode{
Data: perm,
}
// 將測試節點插入 tree 的 nodes map
tree.mu.Lock()
tree.nodes["testID"] = node
tree.mu.Unlock()
// 測試 getNode 返回存在的節點
got := tree.getNode("testID")
if got == nil {
t.Error("Expected to find node with id 'testID', but got nil")
} else if got.Data.ID.Hex() != id.Hex() {
t.Errorf("Expected node ID 'testID', got '%s'", got.Data.ID)
}
// 測試對不存在的 id應回傳 nil
gotNil := tree.getNode("nonexistent")
if gotNil != nil {
t.Errorf("Expected nil for non-existent node, got %+v", gotNil)
}
}
func TestPut(t *testing.T) {
// 建立一個 PermissionTree並初始化 dummy root
tree := &PermissionTree{
nodes: make(map[string]*PermissionNode),
names: make(map[string][]string),
}
// 建立 dummy root 節點,其 ID 為一個隨機 ObjectID但不參與 mapping
dummyRootPerm := entity.Permission{
ID: primitive.NewObjectID(),
Parent: "",
Name: "root",
}
tree.root = &PermissionNode{
Data: dummyRootPerm,
Children: make([]*PermissionNode, 0),
}
// 測試 1放入一筆 Parent 為空的節點,預期掛在 dummy root 下
permA := entity.Permission{
ID: primitive.NewObjectID(),
Parent: "", // 無父節點
Name: "A",
}
tree.put(permA)
nodeA := tree.getNode(permA.ID.Hex())
if nodeA == nil {
t.Errorf("Expected to find node A in tree.nodes")
}
if nodeA.Parent != tree.root {
t.Errorf("Expected node A's parent to be dummy root, got %v", nodeA.Parent.Data.Name)
}
if ids, ok := tree.names["A"]; !ok || len(ids) != 1 || ids[0] != permA.ID.Hex() {
t.Errorf("Expected tree.names for 'A' to contain %s, got %v", permA.ID.Hex(), tree.names["A"])
}
// 測試 2放入一筆 Parent 為存在節點的節點
// 先放入父節點 permB
permB := entity.Permission{
ID: primitive.NewObjectID(),
Parent: "", // 掛在 dummy root 下
Name: "B",
}
tree.put(permB)
nodeB := tree.getNode(permB.ID.Hex())
if nodeB == nil {
t.Errorf("Expected to find node B in tree.nodes")
}
// 再放入子節點 permC其 Parent 為 permB.ID.Hex()
permC := entity.Permission{
ID: primitive.NewObjectID(),
Parent: permB.ID.Hex(),
Name: "C",
}
tree.put(permC)
nodeC := tree.getNode(permC.ID.Hex())
if nodeC == nil {
t.Errorf("Expected to find node C in tree.nodes")
}
if nodeC.Parent != nodeB {
t.Errorf("Expected node C's parent to be node B")
}
// 驗證 nodeB 的 Children 是否包含 nodeC
found := false
for _, child := range nodeB.Children {
if child.Data.ID == permC.ID {
found = true
break
}
}
if !found {
t.Errorf("Expected node B's children to contain node C")
}
}
func TestFilterOpenNodes(t *testing.T) {
// 建立一個 PermissionTree初始化 nodes 與 names並建立 dummy root 節點
tree := &PermissionTree{
nodes: make(map[string]*PermissionNode),
names: make(map[string][]string),
mu: sync.RWMutex{},
}
// 建立 dummy root 節點
dummyRootPerm := entity.Permission{
ID: primitive.NewObjectID(),
Parent: "",
Name: "root",
Status: permission.Open, // dummy root 狀態不影響結果
}
tree.root = &PermissionNode{
Data: dummyRootPerm,
Children: make([]*PermissionNode, 0),
}
// 建立測試節點
// Node AOpen, leaf
permA := entity.Permission{
ID: primitive.NewObjectID(),
Parent: "", // 無父節點 → 掛在 dummy root 下
Name: "A",
Status: permission.Open,
}
tree.put(permA)
// Node BOpen, non-leaf
permB := entity.Permission{
ID: primitive.NewObjectID(),
Parent: "", // 掛在 dummy root 下
Name: "B",
Status: permission.Open,
}
tree.put(permB)
// Node B1Open, leaf, Parent = B
permB1 := entity.Permission{
ID: primitive.NewObjectID(),
Parent: permB.ID.Hex(),
Name: "B1",
Status: permission.Open,
}
tree.put(permB1)
// Node B2Closed, leaf, Parent = B
permB2 := entity.Permission{
ID: primitive.NewObjectID(),
Parent: permB.ID.Hex(),
Name: "B2",
Status: permission.Close,
}
tree.put(permB2)
// Node COpen, non-leaf但其子節點皆 Closed → C 不會展開
permC := entity.Permission{
ID: primitive.NewObjectID(),
Parent: "", // 掛在 dummy root 下
Name: "C",
Status: permission.Close,
}
tree.put(permC)
// Node C1Closed, leaf, Parent = C
permC1 := entity.Permission{
ID: primitive.NewObjectID(),
Parent: permC.ID.Hex(),
Name: "C1",
Status: permission.Open,
}
tree.put(permC1)
// Node C2Closed, leaf, Parent = C
permC2 := entity.Permission{
ID: primitive.NewObjectID(),
Parent: permC.ID.Hex(),
Name: "C2",
Status: permission.Open,
}
tree.put(permC2)
// Node DClosed, leaf, 無父節點
permD := entity.Permission{
ID: primitive.NewObjectID(),
Parent: "",
Name: "D",
Status: permission.Close,
}
tree.put(permD)
// Node EClosed, leaf, 無父節點
permE := entity.Permission{
ID: primitive.NewObjectID(),
Parent: "",
Name: "E",
Status: permission.Open,
}
tree.put(permE)
// Node E1Closed, leaf, Parent = E
permE1 := entity.Permission{
ID: primitive.NewObjectID(),
Parent: permE.ID.Hex(),
Name: "E1",
Status: permission.Close,
}
tree.put(permE1)
// Node E2Closed, leaf, Parent = E
permE2 := entity.Permission{
ID: primitive.NewObjectID(),
Parent: permE.ID.Hex(),
Name: "E2",
Status: permission.Close,
}
tree.put(permE2)
// 執行 filterOpenNodes
openNodes, err := tree.filterOpenNodes()
if err != nil {
t.Fatalf("filterOpenNodes returned error: %v", err)
}
// 預期結果:
// - Node A 應該包含open 且為葉節點)
// - Node B 應該包含open 且其子節點 B1 為 open
// - Node B1 應該包含open, leaf
// - Node B2 不包含closed
// - Node C 不包含closed
// - Node C1, C2 不包含C Node Close
// - Node D 不包含closed
// - Node E 包含open
// - Node E1, E2 不包含本身Close
expectedIDs := map[string]bool{
permA.ID.Hex(): true,
permB.ID.Hex(): true,
permB1.ID.Hex(): true,
permE.ID.Hex(): true,
}
// 檢查結果是否只包含預期的節點
for id, perm := range openNodes {
if !expectedIDs[id] {
t.Errorf("Unexpected node in openNodes: id=%s, name=%s", id, perm.Name)
}
delete(expectedIDs, id)
}
if len(expectedIDs) != 0 {
t.Errorf("Expected nodes not found in openNodes: %v", expectedIDs)
}
}