package callflow import ( "bytes" "context" "errors" "os" "testing" "git.ipao.vip/rogee/go-sip/internal/media" ) func TestRecordingSessionCapturesReadAndSentMediaInMemory(t *testing.T) { inbound := bytes.Repeat([]byte{1, 0}, 320) outbound := bytes.Repeat([]byte{2, 0}, 320) root := t.TempDir() source := NewMemorySession(inbound) recording, err := NewRecordingSession(source, 44+int64(len(inbound)+len(outbound))) if err != nil { t.Fatal(err) } if err := recording.SendPCM16(context.Background(), outbound, 16000); err != nil { t.Fatal(err) } got, err := recording.ReadPayload(context.Background()) if err != nil || !bytes.Equal(got, inbound) { t.Fatalf("recording intercepted or changed the live inbound audio: err=%v", err) } wav, durationMS, err := recording.WAV() if err != nil || durationMS != 40 || !bytes.Equal(wav[44:], append(bytes.Clone(outbound), inbound...)) { t.Fatalf("recording did not preserve media in callflow order: duration=%d err=%v", durationMS, err) } if stats := recording.Stats(); stats.ReceivedPackets != 1 || stats.SentPackets != 1 { t.Fatalf("recording changed live RTP accounting: %+v", stats) } entries, err := os.ReadDir(root) if err != nil || len(entries) != 0 { t.Fatalf("normal in-memory recording created business files: entries=%d err=%v", len(entries), err) } } func TestRecordingSessionReportsNoAudioAndCaptureFailuresWithoutInventingWAV(t *testing.T) { if _, err := NewRecordingSession(nil, 1024); err == nil { t.Fatal("missing media session admitted") } if _, err := NewRecordingSession(NewMemorySession(nil), 44); err == nil { t.Fatal("no room for even one audio sample admitted") } empty, err := NewRecordingSession(NewMemorySession(nil), 1024) if err != nil { t.Fatal(err) } if _, _, err := empty.WAV(); !errors.Is(err, media.ErrWAVEmpty) { t.Fatalf("no call audio became a recording: %v", err) } tooLarge, err := NewRecordingSession(NewMemorySession([]byte{3, 0, 4, 0}), 48) if err != nil { t.Fatal(err) } if err := tooLarge.SendPCM16(context.Background(), []byte{1, 0, 2, 0}, 16000); err != nil { t.Fatal(err) } if frame, err := tooLarge.ReadPayload(context.Background()); err != nil || len(frame) != 4 { t.Fatalf("recording size failure blocked the live call: frame=%v err=%v", frame, err) } if _, _, err := tooLarge.WAV(); !errors.Is(err, media.ErrWAVTooLarge) { t.Fatalf("over-limit call audio became an uploadable WAV: %v", err) } odd, err := NewRecordingSession(NewMemorySession([]byte{1, 2, 3}), 1024) if err != nil { t.Fatal(err) } if frame, err := odd.ReadPayload(context.Background()); err != nil || len(frame) != 3 { t.Fatalf("invalid recorded PCM blocked the original media stream: frame=%v err=%v", frame, err) } if _, _, err := odd.WAV(); !errors.Is(err, media.ErrWAVInvalidPCM) { t.Fatalf("odd PCM16 was reported as a valid recording: %v", err) } } func TestRecordingSessionDoesNotRecordUnsentAudio(t *testing.T) { recording, err := NewRecordingSession(NewMemorySession(nil), 1024) if err != nil { t.Fatal(err) } ctx, cancel := context.WithCancel(context.Background()) cancel() if err := recording.SendPCM16(ctx, []byte{1, 0}, 16000); !errors.Is(err, context.Canceled) { t.Fatalf("canceled media send unexpectedly succeeded: %v", err) } if _, _, err := recording.WAV(); !errors.Is(err, media.ErrWAVEmpty) { t.Fatalf("unsent audio appeared in recording: %v", err) } }