123 lines
4.1 KiB
Go
123 lines
4.1 KiB
Go
package store
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.ipao.vip/rogee/go-sip/contracts"
|
|
"git.ipao.vip/rogee/go-sip/internal/contract"
|
|
"git.ipao.vip/rogee/go-sip/internal/tenant"
|
|
)
|
|
|
|
func TestCallQueryCollectsOnlyBoundRecordedFacts(t *testing.T) {
|
|
s, err := Open(":memory:")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer s.Close()
|
|
if err := s.BindDispatcherID(identityA); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
s.now = func() time.Time { return time.Date(2026, 9, 21, 0, 0, 1, 0, time.UTC) }
|
|
route, err := tenant.NewDispatcherRoute(identityA, "tenant-a")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, name := range []string{"call-status", "transcript-updated", "recording-uploaded"} {
|
|
raw, err := contracts.Files.ReadFile("upstream/v1/examples/event-" + name + ".json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var event map[string]any
|
|
if err := json.Unmarshal(raw, &event); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := s.DB().Exec(`INSERT INTO outbox(event_id,tenant_key,exchange,routing_key,body,status,created_at) VALUES(?,?,'agent-call.saas.v2',?,?,'pending',?)`, event["event_id"], "tenant-a", route.OutboundKey, raw, event["occurred_at"]); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
raw, err := contracts.Files.ReadFile("upstream/v1/examples/call-query.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
id, _, err := s.HandleQuery(raw, route.InboundKey)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var body []byte
|
|
if err := s.DB().QueryRow(`SELECT body FROM outbox WHERE event_id=?`, id).Scan(&body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
response, err := contract.DecodeService(body)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var snapshot struct {
|
|
CallID string `json:"call_id"`
|
|
State string `json:"call_state"`
|
|
Version int64 `json:"call_version"`
|
|
Attempts []json.RawMessage `json:"attempts"`
|
|
Transcript struct {
|
|
Events []json.RawMessage `json:"events"`
|
|
} `json:"transcript"`
|
|
Recordings []json.RawMessage `json:"recordings"`
|
|
Delivery map[string]int `json:"delivery"`
|
|
}
|
|
if err := json.Unmarshal(response.Payload, &snapshot); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if response.MessageType != "call.query.result" || response.Status != "ok" || snapshot.CallID != "call-a" || snapshot.State != "answered" || snapshot.Version != 1 || len(snapshot.Attempts) != 1 || len(snapshot.Transcript.Events) != 1 || len(snapshot.Recordings) != 1 || snapshot.Delivery["pending"] != 3 {
|
|
t.Fatalf("wrong snapshot: %+v", snapshot)
|
|
}
|
|
largeRaw, err := contracts.Files.ReadFile("upstream/v1/examples/event-transcript-updated.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var large map[string]any
|
|
if err := json.Unmarshal(largeRaw, &large); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
large["payload"].(map[string]any)["text"] = strings.Repeat("x", 150000)
|
|
for _, id := range []string{"large-1", "large-2"} {
|
|
large["event_id"] = id
|
|
largeRaw, err = json.Marshal(large)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := s.DB().Exec(`INSERT INTO outbox(event_id,tenant_key,exchange,routing_key,body,status,created_at) VALUES(?,'tenant-a','agent-call.saas.v2',?,?,'pending','2026-09-21T00:00:00Z')`, id, route.OutboundKey, largeRaw); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
var query map[string]any
|
|
if err := json.Unmarshal(raw, &query); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
query["message_id"] = "large-query"
|
|
raw, err = json.Marshal(query)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
id, _, err = s.HandleQuery(raw, route.InboundKey)
|
|
if err != nil {
|
|
t.Fatalf("oversize query must receive a bounded refusal, not endless requeue: %v", err)
|
|
}
|
|
if err := s.DB().QueryRow(`SELECT body FROM outbox WHERE event_id=?`, id).Scan(&body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
response, err = contract.DecodeService(body)
|
|
if err != nil || response.Status != "rejected" || response.ReasonCode != "unavailable" {
|
|
t.Fatalf("oversize response: %+v %v", response, err)
|
|
}
|
|
query["message_id"] = "delivery-only-query"
|
|
query["payload"].(map[string]any)["include"] = []string{"delivery"}
|
|
raw, err = json.Marshal(query)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, _, err := s.HandleQuery(raw, route.InboundKey); err == nil {
|
|
t.Fatal("unapproved include field accepted")
|
|
}
|
|
}
|