301 lines
8.1 KiB
Go
301 lines
8.1 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
"go.uber.org/zap"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
"veza-backend-api/internal/models"
|
|
)
|
|
|
|
func TestNewHLSStreamingService(t *testing.T) {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("Failed to open database: %v", err)
|
|
}
|
|
|
|
logger := zap.NewNop()
|
|
service := NewHLSStreamingService(db, "/tmp/hls", logger)
|
|
|
|
if service == nil {
|
|
t.Error("NewHLSStreamingService() returned nil")
|
|
}
|
|
if service.db == nil {
|
|
t.Error("NewHLSStreamingService() returned service with nil db")
|
|
}
|
|
if service.logger == nil {
|
|
t.Error("NewHLSStreamingService() returned service with nil logger")
|
|
}
|
|
}
|
|
|
|
func TestHLSStreamingService_parsePlaylistSegments(t *testing.T) {
|
|
service := NewHLSStreamingService(nil, "", zap.NewNop())
|
|
|
|
tests := []struct {
|
|
name string
|
|
playlist string
|
|
expected []string
|
|
}{
|
|
{
|
|
name: "valid playlist with segments",
|
|
playlist: `#EXTM3U
|
|
#EXT-X-VERSION:3
|
|
#EXTINF:10.0,
|
|
segment_000.ts
|
|
#EXTINF:10.0,
|
|
segment_001.ts
|
|
#EXTINF:10.0,
|
|
segment_002.ts
|
|
#EXT-X-ENDLIST`,
|
|
expected: []string{"segment_000.ts", "segment_001.ts", "segment_002.ts"},
|
|
},
|
|
{
|
|
name: "playlist with comments only",
|
|
playlist: `#EXTM3U
|
|
#EXT-X-VERSION:3
|
|
#EXT-X-ENDLIST`,
|
|
expected: []string{},
|
|
},
|
|
{
|
|
name: "empty playlist",
|
|
playlist: "",
|
|
expected: []string{},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
segments := service.parsePlaylistSegments(tt.playlist)
|
|
if len(segments) != len(tt.expected) {
|
|
t.Errorf("parsePlaylistSegments() returned %d segments, want %d", len(segments), len(tt.expected))
|
|
}
|
|
for i, seg := range segments {
|
|
if seg != tt.expected[i] {
|
|
t.Errorf("parsePlaylistSegments() segment[%d] = %s, want %s", i, seg, tt.expected[i])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestHLSStreamingService_GetStreamURLs(t *testing.T) {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("Failed to open database: %v", err)
|
|
}
|
|
|
|
if err := db.AutoMigrate(&models.HLSStream{}); err != nil {
|
|
t.Fatalf("Failed to migrate: %v", err)
|
|
}
|
|
|
|
service := NewHLSStreamingService(db, "/tmp/hls", zap.NewNop())
|
|
ctx := context.Background()
|
|
trackID := uuid.New()
|
|
|
|
// Create test stream
|
|
stream := &models.HLSStream{
|
|
TrackID: trackID,
|
|
Status: models.HLSStatusReady,
|
|
PlaylistURL: "/tmp/hls/track_123/master.m3u8",
|
|
Bitrates: models.BitrateList{128, 192, 320},
|
|
SegmentsCount: 10,
|
|
}
|
|
if err := db.Create(stream).Error; err != nil {
|
|
t.Fatalf("Failed to create test stream: %v", err)
|
|
}
|
|
|
|
urls, err := service.GetStreamURLs(ctx, trackID, "https://api.example.com")
|
|
if err != nil {
|
|
t.Fatalf("GetStreamURLs() error = %v", err)
|
|
}
|
|
|
|
if urls == nil {
|
|
t.Error("GetStreamURLs() returned nil urls")
|
|
}
|
|
|
|
// Check master playlist URL
|
|
if urls["master_playlist"] == "" {
|
|
t.Error("GetStreamURLs() missing master_playlist URL")
|
|
}
|
|
|
|
// Check quality URLs
|
|
expectedQualities := []int{128, 192, 320}
|
|
for _, bitrate := range expectedQualities {
|
|
key := fmt.Sprintf("quality_%d", bitrate)
|
|
if urls[key] == "" {
|
|
t.Errorf("GetStreamURLs() missing quality URL for %dk", bitrate)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHLSStreamingService_CheckStreamExists(t *testing.T) {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("Failed to open database: %v", err)
|
|
}
|
|
|
|
if err := db.AutoMigrate(&models.HLSStream{}); err != nil {
|
|
t.Fatalf("Failed to migrate: %v", err)
|
|
}
|
|
|
|
service := NewHLSStreamingService(db, "/tmp/hls", zap.NewNop())
|
|
ctx := context.Background()
|
|
trackID := uuid.New()
|
|
|
|
// Check non-existent stream
|
|
exists, err := service.CheckStreamExists(ctx, trackID)
|
|
if err != nil {
|
|
t.Fatalf("CheckStreamExists() error = %v", err)
|
|
}
|
|
if exists {
|
|
t.Error("CheckStreamExists() returned true for non-existent stream")
|
|
}
|
|
|
|
// Create stream
|
|
stream := &models.HLSStream{
|
|
TrackID: trackID,
|
|
Status: models.HLSStatusReady,
|
|
}
|
|
if err := db.Create(stream).Error; err != nil {
|
|
t.Fatalf("Failed to create test stream: %v", err)
|
|
}
|
|
|
|
// Check existing stream
|
|
exists, err = service.CheckStreamExists(ctx, trackID)
|
|
if err != nil {
|
|
t.Fatalf("CheckStreamExists() error = %v", err)
|
|
}
|
|
if !exists {
|
|
t.Error("CheckStreamExists() returned false for existing stream")
|
|
}
|
|
}
|
|
|
|
func TestHLSStreamingService_UpdateStreamStatus(t *testing.T) {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("Failed to open database: %v", err)
|
|
}
|
|
|
|
if err := db.AutoMigrate(&models.HLSStream{}); err != nil {
|
|
t.Fatalf("Failed to migrate: %v", err)
|
|
}
|
|
|
|
service := NewHLSStreamingService(db, "/tmp/hls", zap.NewNop())
|
|
ctx := context.Background()
|
|
trackID := uuid.New()
|
|
|
|
// Create stream
|
|
stream := &models.HLSStream{
|
|
TrackID: trackID,
|
|
Status: models.HLSStatusProcessing,
|
|
}
|
|
if err := db.Create(stream).Error; err != nil {
|
|
t.Fatalf("Failed to create test stream: %v", err)
|
|
}
|
|
|
|
// Update status
|
|
err = service.UpdateStreamStatus(ctx, trackID, models.HLSStatusReady)
|
|
if err != nil {
|
|
t.Fatalf("UpdateStreamStatus() error = %v", err)
|
|
}
|
|
|
|
// Verify status was updated
|
|
var updatedStream models.HLSStream
|
|
if err := db.Where("track_id = ?", trackID).First(&updatedStream).Error; err != nil {
|
|
t.Fatalf("Failed to query updated stream: %v", err)
|
|
}
|
|
|
|
if updatedStream.Status != models.HLSStatusReady {
|
|
t.Errorf("UpdateStreamStatus() status = %v, want %v", updatedStream.Status, models.HLSStatusReady)
|
|
}
|
|
}
|
|
|
|
func TestHLSStreamingService_GetStreamStatistics(t *testing.T) {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("Failed to open database: %v", err)
|
|
}
|
|
|
|
if err := db.AutoMigrate(&models.HLSStream{}); err != nil {
|
|
t.Fatalf("Failed to migrate: %v", err)
|
|
}
|
|
|
|
service := NewHLSStreamingService(db, "/tmp/hls", zap.NewNop())
|
|
ctx := context.Background()
|
|
|
|
// Create test streams with different statuses
|
|
streams := []*models.HLSStream{
|
|
{TrackID: uuid.New(), Status: models.HLSStatusReady},
|
|
{TrackID: uuid.New(), Status: models.HLSStatusReady},
|
|
{TrackID: uuid.New(), Status: models.HLSStatusProcessing},
|
|
{TrackID: uuid.New(), Status: models.HLSStatusFailed},
|
|
}
|
|
|
|
for _, stream := range streams {
|
|
if err := db.Create(stream).Error; err != nil {
|
|
t.Fatalf("Failed to create test stream: %v", err)
|
|
}
|
|
}
|
|
|
|
stats, err := service.GetStreamStatistics(ctx)
|
|
if err != nil {
|
|
t.Fatalf("GetStreamStatistics() error = %v", err)
|
|
}
|
|
|
|
if stats == nil {
|
|
t.Error("GetStreamStatistics() returned nil stats")
|
|
}
|
|
|
|
// Verify counts
|
|
if stats["total_streams"] != int64(4) {
|
|
t.Errorf("GetStreamStatistics() total_streams = %v, want 4", stats["total_streams"])
|
|
}
|
|
if stats["ready_streams"] != int64(2) {
|
|
t.Errorf("GetStreamStatistics() ready_streams = %v, want 2", stats["ready_streams"])
|
|
}
|
|
if stats["processing_streams"] != int64(1) {
|
|
t.Errorf("GetStreamStatistics() processing_streams = %v, want 1", stats["processing_streams"])
|
|
}
|
|
if stats["failed_streams"] != int64(1) {
|
|
t.Errorf("GetStreamStatistics() failed_streams = %v, want 1", stats["failed_streams"])
|
|
}
|
|
}
|
|
|
|
// Note: Full integration tests would require:
|
|
// 1. Real HLS stream files (master.m3u8, playlists, segments)
|
|
// 2. File system access for validation
|
|
// 3. Verification of stream health checks
|
|
//
|
|
// Example integration test structure:
|
|
// func TestHLSStreamingService_ValidateStream_Integration(t *testing.T) {
|
|
// // Setup test database and file system
|
|
// db := setupTestDB(t)
|
|
// outputDir := setupTestHLSFiles(t)
|
|
// defer cleanupTestFiles(t, outputDir)
|
|
//
|
|
// service := NewHLSStreamingService(db, outputDir, zap.NewNop())
|
|
//
|
|
// // Create test stream
|
|
// trackID := uuid.New()
|
|
// stream := createTestHLSStream(t, db, trackID, outputDir)
|
|
//
|
|
// ctx := context.Background()
|
|
// health, err := service.ValidateStream(ctx, trackID)
|
|
// if err != nil {
|
|
// t.Fatalf("ValidateStream() error = %v", err)
|
|
// }
|
|
//
|
|
// if !health.IsHealthy {
|
|
// t.Error("ValidateStream() stream should be healthy")
|
|
// }
|
|
// if !health.PlaylistExists {
|
|
// t.Error("ValidateStream() playlist should exist")
|
|
// }
|
|
// if !health.SegmentsValid {
|
|
// t.Error("ValidateStream() segments should be valid")
|
|
// }
|
|
// }
|