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.
108 lines
3.3 KiB
Go
108 lines
3.3 KiB
Go
package phraser
|
|
|
|
import (
|
|
"math/rand"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestQueriesLoad(t *testing.T) {
|
|
q, err := LoadQueries(rand.NewSource(1))
|
|
if err != nil {
|
|
t.Fatalf("LoadQueries: %v", err)
|
|
}
|
|
for _, k := range queryKeys {
|
|
if got := q.Say(k, nil); got == "" {
|
|
t.Errorf("%s says nothing", k)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The bug: net_empty carried {tail} in every variant, and a scan that finished
|
|
// the whole range has no caveat to put there. Whatever the file says, an answer
|
|
// he can hear has to come out — never braces, never nothing.
|
|
func TestNetEmptySaysSomethingWithNoTail(t *testing.T) {
|
|
q, err := LoadQueries(rand.NewSource(1))
|
|
if err != nil {
|
|
t.Fatalf("LoadQueries: %v", err)
|
|
}
|
|
for _, vars := range []map[string]string{nil, {"tail": ""}} {
|
|
for i := 0; i < 20; i++ {
|
|
got := q.Say(QueryNetEmpty, vars)
|
|
if got == "" || strings.ContainsAny(got, "{}") {
|
|
t.Fatalf("net_empty with vars %v said %q", vars, got)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// The other half: a caveat he was given is not dropped for a shorter wording.
|
|
func TestNetEmptyKeepsTheTailItIsGiven(t *testing.T) {
|
|
q, err := LoadQueries(rand.NewSource(1))
|
|
if err != nil {
|
|
t.Fatalf("LoadQueries: %v", err)
|
|
}
|
|
const tail = ", но успела посмотреть не всю сеть"
|
|
for i := 0; i < 20; i++ {
|
|
if got := q.Say(QueryNetEmpty, map[string]string{"tail": tail}); !strings.Contains(got, tail) {
|
|
t.Fatalf("net_empty dropped the tail: %q", got)
|
|
}
|
|
}
|
|
}
|
|
|
|
// query_unknown means she looked and found nothing. The phraser's fallback
|
|
// means she failed to phrase an answer she had. Two causes, two sentences, or
|
|
// the distinction the two files exist for is unobservable from the outside.
|
|
func TestQueryUnknownNeverRepeatsAPhrasingFallback(t *testing.T) {
|
|
q, err := LoadQueries(rand.NewSource(1))
|
|
if err != nil {
|
|
t.Fatalf("LoadQueries: %v", err)
|
|
}
|
|
f, err := LoadFallbacks(rand.NewSource(1))
|
|
if err != nil {
|
|
t.Fatalf("LoadFallbacks: %v", err)
|
|
}
|
|
failures := map[string]bool{}
|
|
for _, v := range f.Variants() {
|
|
failures[v] = true
|
|
}
|
|
for _, v := range q.d.VariantsOf(QueryUnknown) {
|
|
if failures[v] {
|
|
t.Errorf("query_unknown variant %q is also a phrasing failure line", v)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The weather line splits the count into a number and a noun, so a variant that
|
|
// says the temperature without {word} is the hardcoded "градусов" coming back.
|
|
func TestWeatherLineCountsWithTheHelper(t *testing.T) {
|
|
q, err := LoadQueries(rand.NewSource(1))
|
|
if err != nil {
|
|
t.Fatalf("LoadQueries: %v", err)
|
|
}
|
|
for _, v := range q.d.VariantsOf(QueryWeatherNow) {
|
|
if strings.Contains(v, "градус") {
|
|
t.Errorf("weather_now variant %q spells the noun out instead of using {word}", v)
|
|
}
|
|
}
|
|
got := q.Say(QueryWeatherNow, map[string]string{
|
|
"location": "Москва", "temp": "1", "word": Degrees(1), "condition": "ясно",
|
|
})
|
|
if !strings.Contains(got, "1 градус,") {
|
|
t.Errorf("weather_now said %q, want the singular noun", got)
|
|
}
|
|
}
|
|
|
|
// No line spoken to him names a config key. She asks instead.
|
|
func TestNoQueryLineRecitesAConfigPath(t *testing.T) {
|
|
q, err := LoadQueries(rand.NewSource(1))
|
|
if err != nil {
|
|
t.Fatalf("LoadQueries: %v", err)
|
|
}
|
|
for _, v := range q.Variants() {
|
|
if strings.Contains(v, "voice.") || strings.Contains(v, "_location") {
|
|
t.Errorf("variant %q says a config path out loud", v)
|
|
}
|
|
}
|
|
}
|