|
- package factory
-
- import (
- "context"
- "testing"
- "time"
-
- "github.com/jan/fm-rds-tx/internal/audio"
- "github.com/jan/fm-rds-tx/internal/config"
- "github.com/jan/fm-rds-tx/internal/ingest"
- )
-
- func TestHTTPRawFactoryToRuntimeSmoke(t *testing.T) {
- cfg := config.Default()
- cfg.Ingest.Kind = "http-raw"
- cfg.Ingest.HTTPRaw.SampleRateHz = 44100
- cfg.Ingest.HTTPRaw.Channels = 2
-
- src, ingress, err := BuildSource(cfg, Deps{})
- if err != nil {
- t.Fatalf("build source: %v", err)
- }
- if src == nil || ingress == nil {
- t.Fatalf("expected source and ingress for kind=http-raw")
- }
-
- sink := audio.NewStreamSource(128, cfg.Ingest.HTTPRaw.SampleRateHz)
- rt := ingest.NewRuntime(sink, src)
- if err := rt.Start(context.Background()); err != nil {
- t.Fatalf("runtime start: %v", err)
- }
- defer rt.Stop()
-
- // Two stereo frames: L1,R1,L2,R2 (S16LE).
- frames, err := ingress.WritePCM16([]byte{
- 0xE8, 0x03, 0x18, 0xFC,
- 0xD0, 0x07, 0x30, 0xF8,
- })
- if err != nil {
- t.Fatalf("write pcm16: %v", err)
- }
- if frames != 2 {
- t.Fatalf("frames=%d want 2", frames)
- }
-
- waitForSinkFrames(t, sink, 2)
-
- stats := rt.Stats()
- if stats.Active.Kind != "http-raw" {
- t.Fatalf("active kind=%q want http-raw", stats.Active.Kind)
- }
- if stats.Source.ChunksIn != 1 {
- t.Fatalf("source chunksIn=%d want 1", stats.Source.ChunksIn)
- }
- if stats.Source.SamplesIn != 4 {
- t.Fatalf("source samplesIn=%d want 4", stats.Source.SamplesIn)
- }
- if stats.Runtime.State != "running" {
- t.Fatalf("runtime state=%q want running", stats.Runtime.State)
- }
- if stats.Runtime.LastChunkAt.IsZero() {
- t.Fatalf("runtime lastChunkAt should be set")
- }
- }
-
- func waitForSinkFrames(t *testing.T, sink *audio.StreamSource, minFrames int) {
- t.Helper()
- deadline := time.Now().Add(1 * time.Second)
- for time.Now().Before(deadline) {
- if sink.Available() >= minFrames {
- return
- }
- time.Sleep(10 * time.Millisecond)
- }
- t.Fatalf("timeout waiting for sink frames: have=%d want>=%d", sink.Available(), minFrames)
- }
|