package service import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tcs-iptv/tcs/internal/chain" "github.com/tcs-iptv/tcs/internal/model" ) // ---- F22 授权链与发布前核验 ---- func TestAuthorization_PlatformGate(t *testing.T) { s := newService(t) maCode, ctid, cert := issueOne(t, s) require.NoError(t, s.IngestToLibrary(chain.RoleReviewer, maCode, ctid, "M", "媒资库")) require.NoError(t, s.PublishToOperator(PublishRequest{MACode: maCode, Certificate: cert})) // 仅授权 CT-SX require.NoError(t, s.RecordAuthorization(maCode, nil, []string{"CT-SX"}, time.Time{})) // 授权平台注入通过 _, err := s.InjectToCDN(chain.RoleOperator, ctid, maCode, "filehash-abc", "CT-SX", "cdn://ct") require.NoError(t, err) // 非授权平台注入被拒 _, err = s.InjectToCDN(chain.RoleOperator, ctid, maCode, "filehash-abc", "CM-SX", "cdn://cm") assert.ErrorIs(t, err, ErrNotApproved) } func TestAuthorization_Expiry(t *testing.T) { s := newService(t) maCode, _, _ := issueOne(t, s) // 已过期授权 require.NoError(t, s.RecordAuthorization(maCode, nil, nil, time.Now().Add(-time.Hour))) res := s.CheckAuthorization(maCode, "", "") assert.False(t, res.Allowed) assert.Contains(t, res.Reason, "过期") } func TestAuthorization_RegionGate(t *testing.T) { s := newService(t) maCode, _, _ := issueOne(t, s) require.NoError(t, s.RecordAuthorization(maCode, []string{"610000"}, nil, time.Time{})) assert.True(t, s.CheckAuthorization(maCode, "610000", "").Allowed) // 陕西 assert.False(t, s.CheckAuthorization(maCode, "440000", "").Allowed) // 广东,超域 } // ---- F21 追更 ---- func TestAddEpisodes_NoReissue(t *testing.T) { s := newService(t) // 初始 2 集 sub := sampleSub() sub.Episodes = []model.EpisodeHash{{Episode: 1, FileSHA256: "e1"}, {Episode: 2, FileSHA256: "e2"}} r, _ := s.SubmitForReview(sub) require.NoError(t, s.ReviewCSPS(r.ReviewID, true, "rv")) issued, err := s.ApproveAndIssue(chain.RoleRegulator, r.ReviewID, "陕西IPTV") require.NoError(t, err) // 追更第 3、4 集(不重新发码) require.NoError(t, s.AddEpisodes(chain.RoleReviewer, issued.MACode, []model.EpisodeHash{ {Episode: 3, FileSHA256: "e3"}, {Episode: 4, FileSHA256: "e4"}, })) list, err := s.ListEpisodes(issued.MACode) require.NoError(t, err) assert.Len(t, list, 4, "应有 4 集") // 新集可独立验真 res, err := s.VerifyEpisode(issued.MACode, 3, "e3") require.NoError(t, err) assert.True(t, res.Match) } // ---- F13 跨省复用 ---- func TestCrossProvince_Admit(t *testing.T) { s := newService(t) maCode, _, _ := issueOne(t, s) // sampleSub FileHash=filehash-abc res := s.CrossProvinceAdmit(maCode, "filehash-abc", "610000") assert.True(t, res.Admitted) assert.True(t, res.MACodeValid && res.HashConsistent && res.NotBlacklisted) assert.NotEmpty(t, res.ProvinceFlowNo) } func TestCrossProvince_HashMismatch(t *testing.T) { s := newService(t) maCode, _, _ := issueOne(t, s) res := s.CrossProvinceAdmit(maCode, "tampered", "610000") assert.False(t, res.Admitted) assert.True(t, res.MACodeValid) assert.False(t, res.HashConsistent) } func TestCrossProvince_Blacklisted(t *testing.T) { s := newService(t) maCode, _, _ := issueOne(t, s) s.Blacklist(maCode) res := s.CrossProvinceAdmit(maCode, "filehash-abc", "610000") assert.False(t, res.Admitted) assert.False(t, res.NotBlacklisted) assert.Contains(t, res.Reason, "黑名单") } func TestCrossProvince_UnknownMA(t *testing.T) { s := newService(t) res := s.CrossProvinceAdmit("MA.156.8531.6101/WD/不存在", "h", "610000") assert.False(t, res.Admitted) assert.False(t, res.MACodeValid) } // ---- F08 终端抽检 ---- func TestTerminalVerifySegment(t *testing.T) { s := newService(t) sub := sampleSub() sub.Episodes = []model.EpisodeHash{{Episode: 1, FileSHA256: "seg1"}} r, _ := s.SubmitForReview(sub) require.NoError(t, s.ReviewCSPS(r.ReviewID, true, "rv")) issued, err := s.ApproveAndIssue(chain.RoleRegulator, r.ReviewID, "陕西IPTV") require.NoError(t, err) ok, _ := s.TerminalVerifySegment(issued.MACode, 1, "seg1") assert.True(t, ok) ok, msg := s.TerminalVerifySegment(issued.MACode, 1, "tampered") assert.False(t, ok) assert.Contains(t, msg, "断流") }