diff --git a/internal/adapter/mxl/video_integration_test.go b/internal/adapter/mxl/video_integration_test.go new file mode 100644 index 0000000..c0c638d --- /dev/null +++ b/internal/adapter/mxl/video_integration_test.go @@ -0,0 +1,95 @@ +package mxladapter + +import ( + "context" + "errors" + "os" + "testing" + "time" + + "mxl-player/internal/playback" +) + +type cancelingVideoSink struct { + cancel context.CancelFunc + width uint32 + height uint32 + payloadSize int + got bool +} + +func (s *cancelingVideoSink) ConsumeVideo( + _ context.Context, + frame playback.VideoFrame, +) error { + s.width = frame.Width + s.height = frame.Height + s.payloadSize = len(frame.Payload) + s.got = true + s.cancel() + return nil +} + +func TestVideoWorkerIntegration(t *testing.T) { + domain := os.Getenv("MXL_TEST_VIDEO_DOMAIN") + uuid := os.Getenv("MXL_TEST_VIDEO_UUID") + if domain == "" || uuid == "" { + t.Skip("set MXL_TEST_VIDEO_DOMAIN and MXL_TEST_VIDEO_UUID") + } + + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + sink := &cancelingVideoSink{cancel: cancel} + var statuses []playback.Status + + worker, err := playback.NewVideoWorker( + VideoFactory{}, + sink, + playback.RetryPolicy{ + MaxAttempts: 1, + InitialDelay: 100 * time.Millisecond, + MaxDelay: time.Second, + }, + ShouldRetry, + func(status playback.Status) { + statuses = append(statuses, status) + }, + ) + if err != nil { + t.Fatalf("NewVideoWorker() error = %v", err) + } + + err = worker.Run(ctx, playback.FeedConfig{ + Domain: domain, + UUID: uuid, + Active: true, + }) + if !errors.Is(err, context.Canceled) { + t.Fatalf("Run() error = %v, want context.Canceled", err) + } + if !sink.got { + t.Fatal("worker did not deliver a video frame") + } + if sink.width == 0 || sink.height == 0 { + t.Fatalf( + "invalid frame dimensions: %dx%d", + sink.width, + sink.height, + ) + } + if sink.payloadSize == 0 { + t.Fatal("video frame payload is empty") + } + + foundPlaying := false + for _, status := range statuses { + if status.State == playback.StatePlaying { + foundPlaying = true + break + } + } + if !foundPlaying { + t.Fatalf("statuses contain no Playing transition: %+v", statuses) + } +}