Files
MAcode/tcs-iptv/internal/service/phase2_test.go
T
selfrelease 468c3b5daa feat(phase2): 追更/授权链/跨省复用/终端抽检/CI(F21/F22/F13/F08/K)
- F21 追更: AddEpisodes 追加新集不重新发码; Merkle定位变更集
- F22 授权链: RecordAuthorization + CheckAuthorization(地域/平台/期限), 嵌入注入前核验
- F13 跨省复用: CrossProvinceAdmit 三重校验(MA有效+哈希一致+非黑名单)快速准入
- F08 终端抽检: TerminalVerifySegment 片段校验+断流提示
- K.1 CI: .gitlab-ci.yml(后端构建/测试/前端构建)
- 新增6个API; 16项测试通过; 二期纯代码功能全部完成
- A(真实链)/B(BFF)延后至有环境/三期, MemoryChain接口已就绪可平滑替换
2026-06-14 17:24:56 +08:00

134 lines
4.2 KiB
Go

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, "断流")
}