533db535f1
build / build (push) Successful in 1m12s
按已确认需求提供独立安全模型配置、真实探测、正式字典字段评估与原问题译中,持久批次支持只补空白、暂停恢复、有限重试、幂等和逐字段依据。覆盖固定规则、本地语言、组织关联与主表有效看板共用治理侧读模型,保留源生产和冻结历史。 验证:完整 make verify 退出0,702项Go与329项前端通过;默认118项外部/隔离集成明确跳过,另跑完整镜像及组织隔离PG竞态。12并发、输入漂移、过期租约、暂停/恢复及有限重试通过。用户授权的百炼 deepseek-v4.1-flash 完成真实后台与浏览器评估/翻译;552行、16列、11块看板及完整PNG、独立配置页测试/保存、重开恢复和零JS异常通过。仅非业务样本外发,自动处理关闭,原payload不变。 上线前治理库已做导出快照原生备份并真实恢复,60表行数与17个QA表内容哈希一致;不修改DobotAI生产或隧道。本提交时尚未部署,线上验收须独立完成。
68 lines
3.4 KiB
Go
68 lines
3.4 KiB
Go
package qaopsorg
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
func TestAttributionUsesStableIdentityAndKeepsAmbiguitiesExplicit(t *testing.T) {
|
|
d := Directory{Departments: []Department{{ID: "root", Name: "fixture"}, {ID: "a", ParentID: "root", Name: "one"}, {ID: "b", ParentID: "root", Name: "two"}}, People: []Person{{ID: "staff-a", UnionID: "union-a", DepartmentIDs: []string{"a", "a"}}, {ID: "staff-cross", UnionID: "union-cross", DepartmentIDs: []string{"a", "b"}}, {ID: "duplicate-one", UnionID: "duplicate", DepartmentIDs: []string{"a"}}, {ID: "duplicate-two", UnionID: "duplicate", DepartmentIDs: []string{"b"}}}}
|
|
p, err := BuildAttribution(State{State: "ready", DirectoryID: "d", RevisionID: "r", Rules: []Rule{{DepartmentID: "root", Region: "国内工业"}, {DepartmentID: "b", Region: "APAC"}}}, d)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, key := range [][2]string{{"staff-a", ""}, {"", "union-a"}} {
|
|
got := p.Resolve(key[0], key[1])
|
|
if got.State != "matched" || got.Region != "国内工业" || len(got.Departments) != 1 || got.PersonID != "staff-a" {
|
|
t.Fatalf("stable identity not resolved/deduplicated: %+v", got)
|
|
}
|
|
}
|
|
if got := p.Resolve("staff-cross", ""); got.State != "cross_region" || got.Region != "" || len(got.Departments) != 2 {
|
|
t.Fatalf("invented primary region: %+v", got)
|
|
}
|
|
if got := p.Resolve("", "duplicate"); got.State != "identity_conflict" {
|
|
t.Fatalf("duplicate union selected first person: %+v", got)
|
|
}
|
|
if got := p.Resolve("staff-a", "union-cross"); got.State != "identity_conflict" {
|
|
t.Fatalf("contradictory identifiers silently preferred: %+v", got)
|
|
}
|
|
if got := p.Resolve("absent", ""); got.State != "unmatched" {
|
|
t.Fatalf("unknown identity inferred: %+v", got)
|
|
}
|
|
if got := p.Resolve("", ""); got.State != "no_identity" {
|
|
t.Fatalf("anonymous identity inferred: %+v", got)
|
|
}
|
|
}
|
|
func TestLegacyUnionAndUniqueAskerNameResolveWithoutInventingPeople(t *testing.T) {
|
|
d := Directory{Departments: []Department{{ID: "r", Name: "示例部门"}}, People: []Person{{ID: "a", UnionID: "ua", Name: "唯一姓名", DepartmentIDs: []string{"r"}}, {ID: "b", UnionID: "ub", Name: "重复姓名", DepartmentIDs: []string{"r"}}, {ID: "c", Name: "重复姓名", DepartmentIDs: []string{"r"}}}}
|
|
p, err := BuildAttribution(State{State: "ready", DirectoryID: "d", RevisionID: "v", Rules: []Rule{{DepartmentID: "r", Region: "APAC"}}}, d)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, c := range []struct{ staff, union, asker, raw, want, state string }{
|
|
{"", "", "", "{\"name\":\"旧显示姓名\",\"unionId\":\"ua\"}", "a", "matched"},
|
|
{"", "", "唯一姓名", "", "a", "matched"},
|
|
{"", "", "重复姓名", "", "", "identity_conflict"},
|
|
{"", "", "唯一姓名", "{\"unionId\":\"absent\"}", "", "unmatched"},
|
|
{"a", "", "", "{\"unionId\":\"ub\"}", "", "identity_conflict"},
|
|
{"", "", "唯一姓名", "{bad", "", "identity_conflict"},
|
|
} {
|
|
got := p.Resolve(c.staff, c.union, c.asker, c.raw)
|
|
if got.PersonID != c.want || got.State != c.state {
|
|
t.Errorf("got=%+v want person=%q state=%q", got, c.want, c.state)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAttributionDoesNotTreatMissingDirectoryAsPermissionSuccess(t *testing.T) {
|
|
p, err := BuildAttribution(State{State: "empty"}, Directory{})
|
|
if err != nil || p.Resolve("staff", "").State != "directory_missing" {
|
|
t.Fatal("missing directory not explicit")
|
|
}
|
|
var store *Store
|
|
if _, err = store.GetAttribution(context.Background()); !errors.Is(err, ErrUnavailable) {
|
|
t.Fatal("unavailable store returned an empty directory")
|
|
}
|
|
}
|