Initial commit: Null DRM Official
Capture, decrypt, and restream toolkit with compiled-in app modules (RTE, TG4, BBC), on-device MITM proxy, streamd control plane, and www. BBC module.yaml is published (clear streams); other module values stay local.
This commit is contained in:
commit
2fa8f2435f
121 changed files with 17802 additions and 0 deletions
129
apps/modules/tg4/tg4_test.go
Normal file
129
apps/modules/tg4/tg4_test.go
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
package tg4
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
appreg "drmdecryption/app"
|
||||
"drmdecryption/modcfg"
|
||||
"drmdecryption/modules/provider"
|
||||
)
|
||||
|
||||
// Compile-time proof the plugin satisfies every interface the host expects.
|
||||
var (
|
||||
_ appreg.App = (*App)(nil)
|
||||
_ appreg.Catalog = (*App)(nil)
|
||||
_ appreg.StreamDefaults = (*App)(nil)
|
||||
)
|
||||
|
||||
func testApp(t *testing.T) *App {
|
||||
t.Helper()
|
||||
cfg := Config{
|
||||
AccountID: "acct",
|
||||
PolicyKey: "pk",
|
||||
PlaybackConfigURL: "https://cfg.test/playback.json",
|
||||
Channels: map[string]Channel{
|
||||
"main": {Label: "Main", VideoID: "111", TokenField: "mainToken", LiveCardIndex: 0},
|
||||
"extra": {Label: "Extra", StreamIDField: "extraStreamId", TokenField: "extraToken", LiveCardIndex: 1},
|
||||
"phone": {Label: "Phone only", PhoneOnly: true, LiveCardIndex: 3},
|
||||
},
|
||||
Common: provider.Common{
|
||||
Aliases: map[string]string{"primary": "main", "second": "extra"},
|
||||
},
|
||||
}.withDefaults()
|
||||
labels := map[string]string{}
|
||||
for id, ch := range cfg.Channels {
|
||||
labels[id] = ch.Label
|
||||
}
|
||||
return &App{Base: provider.New(Name, cfg.Common, labels, modcfg.Result{Path: "test"}), cfg: cfg}
|
||||
}
|
||||
|
||||
func TestAliasesResolveFromConfig(t *testing.T) {
|
||||
a := testApp(t)
|
||||
for in, want := range map[string]string{
|
||||
"main": "main", "MAIN": "main", "primary": "main",
|
||||
"second": "extra", "extra": "extra",
|
||||
} {
|
||||
got, err := a.Base.Resolve(in)
|
||||
if err != nil {
|
||||
t.Fatalf("resolve %q: %v", in, err)
|
||||
}
|
||||
if got != want {
|
||||
t.Errorf("resolve(%q) = %q, want %q", in, got, want)
|
||||
}
|
||||
}
|
||||
if _, err := a.Base.Resolve("nope"); err == nil {
|
||||
t.Error("unknown channel must error")
|
||||
}
|
||||
}
|
||||
|
||||
// A video id pinned in config wins; otherwise it is read from the named remote
|
||||
// playback-config field. Both paths are data-driven, no channel name switch.
|
||||
func TestResolveChannelReadsConfiguredFields(t *testing.T) {
|
||||
a := testApp(t)
|
||||
pc := playbackConfig{
|
||||
"mainToken": "tok-main",
|
||||
"extraToken": "tok-extra",
|
||||
"extraStreamId": "222",
|
||||
}
|
||||
_, vid, tok, err := a.resolveChannel(pc, "main")
|
||||
if err != nil {
|
||||
t.Fatalf("main: %v", err)
|
||||
}
|
||||
if vid != "111" || tok != "tok-main" {
|
||||
t.Errorf("main → video %q token %q", vid, tok)
|
||||
}
|
||||
_, vid, tok, err = a.resolveChannel(pc, "extra")
|
||||
if err != nil {
|
||||
t.Fatalf("extra: %v", err)
|
||||
}
|
||||
if vid != "222" || tok != "tok-extra" {
|
||||
t.Errorf("extra → video %q token %q", vid, tok)
|
||||
}
|
||||
}
|
||||
|
||||
// A phone-only channel must say so rather than fail with a confusing catalog error.
|
||||
func TestPhoneOnlyChannelExplainsItself(t *testing.T) {
|
||||
a := testApp(t)
|
||||
_, _, _, err := a.resolveChannel(playbackConfig{}, "phone")
|
||||
if err == nil {
|
||||
t.Fatal("phone-only channel must not resolve from the catalog")
|
||||
}
|
||||
if want := "drm capture"; !contains(err.Error(), want) {
|
||||
t.Errorf("error %q should point at %q", err, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaybackConfigCoercesNumericIDs(t *testing.T) {
|
||||
pc := playbackConfig{"a": "123", "b": float64(456), "c": true}
|
||||
if pc.str("a") != "123" {
|
||||
t.Error("string field")
|
||||
}
|
||||
if pc.str("b") != "456" {
|
||||
t.Errorf("numeric field = %q, want 456", pc.str("b"))
|
||||
}
|
||||
if pc.str("missing") != "" || pc.str("") != "" {
|
||||
t.Error("missing field must be empty")
|
||||
}
|
||||
if !pc.Flags()["c"] {
|
||||
t.Error("bool flags should be reported")
|
||||
}
|
||||
}
|
||||
|
||||
// No provider identity may be compiled in.
|
||||
func TestNoHardcodedCredentials(t *testing.T) {
|
||||
cfg := Config{}.withDefaults()
|
||||
if cfg.AccountID != "" || cfg.PolicyKey != "" || cfg.PlaybackConfigURL != "" || cfg.Package != "" {
|
||||
t.Fatal("account id / policy key / config URL / package must come from module.yaml")
|
||||
}
|
||||
}
|
||||
|
||||
func contains(s, sub string) bool {
|
||||
return len(s) >= len(sub) && (func() bool {
|
||||
for i := 0; i+len(sub) <= len(s); i++ {
|
||||
if s[i:i+len(sub)] == sub {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue