217 lines
5.1 KiB
Go
217 lines
5.1 KiB
Go
|
package jwtx
|
|||
|
|
|||
|
import (
|
|||
|
"fmt"
|
|||
|
"testing"
|
|||
|
)
|
|||
|
|
|||
|
func TestGenerateJwtToken(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
name string
|
|||
|
userId int64
|
|||
|
secret string
|
|||
|
expireTime int64
|
|||
|
wantErr bool
|
|||
|
}{
|
|||
|
{
|
|||
|
name: "正常情况 - 生成有效token",
|
|||
|
userId: 144,
|
|||
|
secret: "Mf5Xph3PoyKzVpRw0Zy1+X4uR/tM7JvGMEV/5p2M/tU=",
|
|||
|
expireTime: 3600, // 1小时
|
|||
|
wantErr: false,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "用户ID为0",
|
|||
|
userId: 0,
|
|||
|
secret: "test-secret-key",
|
|||
|
expireTime: 3600,
|
|||
|
wantErr: false,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "用户ID为负数",
|
|||
|
userId: -1,
|
|||
|
secret: "test-secret-key",
|
|||
|
expireTime: 3600,
|
|||
|
wantErr: false,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "过期时间为0",
|
|||
|
userId: 12345,
|
|||
|
secret: "test-secret-key",
|
|||
|
expireTime: 0,
|
|||
|
wantErr: false,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "过期时间为负数",
|
|||
|
userId: 12345,
|
|||
|
secret: "test-secret-key",
|
|||
|
expireTime: -3600,
|
|||
|
wantErr: false,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "空密钥",
|
|||
|
userId: 12345,
|
|||
|
secret: "",
|
|||
|
expireTime: 3600,
|
|||
|
wantErr: false,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "长密钥",
|
|||
|
userId: 12345,
|
|||
|
secret: "very-long-secret-key-that-is-more-than-32-characters-long",
|
|||
|
expireTime: 3600,
|
|||
|
wantErr: false,
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
for _, tt := range tests {
|
|||
|
t.Run(tt.name, func(t *testing.T) {
|
|||
|
token, err := GenerateJwtToken(tt.userId, tt.secret, tt.expireTime)
|
|||
|
fmt.Printf("tt.userId: %d, token: %s\n", tt.userId, token)
|
|||
|
if (err != nil) != tt.wantErr {
|
|||
|
t.Errorf("GenerateJwtToken() error = %v, wantErr %v", err, tt.wantErr)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if !tt.wantErr {
|
|||
|
// 验证token不为空
|
|||
|
if token == "" {
|
|||
|
t.Error("GenerateJwtToken() returned empty token")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 验证token长度合理
|
|||
|
if len(token) < 10 {
|
|||
|
t.Errorf("GenerateJwtToken() returned token too short: %s", token)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 验证可以解析token(对于过期时间为0或负数的情况,token会立即过期)
|
|||
|
if tt.expireTime <= 0 {
|
|||
|
// 对于立即过期的token,我们只验证生成成功,不验证解析
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
parsedUserId, parseErr := ParseJwtToken(token, tt.secret)
|
|||
|
if parseErr != nil {
|
|||
|
t.Errorf("Failed to parse generated token: %v", parseErr)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if parsedUserId != tt.userId {
|
|||
|
t.Errorf("Parsed userId = %v, want %v", parsedUserId, tt.userId)
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestGenerateJwtToken_ExpirationTime(t *testing.T) {
|
|||
|
userId := int64(12345)
|
|||
|
secret := "test-secret-key"
|
|||
|
expireTime := int64(3600) // 1小时
|
|||
|
|
|||
|
token, err := GenerateJwtToken(userId, secret, expireTime)
|
|||
|
if err != nil {
|
|||
|
t.Fatalf("GenerateJwtToken() failed: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
// 验证token可以立即解析
|
|||
|
parsedUserId, err := ParseJwtToken(token, secret)
|
|||
|
if err != nil {
|
|||
|
t.Fatalf("Failed to parse token immediately: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
if parsedUserId != userId {
|
|||
|
t.Errorf("Parsed userId = %v, want %v", parsedUserId, userId)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestGenerateJwtToken_Consistency(t *testing.T) {
|
|||
|
userId := int64(12345)
|
|||
|
secret := "test-secret-key"
|
|||
|
expireTime := int64(3600)
|
|||
|
|
|||
|
// 生成多个token,验证相同参数生成的token是一致的
|
|||
|
var firstToken string
|
|||
|
|
|||
|
for i := 0; i < 5; i++ {
|
|||
|
token, err := GenerateJwtToken(userId, secret, expireTime)
|
|||
|
if err != nil {
|
|||
|
t.Fatalf("GenerateJwtToken() failed on iteration %d: %v", i, err)
|
|||
|
}
|
|||
|
|
|||
|
if i == 0 {
|
|||
|
firstToken = token
|
|||
|
} else {
|
|||
|
// 由于JWT基于相同claims生成,相同参数应该产生相同的token
|
|||
|
// 但由于时间戳可能略有差异,我们验证token长度和格式一致
|
|||
|
if len(token) != len(firstToken) {
|
|||
|
t.Errorf("Token length inconsistent: got %d, want %d", len(token), len(firstToken))
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestGenerateJwtToken_LargeUserId(t *testing.T) {
|
|||
|
// 测试大数值的userId
|
|||
|
largeUserId := int64(999999999999999) // 使用一个大的但合理的值
|
|||
|
secret := "test-secret-key"
|
|||
|
expireTime := int64(3600)
|
|||
|
|
|||
|
token, err := GenerateJwtToken(largeUserId, secret, expireTime)
|
|||
|
if err != nil {
|
|||
|
t.Fatalf("GenerateJwtToken() failed with large userId: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
parsedUserId, err := ParseJwtToken(token, secret)
|
|||
|
if err != nil {
|
|||
|
t.Fatalf("Failed to parse token with large userId: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
if parsedUserId != largeUserId {
|
|||
|
t.Errorf("Parsed userId = %v, want %v", parsedUserId, largeUserId)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestGenerateJwtToken_Concurrent(t *testing.T) {
|
|||
|
userId := int64(12345)
|
|||
|
secret := "test-secret-key"
|
|||
|
expireTime := int64(3600)
|
|||
|
|
|||
|
// 并发测试
|
|||
|
done := make(chan bool, 10)
|
|||
|
|
|||
|
for i := 0; i < 10; i++ {
|
|||
|
go func() {
|
|||
|
token, err := GenerateJwtToken(userId, secret, expireTime)
|
|||
|
if err != nil {
|
|||
|
t.Errorf("GenerateJwtToken() failed in goroutine: %v", err)
|
|||
|
done <- false
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
parsedUserId, err := ParseJwtToken(token, secret)
|
|||
|
if err != nil {
|
|||
|
t.Errorf("Failed to parse token in goroutine: %v", err)
|
|||
|
done <- false
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if parsedUserId != userId {
|
|||
|
t.Errorf("Parsed userId = %v, want %v in goroutine", parsedUserId, userId)
|
|||
|
done <- false
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
done <- true
|
|||
|
}()
|
|||
|
}
|
|||
|
|
|||
|
// 等待所有goroutine完成
|
|||
|
for i := 0; i < 10; i++ {
|
|||
|
if !<-done {
|
|||
|
t.Fail()
|
|||
|
}
|
|||
|
}
|
|||
|
}
|