Files
MAcode/tcs-iptv/internal/hash/hash_test.go
T
selfrelease a329d4906b init: AIGC-Hub/AVCC 方案文档 + TCS-IPTV 内容可信锁定系统 MVP
- 方案文档: AVCC 体系建设、IPTV TCS 需求(0-req)/PRD(1-prd)/任务(2-task)/二三四期任务
- tcs-iptv: Go 后端(哈希SDK/MA码生成/可信数据空间mock/业务编排/HTTP API+HMAC鉴权)
- web-console: React+AntD 监管大屏(角色工作台/全流程演示/监管片库)
- 一剧一码+集级哈希, 集级下架/恢复, 全栈测试通过
2026-06-14 16:50:31 +08:00

152 lines
4.3 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 hash
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func writeTempFile(t *testing.T, data []byte) string {
t.Helper()
dir := t.TempDir()
p := filepath.Join(dir, "master.bin")
require.NoError(t, os.WriteFile(p, data, 0o644))
return p
}
func TestSHA256Hex_Deterministic(t *testing.T) {
a := SHA256Hex([]byte("hello"))
b := SHA256Hex([]byte("hello"))
assert.Equal(t, a, b)
// 已知向量
assert.Equal(t, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", a)
}
func TestFileSHA256_MatchesBytes(t *testing.T) {
data := []byte("the quick brown fox")
p := writeTempFile(t, data)
got, err := FileSHA256(p)
require.NoError(t, err)
assert.Equal(t, SHA256Hex(data), got)
}
func TestSegmentHashes_SmallSegments(t *testing.T) {
// 25 字节,分段 10 → 3 段(10/10/5
data := []byte("0123456789ABCDEFGHIJ12345")
p := writeTempFile(t, data)
segs, err := SegmentHashes(p, 10)
require.NoError(t, err)
require.Len(t, segs, 3)
assert.Equal(t, SHA256Hex(data[0:10]), segs[0])
assert.Equal(t, SHA256Hex(data[10:20]), segs[1])
assert.Equal(t, SHA256Hex(data[20:25]), segs[2])
}
func TestMerkleTree_RootStableAndChangesOnEdit(t *testing.T) {
leaves := []string{
SHA256Hex([]byte("ep1")),
SHA256Hex([]byte("ep2")),
SHA256Hex([]byte("ep3")),
SHA256Hex([]byte("ep4")),
}
root1 := BuildMerkleTree(leaves).Root()
root2 := BuildMerkleTree(leaves).Root()
assert.Equal(t, root1, root2, "同样叶子根应一致")
assert.NotEmpty(t, root1)
// 改第3集 → 根变化
edited := append([]string(nil), leaves...)
edited[2] = SHA256Hex([]byte("ep3-tampered"))
root3 := BuildMerkleTree(edited).Root()
assert.NotEqual(t, root1, root3, "篡改任一集,根必变")
}
func TestMerkleTree_OddLeaves(t *testing.T) {
leaves := []string{
SHA256Hex([]byte("a")),
SHA256Hex([]byte("b")),
SHA256Hex([]byte("c")),
}
mt := BuildMerkleTree(leaves)
assert.NotEmpty(t, mt.Root())
}
func TestLocateChangedLeaves(t *testing.T) {
old := []string{"h1", "h2", "h3", "h4"}
neu := []string{"h1", "x2", "h3", "x4"}
changed := LocateChangedLeaves(old, neu)
assert.Equal(t, []int{1, 3}, changed, "应定位到第2集和第4集被改")
}
func TestComputeFile_FullPackage(t *testing.T) {
data := make([]byte, 25*1024) // 25KB
for i := range data {
data[i] = byte(i % 251)
}
p := writeTempFile(t, data)
pkg, err := ComputeFile(p, Options{SegmentSize: 10 * 1024})
require.NoError(t, err)
require.NoError(t, pkg.Validate())
assert.Equal(t, int64(25*1024), pkg.FileSize)
assert.Len(t, pkg.SegmentHashes, 3)
assert.NotEmpty(t, pkg.MerkleRoot)
assert.Equal(t, SHA256Hex(data), pkg.FileSHA256)
}
func TestComputeFile_EmptyFileRejected(t *testing.T) {
p := writeTempFile(t, []byte{})
_, err := ComputeFile(p, Options{})
assert.ErrorIs(t, err, ErrEmptyInput)
}
func TestComputeFile_MissingFile(t *testing.T) {
_, err := ComputeFile("/no/such/file.bin", Options{})
assert.Error(t, err)
}
func TestHashPackage_ValidateMissingFields(t *testing.T) {
assert.Error(t, (&HashPackage{MerkleRoot: "x"}).Validate()) // 缺 file_sha256
assert.Error(t, (&HashPackage{FileSHA256: "x"}).Validate()) // 缺 merkle_root
assert.NoError(t, (&HashPackage{FileSHA256: "a", MerkleRoot: "b"}).Validate())
}
func TestPerceptualHash_IdenticalAndDifferent(t *testing.T) {
// 全黑与全白图,aHash/dHash 应可区分
black := make([][]uint8, 16)
white := make([][]uint8, 16)
grad := make([][]uint8, 16)
for y := 0; y < 16; y++ {
black[y] = make([]uint8, 16)
white[y] = make([]uint8, 16)
grad[y] = make([]uint8, 16)
for x := 0; x < 16; x++ {
white[y][x] = 255
grad[y][x] = uint8(x * 16) // 水平渐变
}
}
imgBlack := newGrayTestImage(black)
imgWhite := newGrayTestImage(white)
imgGrad := newGrayTestImage(grad)
// 同一图的哈希稳定
assert.Equal(t, AHash(imgGrad), AHash(imgGrad))
assert.Equal(t, DHash(imgGrad), DHash(imgGrad))
// 渐变图的 dHash 应与纯色不同
assert.NotEqual(t, DHash(imgGrad), DHash(imgBlack))
// 汉明距离:渐变 vs 纯白 应 > 0
d, err := HammingDistance(DHash(imgGrad), DHash(imgWhite))
require.NoError(t, err)
assert.Greater(t, d, 0)
}
func TestHammingDistance_LengthMismatch(t *testing.T) {
_, err := HammingDistance("ffff", "ffffffff")
assert.Error(t, err)
}