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