114 lines
4.6 KiB
Go
114 lines
4.6 KiB
Go
package elderagent
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"encoding/json"
|
||
|
|
"fmt"
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestProviderCreateAndRecover(t *testing.T) {
|
||
|
|
var created, updated int
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
if r.Method != "POST" || r.URL.Query().Get("Version") != "2025-08-01" || r.Header.Get("Authorization") == "" {
|
||
|
|
t.Error("incorrect signed API request")
|
||
|
|
}
|
||
|
|
var body map[string]any
|
||
|
|
json.NewDecoder(r.Body).Decode(&body)
|
||
|
|
switch r.URL.Query().Get("Action") {
|
||
|
|
case "AibotQuery":
|
||
|
|
if body["AccessType"] != "public" {
|
||
|
|
t.Error("name lookup requires public AccessType")
|
||
|
|
}
|
||
|
|
if created == 0 {
|
||
|
|
fmt.Fprint(w, `{"Result":{"Bots":[]}}`)
|
||
|
|
} else {
|
||
|
|
fmt.Fprint(w, `{"Result":{"Bots":[{"Id":"bot-elder","Name":"elder-1"}]}}`)
|
||
|
|
}
|
||
|
|
case "AibotCreate":
|
||
|
|
created++
|
||
|
|
if body["AccessType"] != "public" || body["Config"] == nil || body["Name"] != "elder-1" {
|
||
|
|
t.Error("missing creation fields")
|
||
|
|
}
|
||
|
|
fmt.Fprint(w, `{"Result":{"Id":"bot-elder"}}`)
|
||
|
|
case "AibotUpdate":
|
||
|
|
updated++
|
||
|
|
fmt.Fprint(w, `{"Result":{}}`)
|
||
|
|
default:
|
||
|
|
t.Error("unexpected action")
|
||
|
|
}
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
c := NewClient("test-ak", "test-sk", "", server.URL, "")
|
||
|
|
for n := 0; n < 2; n++ {
|
||
|
|
b, err := c.Ensure(context.Background(), "elder-1", map[string]any{"S2SConfig": map[string]any{}}, map[string]any{})
|
||
|
|
if err != nil || b.ID != "bot-elder" {
|
||
|
|
t.Fatal(b, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if created != 1 || updated != 1 {
|
||
|
|
t.Fatal(created, updated)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
func TestConfigurationIsPerElderAndKeepsS2SOnServer(t *testing.T) {
|
||
|
|
s := Service{Template: []byte(`{"templates":{"s2s_hybrid":{"Config":{"S2SConfig":{"Provider":"volcano","OutputMode":1,"ProviderParams":{"app":{"appid":"test-app","token":"test-token"},"dialog":{"system_role":"温暖陪伴","dialog_id":"shared"}}},"MemoryConfig":{"Enable":true}}}}}`), CallbackURL: "https://example.com/callback", CallbackSecret: []byte(strings.Repeat("k", 32))}
|
||
|
|
a, aa, err := s.Configuration("elder-1", "张奶奶")
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
b, ba, err := s.Configuration("elder-2", "李爷爷")
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
rawA, _ := json.Marshal(a)
|
||
|
|
rawB, _ := json.Marshal(b)
|
||
|
|
if !strings.Contains(string(rawA), "张奶奶") || strings.Contains(string(rawB), "张奶奶") || strings.Contains(string(rawA), "dialog_id") {
|
||
|
|
t.Fatal("elder config isolation failed")
|
||
|
|
}
|
||
|
|
if a["S2SConfig"].(map[string]any)["OutputMode"] != 0 || aa["ServerMessageURLForRTS"] == ba["ServerMessageURLForRTS"] {
|
||
|
|
t.Fatal("incorrect S2S/callback config")
|
||
|
|
}
|
||
|
|
if a["MemoryConfig"].(map[string]any)["Enable"] != false {
|
||
|
|
t.Fatal("inherited shared memory")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
func TestProviderErrorDoesNotExposeConfiguration(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
fmt.Fprint(w, `{"ResponseMetadata":{"Error":{"Code":"InvalidParameter","Message":"secret-token"}}}`)
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
_, err := NewClient("ak", "sk", "", server.URL, "").Ensure(context.Background(), "elder", nil, nil)
|
||
|
|
if err == nil || strings.Contains(err.Error(), "secret-token") {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestPersonaReadbackChecksManagedFieldsAndMasksErrors(t *testing.T) {
|
||
|
|
config := map[string]any{"S2SConfig": map[string]any{"ProviderParams": map[string]any{"app": map[string]any{"token": "SECRET_TOKEN"}, "dialog": map[string]any{"system_role": "新角色"}}}, "MemoryConfig": map[string]any{"Enable": false}}
|
||
|
|
agent := map[string]any{"WelcomeMessage": "开场", "ServerMessageURLForRTS": "https://example.com/callback", "ServerMessageSignatureForRTS": "signature"}
|
||
|
|
stale := false
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
if r.URL.Query().Get("Action") != "AibotQuery" {
|
||
|
|
t.Error("wrong verification action")
|
||
|
|
}
|
||
|
|
role := "新角色"
|
||
|
|
if stale {
|
||
|
|
role = "SECRET_STALE_ROLE"
|
||
|
|
}
|
||
|
|
actual := map[string]any{"S2SConfig": map[string]any{"ProviderParams": map[string]any{"dialog": map[string]any{"system_role": role}}}, "MemoryConfig": map[string]any{"Enable": false}}
|
||
|
|
json.NewEncoder(w).Encode(map[string]any{"Result": map[string]any{"Bots": []Bot{{ID: "bot", Config: actual, AgentConfig: agent}}}})
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
c := NewClient("ak", "sk", "", server.URL, "")
|
||
|
|
if err := c.VerifyConfiguration(context.Background(), "bot", config, agent); err != nil {
|
||
|
|
t.Fatal("masked credentials failed verification", err)
|
||
|
|
}
|
||
|
|
stale = true
|
||
|
|
if err := c.VerifyConfiguration(context.Background(), "bot", config, agent); err == nil || strings.Contains(err.Error(), "SECRET") {
|
||
|
|
t.Fatal("unverified or exposed provider config", err)
|
||
|
|
}
|
||
|
|
}
|