682 lines
13 KiB
Go
682 lines
13 KiB
Go
package entities
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestSMSCode_Validate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
smsCode *SMSCode
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "有效验证码",
|
|
smsCode: &SMSCode{
|
|
Phone: "13800138000",
|
|
Code: "123456",
|
|
Scene: SMSSceneRegister,
|
|
ExpiresAt: time.Now().Add(time.Hour),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "手机号为空",
|
|
smsCode: &SMSCode{
|
|
Phone: "",
|
|
Code: "123456",
|
|
Scene: SMSSceneRegister,
|
|
ExpiresAt: time.Now().Add(time.Hour),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "验证码为空",
|
|
smsCode: &SMSCode{
|
|
Phone: "13800138000",
|
|
Code: "",
|
|
Scene: SMSSceneRegister,
|
|
ExpiresAt: time.Now().Add(time.Hour),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "场景为空",
|
|
smsCode: &SMSCode{
|
|
Phone: "13800138000",
|
|
Code: "123456",
|
|
Scene: "",
|
|
ExpiresAt: time.Now().Add(time.Hour),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "过期时间为零",
|
|
smsCode: &SMSCode{
|
|
Phone: "13800138000",
|
|
Code: "123456",
|
|
Scene: SMSSceneRegister,
|
|
ExpiresAt: time.Time{},
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "手机号格式无效",
|
|
smsCode: &SMSCode{
|
|
Phone: "123",
|
|
Code: "123456",
|
|
Scene: SMSSceneRegister,
|
|
ExpiresAt: time.Now().Add(time.Hour),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "验证码格式无效-包含字母",
|
|
smsCode: &SMSCode{
|
|
Phone: "13800138000",
|
|
Code: "12345a",
|
|
Scene: SMSSceneRegister,
|
|
ExpiresAt: time.Now().Add(time.Hour),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "验证码长度过短",
|
|
smsCode: &SMSCode{
|
|
Phone: "13800138000",
|
|
Code: "123",
|
|
Scene: SMSSceneRegister,
|
|
ExpiresAt: time.Now().Add(time.Hour),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := tt.smsCode.Validate()
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_VerifyCode(t *testing.T) {
|
|
now := time.Now()
|
|
expiresAt := now.Add(time.Hour)
|
|
|
|
tests := []struct {
|
|
name string
|
|
smsCode *SMSCode
|
|
inputCode string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "验证码正确",
|
|
smsCode: &SMSCode{
|
|
Code: "123456",
|
|
Used: false,
|
|
ExpiresAt: expiresAt,
|
|
},
|
|
inputCode: "123456",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "验证码错误",
|
|
smsCode: &SMSCode{
|
|
Code: "123456",
|
|
Used: false,
|
|
ExpiresAt: expiresAt,
|
|
},
|
|
inputCode: "654321",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "验证码已使用",
|
|
smsCode: &SMSCode{
|
|
Code: "123456",
|
|
Used: true,
|
|
ExpiresAt: expiresAt,
|
|
},
|
|
inputCode: "123456",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "验证码已过期",
|
|
smsCode: &SMSCode{
|
|
Code: "123456",
|
|
Used: false,
|
|
ExpiresAt: now.Add(-time.Hour),
|
|
},
|
|
inputCode: "123456",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := tt.smsCode.VerifyCode(tt.inputCode)
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
// 验证码正确时应该被标记为已使用
|
|
assert.True(t, tt.smsCode.Used)
|
|
assert.NotNil(t, tt.smsCode.UsedAt)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_IsExpired(t *testing.T) {
|
|
now := time.Now()
|
|
|
|
tests := []struct {
|
|
name string
|
|
smsCode *SMSCode
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "未过期",
|
|
smsCode: &SMSCode{
|
|
ExpiresAt: now.Add(time.Hour),
|
|
},
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "已过期",
|
|
smsCode: &SMSCode{
|
|
ExpiresAt: now.Add(-time.Hour),
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "刚好过期",
|
|
smsCode: &SMSCode{
|
|
ExpiresAt: now,
|
|
},
|
|
expected: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := tt.smsCode.IsExpired()
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_IsValid(t *testing.T) {
|
|
now := time.Now()
|
|
|
|
tests := []struct {
|
|
name string
|
|
smsCode *SMSCode
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "有效验证码",
|
|
smsCode: &SMSCode{
|
|
Used: false,
|
|
ExpiresAt: now.Add(time.Hour),
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "已使用",
|
|
smsCode: &SMSCode{
|
|
Used: true,
|
|
ExpiresAt: now.Add(time.Hour),
|
|
},
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "已过期",
|
|
smsCode: &SMSCode{
|
|
Used: false,
|
|
ExpiresAt: now.Add(-time.Hour),
|
|
},
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "已使用且已过期",
|
|
smsCode: &SMSCode{
|
|
Used: true,
|
|
ExpiresAt: now.Add(-time.Hour),
|
|
},
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := tt.smsCode.IsValid()
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_CanResend(t *testing.T) {
|
|
now := time.Now()
|
|
minInterval := 60 * time.Second
|
|
|
|
tests := []struct {
|
|
name string
|
|
smsCode *SMSCode
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "已使用-可以重发",
|
|
smsCode: &SMSCode{
|
|
Used: true,
|
|
CreatedAt: now.Add(-30 * time.Second),
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "已过期-可以重发",
|
|
smsCode: &SMSCode{
|
|
Used: false,
|
|
ExpiresAt: now.Add(-time.Hour),
|
|
CreatedAt: now.Add(-30 * time.Second),
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "未过期且未使用-间隔足够-可以重发",
|
|
smsCode: &SMSCode{
|
|
Used: false,
|
|
ExpiresAt: now.Add(time.Hour),
|
|
CreatedAt: now.Add(-2 * time.Minute),
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "未过期且未使用-间隔不足-不能重发",
|
|
smsCode: &SMSCode{
|
|
Used: false,
|
|
ExpiresAt: now.Add(time.Hour),
|
|
CreatedAt: now.Add(-30 * time.Second),
|
|
},
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := tt.smsCode.CanResend(minInterval)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_GetRemainingTime(t *testing.T) {
|
|
now := time.Now()
|
|
|
|
tests := []struct {
|
|
name string
|
|
smsCode *SMSCode
|
|
expected time.Duration
|
|
}{
|
|
{
|
|
name: "未过期",
|
|
smsCode: &SMSCode{
|
|
ExpiresAt: now.Add(time.Hour),
|
|
},
|
|
expected: time.Hour,
|
|
},
|
|
{
|
|
name: "已过期",
|
|
smsCode: &SMSCode{
|
|
ExpiresAt: now.Add(-time.Hour),
|
|
},
|
|
expected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := tt.smsCode.GetRemainingTime()
|
|
// 由于时间计算可能有微小差异,我们检查是否在合理范围内
|
|
if tt.expected > 0 {
|
|
assert.True(t, result > 0)
|
|
assert.True(t, result <= tt.expected)
|
|
} else {
|
|
assert.Equal(t, tt.expected, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_GetMaskedCode(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
code string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "6位验证码",
|
|
code: "123456",
|
|
expected: "1***6",
|
|
},
|
|
{
|
|
name: "4位验证码",
|
|
code: "1234",
|
|
expected: "1***4",
|
|
},
|
|
{
|
|
name: "短验证码",
|
|
code: "12",
|
|
expected: "***",
|
|
},
|
|
{
|
|
name: "单字符",
|
|
code: "1",
|
|
expected: "***",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
smsCode := &SMSCode{Code: tt.code}
|
|
result := smsCode.GetMaskedCode()
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_GetMaskedPhone(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
phone string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "标准手机号",
|
|
phone: "13800138000",
|
|
expected: "138****8000",
|
|
},
|
|
{
|
|
name: "短手机号",
|
|
phone: "138001",
|
|
expected: "138001",
|
|
},
|
|
{
|
|
name: "空手机号",
|
|
phone: "",
|
|
expected: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
smsCode := &SMSCode{Phone: tt.phone}
|
|
result := smsCode.GetMaskedPhone()
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_IsSceneValid(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
scene SMSScene
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "注册场景",
|
|
scene: SMSSceneRegister,
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "登录场景",
|
|
scene: SMSSceneLogin,
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "无效场景",
|
|
scene: "invalid",
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
smsCode := &SMSCode{Scene: tt.scene}
|
|
result := smsCode.IsSceneValid()
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_GetSceneName(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
scene SMSScene
|
|
expected string
|
|
}{
|
|
{
|
|
name: "注册场景",
|
|
scene: SMSSceneRegister,
|
|
expected: "用户注册",
|
|
},
|
|
{
|
|
name: "登录场景",
|
|
scene: SMSSceneLogin,
|
|
expected: "用户登录",
|
|
},
|
|
{
|
|
name: "无效场景",
|
|
scene: "invalid",
|
|
expected: "invalid",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
smsCode := &SMSCode{Scene: tt.scene}
|
|
result := smsCode.GetSceneName()
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_IsSuspicious(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
smsCode *SMSCode
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "正常记录",
|
|
smsCode: &SMSCode{
|
|
IP: "192.168.1.1",
|
|
UserAgent: "Mozilla/5.0",
|
|
},
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "IP为空-可疑",
|
|
smsCode: &SMSCode{
|
|
IP: "",
|
|
UserAgent: "Mozilla/5.0",
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "UserAgent为空-可疑",
|
|
smsCode: &SMSCode{
|
|
IP: "192.168.1.1",
|
|
UserAgent: "",
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "IP和UserAgent都为空-可疑",
|
|
smsCode: &SMSCode{
|
|
IP: "",
|
|
UserAgent: "",
|
|
},
|
|
expected: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := tt.smsCode.IsSuspicious()
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSMSCode_GetSecurityInfo(t *testing.T) {
|
|
now := time.Now()
|
|
smsCode := &SMSCode{
|
|
IP: "192.168.1.1",
|
|
UserAgent: "Mozilla/5.0",
|
|
Scene: SMSSceneRegister,
|
|
CreatedAt: now,
|
|
}
|
|
|
|
securityInfo := smsCode.GetSecurityInfo()
|
|
|
|
assert.Equal(t, "192.168.1.1", securityInfo["ip"])
|
|
assert.Equal(t, "Mozilla/5.0", securityInfo["user_agent"])
|
|
assert.Equal(t, false, securityInfo["suspicious"])
|
|
assert.Equal(t, "用户注册", securityInfo["scene"])
|
|
assert.Equal(t, now, securityInfo["created_at"])
|
|
}
|
|
|
|
func TestIsValidScene(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
scene SMSScene
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "注册场景",
|
|
scene: SMSSceneRegister,
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "登录场景",
|
|
scene: SMSSceneLogin,
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "无效场景",
|
|
scene: "invalid",
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := IsValidScene(tt.scene)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetSceneName(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
scene SMSScene
|
|
expected string
|
|
}{
|
|
{
|
|
name: "注册场景",
|
|
scene: SMSSceneRegister,
|
|
expected: "用户注册",
|
|
},
|
|
{
|
|
name: "登录场景",
|
|
scene: SMSSceneLogin,
|
|
expected: "用户登录",
|
|
},
|
|
{
|
|
name: "无效场景",
|
|
scene: "invalid",
|
|
expected: "invalid",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := GetSceneName(tt.scene)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewSMSCode(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
phone string
|
|
code string
|
|
scene SMSScene
|
|
expireTime time.Duration
|
|
clientIP string
|
|
userAgent string
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "有效参数",
|
|
phone: "13800138000",
|
|
code: "123456",
|
|
scene: SMSSceneRegister,
|
|
expireTime: time.Hour,
|
|
clientIP: "192.168.1.1",
|
|
userAgent: "Mozilla/5.0",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "无效手机号",
|
|
phone: "123",
|
|
code: "123456",
|
|
scene: SMSSceneRegister,
|
|
expireTime: time.Hour,
|
|
clientIP: "192.168.1.1",
|
|
userAgent: "Mozilla/5.0",
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "无效验证码",
|
|
phone: "13800138000",
|
|
code: "123",
|
|
scene: SMSSceneRegister,
|
|
expireTime: time.Hour,
|
|
clientIP: "192.168.1.1",
|
|
userAgent: "Mozilla/5.0",
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
smsCode, err := NewSMSCode(tt.phone, tt.code, tt.scene, tt.expireTime, tt.clientIP, tt.userAgent)
|
|
if tt.expectError {
|
|
assert.Error(t, err)
|
|
assert.Nil(t, smsCode)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, smsCode)
|
|
assert.Equal(t, tt.phone, smsCode.Phone)
|
|
assert.Equal(t, tt.code, smsCode.Code)
|
|
assert.Equal(t, tt.scene, smsCode.Scene)
|
|
assert.Equal(t, tt.clientIP, smsCode.IP)
|
|
assert.Equal(t, tt.userAgent, smsCode.UserAgent)
|
|
assert.False(t, smsCode.Used)
|
|
assert.True(t, smsCode.ExpiresAt.After(time.Now()))
|
|
}
|
|
})
|
|
}
|
|
}
|