The first want at the switch skips the record hold only where the composition changes nothing on the node.
126 lines
6.0 KiB
Go
126 lines
6.0 KiB
Go
package delivery
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// 1943/AC1: a node's composition bucket is named for the node, and a node with no name, or one a bucket refuses,
|
|
// is refused, naming why.
|
|
func TestComposedBucketFor(t *testing.T) {
|
|
b, err := ComposedBucketFor("ace")
|
|
if err != nil || b != "composed-ace" {
|
|
t.Fatalf("ComposedBucketFor(ace) = %q, %v", b, err)
|
|
}
|
|
for _, bad := range []string{"", "a.b", "a*", "a b", "a>"} {
|
|
if _, err := ComposedBucketFor(bad); err == nil || !strings.Contains(err.Error(), "node") {
|
|
t.Errorf("ComposedBucketFor(%q) = %v, want a refusal naming the node", bad, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 1943/AC1: a module's composition key and the node's own key round-trip through one parser; an empty node, a
|
|
// module named node, a bad fingerprint and a key of another shape are refused, naming why.
|
|
func TestComposedKeys(t *testing.T) {
|
|
fp := fp2of('c')
|
|
key, err := ComposedKey("ace", "mesh-mail", fp)
|
|
if err != nil || key != "ace.mesh-mail."+strings.Repeat("c", 64) {
|
|
t.Fatalf("ComposedKey = %q, %v", key, err)
|
|
}
|
|
node, module, back, isNode, err := ParseComposedKey(key)
|
|
if err != nil || node != "ace" || module != "mesh-mail" || back != fp || isNode {
|
|
t.Errorf("ParseComposedKey(%q) = %q, %q, %q, %v, %v", key, node, module, back, isNode, err)
|
|
}
|
|
own, err := ComposedNodeKey("ace")
|
|
if err != nil || own != "ace.node" {
|
|
t.Fatalf("ComposedNodeKey = %q, %v", own, err)
|
|
}
|
|
node, module, back, isNode, err = ParseComposedKey(own)
|
|
if err != nil || node != "ace" || module != "" || back != "" || !isNode {
|
|
t.Errorf("ParseComposedKey(%q) = %q, %q, %q, %v, %v", own, node, module, back, isNode, err)
|
|
}
|
|
|
|
refusals := []struct {
|
|
node, module, fp, why string
|
|
}{
|
|
{"", "mesh-mail", fp, "node name is empty"},
|
|
{"ace", "node", fp, `"node" is refused`},
|
|
{"ace", "", fp, "module name is empty"},
|
|
{"ace", "mesh-mail", "src2:abc", "not a fingerprint of the new form"},
|
|
{"ace", "mesh-mail", "src1:" + strings.Repeat("c", 64), "not a fingerprint of the new form"},
|
|
{"a.b", "mesh-mail", fp, "node name"},
|
|
}
|
|
for _, r := range refusals {
|
|
if _, err := ComposedKey(r.node, r.module, r.fp); err == nil || !strings.Contains(err.Error(), r.why) {
|
|
t.Errorf("ComposedKey(%q, %q, %q) = %v, want a refusal saying %q", r.node, r.module, r.fp, err, r.why)
|
|
}
|
|
}
|
|
if _, err := ComposedNodeKey(""); err == nil {
|
|
t.Errorf("ComposedNodeKey(\"\") accepted")
|
|
}
|
|
for _, bad := range []string{"", "ace", "ace.mesh-mail", "ace.node.x", "ace.mesh-mail.abc", ".mesh-mail." + strings.Repeat("c", 64),
|
|
"ace.node." + strings.Repeat("c", 64), "ace.mesh-mail." + strings.Repeat("c", 64) + ".x", "want.ace.mesh-mail"} {
|
|
if _, _, _, _, err := ParseComposedKey(bad); err == nil || !strings.Contains(err.Error(), "\""+bad+"\"") {
|
|
t.Errorf("ParseComposedKey(%q) = %v, want a refusal naming it", bad, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 1943/AC1: the controller's value beside a composition, its digest and the judgement of the move, round-trips; an
|
|
// unknown judgement, a digest not of the sha256 form, a move judged against nothing, a cannot-judge without its
|
|
// reason, and an upgrade policy or source outside the catalogue's words are refused, naming why; an unknown version is
|
|
// refused as one. The module's upgrade policy and its source ride beside the judgement, for the assigner's hold.
|
|
func TestComposedDigestValue(t *testing.T) {
|
|
digest := "sha256:" + strings.Repeat("d", 64)
|
|
against := "sha256:" + strings.Repeat("e", 64)
|
|
for _, v := range []ComposedDigest{
|
|
{Digest: digest, Judgement: JudgedNeither},
|
|
{Digest: digest, Judgement: JudgedNeither, Against: against},
|
|
{Digest: digest, Judgement: JudgedRecreates, Against: against, Words: "the container's image changes"},
|
|
{Digest: digest, Judgement: JudgedMovesData, Against: against},
|
|
{Digest: digest, Judgement: JudgedCannot, Words: "the composition the node runs is gone"},
|
|
{Digest: digest, Judgement: JudgedUnchanged, Words: "equal to the declaration the node last applied"},
|
|
{Digest: digest, Judgement: JudgedNeither, Policy: "record", PolicyFrom: "person", PolicyWhy: "the operator: its data"},
|
|
{Digest: digest, Judgement: JudgedNeither, Policy: "roll", PolicyFrom: "default"},
|
|
{Digest: digest, Judgement: JudgedNeither, Against: against, UserListOnly: true, Words: "only the bus's user list changes"},
|
|
} {
|
|
raw, err := EncodeComposedDigest(v)
|
|
if err != nil {
|
|
t.Fatalf("EncodeComposedDigest(%+v): %v", v, err)
|
|
}
|
|
back, err := DecodeComposedDigest(raw)
|
|
v.V = Version
|
|
if err != nil || !SameComposedDigest(back, v) {
|
|
t.Errorf("round trip of %+v = %+v, %v", v, back, err)
|
|
}
|
|
}
|
|
refusals := []struct {
|
|
v ComposedDigest
|
|
why string
|
|
}{
|
|
{ComposedDigest{Digest: digest, Judgement: "maybe"}, `judgement "maybe"`},
|
|
{ComposedDigest{Digest: digest}, `judgement ""`},
|
|
{ComposedDigest{Digest: "sha256:abc", Judgement: JudgedNeither}, "not sha256"},
|
|
{ComposedDigest{Judgement: JudgedNeither}, "not sha256"},
|
|
{ComposedDigest{Digest: digest, Judgement: JudgedRecreates}, "against"},
|
|
{ComposedDigest{Digest: digest, Judgement: JudgedMovesData}, "against"},
|
|
{ComposedDigest{Digest: digest, Judgement: JudgedCannot}, "why"},
|
|
{ComposedDigest{Digest: digest, Judgement: JudgedNeither, Against: "sha256:zz"}, "not sha256"},
|
|
{ComposedDigest{Digest: digest, Judgement: JudgedNeither, Policy: "sometimes", PolicyFrom: "person"}, `policy "sometimes"`},
|
|
{ComposedDigest{Digest: digest, Judgement: JudgedNeither, Policy: "record"}, `source ""`},
|
|
{ComposedDigest{Digest: digest, Judgement: JudgedNeither, PolicyFrom: "person"}, `policy ""`},
|
|
}
|
|
for _, r := range refusals {
|
|
if _, err := EncodeComposedDigest(r.v); err == nil || !strings.Contains(err.Error(), r.why) {
|
|
t.Errorf("EncodeComposedDigest(%+v) = %v, want a refusal saying %q", r.v, err, r.why)
|
|
}
|
|
}
|
|
if _, err := DecodeComposedDigest([]byte(`{"v":2,"digest":"` + digest + `","judgement":"neither"}`)); !errors.Is(err, ErrUnknownVersion) {
|
|
t.Errorf("version 2 = %v, want ErrUnknownVersion", err)
|
|
}
|
|
if _, err := DecodeComposedDigest([]byte(`{"v":1,"digest":"` + digest + `","judgement":"perhaps"}`)); err == nil {
|
|
t.Errorf("an unknown judgement was read")
|
|
}
|
|
}
|