feat: expand companion platform, device controls, and memoir workflows
ci / verify (push) Canceled after 0s
ci / verify (push) Canceled after 0s
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user