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") } } }