190 lines
4.1 KiB
Go
190 lines
4.1 KiB
Go
package jwtx
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/golang-jwt/jwt/v4"
|
|
)
|
|
|
|
func TestGenerateJwtToken(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
userId int64
|
|
secret string
|
|
expireTime int64
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "正常生成token",
|
|
userId: 7816,
|
|
secret: "WUvoIwL-FK0qnlxhvxR9tV6SjfOpeJMpKmY2QvT99lA",
|
|
expireTime: 2592000,
|
|
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,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
token, err := GenerateJwtToken(tt.userId, tt.secret, tt.expireTime)
|
|
fmt.Printf("name: %s, token: %s\n", tt.name, token)
|
|
if tt.wantErr {
|
|
if err == nil {
|
|
t.Errorf("GenerateJwtToken() 期望错误,但没有返回错误")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("GenerateJwtToken() 错误 = %v, 期望无错误", err)
|
|
return
|
|
}
|
|
|
|
if token == "" {
|
|
t.Errorf("GenerateJwtToken() 返回空token")
|
|
return
|
|
}
|
|
|
|
// 验证生成的token是否可以正确解析
|
|
parsedUserId, err := ParseJwtToken(token, tt.secret)
|
|
if err != nil {
|
|
t.Errorf("ParseJwtToken() 解析生成的token失败: %v", err)
|
|
return
|
|
}
|
|
|
|
if parsedUserId != tt.userId {
|
|
t.Errorf("ParseJwtToken() 解析出的userId = %v, 期望 %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() 错误 = %v", err)
|
|
}
|
|
|
|
// 解析token并验证过期时间
|
|
parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
|
|
return []byte(secret), nil
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("jwt.Parse() 错误 = %v", err)
|
|
}
|
|
|
|
claims, ok := parsedToken.Claims.(jwt.MapClaims)
|
|
if !ok {
|
|
t.Fatal("无法获取JWT claims")
|
|
}
|
|
|
|
// 验证签发时间
|
|
iat, ok := claims["iat"].(float64)
|
|
if !ok {
|
|
t.Fatal("无法获取签发时间")
|
|
}
|
|
|
|
// 验证过期时间
|
|
exp, ok := claims["exp"].(float64)
|
|
if !ok {
|
|
t.Fatal("无法获取过期时间")
|
|
}
|
|
|
|
// 验证过期时间是否正确设置
|
|
expectedExp := float64(time.Now().Unix()) + float64(expireTime)
|
|
if exp < expectedExp-5 || exp > expectedExp+5 { // 允许5秒的误差
|
|
t.Errorf("过期时间不正确: 期望接近 %v, 实际 %v", expectedExp, exp)
|
|
}
|
|
|
|
// 验证签发时间
|
|
expectedIat := float64(time.Now().Unix())
|
|
if iat < expectedIat-5 || iat > expectedIat+5 { // 允许5秒的误差
|
|
t.Errorf("签发时间不正确: 期望接近 %v, 实际 %v", expectedIat, iat)
|
|
}
|
|
}
|
|
|
|
func TestGenerateJwtToken_Concurrent(t *testing.T) {
|
|
userId := int64(12345)
|
|
secret := "test-secret-key"
|
|
expireTime := int64(3600)
|
|
|
|
// 并发测试
|
|
ch := make(chan string, 10)
|
|
errCh := make(chan error, 10)
|
|
|
|
for i := 0; i < 10; i++ {
|
|
go func() {
|
|
token, err := GenerateJwtToken(userId, secret, expireTime)
|
|
if err != nil {
|
|
errCh <- err
|
|
return
|
|
}
|
|
ch <- token
|
|
}()
|
|
}
|
|
|
|
// 收集结果
|
|
tokens := make([]string, 0, 10)
|
|
for i := 0; i < 10; i++ {
|
|
select {
|
|
case token := <-ch:
|
|
tokens = append(tokens, token)
|
|
case err := <-errCh:
|
|
t.Errorf("并发生成token时发生错误: %v", err)
|
|
}
|
|
}
|
|
|
|
// 验证所有token都是有效的
|
|
for i, token := range tokens {
|
|
parsedUserId, err := ParseJwtToken(token, secret)
|
|
if err != nil {
|
|
t.Errorf("token[%d] 解析失败: %v", i, err)
|
|
continue
|
|
}
|
|
|
|
if parsedUserId != userId {
|
|
t.Errorf("token[%d] 解析出的userId = %v, 期望 %v", i, parsedUserId, userId)
|
|
}
|
|
}
|
|
}
|