127 lines
4.0 KiB
Go
127 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.ipao.vip/rogee/go-sip/internal/ai"
|
|
"git.ipao.vip/rogee/go-sip/internal/configread"
|
|
"git.ipao.vip/rogee/go-sip/internal/contract"
|
|
)
|
|
|
|
func TestSaaSMockServesApprovedHangupGroupsOverHTTP(t *testing.T) {
|
|
data, err := loadDataset(testDataDir(t), testDispatcher)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
server := httptest.NewTLSServer(data.handler("test-only-secret"))
|
|
defer server.Close()
|
|
client, err := configread.NewClient(server.URL, testDispatcher, "test-only-secret", server.Client())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx := context.Background()
|
|
sip, err := client.ReadSIP(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
providers, err := client.ReadProviders(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
snapshot, err := client.ReadTask(ctx, "task-full", 1001, sip, providers)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
bound, err := ai.Bind(snapshot.Task, snapshot.Providers)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(bound.HangupKeywords) != 1 || bound.HangupKeywords[0].Name != "结束通话" || len(bound.HangupKeywords[0].Triggers) != 1 || bound.HangupKeywords[0].Triggers[0] != "不用了" || bound.HangupKeywords[0].ClosingRemark != "好的,祝您生活愉快。" {
|
|
t.Fatalf("HTTP task snapshot lost the approved hangup group: %+v", bound.HangupKeywords)
|
|
}
|
|
}
|
|
|
|
// Both unit and live-broker checks use this to enforce the HTTP/MQ boundary.
|
|
func verifyExecutePayload(body []byte, taskID, callee string) error {
|
|
var message struct {
|
|
Payload map[string]any `json:"payload"`
|
|
}
|
|
if err := json.Unmarshal(body, &message); err != nil {
|
|
return err
|
|
}
|
|
if len(message.Payload) != 2 || message.Payload["task_id"] != taskID || message.Payload["callee"] != callee {
|
|
return errors.New("Mock MQ command must contain only task_id and the original callee")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestSaaSMockMQRejectsInlineHangupConfiguration(t *testing.T) {
|
|
data, err := loadDataset(testDataDir(t), testDispatcher)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, body, err := buildExecute(data, "event-config-boundary", "task-full", "13900000000", time.Date(2026, 10, 4, 2, 0, 0, 0, time.UTC))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := verifyExecutePayload(body, "task-full", "13900000000"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, field := range []string{"agent", "hangup_keywords", "closingRemark"} {
|
|
t.Run(field, func(t *testing.T) {
|
|
var message map[string]any
|
|
if err := json.Unmarshal(body, &message); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
message["payload"].(map[string]any)[field] = map[string]any{"name": "挂机1", "triggers": []string{"再见"}, "closingRemark": "好的,再见。"}
|
|
bad, err := json.Marshal(message)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := contract.ValidateCurrent("mq", bad); err == nil {
|
|
t.Fatal("MQ accepted inline configuration instead of the task snapshot")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSaaSMockRejectsLegacyAndIncompleteHangupSnapshots(t *testing.T) {
|
|
for name, groups := range map[string]any{
|
|
"legacy-strings": []string{"不用了"},
|
|
"missing-closing": []any{map[string]any{"name": "挂机1", "triggers": []string{"不用了"}}},
|
|
"empty-triggers": []any{map[string]any{"name": "挂机1", "triggers": []string{}, "closingRemark": "好的,再见。"}},
|
|
"blank-closing": []any{map[string]any{"name": "挂机1", "triggers": []string{"不用了"}, "closingRemark": " "}},
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
root := testDataDir(t)
|
|
path := filepath.Join(root, "tasks", "task-full.json")
|
|
body, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var task map[string]any
|
|
if err := json.Unmarshal(body, &task); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
task["agent"].(map[string]any)["conversation"].(map[string]any)["hangup_keywords"] = groups
|
|
body, err = json.Marshal(task)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(path, body, 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := loadDataset(root, testDispatcher); err == nil {
|
|
t.Fatal("removed or incomplete hangup structure was accepted")
|
|
}
|
|
})
|
|
}
|
|
}
|