101 lines
4.4 KiB
Go
101 lines
4.4 KiB
Go
package rpc
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
agentpb "git.ipao.vip/rogee/go-sip/gen/agent"
|
|
"git.ipao.vip/rogee/go-sip/internal/calllog"
|
|
"git.ipao.vip/rogee/go-sip/internal/contract"
|
|
"git.ipao.vip/rogee/go-sip/internal/testfixture"
|
|
)
|
|
|
|
func TestServerWritesPhoneCorrelatedCallBusinessLog(t *testing.T) {
|
|
now := time.Date(2026, 9, 18, 1, 0, 0, 0, time.UTC)
|
|
logger, err := calllog.New(filepath.Join(t.TempDir(), "business", "calls.jsonl"), []byte("0123456789abcdef"), func() time.Time { return now })
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
server := NewServer(ServerOptions{Now: func() time.Time { return now }, CallLogger: logger})
|
|
meta := testMeta("activate-log", "", 0)
|
|
if _, err := server.ActivateAgent(context.Background(), &agentpb.ActivateAgentRequest{
|
|
Meta: meta,
|
|
Binding: &agentpb.AgentBinding{AgentId: "agent-1", CellId: "cell-1", ExpectedBootId: "boot-1", DispatcherEpoch: "epoch-1", SessionGeneration: 1},
|
|
ActivationOperationId: "activate-log",
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
raw, err := testfixture.Execute()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
envelope, payload, err := contract.DecodeExecute(raw)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
binding := &agentpb.ExecutionBinding{
|
|
TenantId: envelope.TenantID, TenantKey: envelope.TenantKey, ExecutionId: payload.ExecutionID,
|
|
TaskId: payload.TaskID, TaskItemId: payload.TaskItemID, TaskRevision: payload.TaskRevision,
|
|
AgentVersionId: payload.AgentVersionID, RoutePolicyId: payload.RoutePolicyID, CallerProfileId: payload.CallerProfileID,
|
|
}
|
|
if _, err := server.Execute(context.Background(), &agentpb.ExecuteRequest{
|
|
Meta: testMeta("execute-log", "execute-log-key", 1), Binding: binding, CallExecuteJson: raw,
|
|
ConfigSha256: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
statusPayload := []byte(`{"call_id":"call-1","execution_id":"execution-1","call_state":"answered","attempt_id":"attempt-1","attempt_state":"active","route_policy_id":"route-sip-first","caller_profile_id":"caller-sip-first","trunk_id":"provider-primary","cell_id":"cell-1","sip_stage":"invite","sip_status_code":183}`)
|
|
if _, err := server.ReportExecutionEvent(context.Background(), &agentpb.ReportExecutionEventRequest{
|
|
Meta: testMeta("fact-status", "fact-status-key", 1), Fact: &agentpb.ExecutionFact{
|
|
FactId: "fact-status", ContentSha256: "digest-status", Binding: binding,
|
|
Kind: agentpb.FactKind_FACT_KIND_CALL_STATUS, PayloadJson: statusPayload,
|
|
},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
finishedPayload := []byte(`{"call_id":"call-1","execution_id":"execution-1","outcome":"no_answer","duration_ms":3000,"reason_code":"provider_480","asset_state":"failed","attempt_summary":[{"attempt_id":"attempt-1","state":"ended","trunk_id":"provider-primary","cell_id":"cell-1","reason_code":"provider_480"}],"recording_id":"recording-1","recording_state":"failed"}`)
|
|
if _, err := server.ReportExecutionEvent(context.Background(), &agentpb.ReportExecutionEventRequest{
|
|
Meta: testMeta("fact-finished", "fact-finished-key", 1), Fact: &agentpb.ExecutionFact{
|
|
FactId: "fact-finished", ContentSha256: "digest-finished", Binding: binding,
|
|
Kind: agentpb.FactKind_FACT_KIND_CALL_FINISHED, PayloadJson: finishedPayload,
|
|
},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
data, err := os.ReadFile(logger.Path())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
text := string(data)
|
|
if strings.Contains(text, payload.Callee) {
|
|
t.Fatalf("business log contains original phone: %s", text)
|
|
}
|
|
lines := strings.Split(strings.TrimSpace(text), "\n")
|
|
if len(lines) != 4 {
|
|
t.Fatalf("got %d business log lines, want prepared/status/finished/attempt: %s", len(lines), text)
|
|
}
|
|
var records []map[string]any
|
|
for _, line := range lines {
|
|
var record map[string]any
|
|
if err := json.Unmarshal([]byte(line), &record); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
records = append(records, record)
|
|
}
|
|
if records[0]["event_type"] != "execution.prepared" || records[1]["sip_status_code"] != float64(183) {
|
|
t.Fatalf("prepared or SIP status record missing: %#v", records)
|
|
}
|
|
if records[2]["recording_id"] != "recording-1" || records[2]["result"] != "no_answer" || records[3]["trunk_id"] != "provider-primary" {
|
|
t.Fatalf("finished or attempt record missing: %#v", records)
|
|
}
|
|
if records[0]["phone_ref"] != records[1]["phone_ref"] || records[1]["phone_ref"] != records[2]["phone_ref"] {
|
|
t.Fatalf("phone correlation changed across events: %#v", records)
|
|
}
|
|
}
|