111 lines
3.6 KiB
Go
111 lines
3.6 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
sdkdecl "git.novox.be/novox/mesh-sdk/go/declaration"
|
|
"git.novox.be/novox/mesh-sdk/go/overlay"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/compose"
|
|
)
|
|
|
|
// 1696/AC2, ADR 0486 §5: a node is sent a file by digest only when its profile reports the capability. A node whose profile lacks
|
|
// it, and a node the mesh has no profile of, are sent every content inline; a node that reports it is sent the reference. The test
|
|
// goes through composeQuestion and composeSend, the two places readsFileReferences is read (compose_sdk.go).
|
|
func TestAFileTravelsByDigestOnlyToANodeThatReportsTheCapability(t *testing.T) {
|
|
open := aMesh(t) // anchor and laptop report no file-references
|
|
ctx := t.Context()
|
|
big := strings.Repeat("0123456789abcdef", 8<<10) // 128 KiB
|
|
register(t, open, catalogue.Manifest{Module: "bigfile", Version: "1",
|
|
Resources: []map[string]any{{"id": "blob", "type": "file", "path": "/etc/bigfile/blob", "mode": "0644", "content": big}}})
|
|
|
|
// reader reports the capability; bare has never reported a profile at all.
|
|
for i, n := range []struct {
|
|
name string
|
|
profile map[string]any
|
|
}{
|
|
{"reader", map[string]any{"capabilities": []any{
|
|
map[string]any{"name": "container-runtime", "present": true},
|
|
map[string]any{"name": "systemd", "present": true},
|
|
map[string]any{"name": sdkdecl.FileReferencesCapability, "present": true}}}},
|
|
{"bare", nil},
|
|
} {
|
|
record, err := open.inventory.AddNode(ctx, n.name)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := open.inventory.SetPlace(ctx, n.name, n.name+".example:51820", "here", false, fmt.Sprintf("10.77.0.%d", i+10)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if n.profile != nil {
|
|
if err := open.inventory.RecordProfile(ctx, record.ID, n.profile); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if err := open.inventory.RecordSealingKey(ctx, record.ID, aPublicKey(t)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := open.inventory.RecordOverlayKey(ctx, record.ID, aPublicKey(t)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := open.inventory.Assign(ctx, n.name, overlay.Name); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
for _, node := range []string{"laptop", "reader", "bare"} {
|
|
if _, err := assign(ctx, open, node, "bigfile"); err != nil {
|
|
t.Fatalf("assign %s: %v", node, err)
|
|
}
|
|
}
|
|
|
|
byDigest := map[string]bool{"laptop": false, "bare": false, "reader": true}
|
|
for node, want := range byDigest {
|
|
asked, _, err := composeQuestion(ctx, open, node, compose.Reading, false)
|
|
if err != nil {
|
|
t.Fatalf("%s: %v", node, err)
|
|
}
|
|
sent, err := composeSend(ctx, open, node)
|
|
if err != nil {
|
|
t.Fatalf("%s: %v", node, err)
|
|
}
|
|
for what, s := range map[string]sendable{"question": asked, "send": sent} {
|
|
if s.fileReferences != want {
|
|
t.Fatalf("%s, %s: fileReferences %v, want %v", node, what, s.fileReferences, want)
|
|
}
|
|
body, err := s.Body()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var got struct {
|
|
Resources []map[string]any `json:"resources"`
|
|
}
|
|
if err := json.Unmarshal(body, &got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var found bool
|
|
for _, r := range got.Resources {
|
|
if r["path"] != "/etc/bigfile/blob" {
|
|
continue
|
|
}
|
|
found = true
|
|
inline := r["content"] == big
|
|
if want && (inline || r["digest"] == nil || r["size"] == nil) {
|
|
t.Fatalf("%s, %s: a node that reads references is sent the content inline", node, what)
|
|
}
|
|
if !want && (!inline || r["digest"] != nil) {
|
|
t.Fatalf("%s, %s: a node that does not report the capability is sent a reference", node, what)
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("%s, %s: the file is not in the declaration", node, what)
|
|
}
|
|
}
|
|
}
|
|
}
|