package output import ( "bytes" "errors" "testing" "mxl-player/internal/playback" ) func validAudioFrame() playback.AudioFrame { return playback.AudioFrame{ Index: 42, SampleCount: 2, Channels: 2, SampleRateNumerator: 48000, SampleRateDenominator: 1, Samples: [][]byte{ {1, 2, 3, 4, 5, 6, 7, 8}, {9, 10, 11, 12, 13, 14, 15, 16}, }, } } func TestInterleaveF32OrdersSamplesByFrameThenChannel(t *testing.T) { frame := validAudioFrame() want := []byte{ 1, 2, 3, 4, 9, 10, 11, 12, 5, 6, 7, 8, 13, 14, 15, 16, } got, err := InterleaveF32(frame) if err != nil { t.Fatalf("InterleaveF32() error = %v", err) } if !bytes.Equal(got, want) { t.Fatalf("InterleaveF32() = %v, want %v", got, want) } } func TestInterleaveF32IgnoresBytesAfterSampleCount(t *testing.T) { frame := validAudioFrame() frame.SampleCount = 1 got, err := InterleaveF32(frame) if err != nil { t.Fatalf("InterleaveF32() error = %v", err) } want := []byte{1, 2, 3, 4, 9, 10, 11, 12} if !bytes.Equal(got, want) { t.Fatalf("InterleaveF32() = %v, want %v", got, want) } } func TestInterleaveF32RejectsInvalidMetadata(t *testing.T) { tests := []struct { name string mutate func(*playback.AudioFrame) }{ {name: "zero samples", mutate: func(f *playback.AudioFrame) { f.SampleCount = 0 }}, {name: "zero channels", mutate: func(f *playback.AudioFrame) { f.Channels = 0 }}, {name: "zero rate numerator", mutate: func(f *playback.AudioFrame) { f.SampleRateNumerator = 0 }}, {name: "negative rate numerator", mutate: func(f *playback.AudioFrame) { f.SampleRateNumerator = -1 }}, {name: "zero rate denominator", mutate: func(f *playback.AudioFrame) { f.SampleRateDenominator = 0 }}, {name: "wrong channel count", mutate: func(f *playback.AudioFrame) { f.Channels = 3 }}, {name: "sample size overflow", mutate: func(f *playback.AudioFrame) { f.SampleCount = ^uint64(0) }}, { name: "allocation size overflow", mutate: func(f *playback.AudioFrame) { f.SampleCount = uint64(^uint(0)>>1) / 4 }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { frame := validAudioFrame() tt.mutate(&frame) result, err := InterleaveF32(frame) if result != nil { t.Fatalf("InterleaveF32() result = %v, want nil", result) } if !errors.Is(err, ErrInvalidAudioFrame) { t.Fatalf("InterleaveF32() error = %v, want %v", err, ErrInvalidAudioFrame) } }) } } func TestInterleaveF32RejectsShortChannel(t *testing.T) { frame := validAudioFrame() frame.Samples[1] = frame.Samples[1][:7] result, err := InterleaveF32(frame) if result != nil { t.Fatalf("InterleaveF32() result = %v, want nil", result) } if !errors.Is(err, ErrAudioPayloadTooSmall) { t.Fatalf("InterleaveF32() error = %v, want %v", err, ErrAudioPayloadTooSmall) } } func TestInterleaveF32ReturnsIndependentOutput(t *testing.T) { frame := validAudioFrame() result, err := InterleaveF32(frame) if err != nil { t.Fatalf("InterleaveF32() error = %v", err) } frame.Samples[0][0] = 99 if result[0] != 1 { t.Fatalf("output changed with borrowed input: first byte = %d, want 1", result[0]) } }