feat: 更新CC码监管方案业务版文档,新增摘要、UGC专项、直播专项、存量处置、误判申诉、水印嵌入、CC码生命周期、组织保障等章节;同步macode到cccode重命名及其他代码变更
This commit is contained in:
@@ -10,20 +10,20 @@ import (
|
||||
)
|
||||
|
||||
// issueAndPublish 走完送审→审核→发码→入库→发布,返回已流通内容的 MA 码与 ctid。
|
||||
func issueAndPublish(t *testing.T, s *Service) (maCode, ctid string) {
|
||||
func issueAndPublish(t *testing.T, s *Service) (ccCode, ctid string) {
|
||||
t.Helper()
|
||||
sub, err := s.SubmitForReview(sampleSub())
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.ReviewCSPS(sub.ReviewID, true, "rv-1"))
|
||||
issued, err := s.ApproveAndIssue(chain.RoleRegulator, sub.ReviewID, "陕西省广播电视局")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.IngestToLibrary(chain.RoleReviewer, issued.MACode, issued.ContentTwinID, "MA-001", "省媒资库"))
|
||||
require.NoError(t, s.PublishToOperator(PublishRequest{MACode: issued.MACode, Certificate: issued.Certificate}))
|
||||
return issued.MACode, issued.ContentTwinID
|
||||
require.NoError(t, s.IngestToLibrary(chain.RoleReviewer, issued.CCCode, issued.ContentTwinID, "MA-001", "省媒资库"))
|
||||
require.NoError(t, s.PublishToOperator(PublishRequest{CCCode: issued.CCCode, Certificate: issued.Certificate}))
|
||||
return issued.CCCode, issued.ContentTwinID
|
||||
}
|
||||
|
||||
func TestParseMACode_Valid(t *testing.T) {
|
||||
p := ParseMACode("MA.156.8531.6101/WD/20260000004")
|
||||
func TestParseCCCode_Valid(t *testing.T) {
|
||||
p := ParseCCCode("MA.156.8531.6101/WD/20260000004")
|
||||
assert.True(t, p.Valid)
|
||||
assert.Equal(t, "156", p.CountryCode)
|
||||
assert.Equal(t, "8531", p.IndustryNode)
|
||||
@@ -33,24 +33,24 @@ func TestParseMACode_Valid(t *testing.T) {
|
||||
assert.Equal(t, 0, p.Episode)
|
||||
}
|
||||
|
||||
func TestParseMACode_WithEpisode(t *testing.T) {
|
||||
p := ParseMACode("MA.156.8531.6101/WD/20260000004#E07")
|
||||
func TestParseCCCode_WithEpisode(t *testing.T) {
|
||||
p := ParseCCCode("MA.156.8531.6101/WD/20260000004#E07")
|
||||
assert.True(t, p.Valid)
|
||||
assert.Equal(t, 7, p.Episode)
|
||||
}
|
||||
|
||||
func TestParseMACode_Invalid(t *testing.T) {
|
||||
func TestParseCCCode_Invalid(t *testing.T) {
|
||||
for _, bad := range []string{"", "not-a-code", "MA.156", "XX.156.8531.6101/WD/20260000004"} {
|
||||
p := ParseMACode(bad)
|
||||
p := ParseCCCode(bad)
|
||||
assert.False(t, p.Valid, "应判定非法: %q", bad)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolve_PublishedAvailableAllScreens(t *testing.T) {
|
||||
s := newService(t)
|
||||
maCode, _ := issueAndPublish(t, s)
|
||||
ccCode, _ := issueAndPublish(t, s)
|
||||
|
||||
r := s.Resolve(maCode)
|
||||
r := s.Resolve(ccCode)
|
||||
assert.True(t, r.Resolved)
|
||||
assert.True(t, r.InCirculation)
|
||||
assert.Equal(t, model.StatusPublished, r.Status)
|
||||
@@ -59,9 +59,9 @@ func TestResolve_PublishedAvailableAllScreens(t *testing.T) {
|
||||
|
||||
func TestResolve_EpisodeSubIDResolvesToBase(t *testing.T) {
|
||||
s := newService(t)
|
||||
maCode, _ := issueAndPublish(t, s)
|
||||
ccCode, _ := issueAndPublish(t, s)
|
||||
|
||||
r := s.Resolve(maCode + "#E03")
|
||||
r := s.Resolve(ccCode + "#E03")
|
||||
assert.True(t, r.Resolved)
|
||||
assert.Equal(t, 3, r.Parsed.Episode)
|
||||
assert.True(t, r.InCirculation)
|
||||
@@ -83,11 +83,11 @@ func TestResolve_UnregisteredCode(t *testing.T) {
|
||||
|
||||
func TestResolve_RevokedNotInCirculation(t *testing.T) {
|
||||
s := newService(t)
|
||||
maCode, _ := issueAndPublish(t, s)
|
||||
_, err := s.Takedown(chain.RoleRegulator, maCode, "违规")
|
||||
ccCode, _ := issueAndPublish(t, s)
|
||||
_, err := s.Takedown(chain.RoleRegulator, ccCode, "违规")
|
||||
require.NoError(t, err)
|
||||
|
||||
r := s.Resolve(maCode)
|
||||
r := s.Resolve(ccCode)
|
||||
assert.True(t, r.Resolved)
|
||||
assert.False(t, r.InCirculation)
|
||||
assert.Empty(t, r.Screens)
|
||||
@@ -95,9 +95,9 @@ func TestResolve_RevokedNotInCirculation(t *testing.T) {
|
||||
|
||||
func TestScanVerify_AuthenticAndCompliant(t *testing.T) {
|
||||
s := newService(t)
|
||||
maCode, _ := issueAndPublish(t, s)
|
||||
ccCode, _ := issueAndPublish(t, s)
|
||||
|
||||
r := s.ScanVerify(maCode)
|
||||
r := s.ScanVerify(ccCode)
|
||||
assert.True(t, r.Authentic)
|
||||
assert.True(t, r.Compliant)
|
||||
}
|
||||
@@ -111,23 +111,23 @@ func TestScanVerify_FakeCode(t *testing.T) {
|
||||
|
||||
func TestScanVerify_RevokedNotCompliant(t *testing.T) {
|
||||
s := newService(t)
|
||||
maCode, _ := issueAndPublish(t, s)
|
||||
_, err := s.Takedown(chain.RoleRegulator, maCode, "违规")
|
||||
ccCode, _ := issueAndPublish(t, s)
|
||||
_, err := s.Takedown(chain.RoleRegulator, ccCode, "违规")
|
||||
require.NoError(t, err)
|
||||
|
||||
r := s.ScanVerify(maCode)
|
||||
r := s.ScanVerify(ccCode)
|
||||
assert.True(t, r.Authentic, "下架仍是真码")
|
||||
assert.False(t, r.Compliant, "下架内容不合规")
|
||||
}
|
||||
|
||||
func TestRecordPurchase_InvalidScreenRejected(t *testing.T) {
|
||||
s := newService(t)
|
||||
maCode, _ := issueAndPublish(t, s)
|
||||
_, err := s.RecordPurchase(maCode, "user-1", "smartwatch")
|
||||
ccCode, _ := issueAndPublish(t, s)
|
||||
_, err := s.RecordPurchase(ccCode, "user-1", "smartwatch")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestRecordPurchase_UnknownMACodeRejected(t *testing.T) {
|
||||
func TestRecordPurchase_UnknownCCCodeRejected(t *testing.T) {
|
||||
s := newService(t)
|
||||
_, err := s.RecordPurchase("MA.156.8531.6101/WD/20269999999", "user-1", model.ScreenIPTV)
|
||||
assert.Error(t, err)
|
||||
@@ -135,38 +135,38 @@ func TestRecordPurchase_UnknownMACodeRejected(t *testing.T) {
|
||||
|
||||
func TestCrossScreenRights_BuyOnceWatchEverywhere(t *testing.T) {
|
||||
s := newService(t)
|
||||
maCode, _ := issueAndPublish(t, s)
|
||||
ccCode, _ := issueAndPublish(t, s)
|
||||
|
||||
// 电视端购买
|
||||
rec, err := s.RecordPurchase(maCode, "user-1", model.ScreenIPTV)
|
||||
rec, err := s.RecordPurchase(ccCode, "user-1", model.ScreenIPTV)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, model.ScreenIPTV, rec.Screen)
|
||||
|
||||
// 手机端通看,不重复付费
|
||||
r := s.VerifyCrossScreenRights(maCode, "user-1", model.ScreenApp)
|
||||
r := s.VerifyCrossScreenRights(ccCode, "user-1", model.ScreenApp)
|
||||
assert.True(t, r.Entitled)
|
||||
assert.Equal(t, model.ScreenIPTV, r.PurchaseScreen)
|
||||
|
||||
// OTT 端通看
|
||||
r2 := s.VerifyCrossScreenRights(maCode, "user-1", model.ScreenOTT)
|
||||
r2 := s.VerifyCrossScreenRights(ccCode, "user-1", model.ScreenOTT)
|
||||
assert.True(t, r2.Entitled)
|
||||
}
|
||||
|
||||
func TestCrossScreenRights_NotPurchased(t *testing.T) {
|
||||
s := newService(t)
|
||||
maCode, _ := issueAndPublish(t, s)
|
||||
r := s.VerifyCrossScreenRights(maCode, "user-x", model.ScreenApp)
|
||||
ccCode, _ := issueAndPublish(t, s)
|
||||
r := s.VerifyCrossScreenRights(ccCode, "user-x", model.ScreenApp)
|
||||
assert.False(t, r.Entitled)
|
||||
}
|
||||
|
||||
func TestRecordPurchase_IdempotentNoDoubleCharge(t *testing.T) {
|
||||
s := newService(t)
|
||||
maCode, _ := issueAndPublish(t, s)
|
||||
ccCode, _ := issueAndPublish(t, s)
|
||||
|
||||
first, err := s.RecordPurchase(maCode, "user-1", model.ScreenIPTV)
|
||||
first, err := s.RecordPurchase(ccCode, "user-1", model.ScreenIPTV)
|
||||
require.NoError(t, err)
|
||||
// 在手机端再次"购买"同内容 → 返回首次记录,不新建(跨屏通兑)
|
||||
second, err := s.RecordPurchase(maCode, "user-1", model.ScreenApp)
|
||||
second, err := s.RecordPurchase(ccCode, "user-1", model.ScreenApp)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, first.Screen, second.Screen, "重复购买应返回首次记录的购买屏")
|
||||
assert.Equal(t, first.PurchasedAt, second.PurchasedAt)
|
||||
@@ -174,10 +174,10 @@ func TestRecordPurchase_IdempotentNoDoubleCharge(t *testing.T) {
|
||||
|
||||
func TestCrossScreenRights_EpisodeSubIDSharesEntitlement(t *testing.T) {
|
||||
s := newService(t)
|
||||
maCode, _ := issueAndPublish(t, s)
|
||||
_, err := s.RecordPurchase(maCode, "user-1", model.ScreenIPTV)
|
||||
ccCode, _ := issueAndPublish(t, s)
|
||||
_, err := s.RecordPurchase(ccCode, "user-1", model.ScreenIPTV)
|
||||
require.NoError(t, err)
|
||||
// 用集级子标识核验权益应归一到整剧 MA 码
|
||||
r := s.VerifyCrossScreenRights(maCode+"#E05", "user-1", model.ScreenApp)
|
||||
r := s.VerifyCrossScreenRights(ccCode+"#E05", "user-1", model.ScreenApp)
|
||||
assert.True(t, r.Entitled)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user