package config import ( "os" "path/filepath" "strings" "testing" ) // writeConfig 写一份最小可用配置并加载它。 func writeConfig(t *testing.T, extra string) *Config { t.Helper() body := ` system: data-dir: /tmp/idsync-test server: admin-user: admin admin-password: pw feishu: app-id: a app-secret: b ldap: url: ldap://localhost:3890 base-dn: "dc=example,dc=org" admin-dn: "uid=admin,ou=people,dc=example,dc=org" admin-pass: pw lldap: base-url: http://localhost:17170 admin-user: admin admin-pass: pw ` + extra dir := t.TempDir() path := filepath.Join(dir, "config.yml") if err := os.WriteFile(path, []byte(body), 0o600); err != nil { t.Fatalf("写配置失败: %v", err) } cfg, err := Load(path) if err != nil { t.Fatalf("加载配置失败: %v", err) } return cfg } // TestDefaultsForLLDAP 验证 OUDN 固定为 LLDAP 形态:用户在 ou=people、组在 ou=groups。 func TestDefaultsForLLDAP(t *testing.T) { cfg := writeConfig(t, "") if got := cfg.UserOUDN(); got != "ou=people,dc=example,dc=org" { t.Errorf("UserOUDN = %q, 期望 ou=people(LLDAP 固定 OU)", got) } if got := cfg.GroupRootDN(); got != "ou=groups,dc=example,dc=org" { t.Errorf("GroupRootDN = %q, 期望 ou=groups", got) } } // TestAdminDNDerived 验证未显式配 admin-dn 时按 LLDAP 管理员用户补全。 func TestAdminDNDerived(t *testing.T) { cfg := writeConfig(t, " admin-dn: \"\"\n") want := "uid=admin,ou=people,dc=example,dc=org" if cfg.Ldap.AdminDN != want { t.Errorf("AdminDN = %q, 期望自动补全为 %q", cfg.Ldap.AdminDN, want) } } // TestNormalizeRejectsMissingCredentials 验证关键字段缺失时启动即失败。 func TestNormalizeRejectsMissingCredentials(t *testing.T) { cases := []struct { name string // override 以 YAML 片段替换掉基础配置里对应的一行,避免重复键。 override string mark string }{ {"缺少 app-id", "feishu:\n app-id: \"\"\n", "app-id"}, {"缺少 base-dn", "ldap:\n base-dn: \"\"\n", "base-dn"}, {"缺少 lldap base-url", "lldap:\n base-url: \"\"\n", "base-url"}, {"缺少 lldap admin-pass", "lldap:\n admin-pass: \"\"\n", "admin-pass"}, } base := ` system: data-dir: /tmp/idsync-test server: admin-user: admin admin-password: pw ` for _, c := range cases { t.Run(c.name, func(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "config.yml") body := base + c.override + ` ldap: url: ldap://localhost:3890 base-dn: "dc=example,dc=org" admin-dn: "uid=admin,ou=people,dc=example,dc=org" admin-pass: pw lldap: base-url: http://localhost:17170 admin-user: admin admin-pass: pw ` if err := os.WriteFile(path, []byte(body), 0o600); err != nil { t.Fatalf("写配置失败: %v", err) } if _, err := Load(path); err == nil { t.Errorf("缺少必要配置项(%s)时应加载失败", c.mark) } }) } } // TestEdgeRemoved 验证 OpenLDAP 时代的分组/OU/密码配置项已彻底移除, // 不再出现在结构体里(通过在导出字段上做类型断言编译来保证)。 func TestEdgeRemoved(t *testing.T) { _ = func(c *Config) { // 编译期确认这些字段已不存在:直接引用会在编译时失败。 _ = strings.TrimSpace(c.Ldap.URL) _ = c.Guard.MaxDeactivatePercent } }