361 lines
9.0 KiB
Go
361 lines
9.0 KiB
Go
package web
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"axenov/iptv-checker/app/playlist"
|
|
)
|
|
|
|
func TestHasTokensString(t *testing.T) {
|
|
cases := []struct {
|
|
in string
|
|
want bool
|
|
}{
|
|
{"http://example.com/stream.m3u8?token=abc", true},
|
|
{"http://example.com/stream?user=test&pwd=secret", true},
|
|
{"http://example.com/stream?drmreq=xyz", true},
|
|
{"http://example.com/stream?u=foo", true},
|
|
{"http://example.com/stream?password=123", true},
|
|
{"http://example.com/stream.m3u8", false},
|
|
{"", false},
|
|
{"plain text without tokens", false},
|
|
}
|
|
for _, c := range cases {
|
|
got := hasTokensString(c.in)
|
|
if got != c.want {
|
|
t.Errorf("hasTokensString(%q) = %v, want %v", c.in, got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStatusClass(t *testing.T) {
|
|
cases := []struct {
|
|
view *PlaylistView
|
|
want string
|
|
}{
|
|
{&PlaylistView{IsKnown: false}, "secondary"},
|
|
{&PlaylistView{IsKnown: true, Playlist: playlist.Playlist{IsOnline: true}}, "success"},
|
|
{&PlaylistView{IsKnown: true, Playlist: playlist.Playlist{IsOnline: false}}, "danger"},
|
|
}
|
|
for _, c := range cases {
|
|
got := statusClass(c.view)
|
|
if got != c.want {
|
|
t.Errorf("statusClass() = %s, want %s", got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStatusBadge(t *testing.T) {
|
|
cases := []struct {
|
|
view *PlaylistView
|
|
want string
|
|
}{
|
|
{&PlaylistView{IsKnown: false}, "unknown"},
|
|
{&PlaylistView{IsKnown: true, Playlist: playlist.Playlist{IsOnline: true}}, "online"},
|
|
{&PlaylistView{IsKnown: true, Playlist: playlist.Playlist{IsOnline: false}}, "offline"},
|
|
}
|
|
for _, c := range cases {
|
|
got := statusBadge(c.view)
|
|
if got != c.want {
|
|
t.Errorf("statusBadge() = %s, want %s", got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFormatDate(t *testing.T) {
|
|
if formatDate(0) != "" {
|
|
t.Error("expected empty string for ts=0")
|
|
}
|
|
result := formatDate(1700000000)
|
|
if result == "" {
|
|
t.Error("expected non-empty date string")
|
|
}
|
|
}
|
|
|
|
func TestIsAlphanumeric(t *testing.T) {
|
|
cases := []struct {
|
|
in string
|
|
want bool
|
|
}{
|
|
{"ABC123", true},
|
|
{"abc", true},
|
|
{"123", true},
|
|
{"", false},
|
|
{"ABC-123", false},
|
|
{"ABC_123", false},
|
|
{"ABC 123", false},
|
|
{"Привет", false},
|
|
}
|
|
for _, c := range cases {
|
|
got := isAlphanumeric(c.in)
|
|
if got != c.want {
|
|
t.Errorf("isAlphanumeric(%q) = %v, want %v", c.in, got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseRedisVersion(t *testing.T) {
|
|
info := "# Server\nredis_version:6.2.6\nredis_mode:standalone\n"
|
|
got := parseRedisVersion(info)
|
|
if got != "6.2.6" {
|
|
t.Errorf("expected '6.2.6', got '%s'", got)
|
|
}
|
|
}
|
|
|
|
func TestParseRedisVersion_NotFound(t *testing.T) {
|
|
info := "# Server\nsome_other_field:foo\n"
|
|
got := parseRedisVersion(info)
|
|
if got != "unknown" {
|
|
t.Errorf("expected 'unknown', got '%s'", got)
|
|
}
|
|
}
|
|
|
|
func TestContainsTag(t *testing.T) {
|
|
tags := []string{"hd", "adult", "russian"}
|
|
if !containsTag(tags, "adult") {
|
|
t.Error("expected true for 'adult'")
|
|
}
|
|
if containsTag(tags, "movies") {
|
|
t.Error("expected false for 'movies'")
|
|
}
|
|
if containsTag([]string{}, "x") {
|
|
t.Error("expected false for empty list")
|
|
}
|
|
}
|
|
|
|
func TestMakeUnknownView(t *testing.T) {
|
|
iniPls := playlist.Playlist{
|
|
Name: "Test",
|
|
Description: "Desc",
|
|
Url: "http://example.com",
|
|
Source: "public",
|
|
}
|
|
view := makeUnknownView("CODE", iniPls)
|
|
if view.Code != "CODE" {
|
|
t.Errorf("expected Code='CODE', got '%s'", view.Code)
|
|
}
|
|
if view.IsKnown {
|
|
t.Error("expected IsKnown=false")
|
|
}
|
|
if view.Name != "Test" {
|
|
t.Errorf("expected Name='Test', got '%s'", view.Name)
|
|
}
|
|
if len(view.Tags) != 0 {
|
|
t.Errorf("expected 0 tags, got %d", len(view.Tags))
|
|
}
|
|
}
|
|
|
|
func TestEnrichPlaylist_OnlinePercent(t *testing.T) {
|
|
view := &PlaylistView{
|
|
Playlist: playlist.Playlist{
|
|
IsOnline: true,
|
|
OnlineCount: 8,
|
|
OfflineCount: 2,
|
|
Channels: map[string]playlist.Channel{
|
|
"1": {},
|
|
"2": {},
|
|
"3": {},
|
|
"4": {},
|
|
"5": {},
|
|
"6": {},
|
|
"7": {},
|
|
"8": {},
|
|
"9": {},
|
|
"10": {},
|
|
},
|
|
Attributes: map[string]string{},
|
|
Groups: map[string]playlist.Group{},
|
|
Content: "#EXTM3U",
|
|
},
|
|
IsKnown: true,
|
|
}
|
|
enrichPlaylist(view)
|
|
if view.OnlinePercent != 80 {
|
|
t.Errorf("expected 80%%, got %d%%", view.OnlinePercent)
|
|
}
|
|
if view.OfflinePercent != 20 {
|
|
t.Errorf("expected 20%%, got %d%%", view.OfflinePercent)
|
|
}
|
|
}
|
|
|
|
func TestEnrichPlaylist_Unknown(t *testing.T) {
|
|
view := &PlaylistView{
|
|
Playlist: playlist.Playlist{
|
|
Channels: map[string]playlist.Channel{"1": {}},
|
|
Attributes: map[string]string{},
|
|
Groups: map[string]playlist.Group{},
|
|
Content: "",
|
|
},
|
|
IsKnown: false,
|
|
}
|
|
enrichPlaylist(view)
|
|
if view.OnlinePercent != 0 || view.OfflinePercent != 0 {
|
|
t.Errorf("expected 0%% for unknown, got online=%d%% offline=%d%%",
|
|
view.OnlinePercent, view.OfflinePercent)
|
|
}
|
|
}
|
|
|
|
func TestEnrichPlaylist_HasCatchup(t *testing.T) {
|
|
view := &PlaylistView{
|
|
Playlist: playlist.Playlist{
|
|
Content: "#EXTM3U catchup=default",
|
|
Channels: map[string]playlist.Channel{},
|
|
Attributes: map[string]string{},
|
|
Groups: map[string]playlist.Group{},
|
|
},
|
|
IsKnown: true,
|
|
}
|
|
enrichPlaylist(view)
|
|
if !view.HasCatchup {
|
|
t.Error("expected HasCatchup=true")
|
|
}
|
|
}
|
|
|
|
func TestEnrichPlaylist_HasTvg(t *testing.T) {
|
|
view := &PlaylistView{
|
|
Playlist: playlist.Playlist{
|
|
Attributes: map[string]string{"url-tvg": "http://example.com/epg.xml"},
|
|
Channels: map[string]playlist.Channel{},
|
|
Groups: map[string]playlist.Group{},
|
|
Content: "",
|
|
},
|
|
IsKnown: true,
|
|
}
|
|
enrichPlaylist(view)
|
|
if !view.HasTvg {
|
|
t.Error("expected HasTvg=true")
|
|
}
|
|
}
|
|
|
|
func TestEnrichPlaylist_HasTokens(t *testing.T) {
|
|
view := &PlaylistView{
|
|
Playlist: playlist.Playlist{
|
|
Url: "http://example.com/list.m3u8?token=abc",
|
|
Content: "#EXTM3U",
|
|
Channels: map[string]playlist.Channel{},
|
|
Attributes: map[string]string{},
|
|
Groups: map[string]playlist.Group{},
|
|
},
|
|
IsKnown: true,
|
|
}
|
|
enrichPlaylist(view)
|
|
if !view.HasTokens {
|
|
t.Error("expected HasTokens=true")
|
|
}
|
|
}
|
|
|
|
func TestEnrichPlaylist_TagsCollection(t *testing.T) {
|
|
view := &PlaylistView{
|
|
Playlist: playlist.Playlist{
|
|
Channels: map[string]playlist.Channel{
|
|
"1": {Tags: []string{"hd", "russian"}},
|
|
"2": {Tags: []string{"adult", "hd"}},
|
|
},
|
|
Attributes: map[string]string{},
|
|
Groups: map[string]playlist.Group{},
|
|
Content: "",
|
|
},
|
|
IsKnown: true,
|
|
}
|
|
enrichPlaylist(view)
|
|
if len(view.Tags) != 3 {
|
|
t.Errorf("expected 3 unique tags, got %d: %v", len(view.Tags), view.Tags)
|
|
}
|
|
}
|
|
|
|
func TestEnrichPlaylist_ChannelHasToken(t *testing.T) {
|
|
view := &PlaylistView{
|
|
Playlist: playlist.Playlist{
|
|
Channels: map[string]playlist.Channel{
|
|
"1": {URL: "http://example.com/stream?token=abc"},
|
|
},
|
|
Attributes: map[string]string{},
|
|
Groups: map[string]playlist.Group{},
|
|
Content: "",
|
|
},
|
|
IsKnown: true,
|
|
}
|
|
enrichPlaylist(view)
|
|
for _, cv := range view.ViewChannels {
|
|
if !cv.HasToken {
|
|
t.Error("expected channel HasToken=true")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestComputeStats(t *testing.T) {
|
|
playlists := []PlaylistView{
|
|
{
|
|
Playlist: playlist.Playlist{
|
|
Code: "RU",
|
|
IsOnline: true,
|
|
CheckedAt: 1700000000,
|
|
Channels: map[string]playlist.Channel{"1": {IsOnline: true}, "2": {IsOnline: false}},
|
|
Groups: map[string]playlist.Group{"g1": {}},
|
|
Attributes: map[string]string{"url-tvg": "http://epg.xml"},
|
|
Content: "#EXTM3U catchup=default",
|
|
},
|
|
IsKnown: true,
|
|
HasCatchup: true,
|
|
HasTvg: true,
|
|
Tags: []string{"adult"},
|
|
},
|
|
{
|
|
Playlist: playlist.Playlist{
|
|
Code: "EN",
|
|
IsOnline: false,
|
|
CheckedAt: 1700000100,
|
|
Channels: map[string]playlist.Channel{"1": {IsOnline: false}},
|
|
},
|
|
IsKnown: false,
|
|
},
|
|
}
|
|
stats := computeStats(playlists)
|
|
plsStats := stats["playlists"].(map[string]interface{})
|
|
if plsStats["all"].(int) != 2 {
|
|
t.Errorf("expected 2 playlists, got %d", plsStats["all"])
|
|
}
|
|
if plsStats["online"].(int) != 1 {
|
|
t.Errorf("expected 1 online, got %d", plsStats["online"])
|
|
}
|
|
if plsStats["unknown"].(int) != 1 {
|
|
t.Errorf("expected 1 unknown, got %d", plsStats["unknown"])
|
|
}
|
|
if plsStats["adult"].(int) != 1 {
|
|
t.Errorf("expected 1 adult, got %d", plsStats["adult"])
|
|
}
|
|
if plsStats["hasCatchup"].(int) != 1 {
|
|
t.Errorf("expected 1 catchup, got %d", plsStats["hasCatchup"])
|
|
}
|
|
if plsStats["hasTvg"].(int) != 1 {
|
|
t.Errorf("expected 1 tvg, got %d", plsStats["hasTvg"])
|
|
}
|
|
if plsStats["groupped"].(int) != 1 {
|
|
t.Errorf("expected 1 groupped, got %d", plsStats["groupped"])
|
|
}
|
|
|
|
chStats := stats["channels"].(map[string]interface{})
|
|
if chStats["all"].(int) != 3 {
|
|
t.Errorf("expected 3 channels, got %d", chStats["all"])
|
|
}
|
|
if chStats["online"].(int) != 1 {
|
|
t.Errorf("expected 1 online channel, got %d", chStats["online"])
|
|
}
|
|
if chStats["offline"].(int) != 2 {
|
|
t.Errorf("expected 2 offline channels, got %d", chStats["offline"])
|
|
}
|
|
|
|
latest := plsStats["latest"].(map[string]interface{})
|
|
if latest["code"] != "EN" {
|
|
t.Errorf("expected latest code 'EN', got '%v'", latest["code"])
|
|
}
|
|
}
|
|
|
|
func TestComputeStats_Empty(t *testing.T) {
|
|
stats := computeStats([]PlaylistView{})
|
|
plsStats := stats["playlists"].(map[string]interface{})
|
|
if plsStats["all"].(int) != 0 {
|
|
t.Errorf("expected 0, got %d", plsStats["all"])
|
|
}
|
|
}
|