a329d4906b
- 方案文档: AVCC 体系建设、IPTV TCS 需求(0-req)/PRD(1-prd)/任务(2-task)/二三四期任务 - tcs-iptv: Go 后端(哈希SDK/MA码生成/可信数据空间mock/业务编排/HTTP API+HMAC鉴权) - web-console: React+AntD 监管大屏(角色工作台/全流程演示/监管片库) - 一剧一码+集级哈希, 集级下架/恢复, 全栈测试通过
136 lines
3.8 KiB
Go
136 lines
3.8 KiB
Go
package macode
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// fixedTime 固定为 2025 年,便于断言年份段。
|
|
var fixedTime = time.Date(2025, 6, 1, 0, 0, 0, 0, time.UTC)
|
|
|
|
func newGen(t *testing.T) *Generator {
|
|
t.Helper()
|
|
g := NewGenerator(NewMemoryStore())
|
|
require.NoError(t, g.RegisterSegment(Segment{
|
|
IndustryNode: "8531", OrgNode: "4401", Category: CategoryMicroDrama,
|
|
Start: 1, End: 100, SeqWidth: 7,
|
|
}))
|
|
// 固定年份便于断言
|
|
g.clock = func() time.Time { return fixedTime }
|
|
return g
|
|
}
|
|
|
|
func TestAllocate_SequentialUnique(t *testing.T) {
|
|
g := newGen(t)
|
|
seen := make(map[string]bool)
|
|
for i := 0; i < 50; i++ {
|
|
issued, err := g.Allocate(CategoryMicroDrama)
|
|
require.NoError(t, err)
|
|
assert.False(t, seen[issued.MACode], "MA 码必须唯一: %s", issued.MACode)
|
|
seen[issued.MACode] = true
|
|
assert.True(t, IsValid(issued.MACode), "应符合格式: %s", issued.MACode)
|
|
}
|
|
assert.Len(t, seen, 50)
|
|
}
|
|
|
|
func TestAllocate_FormatCorrect(t *testing.T) {
|
|
g := newGen(t)
|
|
issued, err := g.Allocate(CategoryMicroDrama)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "MA.156.8531.4401/WD/20250000001", issued.MACode)
|
|
assert.Equal(t, uint64(1), issued.Sequence)
|
|
assert.Equal(t, 2025, issued.Year)
|
|
}
|
|
|
|
func TestAllocate_UnknownCategory(t *testing.T) {
|
|
g := newGen(t)
|
|
_, err := g.Allocate("XX")
|
|
assert.ErrorIs(t, err, ErrUnknownCategory)
|
|
}
|
|
|
|
func TestAllocate_SegmentExhausted(t *testing.T) {
|
|
g := NewGenerator(NewMemoryStore())
|
|
g.clock = func() time.Time { return fixedTime }
|
|
require.NoError(t, g.RegisterSegment(Segment{
|
|
IndustryNode: "8531", OrgNode: "4401", Category: CategoryWebMovie,
|
|
Start: 1, End: 2, SeqWidth: 5,
|
|
}))
|
|
_, err := g.Allocate(CategoryWebMovie)
|
|
require.NoError(t, err)
|
|
_, err = g.Allocate(CategoryWebMovie)
|
|
require.NoError(t, err)
|
|
_, err = g.Allocate(CategoryWebMovie) // 第3个超出 [1,2]
|
|
assert.ErrorIs(t, err, ErrSegmentExhausted)
|
|
}
|
|
|
|
func TestAllocate_ConcurrentNoDuplicate(t *testing.T) {
|
|
g := NewGenerator(NewMemoryStore())
|
|
g.clock = func() time.Time { return fixedTime }
|
|
require.NoError(t, g.RegisterSegment(Segment{
|
|
IndustryNode: "8531", OrgNode: "4401", Category: CategoryWebSeries,
|
|
Start: 1, End: 1000, SeqWidth: 7,
|
|
}))
|
|
|
|
var wg sync.WaitGroup
|
|
var mu sync.Mutex
|
|
seen := make(map[string]bool)
|
|
dup := 0
|
|
for i := 0; i < 200; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
issued, err := g.Allocate(CategoryWebSeries)
|
|
if err != nil {
|
|
return
|
|
}
|
|
mu.Lock()
|
|
if seen[issued.MACode] {
|
|
dup++
|
|
}
|
|
seen[issued.MACode] = true
|
|
mu.Unlock()
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
assert.Equal(t, 0, dup, "并发分配不得出现重号")
|
|
assert.Len(t, seen, 200)
|
|
}
|
|
|
|
func TestParse_RoundTrip(t *testing.T) {
|
|
seg := Segment{IndustryNode: "8531", OrgNode: "4401", Category: CategoryMicroDrama, SeqWidth: 7}
|
|
code := Format(seg, 2025, 123)
|
|
assert.Equal(t, "MA.156.8531.4401/WD/20250000123", code)
|
|
|
|
p, err := Parse(code)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "MA", p.Root)
|
|
assert.Equal(t, "156", p.CountryCode)
|
|
assert.Equal(t, "8531", p.IndustryNode)
|
|
assert.Equal(t, "4401", p.OrgNode)
|
|
assert.Equal(t, "WD", p.Category)
|
|
assert.Equal(t, 2025, p.Year)
|
|
assert.Equal(t, uint64(123), p.Sequence)
|
|
}
|
|
|
|
func TestParse_Invalid(t *testing.T) {
|
|
bad := []string{
|
|
"", "MA.156", "MA.156.8531.4401/WD", "(京)网微剧审字(2025)第123号",
|
|
"MA.156.8531.4401/wd/20250000123", // 类目须大写两位
|
|
}
|
|
for _, b := range bad {
|
|
_, err := Parse(b)
|
|
assert.Error(t, err, "应判为非法: %q", b)
|
|
assert.False(t, IsValid(b))
|
|
}
|
|
}
|
|
|
|
func TestSegment_Validate(t *testing.T) {
|
|
assert.Error(t, Segment{}.Validate())
|
|
assert.Error(t, Segment{IndustryNode: "1", OrgNode: "2", Category: "WD", Start: 10, End: 5}.Validate())
|
|
assert.NoError(t, Segment{IndustryNode: "1", OrgNode: "2", Category: "WD", Start: 1, End: 5, SeqWidth: 7}.Validate())
|
|
}
|