Files
mesh-catalog/modules/mesh-mail-reader/cmd/mesh-mail-reader/tools_test.go
T

110 lines
4.2 KiB
Go

package main
import (
"context"
"strings"
"testing"
)
// 1426/AC3: the bundle's Tools() lists the six mail-reading verbs and mail_reader_health, each with its own
// argument schema.
func TestToolsListsTheSixVerbsAndHealth(t *testing.T) {
b := &Bundle{}
var names []string
for _, tool := range b.Tools() {
names = append(names, tool.Name)
if tool.Input == nil {
t.Errorf("%s has no argument schema", tool.Name)
}
if tool.Description == "" {
t.Errorf("%s has no description", tool.Name)
}
}
want := []string{
"mail-reading.entries", "mail-reading.groups", "mail-reading.correct", "mail-reading.lessons",
"mail-reading.undo", "mail-reading.status", "mail_reader_health",
}
if len(names) != len(want) {
t.Fatalf("Tools() = %v, want %v", names, want)
}
for i, n := range want {
if names[i] != n {
t.Fatalf("Tools()[%d] = %q, want %q", i, names[i], n)
}
}
}
// 1426/AC4, 1428/AC5: a mail-reading verb answers a caller the setting callers names, and refuses any other,
// naming why — before anything else about the verb (business errors such as an unknown id are not caller
// refusals, and are exercised by correct_test.go and 1521's own tests, not here).
func TestAMailReadingVerbChecksItsCaller(t *testing.T) {
granted := func(map[string]any) string { return "mesh-mail-web" }
refused := func(map[string]any) string { return "person.someoneelse" }
unproven := func(map[string]any) string { return Unproven }
storeOf := func(context.Context) (Store, error) { return newMemStore(), nil }
for _, tool := range []struct {
name string
run func(*Bundle) (any, error)
}{
{EntriesTool, func(b *Bundle) (any, error) { return b.entriesTool(map[string]any{}) }},
{GroupsTool, func(b *Bundle) (any, error) { return b.groupsTool(map[string]any{}) }},
{CorrectTool, func(b *Bundle) (any, error) {
return b.correctTool(map[string]any{"id": float64(1), "mark": "matters"})
}},
{LessonsTool, func(b *Bundle) (any, error) { return b.lessonsTool(map[string]any{}) }},
{UndoTool, func(b *Bundle) (any, error) { return b.undoTool(map[string]any{"id": float64(1)}) }},
{StatusTool, func(b *Bundle) (any, error) { return b.statusTool(map[string]any{}) }},
} {
callers := func() (Callers, error) { return Callers{"mesh-mail-web"}, nil }
b := &Bundle{Caller: granted, callersOverride: callers, Store: storeOf}
_, err := tool.run(b)
if err != nil && strings.Contains(err.Error(), "is not named in the setting callers") {
t.Errorf("%s granted: %v, want it to pass the caller check (any other error is its own business, not a caller refusal)", tool.name, err)
}
b = &Bundle{Caller: refused, callersOverride: callers, Store: storeOf}
_, err = tool.run(b)
if err == nil || !strings.Contains(err.Error(), "refused") || !strings.Contains(err.Error(), "person.someoneelse") {
t.Errorf("%s refused caller: %v, want a refusal naming person.someoneelse", tool.name, err)
}
b = &Bundle{Caller: unproven, callersOverride: callers, Store: storeOf}
_, err = tool.run(b)
if err == nil || !strings.Contains(err.Error(), "refused") {
t.Errorf("%s unproven caller: %v, want a refusal", tool.name, err)
}
}
}
// 1426/AC4: a setting that cannot be read allows nobody, and says why — before the store is ever reached.
func TestAMailReadingVerbRefusesWhenCallersCannotBeRead(t *testing.T) {
b := &Bundle{
Caller: func(map[string]any) string { return "mesh-mail-web" },
callersOverride: func() (Callers, error) { return nil, errFake },
}
_, err := b.entriesTool(map[string]any{})
if err == nil || !strings.Contains(err.Error(), "cannot be read") {
t.Fatalf("entriesTool with an unreadable setting: %v", err)
}
}
// mail_reader_health carries no caller check (1426: "mail_reader_health is asked by the node-engine itself").
func TestHealthToolHasNoCallerCheck(t *testing.T) {
b := &Bundle{
callersOverride: func() (Callers, error) { return nil, errFake },
Store: func(context.Context) (Store, error) { return newMemStore(), nil },
}
_, err := b.healthTool(map[string]any{})
if err != nil {
t.Fatalf("mail_reader_health: %v, want it to skip the caller check entirely and answer", err)
}
}
type fakeErr struct{}
func (fakeErr) Error() string { return "the setting cannot be read (fake)" }
var errFake = fakeErr{}