Split the unit level from the integration level in cmd, builder, link, catalogue, inventory; cheap fixtures for the archive-entry bound, the registry waits and the catalogue copy (issue 895)
This commit is contained in:
@@ -14,7 +14,6 @@ import (
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/asks"
|
||||
|
||||
"github.com/novox/mesh-controller/internal/catalogue"
|
||||
"github.com/novox/mesh-controller/internal/conditions"
|
||||
"github.com/novox/mesh-controller/internal/outward"
|
||||
)
|
||||
@@ -708,132 +707,11 @@ func TestTheSettingsVerbComposesProposeAndProposals(t *testing.T) {
|
||||
|
||||
// setLayerIn sets the layer as the terminal does — judged, the removal meant, the history kept — with who approved it
|
||||
// beside it; and refuses once the layer is no longer the one the operator was shown the change against.
|
||||
func TestSetOnAWarrantJudgesTheLayerAndKeepsWhoApprovedIt(t *testing.T) {
|
||||
open := aMesh(t)
|
||||
ctx := t.Context()
|
||||
register(t, open, catalogue.Manifest{Module: "notes", Version: "1",
|
||||
// y is a preference with a default, so a layer may leave it out; x is the operator's own (ADR 0262).
|
||||
Settings: map[string]catalogue.SettingDeclaration{"y": {Kind: "preference", Default: "10", Why: "a size"}},
|
||||
Resources: []map[string]any{{"id": "data", "type": "directory", "mode": "0755"},
|
||||
// A trusted file (unmarked), so its keys are the terminal's — and now the warrant's (novox/hq ADR 0277).
|
||||
{"id": "rc", "type": "file", "path": "/etc/notes.conf", "mode": "0644", "content": "x = ${setting:x}\ny = ${setting:y}\n"}}})
|
||||
if _, err := assign(ctx, open, "laptop", "notes"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
set := setLayerIn(open)
|
||||
now := time.Now()
|
||||
first := map[string]any{"x": "1", "y": "2"}
|
||||
p := settingsProposal{Module: "notes", Node: "laptop", Values: first, From: "g14/claude-code", At: now,
|
||||
Digest: layerDigest(first), BeforeDigest: layerDigest(nil)}
|
||||
changed, err := set(ctx, p, "s9", "approved by the operator, as telegram identity 42 via telegram at 14:05 (ask s9)")
|
||||
if err != nil || !strings.Contains(changed, "+ x") {
|
||||
t.Fatalf("%q %v", changed, err)
|
||||
}
|
||||
layer, has, err := open.inventory.Layer(ctx, "laptop", "notes")
|
||||
if err != nil || !has || layer["x"] != "1" {
|
||||
t.Fatalf("the layer: %v %v %v", layer, has, err)
|
||||
}
|
||||
setBy, _, has, err := open.inventory.LayerOrigin(ctx, "laptop", "notes")
|
||||
if err != nil || !has || !strings.HasPrefix(setBy, "approved by the operator, as telegram identity 42 via telegram") {
|
||||
t.Fatalf("who set it: %q %v", setBy, err)
|
||||
}
|
||||
// Shown by `settings show`, at the terminal and through the verb.
|
||||
out := captureStdout(t, func() {
|
||||
if err := atTheTerminal(t, "settings", "show", "notes", "--node", "laptop"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
if !strings.Contains(out, "approved by the operator, as telegram identity 42 via telegram") {
|
||||
t.Errorf("settings show says:\n%s", out)
|
||||
}
|
||||
// The same proposal again: the layer is no longer the one the operator was shown it against.
|
||||
if _, err := set(ctx, p, "s9", "approved …"); err == nil || !strings.Contains(err.Error(), "changed since the operator was shown") {
|
||||
t.Errorf("a stale proposal: %v", err)
|
||||
}
|
||||
// A removal not meant is refused; one meant is taken, and the history says who had set the layer.
|
||||
second := map[string]any{"x": "1"}
|
||||
q := settingsProposal{Module: "notes", Node: "laptop", Values: second, Before: first, HadLayer: true,
|
||||
From: "g14/claude-code", At: now, Digest: layerDigest(second), BeforeDigest: layerDigest(first)}
|
||||
if _, err := set(ctx, q, "s10", "approved …"); err == nil || !strings.Contains(err.Error(), "removal was not meant") {
|
||||
t.Errorf("a silent removal: %v", err)
|
||||
}
|
||||
// A layer the mesh refuses is refused here too, with the same words as at the terminal.
|
||||
bad := q
|
||||
bad.Values, bad.Digest = map[string]any{"x": "a\nb", "y": "2"}, layerDigest(map[string]any{"x": "a\nb", "y": "2"})
|
||||
if _, err := set(ctx, bad, "s11", "approved …"); err == nil || !strings.Contains(err.Error(), "line break") {
|
||||
t.Errorf("a line break on a warrant: %v", err)
|
||||
}
|
||||
if layer, _, _ := open.inventory.Layer(ctx, "laptop", "notes"); layer["y"] != "2" {
|
||||
t.Fatalf("a refused act changed the layer: %v", layer)
|
||||
}
|
||||
q.Replace = true
|
||||
if _, err := set(ctx, q, "s10", "approved later"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
past, err := open.inventory.SettingsHistory(ctx, "laptop", "notes")
|
||||
if err != nil || len(past) != 1 || !strings.HasPrefix(past[0].SetBy, "approved by the operator") {
|
||||
t.Errorf("the history: %+v %v", past, err)
|
||||
}
|
||||
// And a clear, keeping who cleared it with the copy.
|
||||
c := settingsProposal{Module: "notes", Node: "laptop", Clear: true, Before: second, HadLayer: true, From: "x", At: now,
|
||||
Digest: layerDigest(second), BeforeDigest: layerDigest(second)}
|
||||
if _, err := set(ctx, c, "s12", "approved by the operator at 15:00"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, has, _ := open.inventory.Layer(ctx, "laptop", "notes"); has {
|
||||
t.Error("the layer was not cleared")
|
||||
}
|
||||
past, _ = open.inventory.SettingsHistory(ctx, "laptop", "notes")
|
||||
if len(past) != 2 || !strings.Contains(past[0].SetBy, "cleared approved by the operator at 15:00") {
|
||||
t.Errorf("the history after a clear: %+v", past)
|
||||
}
|
||||
}
|
||||
|
||||
// A layer set at the terminal says so, and one set through a verb names the verb (novox/hq ADR 0277).
|
||||
func TestALayerSaysWhoSetIt(t *testing.T) {
|
||||
open := aMesh(t)
|
||||
ctx := t.Context()
|
||||
register(t, open, catalogue.Manifest{Module: "notes", Version: "1",
|
||||
Resources: []map[string]any{{"id": "rc", "type": "file", "path": "/etc/notes.conf", "mode": "0644", "trusted": false,
|
||||
"content": "x = ${setting:x}\n"}}})
|
||||
if _, err := assign(ctx, open, "laptop", "notes"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := atTheTerminal(t, "settings", "set", "notes", `{"x":"1"}`, "--node", "laptop"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
setBy, _, _, _ := open.inventory.LayerOrigin(ctx, "laptop", "notes")
|
||||
if !strings.HasPrefix(setBy, "set at the controller's terminal by ") {
|
||||
t.Errorf("at the terminal: %q", setBy)
|
||||
}
|
||||
if err := throughVerb(t, "settings", map[string]any{"module": "notes", "node": "laptop", "values": `{"x":"2"}`}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
setBy, _, _, _ = open.inventory.LayerOrigin(ctx, "laptop", "notes")
|
||||
if !strings.HasPrefix(setBy, "set by ") || !strings.Contains(setBy, "through settings") {
|
||||
t.Errorf("through the verb: %q", setBy)
|
||||
}
|
||||
}
|
||||
|
||||
// A trusted setting is still refused through the settings verb (novox/hq issue 339), and the refusal now names the
|
||||
// proposal as the way.
|
||||
func TestATrustedSettingThroughAVerbNamesTheProposal(t *testing.T) {
|
||||
open := aMesh(t)
|
||||
ctx := t.Context()
|
||||
register(t, open, catalogue.Manifest{Module: "notes", Version: "1",
|
||||
Resources: []map[string]any{{"id": "data", "type": "directory", "mode": "0755"}}})
|
||||
if _, err := assign(ctx, open, "laptop", "notes"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err := throughVerb(t, "settings", map[string]any{"module": "notes", "node": "laptop",
|
||||
"values": `{"places":{"data":{"path":"/srv/notes","owner":"1001:1001"}}}`})
|
||||
if err == nil || !strings.Contains(err.Error(), "issue 339") || !strings.Contains(err.Error(), "propose") {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
if _, has, _ := open.inventory.Layer(ctx, "laptop", "notes"); has {
|
||||
t.Error("a layer was kept")
|
||||
}
|
||||
}
|
||||
|
||||
// captureStdout runs f and answers what it printed to standard output.
|
||||
func captureStdout(t *testing.T, f func()) string {
|
||||
|
||||
Reference in New Issue
Block a user