94 lines
4.0 KiB
Go
94 lines
4.0 KiB
Go
package ai
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gorilla/websocket"
|
|
)
|
|
|
|
type currentASRWireCapture struct {
|
|
path, key, resourceID string
|
|
frame []byte
|
|
err error
|
|
}
|
|
|
|
func TestASRParametersReachDoubaoSDKWebSocket(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
mode, resultType string
|
|
nonstream bool
|
|
}{
|
|
{"full_ai", "full", false},
|
|
{"asr_only", "single", true},
|
|
} {
|
|
t.Run(tc.mode, func(t *testing.T) {
|
|
captures := make(chan currentASRWireCapture, 1)
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
conn, err := (&websocket.Upgrader{}).Upgrade(w, r, nil)
|
|
if err != nil {
|
|
captures <- currentASRWireCapture{err: err}
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
_, frame, err := conn.ReadMessage()
|
|
captures <- currentASRWireCapture{path: r.URL.Path, key: r.Header.Get("X-Api-Key"), resourceID: r.Header.Get("X-Api-Resource-Id"), frame: frame, err: err}
|
|
}))
|
|
defer server.Close()
|
|
task, providers := currentFixture(t, tc.mode)
|
|
task = changeCurrentAgent(t, task, func(a map[string]any) {
|
|
a["asr"].(map[string]any)["params"] = map[string]any{"reqid": "ignored-params-reqid", "sequence": 99, "model_name": "ignored-params-model", "result_type": tc.resultType, "enable_nonstream": tc.nonstream, "unknown_flag": false, "nullable": nil, "opaque": "vendor-only", "large_number": json.Number("9007199254740993")}
|
|
})
|
|
asrProvider := providers["volcengine"]
|
|
asrProvider.WSEndpoint = "ws" + strings.TrimPrefix(server.URL, "http")
|
|
providers[asrProvider.Code] = asrProvider
|
|
bound, err := Bind(task, providers)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
defer cancel()
|
|
if _, err := bound.Recognize(ctx, []byte{1, 0}); err == nil {
|
|
t.Fatal("disconnected mock ASR cannot pretend recognition completed")
|
|
}
|
|
select {
|
|
case got := <-captures:
|
|
if got.err != nil || got.path != "/api/v3/sauc/bigmodel" || got.key != asrProvider.Credential || got.resourceID != "volc.seedasr.sauc.duration" {
|
|
t.Fatalf("SDK ASR WebSocket endpoint/credential was changed: path=%q err=%v", got.path, got.err)
|
|
}
|
|
// Inspect the SDK-emitted JSON payload. No provider protocol is
|
|
// implemented by the application or by this mock responder.
|
|
start := bytes.IndexByte(got.frame, '{')
|
|
if start < 0 {
|
|
t.Fatal("SDK sent no ASR start JSON frame")
|
|
}
|
|
if !bytes.Contains(got.frame[start:], []byte(`"large_number":9007199254740993`)) {
|
|
t.Fatal("large integer changed")
|
|
}
|
|
var payload map[string]any
|
|
if err := json.Unmarshal(got.frame[start:], &payload); err != nil {
|
|
t.Fatalf("SDK ASR start JSON cannot be decoded: %v", err)
|
|
}
|
|
audio := payload["audio"].(map[string]any)
|
|
request := payload["request"].(map[string]any)
|
|
if request["model_name"] != bound.ASR.Model || request["reqid"] == "ignored-params-reqid" || request["reqid"] == "" || request["sequence"] != float64(1) {
|
|
t.Fatal("params overrode the ASR task model or session identity")
|
|
}
|
|
if string(bound.ASR.Params["model_name"]) != `"ignored-params-model"` || string(bound.ASR.Params["reqid"]) != `"ignored-params-reqid"` || string(bound.ASR.Params["sequence"]) != "99" {
|
|
t.Fatal("ASR request construction changed the original params")
|
|
}
|
|
if len(audio) != 4 || len(request) != 9 || audio["format"] != "pcm_s16le" || audio["sample_rate"] != float64(16000) || audio["channel"] != float64(1) || audio["bits"] != float64(16) || request["result_type"] != tc.resultType || request["enable_nonstream"] != tc.nonstream || request["unknown_flag"] != false || request["nullable"] != nil || request["opaque"] != "vendor-only" {
|
|
t.Fatalf("SDK ASR request omitted approved input/interim fields: audio=%v request=%v", audio, request)
|
|
}
|
|
case <-ctx.Done():
|
|
t.Fatal("SDK did not send an ASR start request to isolated mock")
|
|
}
|
|
})
|
|
}
|
|
}
|