86 lines
3.0 KiB
Go
86 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.ipao.vip/rogee/go-sip/internal/ai"
|
|
)
|
|
|
|
func writeApprovedMockScenario(t *testing.T, fields map[string]any) string {
|
|
t.Helper()
|
|
path := filepath.Join(t.TempDir(), "scenario.json")
|
|
data, err := json.Marshal(fields)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(path, data, 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return path
|
|
}
|
|
|
|
func validApprovedMockScenario() map[string]any {
|
|
return map[string]any{
|
|
"inbound_pcm16": bytes.Repeat([]byte{1, 0}, 1600),
|
|
"script": ai.ApprovedMockScript{Turns: []ai.ApprovedMockTurn{{Transcript: "synthetic final ASR fixture"}}},
|
|
"max_wav_bytes": int64(4096),
|
|
"expected_recording": true,
|
|
"outcome": "answered",
|
|
"reason_message": "isolated Mock answered",
|
|
}
|
|
}
|
|
|
|
func TestLoadApprovedMockScenarioPreservesExplicitSyntheticMedia(t *testing.T) {
|
|
path := writeApprovedMockScenario(t, validApprovedMockScenario())
|
|
scenario, err := loadApprovedMockScenario(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(scenario.InboundPCM16, bytes.Repeat([]byte{1, 0}, 1600)) ||
|
|
len(scenario.Script.Turns) != 1 || scenario.Script.Turns[0].Transcript != "synthetic final ASR fixture" ||
|
|
scenario.MaxWAVBytes != 4096 || !scenario.ExpectedRecording || scenario.Outcome != "answered" || scenario.ReasonMessage != "isolated Mock answered" {
|
|
t.Fatal("explicit isolated Mock facts were changed or silently defaulted")
|
|
}
|
|
}
|
|
|
|
func TestLoadApprovedMockScenarioRequiresExplicitFieldsAndRejectsUnknown(t *testing.T) {
|
|
if _, err := loadApprovedMockScenario(""); err == nil {
|
|
t.Fatal("missing Mock scenario was defaulted")
|
|
}
|
|
for _, key := range []string{"inbound_pcm16", "script", "max_wav_bytes", "expected_recording", "outcome", "reason_message"} {
|
|
t.Run(key, func(t *testing.T) {
|
|
fields := validApprovedMockScenario()
|
|
delete(fields, key)
|
|
if _, err := loadApprovedMockScenario(writeApprovedMockScenario(t, fields)); err == nil {
|
|
t.Fatalf("missing %s was silently defaulted", key)
|
|
}
|
|
})
|
|
}
|
|
fields := validApprovedMockScenario()
|
|
fields["legacy_schema_version"] = "v3"
|
|
if _, err := loadApprovedMockScenario(writeApprovedMockScenario(t, fields)); err == nil || strings.Contains(err.Error(), "synthetic final ASR fixture") {
|
|
t.Fatalf("unknown implementation version was accepted or scenario content leaked: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestLoadApprovedMockScenarioRejectsMalformedAndUnboundedInput(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "scenario.json")
|
|
for _, data := range [][]byte{
|
|
[]byte(`{"inbound_pcm16":"%%%","script":{"Turns":[{"Transcript":"synthetic"}]},"max_wav_bytes":4096,"expected_recording":true,"outcome":"answered","reason_message":"isolated"}`),
|
|
[]byte(`{} {}`),
|
|
bytes.Repeat([]byte("x"), 4<<20+1),
|
|
} {
|
|
if err := os.WriteFile(path, data, 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := loadApprovedMockScenario(path); err == nil {
|
|
t.Fatal("malformed or oversized Mock scenario was accepted")
|
|
}
|
|
}
|
|
}
|