mesh/delivery-group group feat/774-l3-reland rejected: composed together: the checker's verdict at the members' heads (b48c90fea31f): integration: mesh-self-ch…
mesh/delivery closed: a newer head of the same pull request
mesh/check failed: integration: mesh-self-check/cmd/mesh-self-check.TestTheSelfCheckWholeRunsOnTheBus: the run answered {Run:doctor-1793351737-1 At:20…
One commit with exactly the tree of the reviewed head35b4509c0a, on main12c2574c9d, so two compiled programs added and removed on the branch leave no trace in history (issue 1577).
137 lines
4.5 KiB
Go
137 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"git.novox.be/novox/mesh-sdk/go/provider/harness"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type world struct {
|
|
t *testing.T
|
|
dir string
|
|
receives string
|
|
now time.Time
|
|
h *harness.Harness
|
|
a *recorder
|
|
said []string
|
|
}
|
|
|
|
func newWorld(t *testing.T) *world {
|
|
w := &world{t: t, dir: t.TempDir(), now: time.Date(2026, 10, 5, 12, 0, 0, 0, time.UTC), a: &recorder{}}
|
|
w.receives = filepath.Join(w.dir, "mesh.json")
|
|
w.h = &harness.Harness{Resource: "postgres-database", Receives: w.receives, Adapter: w.a,
|
|
Now: func() time.Time { return w.now },
|
|
Log: func(f string, a ...any) { w.said = append(w.said, f) }}
|
|
return w
|
|
}
|
|
|
|
// recorder is an adapter that remembers what it was asked to create; the loop's own behaviour is proven in the SDK's
|
|
// harness package, and this module's tests hold only what the module adds (issue 849).
|
|
type recorder struct{ created []harness.Provision }
|
|
|
|
func (r *recorder) Create(_ context.Context, p harness.Provision) error {
|
|
r.created = append(r.created, p)
|
|
return nil
|
|
}
|
|
|
|
func (r *recorder) Retire(context.Context, string, map[string]any, string, time.Time) error {
|
|
return nil
|
|
}
|
|
func (r *recorder) Holds(context.Context, harness.Provision) (bool, error) { return true, nil }
|
|
func (r *recorder) Inventory(context.Context) (harness.Inventory, error) {
|
|
return harness.Inventory{}, nil
|
|
}
|
|
func (r *recorder) Delete(context.Context, harness.Retired) (int64, error) { return 0, nil }
|
|
|
|
func (w *world) give(given ...map[string]any) {
|
|
for _, g := range given {
|
|
secret := filepath.Join(w.dir, g["as"].(string)+".secret")
|
|
if err := os.WriteFile(secret, []byte("pw-"+g["as"].(string)+"\n"), 0o600); err != nil {
|
|
w.t.Fatal(err)
|
|
}
|
|
g["secret"] = secret
|
|
}
|
|
if given == nil {
|
|
given = []map[string]any{}
|
|
}
|
|
raw, _ := json.Marshal(map[string]any{"requirement": "postgres-database", "given": given})
|
|
if err := os.WriteFile(w.receives, raw, 0o600); err != nil {
|
|
w.t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestAddingExtensionsAppliesTheConsumerAgain(t *testing.T) {
|
|
w := newWorld(t)
|
|
w.give(map[string]any{"as": "mesh_ace_letta", "values": map[string]any{"name": "letta"}})
|
|
w.h.Reconcile(ctx)
|
|
w.give(map[string]any{"as": "mesh_ace_letta", "values": map[string]any{"name": "letta", "extensions": []any{"vector"}}})
|
|
w.h.Reconcile(ctx)
|
|
if len(w.a.created) != 2 {
|
|
t.Fatalf("created %d times", len(w.a.created))
|
|
}
|
|
if ext, _ := Extensions(w.a.created[1].Values); len(ext) != 1 || ext[0] != "vector" {
|
|
t.Fatal(ext)
|
|
}
|
|
}
|
|
|
|
type pgErr struct{ s string }
|
|
|
|
func (e *pgErr) Error() string { return e.s }
|
|
|
|
func TestProvisionerCreatesTheDatabaseThenItsExtensions(t *testing.T) {
|
|
f, c := newFake(admin)
|
|
f.answer(`FROM pg_available_extensions`, []string{"name"}, []string{"vector"})
|
|
var events []string
|
|
a := provisioner{pg: c, announce: func(e string, _ map[string]string) { events = append(events, e) }}
|
|
p := harness.Provision{As: "mesh_ace_letta", Password: "pw", Values: map[string]any{"name": "letta", "extensions": []any{"vector"}}}
|
|
if err := a.Create(ctx, p); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sql := f.statements()
|
|
// The extension once the database exists, and last the active mark (novox/hq ADR 0230).
|
|
if !strings.HasPrefix(sql[len(sql)-2], `CREATE EXTENSION IF NOT EXISTS "vector"`) || !has(sql, `CREATE DATABASE "mesh_ace_letta"`) ||
|
|
sql[len(sql)-1] != `COMMENT ON ROLE "mesh_ace_letta" IS '{"mesh":"consumer"}'` {
|
|
t.Fatal(strings.Join(sql, "\n"))
|
|
}
|
|
if strings.Join(events, ",") != "database.provisioned" {
|
|
t.Fatal(events)
|
|
}
|
|
|
|
// An extension the server does not offer: refused, and no event says it was provisioned.
|
|
events = nil
|
|
p.Values = map[string]any{"extensions": []any{"nope"}}
|
|
if err := a.Create(ctx, p); err == nil || !strings.Contains(err.Error(), `"nope"`) || len(events) != 0 {
|
|
t.Fatal(err, events)
|
|
}
|
|
// A malformed list: refused before the server is asked anything.
|
|
f.reset()
|
|
p.Values = map[string]any{"extensions": "vector"}
|
|
if err := a.Create(ctx, p); err == nil || len(f.calls) != 0 {
|
|
t.Fatal(err, f.calls)
|
|
}
|
|
|
|
f.reset()
|
|
f.answer(`FROM pg_roles`, []string{"?column?"}, []string{"1"})
|
|
if err := a.Retire(ctx, "mesh_ace_letta", nil, "test", time.Now()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// On the operator's yes the login goes and the database stays (ADR 0570 clause 5).
|
|
if !has(f.statements(), `^DROP ROLE "mesh_ace_letta"$`) || has(f.statements(), `DROP DATABASE`) {
|
|
t.Fatal(f.statements())
|
|
}
|
|
}
|
|
|
|
func listHas(list []string, s string) bool {
|
|
for _, x := range list {
|
|
if x == s {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|