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 })() }