87 lines
2.9 KiB
Go
87 lines
2.9 KiB
Go
package callruntime
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"git.ipao.vip/rogee/go-sip/internal/callflow"
|
|
)
|
|
|
|
func TestConversationRecordingFactsMatchFiles(t *testing.T) {
|
|
directory := t.TempDir()
|
|
incoming := [][]byte{{1, 0, 2, 0}, make([]byte, 32000)}
|
|
outgoing := [][]byte{{4, 0}, {5, 0, 6, 0}}
|
|
in, out, err := persistConversationRecordings(directory, "channel/with:separators", callflow.Result{InboundTurns: incoming, OutboundTurns: outgoing})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(in) != 2 || len(out) != 2 {
|
|
t.Fatal("lost recording segments")
|
|
}
|
|
for side, facts := range [][]RecordingFact{in, out} {
|
|
expected := [][][]byte{incoming, outgoing}[side]
|
|
for index, fact := range facts {
|
|
if filepath.Dir(fact.Path) != directory {
|
|
t.Fatal("recording escaped directory")
|
|
}
|
|
raw, err := os.ReadFile(fact.Path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sum := sha256.Sum256(raw)
|
|
if fact.SHA256 != hex.EncodeToString(sum[:]) || fact.Bytes != len(raw) || fact.DurationMS != int64(len(expected[index]))*1000/32000 {
|
|
t.Fatal("recording fact does not match content")
|
|
}
|
|
if string(raw[:4]) != "RIFF" || string(raw[8:12]) != "WAVE" || string(raw[36:40]) != "data" {
|
|
t.Fatal("invalid WAV header")
|
|
}
|
|
if binary.LittleEndian.Uint32(raw[24:28]) != 16000 || binary.LittleEndian.Uint32(raw[40:44]) != uint32(len(expected[index])) || !bytes.Equal(raw[44:], expected[index]) {
|
|
t.Fatal("incorrect WAV format or payload")
|
|
}
|
|
info, err := os.Stat(fact.Path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if info.Mode().Perm() != 0600 {
|
|
t.Fatal("recording is not restricted")
|
|
}
|
|
}
|
|
}
|
|
if in[0].Segment != "inbound_turn_01" || out[0].Segment != "outbound_segment_00" {
|
|
t.Fatal("segment identities changed")
|
|
}
|
|
}
|
|
|
|
func TestRecordingFailuresAreExplicit(t *testing.T) {
|
|
directory := t.TempDir()
|
|
if err := writeWAV(filepath.Join(directory, "odd.wav"), []byte{1}, 16000); err == nil {
|
|
t.Fatal("odd PCM accepted")
|
|
}
|
|
blocker := filepath.Join(directory, "file")
|
|
if err := os.WriteFile(blocker, []byte("blocked"), 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, _, err := persistConversationRecordings(filepath.Join(blocker, "child"), "channel", callflow.Result{InboundTurns: [][]byte{{0, 0}}}); err == nil {
|
|
t.Fatal("directory creation error hidden")
|
|
}
|
|
for _, flow := range []callflow.Result{{InboundTurns: [][]byte{{1}}}, {OutboundTurns: [][]byte{{1}}}} {
|
|
if _, _, err := persistConversationRecordings(directory, "channel", flow); err == nil {
|
|
t.Fatal("invalid segment accepted")
|
|
}
|
|
}
|
|
for _, dir := range []string{"", directory} {
|
|
in, out, err := persistConversationRecordings(dir, "empty", callflow.Result{})
|
|
if err != nil || len(in) != 0 || len(out) != 0 {
|
|
t.Fatal("empty recording produced facts")
|
|
}
|
|
}
|
|
if _, _, err := fileDigestAndSize(filepath.Join(directory, "missing.wav")); err == nil {
|
|
t.Fatal("missing recording silently returned a checksum")
|
|
}
|
|
}
|