Files
mesh-controller/cmd/mesh-controller/facts_format_test.go
T
mesh-tools b75fb7899e Write the facts snapshot in format 2, with each machine's grants and credential bindings (design 47 R4c-2, issue 1394)
Every reader takes format 2 since R4b (ADR 0456 clause 1), and the assigner's composition check reads the grants and bindings (ADR 0456 clause 2): the writer moves now, names only, never a sealed value.
2026-10-20 18:26:07 +00:00

69 lines
2.5 KiB
Go

package main
import (
"encoding/json"
"strings"
"testing"
"time"
snapshot "git.novox.be/novox/mesh-sdk/go/facts"
)
// 1394 (novox/hq ADR 0456 clause 2): the snapshot this controller writes is format 2, which carries each machine's grants and
// bindings, and the reader it shares with the build seat (mesh-sdk's go/facts) takes formats 1 and 2 and refuses one newer.
func TestTheWriterWritesFormatTwoAndTheReaderTakesBothFormats(t *testing.T) {
if writtenFormat != 2 {
t.Fatalf("the writer writes format %d, not 2", writtenFormat)
}
taken := time.Date(2026, 10, 20, 9, 0, 0, 0, time.UTC)
for format, want := range map[int]bool{1: true, 2: true, 3: false} {
body, err := (snapshot.Facts{Format: format, Taken: taken}).Encode()
if err != nil {
t.Fatal(err)
}
f, err := snapshot.Decode(body)
switch {
case want && err != nil:
t.Errorf("format %d is refused: %v", format, err)
case want && f.Format != format:
t.Errorf("format %d is read as %d", format, f.Format)
case !want && (err == nil || !strings.Contains(err.Error(), "newer")):
t.Errorf("format %d is not refused as newer: %v", format, err)
}
}
// Format 2 carries a machine's grants and bindings, and they are encoded in one order whatever order they were made in.
grants := []snapshot.Grant{{Provision: "s3-bucket", ConsumerNode: "bbbbbb", ConsumerModule: "files"},
{Provision: "s3-bucket", ConsumerNode: "aaaaaa", ConsumerModule: "files"}}
bindings := []snapshot.Binding{{ConsumerModule: "files", Provision: "s3-bucket", ProviderNode: "cccccc", ProviderModule: "objects"}}
encode := func(g []snapshot.Grant) []byte {
body, err := (snapshot.Facts{Format: writtenFormat, Taken: taken, Machines: []snapshot.Machine{{Name: "abcdef", Length: 6,
Grants: g, Bindings: bindings}}}).Encode()
if err != nil {
t.Fatal(err)
}
return body
}
body := encode(grants)
// 1394/AC3 (the bytes do not depend on the order the rows came in)
if reversed := encode([]snapshot.Grant{grants[1], grants[0]}); string(reversed) != string(body) {
t.Error("grants in another order encode to other bytes")
}
var raw struct {
Format int `json:"facts"`
Machines []map[string]json.RawMessage `json:"machines"`
}
if err := json.Unmarshal(body, &raw); err != nil {
t.Fatal(err)
}
if raw.Format != 2 {
t.Errorf("the snapshot says format %d", raw.Format)
}
for _, m := range raw.Machines {
for _, key := range []string{"grants", "bindings"} {
if _, has := m[key]; !has {
t.Errorf("a format 2 snapshot carries no %s", key)
}
}
}
}