Files
backend/internal/service/signature_service_test.go
lan 4b4980820f
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
Test / test (push) Has been cancelled
Test / lint (push) Has been cancelled
Test / build (push) Has been cancelled
chore: 初始化仓库,排除二进制文件和覆盖率文件
2025-11-28 23:30:49 +08:00

359 lines
8.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"crypto/rand"
"crypto/rsa"
"strings"
"testing"
"time"
"go.uber.org/zap/zaptest"
)
// TestSignatureService_Constants 测试签名服务相关常量
func TestSignatureService_Constants(t *testing.T) {
if RSAKeySize != 4096 {
t.Errorf("RSAKeySize = %d, want 4096", RSAKeySize)
}
if PrivateKeyRedisKey == "" {
t.Error("PrivateKeyRedisKey should not be empty")
}
if PublicKeyRedisKey == "" {
t.Error("PublicKeyRedisKey should not be empty")
}
if KeyExpirationTime != 24*7*time.Hour {
t.Errorf("KeyExpirationTime = %v, want 7 days", KeyExpirationTime)
}
if CertificateRefreshInterval != 24*time.Hour {
t.Errorf("CertificateRefreshInterval = %v, want 24 hours", CertificateRefreshInterval)
}
if CertificateExpirationPeriod != 24*7*time.Hour {
t.Errorf("CertificateExpirationPeriod = %v, want 7 days", CertificateExpirationPeriod)
}
}
// TestSignatureService_DataValidation 测试签名数据验证逻辑
func TestSignatureService_DataValidation(t *testing.T) {
tests := []struct {
name string
data string
wantValid bool
}{
{
name: "非空数据有效",
data: "test data",
wantValid: true,
},
{
name: "空数据无效",
data: "",
wantValid: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
isValid := tt.data != ""
if isValid != tt.wantValid {
t.Errorf("Data validation failed: got %v, want %v", isValid, tt.wantValid)
}
})
}
}
// TestPlayerCertificate_Structure 测试PlayerCertificate结构
func TestPlayerCertificate_Structure(t *testing.T) {
cert := PlayerCertificate{
ExpiresAt: "2025-01-01T00:00:00Z",
RefreshedAfter: "2025-01-01T00:00:00Z",
PublicKeySignature: "signature",
PublicKeySignatureV2: "signaturev2",
}
// 验证结构体字段
if cert.ExpiresAt == "" {
t.Error("ExpiresAt should not be empty")
}
if cert.RefreshedAfter == "" {
t.Error("RefreshedAfter should not be empty")
}
// PublicKeySignature是可选的
if cert.PublicKeySignature == "" {
t.Log("PublicKeySignature is optional")
}
}
// TestWrapString 测试字符串换行函数
func TestWrapString(t *testing.T) {
tests := []struct {
name string
str string
width int
expected string
}{
{
name: "正常换行",
str: "1234567890",
width: 5,
expected: "12345\n67890",
},
{
name: "字符串长度等于width",
str: "12345",
width: 5,
expected: "12345",
},
{
name: "字符串长度小于width",
str: "123",
width: 5,
expected: "123",
},
{
name: "width为0返回原字符串",
str: "1234567890",
width: 0,
expected: "1234567890",
},
{
name: "width为负数返回原字符串",
str: "1234567890",
width: -1,
expected: "1234567890",
},
{
name: "空字符串",
str: "",
width: 5,
expected: "",
},
{
name: "width为1",
str: "12345",
width: 1,
expected: "1\n2\n3\n4\n5",
},
{
name: "长字符串多次换行",
str: "123456789012345",
width: 5,
expected: "12345\n67890\n12345",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := WrapString(tt.str, tt.width)
if result != tt.expected {
t.Errorf("WrapString(%q, %d) = %q, want %q", tt.str, tt.width, result, tt.expected)
}
})
}
}
// TestWrapString_LineCount 测试换行后的行数
func TestWrapString_LineCount(t *testing.T) {
tests := []struct {
name string
str string
width int
wantLines int
}{
{
name: "10个字符width=5应该2行",
str: "1234567890",
width: 5,
wantLines: 2,
},
{
name: "15个字符width=5应该3行",
str: "123456789012345",
width: 5,
wantLines: 3,
},
{
name: "5个字符width=5应该1行",
str: "12345",
width: 5,
wantLines: 1,
},
{
name: "width为0应该1行",
str: "1234567890",
width: 0,
wantLines: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := WrapString(tt.str, tt.width)
lines := strings.Count(result, "\n") + 1
if lines != tt.wantLines {
t.Errorf("Line count = %d, want %d (result: %q)", lines, tt.wantLines, result)
}
})
}
}
// TestWrapString_NoTrailingNewline 测试末尾不换行
func TestWrapString_NoTrailingNewline(t *testing.T) {
str := "1234567890"
result := WrapString(str, 5)
// 验证末尾没有换行符
if strings.HasSuffix(result, "\n") {
t.Error("Result should not end with newline")
}
// 验证包含换行符(除了最后一行)
if !strings.Contains(result, "\n") {
t.Error("Result should contain newline for multi-line output")
}
}
// TestEncodePrivateKeyToPEM_ActualCall 实际调用EncodePrivateKeyToPEM函数
func TestEncodePrivateKeyToPEM_ActualCall(t *testing.T) {
// 生成测试用的RSA私钥
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
t.Fatalf("生成RSA私钥失败: %v", err)
}
tests := []struct {
name string
keyType []string
wantError bool
}{
{
name: "默认类型",
keyType: []string{},
wantError: false,
},
{
name: "RSA类型",
keyType: []string{"RSA"},
wantError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pemBytes, err := EncodePrivateKeyToPEM(privateKey, tt.keyType...)
if (err != nil) != tt.wantError {
t.Errorf("EncodePrivateKeyToPEM() error = %v, wantError %v", err, tt.wantError)
return
}
if !tt.wantError {
if len(pemBytes) == 0 {
t.Error("EncodePrivateKeyToPEM() 返回的PEM字节不应为空")
}
pemStr := string(pemBytes)
// 验证PEM格式
if !strings.Contains(pemStr, "BEGIN") || !strings.Contains(pemStr, "END") {
t.Error("EncodePrivateKeyToPEM() 返回的PEM格式不正确")
}
// 验证类型
if len(tt.keyType) > 0 && tt.keyType[0] == "RSA" {
if !strings.Contains(pemStr, "RSA PRIVATE KEY") {
t.Error("EncodePrivateKeyToPEM() 应包含 'RSA PRIVATE KEY'")
}
} else {
if !strings.Contains(pemStr, "PRIVATE KEY") {
t.Error("EncodePrivateKeyToPEM() 应包含 'PRIVATE KEY'")
}
}
}
})
}
}
// TestEncodePublicKeyToPEM_ActualCall 实际调用EncodePublicKeyToPEM函数
func TestEncodePublicKeyToPEM_ActualCall(t *testing.T) {
logger := zaptest.NewLogger(t)
// 生成测试用的RSA密钥对
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
t.Fatalf("生成RSA密钥对失败: %v", err)
}
publicKey := &privateKey.PublicKey
tests := []struct {
name string
keyType []string
wantError bool
}{
{
name: "默认类型",
keyType: []string{},
wantError: false,
},
{
name: "RSA类型",
keyType: []string{"RSA"},
wantError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pemBytes, err := EncodePublicKeyToPEM(logger, publicKey, tt.keyType...)
if (err != nil) != tt.wantError {
t.Errorf("EncodePublicKeyToPEM() error = %v, wantError %v", err, tt.wantError)
return
}
if !tt.wantError {
if len(pemBytes) == 0 {
t.Error("EncodePublicKeyToPEM() 返回的PEM字节不应为空")
}
pemStr := string(pemBytes)
// 验证PEM格式
if !strings.Contains(pemStr, "BEGIN") || !strings.Contains(pemStr, "END") {
t.Error("EncodePublicKeyToPEM() 返回的PEM格式不正确")
}
// 验证类型
if len(tt.keyType) > 0 && tt.keyType[0] == "RSA" {
if !strings.Contains(pemStr, "RSA PUBLIC KEY") {
t.Error("EncodePublicKeyToPEM() 应包含 'RSA PUBLIC KEY'")
}
} else {
if !strings.Contains(pemStr, "PUBLIC KEY") {
t.Error("EncodePublicKeyToPEM() 应包含 'PUBLIC KEY'")
}
}
}
})
}
}
// TestEncodePublicKeyToPEM_NilKey 测试nil公钥
func TestEncodePublicKeyToPEM_NilKey(t *testing.T) {
logger := zaptest.NewLogger(t)
_, err := EncodePublicKeyToPEM(logger, nil)
if err == nil {
t.Error("EncodePublicKeyToPEM() 对于nil公钥应返回错误")
}
}
// TestNewSignatureService 测试创建SignatureService
func TestNewSignatureService(t *testing.T) {
logger := zaptest.NewLogger(t)
// 注意这里需要实际的redis client但我们只测试结构体创建
// 在实际测试中可以使用mock redis client
service := NewSignatureService(logger, nil)
if service == nil {
t.Error("NewSignatureService() 不应返回nil")
}
if service.logger != logger {
t.Error("NewSignatureService() logger 设置不正确")
}
}