98 lines
4.0 KiB
Go
98 lines
4.0 KiB
Go
package callmemory
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"data-terminal-cloud/internal/volcsubtitle"
|
||
|
|
"github.com/google/uuid"
|
||
|
|
"sync"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestSpokenVolumePhrases(t *testing.T) {
|
||
|
|
for _, text := range []string{"调大音量", "把音量调大", "声音放大一点"} {
|
||
|
|
if spokenVolumeAction(text) != "up" {
|
||
|
|
t.Errorf("not recognized: %s", text)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for text, want := range map[string]string{
|
||
|
|
"大点儿声": "up", "大点声": "up", "请你声音大一点": "up", "能不能大点儿声?": "up", "帮我把音量调高一点": "up", "声音太小了": "up", "声音有点低": "up",
|
||
|
|
"小点儿声": "down", "把声音调小一点好吗": "down", "声音太大了": "down", "音量低一点": "down",
|
||
|
|
"不要大点儿声": "", "不用调大音量": "", "他说大点儿声": "", "如果我说大点声会怎样": "", "大点声,小点声": "", "大一点": "", "我年轻时声音太大了": "", "“大点儿声”": "", "声音大一点也没用": "",
|
||
|
|
} {
|
||
|
|
if got := spokenVolumeAction(text); got != want {
|
||
|
|
t.Errorf("%q: got %q want %q", text, got, want)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSpokenVolumeCallbackSafety(t *testing.T) {
|
||
|
|
f, d := directFixture(t)
|
||
|
|
ctx := context.Background()
|
||
|
|
sid := uuid.NewString()
|
||
|
|
if _, err := f.s.DirectRequest(ctx, d, "start", DirectInput{SessionID: sid, BootID: f.boot}); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
f.exec(t, `INSERT INTO device_twin(device_id,tenant_id,desired_revision,desired_config) VALUES($1,$2,1,'{"volume":{"speaker":22},"identity":{"display_name":"保留名称"}}') ON CONFLICT(device_id) DO UPDATE SET desired_config=EXCLUDED.desired_config,desired_revision=1`, f.device, f.tenant)
|
||
|
|
packet := func(round, seq int64, who, text string, final bool) volcsubtitle.Packet {
|
||
|
|
return volcsubtitle.Packet{Type: "subtitle", Data: []volcsubtitle.Segment{{UserID: who, RoundID: &round, Sequence: &seq, Text: text, Definite: final}}}
|
||
|
|
}
|
||
|
|
send := func(p volcsubtitle.Packet) {
|
||
|
|
t.Helper()
|
||
|
|
if err := f.s.DirectSubtitle(ctx, sid, p); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
check := func(want, rev int) {
|
||
|
|
t.Helper()
|
||
|
|
var got, r int
|
||
|
|
var name string
|
||
|
|
if err := f.p.QueryRow(ctx, `SELECT (desired_config->'volume'->>'speaker')::int,desired_revision,desired_config->'identity'->>'display_name' FROM device_twin WHERE device_id=$1`, f.device).Scan(&got, &r, &name); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if got != want || r != rev || name != "保留名称" {
|
||
|
|
t.Fatalf("got volume=%d revision=%d name=%s", got, r, name)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
send(packet(1, 1, "input", "大点声", false))
|
||
|
|
send(packet(2, 1, "output", "大点声", true))
|
||
|
|
send(packet(3, 1, "input", "不要大点声", true))
|
||
|
|
check(22, 1)
|
||
|
|
// Concurrent delivery retries and final fragments in the same round must not
|
||
|
|
// increment twice; the subtitle and action are in the same transaction.
|
||
|
|
p := packet(4, 1, "input", "大点儿声", true)
|
||
|
|
errs := make(chan error, 4)
|
||
|
|
var wg sync.WaitGroup
|
||
|
|
for i := 0; i < 4; i++ {
|
||
|
|
wg.Add(1)
|
||
|
|
go func() { defer wg.Done(); errs <- f.s.DirectSubtitle(ctx, sid, p) }()
|
||
|
|
}
|
||
|
|
wg.Wait()
|
||
|
|
close(errs)
|
||
|
|
for err := range errs {
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
send(packet(4, 2, "input", "声音大一点", true))
|
||
|
|
check(32, 2)
|
||
|
|
send(packet(5, 1, "input", "小点儿声", true))
|
||
|
|
check(22, 3)
|
||
|
|
f.exec(t, `UPDATE device_twin SET desired_config=jsonb_set(desired_config,'{volume,speaker}','95') WHERE device_id=$1`, f.device)
|
||
|
|
send(packet(6, 1, "input", "大点声", true))
|
||
|
|
check(100, 4)
|
||
|
|
send(packet(7, 1, "input", "大点声", true))
|
||
|
|
check(100, 4)
|
||
|
|
f.exec(t, `UPDATE device_twin SET desired_config=jsonb_set(desired_config,'{volume,speaker}','5') WHERE device_id=$1`, f.device)
|
||
|
|
send(packet(8, 1, "input", "小点声", true))
|
||
|
|
check(0, 5)
|
||
|
|
f.exec(t, `UPDATE call_session SET lease_expires_at=now()-interval '1 second' WHERE id=$1`, sid)
|
||
|
|
send(packet(9, 1, "input", "大点声", true))
|
||
|
|
check(0, 5)
|
||
|
|
f.exec(t, `UPDATE call_session SET lease_expires_at=now()+interval '45 seconds' WHERE id=$1`, sid)
|
||
|
|
if _, err := f.s.DirectRequest(ctx, d, "end", DirectInput{SessionID: sid, Reason: "hangup", SDKStopped: true}); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
send(packet(10, 1, "input", "大点声", true))
|
||
|
|
check(0, 5)
|
||
|
|
}
|