Files
gopeed/pkg/download/hls_live_test.go
T

98 lines
2.6 KiB
Go

package download
import (
"fmt"
"os"
"path/filepath"
"testing"
"time"
"github.com/GopeedLab/gopeed/pkg/base"
)
// TestDownloader_HlsLiveSite is a manual acceptance gate against a real site.
// It is skipped unless HLS_LIVE_URL is set, e.g.:
//
// HLS_LIVE_URL="https://host/path/index.m3u8" go test ./pkg/download/ -run TestDownloader_HlsLiveSite -v
func TestDownloader_HlsLiveSite(t *testing.T) {
playlistURL := os.Getenv("HLS_LIVE_URL")
if playlistURL == "" {
t.Skip("set HLS_LIVE_URL to run the live-site acceptance test")
}
referer := os.Getenv("HLS_LIVE_REFERER")
downloader := NewDownloader(&DownloaderConfig{Storage: NewMemStorage(), StorageDir: t.TempDir()})
if err := downloader.Setup(); err != nil {
t.Fatal(err)
}
defer downloader.Clear()
downloadDir := t.TempDir()
cfg, err := downloader.GetConfig()
if err != nil {
t.Fatal(err)
}
cfg.DownloadDir = downloadDir
if err := downloader.PutConfig(cfg); err != nil {
t.Fatal(err)
}
req := &base.Request{URL: playlistURL}
if referer != "" {
req.Extra = map[string]any{"header": map[string]string{"Referer": referer}}
}
rr, err := downloader.Resolve(req)
if err != nil {
t.Fatalf("resolve: %v", err)
}
name := rr.Res.Files[0].Name
size := rr.Res.Size
t.Logf("resolved: name=%s size=%d", name, size)
taskID, err := downloader.Create(rr.ID)
if err != nil {
t.Fatal(err)
}
deadline := time.Now().Add(30 * time.Minute)
var lastLogged int64
for {
task := downloader.GetTask(taskID)
if task == nil {
t.Fatal("task not found")
}
if task.Status == base.DownloadStatusDone {
break
}
if task.Status == base.DownloadStatusError {
t.Fatalf("task entered error state after %d bytes", task.Progress.Downloaded)
}
if time.Now().After(deadline) {
t.Fatalf("timeout, downloaded %d bytes", task.Progress.Downloaded)
}
if tick := task.Progress.Downloaded; tick-lastLogged > 10<<20 {
lastLogged = tick
t.Logf("progress: %d bytes", tick)
}
time.Sleep(500 * time.Millisecond)
}
data, err := os.ReadFile(filepath.Join(downloadDir, name))
if err != nil {
t.Fatal(err)
}
if int64(len(data)) == 0 {
t.Fatal("merged file is empty")
}
t.Logf("merged: %s (%d bytes)", name, len(data))
if filepath.Ext(name) == ".ts" {
// MPEG-TS packets are 188 bytes and start with the 0x47 sync byte.
for i := 0; i < 188*4 && i < len(data); i += 188 {
if data[i] != 0x47 {
t.Fatalf("invalid TS sync byte at offset %d: %#x", i, data[i])
}
}
} else if string(data[4:8]) != "ftyp" {
t.Fatalf("invalid fMP4 header: %q", data[:8])
}
fmt.Printf("LIVE ACCEPTANCE OK: %s (%d bytes)\n", filepath.Join(downloadDir, name), len(data))
}