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) } }