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 设置不正确") } }