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()) }