84 lines
2.8 KiB
Go
84 lines
2.8 KiB
Go
package ai
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
func TestCurrentTTSRejectsExcessPendingAudioWithoutRetry(t *testing.T) {
|
|
task, providers := currentFixture(t, "full_ai")
|
|
task = changeCurrentAgent(t, task, func(agent map[string]any) {
|
|
agent["conversation"].(map[string]any)["max_pending_audio_chunks"] = 1
|
|
})
|
|
var requests atomic.Int32
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
requests.Add(1)
|
|
for _, pcm := range [][]byte{{1, 0}, {2, 0}} {
|
|
_, _ = fmt.Fprintf(w, `{"code":0,"data":%q}`+"\n", base64.StdEncoding.EncodeToString(pcm))
|
|
}
|
|
_, _ = fmt.Fprintln(w, `{"code":20000000,"message":"ok","data":null}`)
|
|
}))
|
|
defer server.Close()
|
|
p := providers["tts-example"]
|
|
p.Endpoint = server.URL
|
|
providers[p.ProviderRef] = p
|
|
bound, err := BindCurrent(task, providers)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := bound.Synthesize(context.Background(), "批准回复"); err == nil || !strings.Contains(err.Error(), "pending audio") || strings.Contains(err.Error(), p.Credential) {
|
|
t.Fatalf("explicit pending-audio bound was ignored or leaked credentials: %v", err)
|
|
}
|
|
if requests.Load() != 1 {
|
|
t.Fatalf("SDK must not automatically retry/bill twice: requests=%d", requests.Load())
|
|
}
|
|
}
|
|
|
|
func TestCurrentReplyChunksUnicodeByApprovedSentenceLimit(t *testing.T) {
|
|
task, providers := currentFixture(t, "full_ai")
|
|
task = changeCurrentAgent(t, task, func(agent map[string]any) {
|
|
conversation := agent["conversation"].(map[string]any)
|
|
conversation["sentence_max_chars"] = 3
|
|
conversation["max_pending_audio_chunks"] = 3
|
|
})
|
|
texts := make(chan string, 3)
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
var payload struct {
|
|
Params struct {
|
|
Text string `json:"text"`
|
|
} `json:"req_params"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
http.Error(w, "invalid SDK request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
texts <- payload.Params.Text
|
|
_, _ = fmt.Fprintf(w, `{"code":0,"data":%q}`+"\n", base64.StdEncoding.EncodeToString([]byte{1, 0}))
|
|
_, _ = fmt.Fprintln(w, `{"code":20000000,"message":"ok","data":null}`)
|
|
}))
|
|
defer server.Close()
|
|
p := providers["tts-example"]
|
|
p.Endpoint = server.URL
|
|
providers[p.ProviderRef] = p
|
|
bound, err := BindCurrent(task, providers)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
audio, err := bound.SynthesizeReply(context.Background(), "你好世界,再见")
|
|
if err != nil || len(audio) != 6 {
|
|
t.Fatalf("reply must synthesize all bounded chunks: len=%d err=%v", len(audio), err)
|
|
}
|
|
for _, want := range []string{"你好世", "界,再", "见"} {
|
|
if got := <-texts; got != want {
|
|
t.Fatalf("Unicode reply was lost/reordered while splitting: got=%q want=%q", got, want)
|
|
}
|
|
}
|
|
}
|