Files
Maven/internal/phraser/query_lines_test.go
claude 28c0ff73bd Merge task/506 into the review-fix branch (V-521)
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.
2026-08-04 16:22:26 +04:00

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)
}
}
}