mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-28 03:06:38 +08:00
204 lines
6.0 KiB
Go
204 lines
6.0 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync/atomic"
|
|
"testing"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/truewhile/MeBox/internal/model"
|
|
"github.com/truewhile/MeBox/internal/repository"
|
|
"github.com/truewhile/MeBox/internal/service/cloud115"
|
|
)
|
|
|
|
func TestCloud115PlaybackInfoTriggersTranscodeOnce(t *testing.T) {
|
|
var playCalls int32
|
|
var pushCalls int32
|
|
var ready int32
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch r.URL.Path {
|
|
case "/open/video/play":
|
|
atomic.AddInt32(&playCalls, 1)
|
|
if atomic.LoadInt32(&ready) == 0 {
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"state": false,
|
|
"code": 0,
|
|
"message": "转码中",
|
|
"data": map[string]any{},
|
|
})
|
|
return
|
|
}
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"state": true,
|
|
"code": 0,
|
|
"message": "",
|
|
"data": map[string]any{
|
|
"file_name": "test.mkv",
|
|
"definition_list_new": map[string]string{
|
|
"4": "1080P",
|
|
},
|
|
"video_url": []map[string]any{
|
|
{
|
|
"url": "http://cdn.example/master.m3u8",
|
|
"definition": 4,
|
|
"definition_n": 4,
|
|
"width": 1920,
|
|
"height": 1080,
|
|
"title": "1080P",
|
|
},
|
|
},
|
|
},
|
|
})
|
|
case "/open/video/video_push":
|
|
atomic.AddInt32(&pushCalls, 1)
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"state": true, "code": 0, "data": []any{}})
|
|
default:
|
|
http.NotFound(w, r)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
oldBase := cloud115.ProAPIBase
|
|
cloud115.ProAPIBase = server.URL
|
|
defer func() { cloud115.ProAPIBase = oldBase }()
|
|
|
|
db := newServiceTestDB(t, &model.StrmAccount{}, &model.Media{})
|
|
repos := repository.New(db)
|
|
strm := NewStrmService(nil, zap.NewNop(), repos, NewCryptoService("test-secret", zap.NewNop()))
|
|
ctx := context.Background()
|
|
account, err := strm.CreateStrmAccount(ctx, "115", model.StrmProvider115, map[string]string{
|
|
"app_id": "100195129",
|
|
"access_token": "at",
|
|
"refresh_token": "rt",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("create account: %v", err)
|
|
}
|
|
media := &model.Media{
|
|
Base: model.Base{ID: "media-1"},
|
|
Title: "test",
|
|
Path: "/media/test.strm",
|
|
Container: "strm",
|
|
Height: 1080,
|
|
STRMURL: "/api/strm/play/cloud115/video.mkv?acct=" + account.ID + "&pickcode=pc",
|
|
}
|
|
if err := db.Create(media).Error; err != nil {
|
|
t.Fatalf("create media: %v", err)
|
|
}
|
|
svc := NewCloud115PlaybackService(nil, zap.NewNop(), repos, strm)
|
|
|
|
info, err := svc.PlaybackInfo(ctx, media.ID, 0)
|
|
if err != nil {
|
|
t.Fatalf("first playback info: %v", err)
|
|
}
|
|
if info.Provider != model.StrmProvider115 || info.DefaultQuality != "4" {
|
|
t.Fatalf("unexpected playback info: %#v", info)
|
|
}
|
|
if info.Transcode.State != "transcoding" {
|
|
t.Fatalf("transcode state = %q, want transcoding", info.Transcode.State)
|
|
}
|
|
if got := atomic.LoadInt32(&pushCalls); got != 1 {
|
|
t.Fatalf("push calls = %d, want 1", got)
|
|
}
|
|
|
|
if _, err := svc.PlaybackInfo(ctx, media.ID, 0); err != nil {
|
|
t.Fatalf("second playback info: %v", err)
|
|
}
|
|
if got := atomic.LoadInt32(&pushCalls); got != 1 {
|
|
t.Fatalf("push calls after polling = %d, want 1", got)
|
|
}
|
|
|
|
atomic.StoreInt32(&ready, 1)
|
|
info, err = svc.PlaybackInfo(ctx, media.ID, 0)
|
|
if err != nil {
|
|
t.Fatalf("ready playback info: %v", err)
|
|
}
|
|
if info.Transcode.State != "ready" {
|
|
t.Fatalf("transcode state = %q, want ready", info.Transcode.State)
|
|
}
|
|
url, _, err := svc.ResolveCloud115URL(ctx, media.ID, 4)
|
|
if err != nil {
|
|
t.Fatalf("resolve cloud url: %v", err)
|
|
}
|
|
if url != "http://cdn.example/master.m3u8" {
|
|
t.Fatalf("url = %q", url)
|
|
}
|
|
if got := atomic.LoadInt32(&playCalls); got < 3 {
|
|
t.Fatalf("play calls = %d, want >= 3", got)
|
|
}
|
|
}
|
|
|
|
func TestCloud115PlaybackInfoTranscodePendingBeforeReady(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch r.URL.Path {
|
|
case "/open/video/play":
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"state": false, "code": 0, "message": "转码中", "data": map[string]any{}})
|
|
case "/open/video/video_push":
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"state": true, "code": 0, "data": []any{}})
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
oldBase := cloud115.ProAPIBase
|
|
cloud115.ProAPIBase = server.URL
|
|
defer func() { cloud115.ProAPIBase = oldBase }()
|
|
|
|
db := newServiceTestDB(t, &model.StrmAccount{}, &model.Media{})
|
|
repos := repository.New(db)
|
|
strm := NewStrmService(nil, zap.NewNop(), repos, NewCryptoService("test-secret", zap.NewNop()))
|
|
ctx := context.Background()
|
|
account, err := strm.CreateStrmAccount(ctx, "115", model.StrmProvider115, map[string]string{
|
|
"app_id": "100195129",
|
|
"access_token": "at",
|
|
"refresh_token": "rt",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("create account: %v", err)
|
|
}
|
|
media := &model.Media{
|
|
Base: model.Base{ID: "media-2"},
|
|
Title: "test",
|
|
Path: "/media/test2.strm",
|
|
Container: "strm",
|
|
Height: 1080,
|
|
STRMURL: "/api/strm/play/cloud115/video.mkv?acct=" + account.ID + "&pickcode=pc2",
|
|
}
|
|
if err := db.Create(media).Error; err != nil {
|
|
t.Fatalf("create media: %v", err)
|
|
}
|
|
svc := NewCloud115PlaybackService(nil, zap.NewNop(), repos, strm)
|
|
if _, _, err := svc.ResolveCloud115URL(ctx, media.ID, 4); !errors.Is(err, ErrCloud115TranscodePending) {
|
|
t.Fatalf("resolve pending err = %v, want ErrCloud115TranscodePending", err)
|
|
}
|
|
}
|
|
|
|
func TestMediaPlaybackProvider(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
raw string
|
|
want string
|
|
}{
|
|
{"115", "/api/strm/play/cloud115/video.mkv?acct=1&pickcode=pc", model.StrmProvider115},
|
|
{"openlist", "/api/strm/play/openlist/video.mkv?acct=1&ref=/a.mkv", model.StrmProviderOpenList},
|
|
{"local", "/media/local.mkv", model.StrmProviderLocal},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
media := &model.Media{Path: tc.raw}
|
|
if tc.name != "local" {
|
|
media.STRMURL = tc.raw
|
|
}
|
|
got := MediaPlaybackProvider(media)
|
|
if got != tc.want {
|
|
t.Fatalf("provider = %q, want %q", got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|