package idverify import "testing" func TestValidIdCard(t *testing.T) { // 校验位由 MOD 11-2 算出,这几个号码的末位都是按算法推出来的合法值。 cases := []struct { no string want bool why string }{ {"11010519491231002X", true, "末位 X 的合法号码"}, {"440301199001011234", true, "普通合法号码(加权和 184,184%%11=8 → 校验码 4)"}, {"440301199001011239", false, "校验位错误"}, {"44030119900101123", false, "17 位,一代证不支持"}, {"4403011990010112349", false, "19 位"}, {"44030119900101123A", false, "末位非数字非 X"}, {"4403011990010A1239", false, "中间含字母"}, {"", false, "空串"}, } for _, c := range cases { if got := ValidIdCard(c.no); got != c.want { t.Errorf("ValidIdCard(%q) = %v, want %v (%s)", c.no, got, c.want, c.why) } } } func TestMaskIdCard(t *testing.T) { if got, want := MaskIdCard("440301199001011234"), "4403**********1234"; got != want { t.Errorf("MaskIdCard = %q, want %q", got, want) } // 非 18 位不能把原文漏出去 if got := MaskIdCard("12345"); got != "*****" { t.Errorf("非法长度应全掩码,得到 %q", got) } } func TestHashIdCard(t *testing.T) { const no, salt = "440301199001011234", "s3cr3t" h1 := HashIdCard(no, salt) if len(h1) != 64 { t.Fatalf("指纹应为 64 位十六进制,得到 %d 位", len(h1)) } // 同号同盐稳定 —— 否则查重功能失效 if h1 != HashIdCard(no, salt) { t.Error("同一号码+盐两次哈希结果不一致") } // 大小写归一(末位 x/X 视为同一个号) if HashIdCard("11010519491231002x", salt) != HashIdCard("11010519491231002X", salt) { t.Error("末位 x/X 应归一为同一指纹") } // 换盐必须变 —— 保证盐真的参与了计算 if h1 == HashIdCard(no, "other") { t.Error("换盐后指纹未变,盐没生效") } // 无盐时必须返回空串,绝不退化成裸哈希(裸哈希对身份证号等同明文) if HashIdCard(no, "") != "" { t.Error("salt 为空时必须返回空串,不得退化为裸哈希") } } func TestGenderFromIdCard(t *testing.T) { cases := []struct { no string want int32 why string }{ {"440301199001011234", 1, "第17位 3 为奇数 → 男"}, {"11010519491231002X", 2, "第17位 2 为偶数 → 女"}, {"12345", 0, "长度不对"}, {"", 0, "空串"}, } for _, c := range cases { if got := GenderFromIdCard(c.no); got != c.want { t.Errorf("GenderFromIdCard(%q) = %d, want %d (%s)", c.no, got, c.want, c.why) } } }