Files
MAcode/tcs-iptv/internal/service/distribution_test.go
T
selfrelease a329d4906b init: AIGC-Hub/AVCC 方案文档 + TCS-IPTV 内容可信锁定系统 MVP
- 方案文档: AVCC 体系建设、IPTV TCS 需求(0-req)/PRD(1-prd)/任务(2-task)/二三四期任务
- tcs-iptv: Go 后端(哈希SDK/MA码生成/可信数据空间mock/业务编排/HTTP API+HMAC鉴权)
- web-console: React+AntD 监管大屏(角色工作台/全流程演示/监管片库)
- 一剧一码+集级哈希, 集级下架/恢复, 全栈测试通过
2026-06-14 16:50:31 +08:00

138 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tcs-iptv/tcs/internal/chain"
"github.com/tcs-iptv/tcs/internal/hash"
)
// issueOne 完成一次"送审→CSPS审核→发码签发",返回 maCode、ctid、证书。
func issueOne(t *testing.T, s *Service) (string, string, string) {
t.Helper()
sub, err := s.SubmitForReview(sampleSub())
require.NoError(t, err)
require.NoError(t, s.ReviewCSPS(sub.ReviewID, true, "reviewer-1")) // 审核在前
issued, err := s.ApproveAndIssue(chain.RoleRegulator, sub.ReviewID, "北京市广播电视局")
require.NoError(t, err)
return issued.MACode, issued.ContentTwinID, issued.Certificate
}
func TestCSPSAndTranscode(t *testing.T) {
s := newService(t)
maCode, ctid, _ := issueOne(t, s)
_, err := s.BindTranscoded(chain.RoleReviewer, ctid, "filehash-abc",
"transcoded-h265-4k", "H.265", "3840x2160", "v1.0-4k")
require.NoError(t, err)
// 转码版也能验真通过
res, err := s.Verify(maCode, "transcoded-h265-4k")
require.NoError(t, err)
assert.True(t, res.Match)
}
func TestCSPSRejected(t *testing.T) {
s := newService(t)
sub, err := s.SubmitForReview(sampleSub())
require.NoError(t, err)
// CSPS 审核驳回 → 不得发码
require.NoError(t, s.ReviewCSPS(sub.ReviewID, false, "reviewer-1"))
_, err = s.ApproveAndIssue(chain.RoleRegulator, sub.ReviewID, "issuer")
assert.ErrorIs(t, err, ErrNotApproved)
}
func TestIssueRequiresCSPSApproval(t *testing.T) {
s := newService(t)
sub, err := s.SubmitForReview(sampleSub())
require.NoError(t, err)
// 未经 CSPS 审核直接发码 → 拒绝
_, err = s.ApproveAndIssue(chain.RoleRegulator, sub.ReviewID, "issuer")
assert.ErrorIs(t, err, ErrNotApproved)
}
func TestIngestAndPublish(t *testing.T) {
s := newService(t)
maCode, ctid, cert := issueOne(t, s)
require.NoError(t, s.IngestToLibrary(chain.RoleReviewer, maCode, ctid, "MEDIA-001", "广东IPTV媒资库"))
// 无证书发布被拒
err := s.PublishToOperator(PublishRequest{MACode: maCode, Certificate: ""})
assert.ErrorIs(t, err, ErrNoCertificate)
// 携带证书发布成功
require.NoError(t, s.PublishToOperator(PublishRequest{MACode: maCode, Certificate: cert}))
}
func TestInjectToCDN_MatchAndMismatch(t *testing.T) {
s := newService(t)
maCode, ctid, cert := issueOne(t, s)
require.NoError(t, s.IngestToLibrary(chain.RoleReviewer, maCode, ctid, "MEDIA-001", "媒资库"))
require.NoError(t, s.PublishToOperator(PublishRequest{MACode: maCode, Certificate: cert}))
// 哈希匹配 → 允许注入
res, err := s.InjectToCDN(chain.RoleOperator, ctid, maCode, "filehash-abc",
"CT-IPTV-GD", "cdn://ct-gd/iptv/vod/008923")
require.NoError(t, err)
assert.True(t, res.Allowed)
assert.NotEmpty(t, res.DistributionID)
// 哈希不匹配 → 拒绝注入
res, err = s.InjectToCDN(chain.RoleOperator, ctid, maCode, "tampered-hash",
"CT-IPTV-GD", "cdn://x")
assert.ErrorIs(t, err, ErrHashMismatch)
assert.False(t, res.Allowed)
}
func TestInjectToCDN_RevokedBlocked(t *testing.T) {
s := newService(t)
maCode, ctid, cert := issueOne(t, s)
require.NoError(t, s.IngestToLibrary(chain.RoleReviewer, maCode, ctid, "MEDIA-001", "媒资库"))
require.NoError(t, s.PublishToOperator(PublishRequest{MACode: maCode, Certificate: cert}))
// 下架后不得注入
_, err := s.Takedown(chain.RoleRegulator, maCode, "违规")
require.NoError(t, err)
_, err = s.InjectToCDN(chain.RoleOperator, ctid, maCode, "filehash-abc", "OP", "cdn://x")
assert.ErrorIs(t, err, ErrNotApproved)
}
func TestTakedown_ResolvesMappings(t *testing.T) {
s := newService(t)
maCode, ctid, cert := issueOne(t, s)
require.NoError(t, s.IngestToLibrary(chain.RoleReviewer, maCode, ctid, "MEDIA-001", "媒资库"))
require.NoError(t, s.PublishToOperator(PublishRequest{MACode: maCode, Certificate: cert}))
_, _ = s.InjectToCDN(chain.RoleOperator, ctid, maCode, "filehash-abc", "CT-IPTV-GD", "cdn://ct-gd/vod/1")
// 非监管主体不得下架
_, err := s.Takedown(chain.RoleOperator, maCode, "越权")
assert.ErrorIs(t, err, chain.ErrPermissionDenied)
// 监管下架,解析出 CDN 端点
res, err := s.Takedown(chain.RoleRegulator, maCode, "违规")
require.NoError(t, err)
assert.Contains(t, res.CDNEndpoints, "cdn://ct-gd/vod/1")
}
func TestReportVersionChange_LocatesEpisode(t *testing.T) {
s := newService(t)
_, ctid, _ := issueOne(t, s)
old := []string{
hash.SHA256Hex([]byte("ep1")),
hash.SHA256Hex([]byte("ep2")),
hash.SHA256Hex([]byte("ep3")),
}
neu := []string{
hash.SHA256Hex([]byte("ep1")),
hash.SHA256Hex([]byte("ep2-tampered")),
hash.SHA256Hex([]byte("ep3")),
}
episodes, err := s.ReportVersionChange(ctid, "第2集被替换", "root-old", "root-new", old, neu)
require.NoError(t, err)
assert.Equal(t, []int{2}, episodes, "应定位到第2集(1-based")
}