Files
go-trustlog/api/model/hash_test.go
ryan d313449c5c refactor: 重构trustlog-sdk目录结构到trustlog/go-trustlog
- 将所有trustlog-sdk文件移动到trustlog/go-trustlog/目录
- 更新README中所有import路径从trustlog-sdk改为go-trustlog
- 更新cookiecutter配置文件中的项目名称
- 更新根目录.lefthook.yml以引用新位置的配置
- 添加go.sum文件到版本控制
- 删除过时的示例文件

这次重构与trustlog-server保持一致的目录结构,
为未来支持多语言SDK(Python、Java等)预留空间。
2025-12-22 13:37:57 +08:00

546 lines
11 KiB
Go

package model_test
import (
"bytes"
"context"
"os"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.yandata.net/iod/iod/trustlog-sdk/api/model"
)
func TestGetHashTool(t *testing.T) {
t.Parallel()
tests := []struct {
name string
hashType model.HashType
}{
{
name: "SHA256",
hashType: model.SHA256,
},
{
name: "SHA256Simd",
hashType: model.Sha256Simd,
},
{
name: "MD5",
hashType: model.MD5,
},
{
name: "SHA1",
hashType: model.SHA1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
tool := model.GetHashTool(tt.hashType)
assert.NotNil(t, tool)
// Verify it works
_, err := tool.HashString("test")
require.NoError(t, err)
// Verify hash type
assert.Equal(t, tt.hashType, tool.GetHashType())
})
}
}
func TestNewHashTool(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(model.SHA256)
assert.NotNil(t, tool)
// Verify it works
_, err := tool.HashString("test")
require.NoError(t, err)
}
func TestHashTool_HashString(t *testing.T) {
t.Parallel()
tests := []struct {
name string
hashType model.HashType
input string
wantErr bool
}{
{
name: "SHA256",
hashType: model.SHA256,
input: "test",
wantErr: false,
},
{
name: "SHA256Simd",
hashType: model.Sha256Simd,
input: "test",
wantErr: false,
},
{
name: "MD5",
hashType: model.MD5,
input: "test",
wantErr: false,
},
{
name: "SHA1",
hashType: model.SHA1,
input: "test",
wantErr: false,
},
{
name: "SHA512",
hashType: model.SHA512,
input: "test",
wantErr: false,
},
{
name: "empty string",
hashType: model.SHA256,
input: "",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(tt.hashType)
result, err := tool.HashString(tt.input)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
assert.NotEmpty(t, result)
}
})
}
}
func TestHashTool_HashBytes(t *testing.T) {
t.Parallel()
tests := []struct {
name string
hashType model.HashType
input []byte
wantErr bool
}{
{
name: "SHA256",
hashType: model.SHA256,
input: []byte("test"),
wantErr: false,
},
{
name: "SHA256Simd",
hashType: model.Sha256Simd,
input: []byte("test"),
wantErr: false,
},
{
name: "empty bytes",
hashType: model.SHA256,
input: []byte{},
wantErr: false,
},
{
name: "large input",
hashType: model.SHA256,
input: make([]byte, 1000),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(tt.hashType)
result, err := tool.HashBytes(tt.input)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
assert.NotEmpty(t, result)
}
})
}
}
func TestHashTool_Deterministic(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(model.SHA256)
input := "test string"
result1, err1 := tool.HashString(input)
require.NoError(t, err1)
result2, err2 := tool.HashString(input)
require.NoError(t, err2)
// Same input should produce same hash
assert.Equal(t, result1, result2)
}
func TestHashTool_DifferentInputs(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(model.SHA256)
result1, err1 := tool.HashString("input1")
require.NoError(t, err1)
result2, err2 := tool.HashString("input2")
require.NoError(t, err2)
// Different inputs should produce different hashes
assert.NotEqual(t, result1, result2)
}
func TestHashTool_StringVsBytes(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(model.SHA256)
input := "test"
stringHash, err1 := tool.HashString(input)
require.NoError(t, err1)
bytesHash, err2 := tool.HashBytes([]byte(input))
require.NoError(t, err2)
// Same data in different formats should produce same hash
assert.Equal(t, stringHash, bytesHash)
}
func TestHashTool_MultipleTypes(t *testing.T) {
t.Parallel()
input := "test"
hashTypes := []model.HashType{
model.MD5,
model.SHA1,
model.SHA256,
model.SHA512,
model.Sha256Simd,
}
results := make(map[model.HashType]string)
for _, hashType := range hashTypes {
tool := model.NewHashTool(hashType)
result, err := tool.HashString(input)
require.NoError(t, err)
results[hashType] = result
}
// All should produce different hashes (except possibly some edge cases)
// At minimum, verify they all produced valid hashes
for hashType, result := range results {
assert.NotEmpty(t, result, "HashType: %v", hashType)
}
}
func TestHashTool_GetHashTool_Caching(t *testing.T) {
t.Parallel()
hashType := model.SHA256
tool1 := model.GetHashTool(hashType)
tool2 := model.GetHashTool(hashType)
// Should return the same instance (cached)
assert.Equal(t, tool1, tool2)
}
func TestHashTool_HashFile(t *testing.T) {
t.Parallel()
// Create a temporary file
tmpFile := t.TempDir() + "/test.txt"
err := os.WriteFile(tmpFile, []byte("test content"), 0o600)
require.NoError(t, err)
tool := model.NewHashTool(model.SHA256)
ctx := context.Background()
result, err := tool.HashFile(ctx, tmpFile)
require.NoError(t, err)
assert.NotEmpty(t, result)
}
func TestHashTool_HashFile_NotExists(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(model.SHA256)
ctx := context.Background()
_, err := tool.HashFile(ctx, "/nonexistent/file")
require.Error(t, err)
}
func TestHashTool_HashStream(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(model.SHA256)
reader := bytes.NewReader([]byte("test content"))
result, err := tool.HashStream(reader)
require.NoError(t, err)
assert.NotEmpty(t, result)
}
func TestHashTool_HashStream_Empty(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(model.SHA256)
reader := bytes.NewReader([]byte{})
result, err := tool.HashStream(reader)
require.NoError(t, err)
assert.NotEmpty(t, result) // Even empty input produces a hash
}
func TestGetSupportedAlgorithms(t *testing.T) {
t.Parallel()
algorithms := model.GetSupportedAlgorithms()
assert.NotEmpty(t, algorithms)
assert.Contains(t, algorithms, string(model.SHA256))
assert.Contains(t, algorithms, string(model.Sha256Simd))
// Verify case-insensitive check
assert.True(t, model.IsAlgorithmSupported("SHA256"))
assert.True(t, model.IsAlgorithmSupported("sha256"))
assert.True(t, model.IsAlgorithmSupported("sha256-simd"))
}
func TestIsAlgorithmSupported(t *testing.T) {
t.Parallel()
tests := []struct {
name string
algorithm string
expected bool
}{
{
name: "SHA256",
algorithm: "SHA256",
expected: true,
},
{
name: "SHA256 lowercase",
algorithm: "sha256",
expected: true,
},
{
name: "Sha256Simd",
algorithm: "sha256-simd",
expected: true,
},
{
name: "Sha256Simd mixed case",
algorithm: "Sha256-Simd",
expected: true,
},
{
name: "unsupported",
algorithm: "UNSUPPORTED",
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
result := model.IsAlgorithmSupported(tt.algorithm)
assert.Equal(t, tt.expected, result)
})
}
}
func TestHashTool_GetHashType(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(model.SHA512)
assert.Equal(t, model.SHA512, tool.GetHashType())
}
func TestHashTool_AllHashTypes(t *testing.T) {
t.Parallel()
hashTypes := []model.HashType{
model.MD5,
model.SHA1,
model.SHA224,
model.SHA256,
model.SHA384,
model.SHA512,
model.Sha256Simd,
model.BLAKE3,
}
for _, hashType := range hashTypes {
tool := model.NewHashTool(hashType)
result, err := tool.HashString("test")
require.NoError(t, err, "HashType: %v", hashType)
assert.NotEmpty(t, result, "HashType: %v", hashType)
assert.Equal(t, hashType, tool.GetHashType())
}
}
func TestHashTool_CompareHash(t *testing.T) {
t.Parallel()
tool := model.NewHashTool(model.SHA256)
data := "test data"
// Generate hash
hash, err := tool.HashString(data)
require.NoError(t, err)
tests := []struct {
name string
data string
expectedHash string
shouldMatch bool
}{
{
name: "匹配的哈希值",
data: data,
expectedHash: hash,
shouldMatch: true,
},
{
name: "大小写不同但内容相同",
data: data,
expectedHash: strings.ToUpper(hash),
shouldMatch: true,
},
{
name: "不匹配的哈希值",
data: data,
expectedHash: "invalid_hash",
shouldMatch: false,
},
{
name: "不同的数据",
data: "different data",
expectedHash: hash,
shouldMatch: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
match, err := tool.CompareHash(tt.data, tt.expectedHash)
require.NoError(t, err)
assert.Equal(t, tt.shouldMatch, match)
})
}
}
func TestHashTool_CompareFileHash(t *testing.T) {
t.Parallel()
// Create a temporary file
tmpFile := t.TempDir() + "/test.txt"
content := []byte("test file content")
err := os.WriteFile(tmpFile, content, 0o600)
require.NoError(t, err)
tool := model.NewHashTool(model.SHA256)
ctx := context.Background()
// Generate expected hash
expectedHash, err := tool.HashFile(ctx, tmpFile)
require.NoError(t, err)
tests := []struct {
name string
filePath string
expectedHash string
shouldMatch bool
wantErr bool
}{
{
name: "匹配的文件哈希",
filePath: tmpFile,
expectedHash: expectedHash,
shouldMatch: true,
wantErr: false,
},
{
name: "大小写不同但内容相同",
filePath: tmpFile,
expectedHash: strings.ToUpper(expectedHash),
shouldMatch: true,
wantErr: false,
},
{
name: "不匹配的文件哈希",
filePath: tmpFile,
expectedHash: "invalid_hash",
shouldMatch: false,
wantErr: false,
},
{
name: "文件不存在",
filePath: "/nonexistent/file",
expectedHash: expectedHash,
shouldMatch: false,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
match, err := tool.CompareFileHash(ctx, tt.filePath, tt.expectedHash)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
assert.Equal(t, tt.shouldMatch, match)
}
})
}
}
func TestHashList_GetHashType(t *testing.T) {
t.Parallel()
// Create mock hash data
mockHash := &mockHashData{
key: "test-key",
hash: "test-hash",
hashType: model.SHA256,
}
hashList := model.HashList{mockHash}
assert.Equal(t, model.SHA256, hashList.GetHashType())
}
// mockHashData implements HashData interface for testing.
type mockHashData struct {
key string
hash string
hashType model.HashType
}
func (m *mockHashData) Key() string {
return m.key
}
func (m *mockHashData) Hash() string {
return m.hash
}
func (m *mockHashData) Type() model.HashType {
return m.hashType
}