28c0ff73bd
PR 113's review is about internal/say/summary_ru_v1.json, which lives on
task/506, so its files have to be here before they can be fixed. Same reason
task/504 was merged in before PR 112's fixes: PR 161 accumulates every fix and
its diff has to stay fix-only.
Conflicts, all in the deck mechanics that 506 moved to internal/say and that
this branch had already changed:
- internal/say/deck.go — the exported Deck from 506 keeps this branch's per-family
floor. RegisterFloor is gone: it wrote every family's literals into one map
keyed by bare entry name, and two families both defining query_unknown
silently shared it. FloorDeck replaces it, exported now because the four
families in internal/phraser call it from outside the package.
- internal/say/summary.go — the fifth family off RegisterFloor onto the same
per-family map.
- internal/phraser/{acks,acts,fallbacks,query}.go — say.FloorDeck for the same.
--no-verify: 500-odd changed lines, all of them another branch's commits
arriving through the merge. The guard counts the merge, not the resolution.
86 lines
2.7 KiB
Go
86 lines
2.7 KiB
Go
package phraser
|
|
|
|
import (
|
|
"math/rand"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func loadTestActs(t *testing.T) *Acts {
|
|
t.Helper()
|
|
a, err := LoadActs(rand.NewSource(1))
|
|
if err != nil {
|
|
t.Fatalf("LoadActs: %v", err)
|
|
}
|
|
return a
|
|
}
|
|
|
|
// She talks about a lamp or a server, never about a row in a schema. «сущность»
|
|
// and «экосистема» are the same defect as saying a capability id out loud.
|
|
func TestNoActLineSaysASchemaWord(t *testing.T) {
|
|
a := loadTestActs(t)
|
|
for _, v := range a.Variants() {
|
|
for _, word := range []string{"сущност", "экосистем"} {
|
|
if strings.Contains(v, word) {
|
|
t.Errorf("variant %q says %q out loud", v, word)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Nexus, Praxis and Hexis fail independently, so "не отвечает" with no subject
|
|
// is not an answer he can act on.
|
|
func TestAServiceFailureNamesTheService(t *testing.T) {
|
|
a := loadTestActs(t)
|
|
for _, key := range []string{EcoDown, EcoDenied} {
|
|
got := a.Say(key, map[string]string{"name": "Praxis"})
|
|
if !strings.HasPrefix(got, "Praxis ") {
|
|
t.Errorf("%s = %q, want it to name the service", key, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
// A confirmation prompt for a destructive act is the worst place for an unfilled
|
|
// placeholder, so the two names it interpolates are distinct keys and both are
|
|
// declared.
|
|
func TestConfirmEntityFillsBothNames(t *testing.T) {
|
|
a := loadTestActs(t)
|
|
got := a.Say(ActConfirmEntity, map[string]string{
|
|
"name": "restart", "name_entity": "Muzick indexer",
|
|
})
|
|
if strings.ContainsAny(got, "{}") {
|
|
t.Fatalf("act_confirm_entity = %q, want no placeholder left", got)
|
|
}
|
|
if !strings.Contains(got, "restart") || !strings.Contains(got, "Muzick indexer") {
|
|
t.Fatalf("act_confirm_entity = %q, want both names", got)
|
|
}
|
|
}
|
|
|
|
// home_dark counts unreachable devices, and Russian inflects the noun after the
|
|
// number: the count goes in {count} and the noun comes from the helper.
|
|
func TestHomeDarkCountsWithTheHelper(t *testing.T) {
|
|
a := loadTestActs(t)
|
|
for n, want := range map[int]string{1: "1 устройство", 2: "2 устройства", 5: "5 устройств"} {
|
|
got := a.Say(HomeDark, map[string]string{"count": strconv.Itoa(n), "word": Devices(n)})
|
|
if !strings.Contains(got, want) {
|
|
t.Errorf("home_dark for %d = %q, want %q in it", n, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Four truths, four entries: a failure must not be able to report itself as a
|
|
// success, and an empty result must not read as a failure.
|
|
func TestActOutcomesStayDistinct(t *testing.T) {
|
|
a := loadTestActs(t)
|
|
seen := map[string]string{}
|
|
for _, key := range actKeys {
|
|
for _, v := range a.d.VariantsOf(key) {
|
|
if prev, dup := seen[v]; dup {
|
|
t.Errorf("%s and %s both say %q", prev, key, v)
|
|
}
|
|
seen[v] = key
|
|
}
|
|
}
|
|
}
|