Files
MAcode/tcs-iptv/internal/macode/store_postgres_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

130 lines
3.0 KiB
Go

package macode
import (
"database/sql"
"fmt"
"os"
"sync"
"testing"
_ "github.com/lib/pq"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// 集成测试:需本地 PostgreSQL。通过 TCS_TEST_PG_DSN 提供连接串;未提供则跳过。
func openTestDB(t *testing.T) *sql.DB {
t.Helper()
dsn := os.Getenv("TCS_TEST_PG_DSN")
if dsn == "" {
dsn = "postgres://postgres@localhost:5432/tcs_iptv?sslmode=disable"
}
db, err := sql.Open("postgres", dsn)
if err != nil {
t.Skipf("跳过 PG 集成测试:%v", err)
}
if err := db.Ping(); err != nil {
t.Skipf("跳过 PG 集成测试(无法连接):%v", err)
}
return db
}
func cleanupKey(t *testing.T, db *sql.DB, key string) {
t.Helper()
_, _ = db.Exec("DELETE FROM macode_cursor WHERE segment_key = $1", key)
}
func TestPostgresStore_Sequential(t *testing.T) {
db := openTestDB(t)
defer db.Close()
store := NewPostgresStore(db)
key := "test:seq:WD"
cleanupKey(t, db, key)
defer cleanupKey(t, db, key)
for want := uint64(1); want <= 5; want++ {
got, err := store.Next(key, 1, 100)
require.NoError(t, err)
assert.Equal(t, want, got)
}
}
func TestPostgresStore_Exhausted(t *testing.T) {
db := openTestDB(t)
defer db.Close()
store := NewPostgresStore(db)
key := "test:exhaust:DY"
cleanupKey(t, db, key)
defer cleanupKey(t, db, key)
_, err := store.Next(key, 1, 2)
require.NoError(t, err)
_, err = store.Next(key, 1, 2)
require.NoError(t, err)
_, err = store.Next(key, 1, 2)
assert.ErrorIs(t, err, ErrSegmentExhausted)
}
func TestPostgresStore_ConcurrentNoDuplicate(t *testing.T) {
db := openTestDB(t)
defer db.Close()
store := NewPostgresStore(db)
key := "test:concurrent:WJ"
cleanupKey(t, db, key)
defer cleanupKey(t, db, key)
const n = 200
var wg sync.WaitGroup
var mu sync.Mutex
seen := make(map[uint64]bool)
dup := 0
errs := 0
for i := 0; i < n; i++ {
wg.Add(1)
go func() {
defer wg.Done()
v, err := store.Next(key, 1, 1000)
if err != nil {
mu.Lock()
errs++
mu.Unlock()
return
}
mu.Lock()
if seen[v] {
dup++
}
seen[v] = true
mu.Unlock()
}()
}
wg.Wait()
assert.Equal(t, 0, errs, "并发分配不应报错")
assert.Equal(t, 0, dup, "并发分配不得重号")
assert.Len(t, seen, n)
}
// TestPostgresStore_WithGenerator 验证 PG 存储与生成器联动产出唯一 MA 码。
func TestPostgresStore_WithGenerator(t *testing.T) {
db := openTestDB(t)
defer db.Close()
key := fmt.Sprintf("%s:%s:%s", "8531", "4401", CategoryAnimation)
cleanupKey(t, db, key)
defer cleanupKey(t, db, key)
g := NewGenerator(NewPostgresStore(db))
require.NoError(t, g.RegisterSegment(Segment{
IndustryNode: "8531", OrgNode: "4401",
Category: CategoryAnimation, Start: 1, End: 1000, SeqWidth: 7,
}))
seen := map[string]bool{}
for i := 0; i < 10; i++ {
issued, err := g.Allocate(CategoryAnimation)
require.NoError(t, err)
assert.False(t, seen[issued.MACode])
assert.True(t, IsValid(issued.MACode))
seen[issued.MACode] = true
}
}