You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

78 lines
2.5 KiB

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)
}
}
}