package mapping // BuildFromMirror(镜像 → 期望状态)的单测。 // // 覆盖:用户 DN 固定 ou=people、组名直接复用镜像拍平 DN、成员关系按用户所属部门 // 归集、分组按层级父先于子排序。 import ( "testing" "idsync/internal/store" ) func mirrorUser(uid, email, deptID string) *store.MirrorUser { return &store.MirrorUser{ UID: uid, Email: email, DisplayName: uid, SN: uid, GivenName: uid, DepartmentIDs: []string{deptID}, } } func mirrorDept(id, name, dn string, level int, parent string) *store.MirrorDepartment { return &store.MirrorDepartment{ DeptID: id, Name: name, DN: dn, Level: level, ParentID: parent, } } // TestBuildFromMirrorUserDN 验证用户 DN 固定挂在 ou=people 下,不再有离职 OU。 func TestBuildFromMirrorUserDN(t *testing.T) { depts := []*store.MirrorDepartment{ mirrorDept("od-root", "Acme", "cn=od-root,ou=groups,dc=example,dc=com", 0, ""), } users := []*store.MirrorUser{mirrorUser("alice", "alice@example.com", "od-root")} st := BuildFromMirror(users, depts, "dc=example,dc=com") if len(st.Users) != 1 { t.Fatalf("期望 1 个用户,实际 %d", len(st.Users)) } u := st.Users[0] if u.DN != "uid=alice,ou=people,dc=example,dc=com" { t.Errorf("用户 DN = %q, 期望固定 ou=people", u.DN) } if u.Mail != "alice@example.com" { t.Errorf("mail = %q", u.Mail) } } // TestBuildFromMirrorGroupMembers 验证成员关系按用户所属部门归集到对应的组。 func TestBuildFromMirrorGroupMembers(t *testing.T) { depts := []*store.MirrorDepartment{ mirrorDept("od-root", "Acme", "cn=od-root,ou=groups,dc=example,dc=com", 0, ""), mirrorDept("od-rd", "研发部", "cn=od-rd,ou=groups,dc=example,dc=com", 1, "od-root"), } users := []*store.MirrorUser{ mirrorUser("alice", "alice@example.com", "od-rd"), // lisi 属多部门 {UID: "lisi", Email: "lisi@example.com", DisplayName: "lisi", SN: "lisi", GivenName: "lisi", DepartmentIDs: []string{"od-root", "od-rd"}}, } st := BuildFromMirror(users, depts, "dc=example,dc=com") rd := st.GroupByDeptID["od-rd"] if _, ok := rd.Members["uid=alice,ou=people,dc=example,dc=com"]; !ok { t.Errorf("alice 未加入 %s", rd.DN) } if _, ok := rd.Members["uid=lisi,ou=people,dc=example,dc=com"]; !ok { t.Errorf("lisi 未加入 %s", rd.DN) } root := st.GroupByDeptID["od-root"] if _, ok := root.Members["uid=alice,ou=people,dc=example,dc=com"]; ok { t.Errorf("alice 只属研发部,不应出现在根部门") } if _, ok := root.Members["uid=lisi,ou=people,dc=example,dc=com"]; !ok { t.Errorf("lisi 属根部门,应出现") } } // TestBuildFromMirrorGroupOrderIsParentFirst 验证分组输出按层级父先于子排序。 func TestBuildFromMirrorGroupOrderIsParentFirst(t *testing.T) { depts := []*store.MirrorDepartment{ // 刻意让子部门先给出,验证 BuildFromMirror 内部仍按 Level 排回父先于子。 mirrorDept("od-rd", "研发部", "cn=od-rd,ou=groups,dc=example,dc=com", 1, "od-root"), mirrorDept("od-root", "Acme", "cn=od-root,ou=groups,dc=example,dc=com", 0, ""), } st := BuildFromMirror(nil, depts, "dc=example,dc=com") seen := map[string]int{} for i, g := range st.Groups { seen[g.DeptID] = i } if seen["od-root"] > seen["od-rd"] { t.Errorf("父部门应排在子部门之前:%v", seen) } }