865623ef3e
The accessors are functions now, so the call sites that compared against one literal compare against the entry instead: IsUnknownFallback and IsSourcesFallback in the daemon tests, the entry key in the phraser tests. A reworded variant no longer breaks a Go test. The eval scores every variant on the persona checks the nudges already pass.
86 lines
3.0 KiB
Go
86 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/kami/maven/internal/phraser"
|
|
"github.com/kami/maven/internal/router"
|
|
)
|
|
|
|
// gapPhraser — a phraser whose world model is configured and asleep, which is
|
|
// the state the naming half exists for.
|
|
type gapPhraser struct {
|
|
*phraser.Stub
|
|
worldCalls int
|
|
}
|
|
|
|
func (g *gapPhraser) PhraseWorld(context.Context, string, []string) (string, error) {
|
|
g.worldCalls++
|
|
return "", phraser.ErrNoWorldModel
|
|
}
|
|
|
|
func worldTurn(utterance string) *queryTurn {
|
|
return &queryTurn{dec: router.Decision{Intent: router.IntentQuery, Utterance: utterance}}
|
|
}
|
|
|
|
// A world question with the workstation asleep says so. The resident model is
|
|
// not asked, because what it produces here is an invention with no signal that
|
|
// it is one.
|
|
func TestQueryGeneralNamesTheGap(t *testing.T) {
|
|
g := &gapPhraser{Stub: phraser.NewStub()}
|
|
h := &reactiveHandler{phraser: g}
|
|
reply, ok := h.queryGeneral(context.Background(), worldTurn("почему небо голубое"))
|
|
if !ok {
|
|
t.Fatal("queryGeneral passed on the last source in the chain")
|
|
}
|
|
if reply != worldGap() {
|
|
t.Fatalf("reply = %q, want the named gap", reply)
|
|
}
|
|
if g.worldCalls != 1 {
|
|
t.Fatalf("PhraseWorld called %d times, want 1", g.worldCalls)
|
|
}
|
|
}
|
|
|
|
// A phraser with no world seam at all — the Stub, and every box with no
|
|
// `workstation` block — answers exactly as it did before this seam existed.
|
|
func TestQueryGeneralWithoutAWorldModelIsUnchanged(t *testing.T) {
|
|
h := &reactiveHandler{phraser: phraser.NewStub()}
|
|
reply, ok := h.queryGeneral(context.Background(), worldTurn("почему небо голубое"))
|
|
if !ok {
|
|
t.Fatal("queryGeneral passed on the last source in the chain")
|
|
}
|
|
if !phraser.IsUnknownFallback(reply) {
|
|
t.Fatalf("reply = %q, want the Stub's answer", reply)
|
|
}
|
|
}
|
|
|
|
// The gap is spoken aloud by a Russian voice, so it is Russian, feminine and
|
|
// informal. "не хочу" and "не могу" are her own verbs; there is no "вы" and no
|
|
// English in it.
|
|
func TestWorldGapIsInPersona(t *testing.T) {
|
|
for _, bad := range []string{"вы", "ваш", "рад ", "дорогой", "милый"} {
|
|
if strings.Contains(worldGap(), bad) {
|
|
t.Errorf("the gap phrase contains %q: %s", bad, worldGap())
|
|
}
|
|
}
|
|
if strings.ContainsAny(worldGap(), "abcdefghijklmnopqrstuvwxyz") {
|
|
t.Errorf("the gap phrase has Latin letters in it: %s", worldGap())
|
|
}
|
|
}
|
|
|
|
// The sources that hold a passage read it back rather than name a gap. He gets a
|
|
// real quote instead of "не могу сейчас", and nothing is invented either way.
|
|
func TestASourceWithAPassageReadsItBackInsteadOfNamingTheGap(t *testing.T) {
|
|
g := &gapPhraser{Stub: phraser.NewStub()}
|
|
h := &reactiveHandler{phraser: g}
|
|
if got := h.phraseSource(context.Background(), "search", "почему небо голубое",
|
|
[]string{"Рэлеевское рассеяние."}); got != "" {
|
|
t.Fatalf("phraseSource = %q, want \"\" so the caller's own floor reads the passage back", got)
|
|
}
|
|
if g.worldCalls != 1 {
|
|
t.Fatalf("PhraseWorld called %d times, want 1", g.worldCalls)
|
|
}
|
|
}
|