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.
69 lines
2.5 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|
|
}
|