repos
/ orchard main

orchard

mirror

Every site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.

blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics

3.4 KB · 116 lines · Go Raw History
  1package tools
  2
  3import (
  4	"context"
  5	"strings"
  6	"testing"
  7)
  8
  9type memStub struct {
 10	facts   []MemoryFact
 11	deleted []int64
 12	changed map[int64]string
 13}
 14
 15func (m *memStub) Facts() ([]MemoryFact, error) { return m.facts, nil }
 16func (m *memStub) Add(t string) (int64, error) {
 17	id := int64(len(m.facts) + 1)
 18	m.facts = append(m.facts, MemoryFact{ID: id, Text: t})
 19	return id, nil
 20}
 21func (m *memStub) Replace(id int64, t string) error {
 22	if m.changed == nil {
 23		m.changed = map[int64]string{}
 24	}
 25	m.changed[id] = t
 26	return nil
 27}
 28func (m *memStub) Delete(id int64) error { m.deleted = append(m.deleted, id); return nil }
 29
 30func withMem(m Memory) *Deps {
 31	d := NewDeps()
 32	d.Memory = m
 33	return d
 34}
 35
 36func TestRememberWritesReadsAndForgets(t *testing.T) {
 37	m := &memStub{}
 38	d := withMem(m)
 39	ctx := context.Background()
 40
 41	if _, err := Remember.Run(ctx, d, map[string]any{"action": "add", "fact": "Isaac wants to watch End of Watch."}); err != nil {
 42		t.Fatalf("add: %v", err)
 43	}
 44	if len(m.facts) != 1 || !strings.Contains(m.facts[0].Text, "End of Watch") {
 45		t.Fatalf("facts = %+v", m.facts)
 46	}
 47
 48	got, err := Remember.Run(ctx, d, map[string]any{"action": "list"})
 49	if err != nil {
 50		t.Fatalf("list: %v", err)
 51	}
 52	if got.(map[string]any)["count"].(int) != 1 {
 53		t.Errorf("list did not report the one fact: %+v", got)
 54	}
 55
 56	// The model renders an id as a number, and json puts it back as a float.
 57	if _, err := Remember.Run(ctx, d, map[string]any{"action": "replace", "id": float64(1), "fact": "Isaac watched it."}); err != nil {
 58		t.Fatalf("replace: %v", err)
 59	}
 60	if m.changed[1] != "Isaac watched it." {
 61		t.Errorf("replace wrote %q", m.changed[1])
 62	}
 63
 64	if _, err := Remember.Run(ctx, d, map[string]any{"action": "forget", "id": "1"}); err != nil {
 65		t.Fatalf("forget: %v", err)
 66	}
 67	if len(m.deleted) != 1 || m.deleted[0] != 1 {
 68		t.Errorf("forgot %v", m.deleted)
 69	}
 70}
 71
 72// A mode that writes nothing down cannot be the one that teaches it something
 73// to write down later, so an incognito turn may read memory and not change it.
 74func TestIncognitoCannotWriteMemory(t *testing.T) {
 75	m := &memStub{facts: []MemoryFact{{ID: 1, Text: "Isaac camps."}}}
 76	d := withMem(m)
 77	d.Incognito = true
 78	ctx := context.Background()
 79
 80	for _, action := range []string{"add", "replace", "forget"} {
 81		if _, err := Remember.Run(ctx, d, map[string]any{"action": action, "fact": "x", "id": 1}); err == nil {
 82			t.Errorf("%s was allowed in an incognito turn", action)
 83		}
 84	}
 85	if len(m.facts) != 1 || len(m.deleted) != 0 {
 86		t.Errorf("an incognito turn changed memory: %+v %v", m.facts, m.deleted)
 87	}
 88	if _, err := Remember.Run(ctx, d, map[string]any{"action": "list"}); err != nil {
 89		t.Errorf("reading memory in incognito failed: %v", err)
 90	}
 91}
 92
 93// Missing arguments have to say what is missing, since the model reads the
 94// error and tries again in the same turn.
 95func TestRememberRefusesIncompleteCalls(t *testing.T) {
 96	d := withMem(&memStub{})
 97	ctx := context.Background()
 98	for _, a := range []map[string]any{
 99		{"action": "add"},
100		{"action": "replace", "id": 1},
101		{"action": "forget"},
102		{"action": "sing"},
103	} {
104		if _, err := Remember.Run(ctx, d, a); err == nil {
105			t.Errorf("%v was accepted", a)
106		}
107	}
108}
109
110// A site with no store must not panic a turn that calls this.
111func TestRememberWithNoStore(t *testing.T) {
112	if _, err := Remember.Run(context.Background(), NewDeps(), map[string]any{"action": "list"}); err == nil {
113		t.Error("a missing store was not reported")
114	}
115}