package main import ( "context" "strings" "testing" "github.com/kami/maven/internal/router" ) // TestSelfFloorClaimsAQuestionAboutHerAndNothingElse — the offline floor, which // is what answers with no embedder. Narrow on purpose, so the rows that must // NOT match are the point. func TestSelfFloorClaimsAQuestionAboutHerAndNothingElse(t *testing.T) { claimed := []string{ "что ты умеешь", "что ты можешь", "а что ты умеешь?", "кто ты", "кто ты такая?", "расскажи о себе", "what can you do", "who are you", } for _, u := range claimed { if !selfFloor(u) { t.Errorf("%q is a question about her and the floor missed it", u) } } declined := []string{ "что у меня сегодня", "расскажи про байкал", "кто изобрёл телефон", "что требует внимания", "запиши что я пил воду", // The floor spells its own word boundaries out, because Go's \b never // fires next to a Cyrillic letter. Without that these would match. "кто тыкал в розетку", "расскажи о себестоимости", } for _, u := range declined { if selfFloor(u) { t.Errorf("%q is not about her and the floor claimed it", u) } } } // TestSelfSourceAnswersFromTheDescription — with no embedder the source falls // to the floor, and the answer has to be the description rather than silence. func TestSelfSourceAnswersFromTheDescription(t *testing.T) { h := personalHandler() reply, claimed := h.querySelf(context.Background(), &queryTurn{ dec: router.Decision{Utterance: "что ты умеешь"}, }) if !claimed { t.Fatal("a question about her must be claimed above the boundary") } if !strings.Contains(reply, "напоминания") { t.Errorf("the answer must come from the description: %q", reply) } if _, claimed := h.querySelf(context.Background(), &queryTurn{ dec: router.Decision{Utterance: "почему небо синее"}, }); claimed { t.Error("a world question must pass this source") } } // TestSelfDescriptionHoldsThePersona — it is her own text and she reads it out, // so the same rules the phrasing eval enforces apply to it. Feminine // self-reference, informal address, no pet names. func TestSelfDescriptionHoldsThePersona(t *testing.T) { lower := strings.ToLower(selfDescription) for _, bad := range []string{"я рад ", "я готов ", "вы ", "ваш", "милый", "дорогой"} { if strings.Contains(lower, bad) { t.Errorf("the description breaks the persona on %q", bad) } } for _, want := range []string{"тво", "ты"} { if !strings.Contains(lower, want) { t.Errorf("the description must address him directly, missing %q", want) } } } // TestSelfDescriptionClaimsNothingUnconditionally — the constraint that makes // this text safe to read out. Every capability that depends on config has to be // named as depending on it, and inventing one here is the same defect as // inventing a fact. func TestSelfDescriptionClaimsNothingUnconditionally(t *testing.T) { conditional := selfDescription[strings.Index(selfDescription, "Что зависит"):] for _, cap := range []string{"дом", "локальная сеть", "ленты", "список покупок", "погода", "телеграм"} { if !strings.Contains(conditional, cap) { t.Errorf("%q is configured, not wired — it must sit under the conditional half", cap) } } }