package user import ( "testing" "yunyan/pb" ) // 设备身份的判定口径:**设备就是 MAC**。 // // 这两个函数决定了「同一台设备」在绑定/接管/解绑三条路径上是否被认出来, // 认错的后果是静默的:去重失效会让 userdevice 表里堆重复行,接管失效会让 // 原用户的设备列表里一直留着一台已经不属于它的耳机。所以用例守在这里。 func TestAlreadyBound_经典蓝牙耳机_code传空也能去重(t *testing.T) { // 客户端对经典蓝牙耳机 code 传空;服务端存进 license 的是 model.Code(=MAC)。 // 旧实现比 `v.License == req.Code` 恒为 false,于是每次重绑都插一条新行。 existing := &pb.DBUserDivice{ Devicename: "Echo-one", Devicemac: "11:11:22:33:33:A4", License: "11:11:22:33:33:A4", } req := &pb.UserBindDeviceReq{ Devicename: "Echo-one", Devicemac: "11:11:22:33:33:A4", Code: "", } if !alreadyBound(existing, req) { t.Fatal("同一台耳机重新绑定应判定为已绑定,否则会插入重复行") } } func TestAlreadyBound_设备名变了仍是同一台(t *testing.T) { // Android 的 getBondedDevices 给的是系统缓存的配对名;固件也改过名 // (DEEPVOICE → Echo-one)。名字参与身份判断会让同一台设备换名就多一行。 existing := &pb.DBUserDivice{ Devicename: "DEEPVOICE", Devicemac: "11:11:22:33:33:A4", } req := &pb.UserBindDeviceReq{ Devicename: "Echo-one", Devicemac: "11:11:22:33:33:A4", } if !alreadyBound(existing, req) { t.Fatal("MAC 相同即同一台,设备名不参与身份判断") } } func TestAlreadyBound_MAC大小写不敏感(t *testing.T) { existing := &pb.DBUserDivice{Devicemac: "11:11:22:33:33:a4"} req := &pb.UserBindDeviceReq{Devicemac: "11:11:22:33:33:A4"} if !alreadyBound(existing, req) { t.Fatal("MAC 写法的大小写取决于当初是谁写的,比较必须大小写不敏感") } } func TestAlreadyBound_不同MAC不是同一台(t *testing.T) { existing := &pb.DBUserDivice{Devicename: "Echo-one", Devicemac: "11:11:22:33:33:A4"} req := &pb.UserBindDeviceReq{Devicename: "Echo-one", Devicemac: "AA:BB:CC:DD:EE:FF"} if alreadyBound(existing, req) { t.Fatal("换了一台耳机必须判为不同设备,否则新设备绑不上") } } func TestAlreadyBound_无MAC的设备回退比设备码(t *testing.T) { // 早年按设备码导入、未登记 MAC 的设备走这条 existing := &pb.DBUserDivice{License: "ABC123"} req := &pb.UserBindDeviceReq{Code: "ABC123"} if !alreadyBound(existing, req) { t.Fatal("没有 MAC 时应回退按设备码认") } req2 := &pb.UserBindDeviceReq{Code: "XYZ789"} if alreadyBound(existing, req2) { t.Fatal("设备码不同即不同设备") } } func TestAlreadyBound_空设备码不匹配空License(t *testing.T) { // 两边都空不能算「同一台」,否则用户名下第一条无 MAC 记录会吞掉所有新绑定 existing := &pb.DBUserDivice{License: ""} req := &pb.UserBindDeviceReq{Code: ""} if alreadyBound(existing, req) { t.Fatal("既无 MAC 又无设备码时不能判为同一台") } } func TestSameUserDevice_MAC对得上就是同一台(t *testing.T) { // license 与 MAC 不一致(后台重导入过 license)时,旧实现只比 license // 会判成「不是同一台」,接管时清不掉原用户那条绑定。 v := &pb.DBUserDivice{Devicemac: "11:11:22:33:33:A4", License: "旧的授权码"} code := &pb.DBAuthCode{Devicemac: "11:11:22:33:33:A4", Code: "11:11:22:33:33:A4"} if !sameUserDevice(v, code) { t.Fatal("MAC 相同即同一台,license 写成什么都不影响") } } func TestSameUserDevice_无MAC时回退比授权码(t *testing.T) { v := &pb.DBUserDivice{License: "ABC123"} code := &pb.DBAuthCode{Code: "ABC123"} if !sameUserDevice(v, code) { t.Fatal("没有 MAC 时应回退按授权码认") } } func TestSameUserDevice_MAC不同且授权码不同则不是同一台(t *testing.T) { v := &pb.DBUserDivice{Devicemac: "11:11:22:33:33:A4", License: "ABC123"} code := &pb.DBAuthCode{Devicemac: "AA:BB:CC:DD:EE:FF", Code: "XYZ789"} if sameUserDevice(v, code) { t.Fatal("两个维度都对不上必须判为不同设备") } } func TestSameUserDevice_空值不panic(t *testing.T) { if sameUserDevice(nil, nil) || sameUserDevice(&pb.DBUserDivice{}, nil) || sameUserDevice(nil, &pb.DBAuthCode{}) { t.Fatal("空值应判为不同设备") } if alreadyBound(nil, nil) || alreadyBound(&pb.DBUserDivice{}, nil) || alreadyBound(nil, &pb.UserBindDeviceReq{}) { t.Fatal("空值应判为不同设备") } }