waits names <name>@<version> on a queued key only; an older reader reads it as queued.
119 lines
5.0 KiB
Go
119 lines
5.0 KiB
Go
package delivery
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func artifactOf(name, kind, digest, reference string) BuiltArtifact {
|
|
return BuiltArtifact{Name: name, Kind: kind, Digest: digest, Reference: reference}
|
|
}
|
|
|
|
// A done key names where each artifact is (novox/hq ADR 0498 clauses 1, 5 and 6; the lead's decision L1 of R4e): a
|
|
// bundle or an archive by its artifact-store blob, an image or an upstream copy by the registry's reference to its
|
|
// digest (or the kept artifact-store form), a package by name and version. A reference of the wrong form for its kind,
|
|
// or naming another digest or artifact, is refused, naming the artifact.
|
|
func TestADoneKeyNamesEachArtifactsReferenceInTheFormOfItsKind(t *testing.T) {
|
|
d := "sha256:" + digestOf('6')
|
|
good := []BuiltArtifact{
|
|
artifactOf("code", "bundle", d, "artifact-store://mail/code/blobs/"+d),
|
|
artifactOf("files", "archive", d, "artifact-store://mail/files/blobs/"+d),
|
|
artifactOf("server", "image", d, "10.0.0.1:5000/mail/server@"+d),
|
|
artifactOf("server", "image", d, "artifact-store://mail/server@"+d),
|
|
artifactOf("nats", "upstream", d, "registry.example/nats/nats@"+d),
|
|
artifactOf("lib", "package", d, "@novox/mesh-sdk@0.1.15"),
|
|
artifactOf("lib", "package", d, "left-pad@1.3.0"),
|
|
artifactOf("old", "", d, "anything at all"),
|
|
}
|
|
for _, a := range good {
|
|
b := doneBuild()
|
|
b.Artifacts = []BuiltArtifact{a}
|
|
if _, err := EncodeBuilderBuild(b); err != nil {
|
|
t.Errorf("%+v was refused: %v", a, err)
|
|
}
|
|
}
|
|
other := "sha256:" + digestOf('7')
|
|
bad := []BuiltArtifact{
|
|
artifactOf("code", "bundle", d, "artifact-store://mail/code/blobs/"+other),
|
|
artifactOf("code", "bundle", d, "artifact-store://mail/other/blobs/"+d),
|
|
artifactOf("code", "bundle", d, "10.0.0.1:5000/mail/code@"+d),
|
|
artifactOf("server", "image", d, "10.0.0.1:5000/mail@"+d),
|
|
artifactOf("server", "image", d, "10.0.0.1:5000/mail/server@"+other),
|
|
artifactOf("server", "image", d, "mail/server@"+d),
|
|
artifactOf("server", "image", d, "artifact-store://mail/server/blobs/"+d),
|
|
artifactOf("lib", "package", d, "@novox/mesh-sdk"),
|
|
artifactOf("lib", "package", d, "0.1.15"),
|
|
}
|
|
for _, a := range bad {
|
|
b := doneBuild()
|
|
b.Artifacts = []BuiltArtifact{a}
|
|
if _, err := EncodeBuilderBuild(b); err == nil || !strings.Contains(err.Error(), `"`+a.Name+`"`) {
|
|
t.Errorf("%+v: %v, wanted a refusal naming the artifact", a, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The controller delivers only from a done key whose every artifact names a reference (ADR 0498 clause 8): Referenced
|
|
// says so and names the artifacts without one.
|
|
func TestReferencedNamesTheArtifactsWithoutAReference(t *testing.T) {
|
|
d := "sha256:" + digestOf('6')
|
|
b := doneBuild()
|
|
b.Artifacts = []BuiltArtifact{
|
|
artifactOf("code", "bundle", d, "artifact-store://mail/code/blobs/"+d),
|
|
artifactOf("server", "image", d, ""),
|
|
}
|
|
if ok, missing := b.Referenced(); ok || len(missing) != 1 || missing[0] != "server" {
|
|
t.Fatalf("Referenced = %v, %v; want false, [server]", ok, missing)
|
|
}
|
|
b.Artifacts[1].Reference = "10.0.0.1:5000/mail/server@" + d
|
|
if ok, missing := b.Referenced(); !ok || len(missing) != 0 {
|
|
t.Fatalf("Referenced = %v, %v; want true", ok, missing)
|
|
}
|
|
if ok, _ := (BuilderBuild{State: BuildQueued}).Referenced(); ok {
|
|
t.Fatal("a queued key is referenced")
|
|
}
|
|
}
|
|
|
|
// The errors a build module answers open with a fixed prefix (ADR 0498 clauses 2, 4 and 5; ADR 0478 clause 2), and three
|
|
// of them are not built again until the module's fingerprint changes; a failed push is.
|
|
func TestOnlyAPushFailureIsBuiltAgainBeforeTheFingerprintChanges(t *testing.T) {
|
|
for _, c := range []struct {
|
|
err string
|
|
again bool
|
|
}{
|
|
{NotStored + "code: the store said 500", true},
|
|
{NotPinned + "nats: upstream names no digest", false},
|
|
{VersionTaken + "@novox/mesh-sdk@0.1.15 holds another file", false},
|
|
{RefusedKind + "a package in go", false},
|
|
{"go test: 2 failed", true},
|
|
} {
|
|
if got := FailedUntilChanged(c.err); got == c.again {
|
|
t.Errorf("FailedUntilChanged(%q) = %v", c.err, got)
|
|
}
|
|
}
|
|
if NotStored != "not stored: " || NotPinned != "not pinned: " || VersionTaken != "version taken: " || RefusedKind != "refused kind: " {
|
|
t.Fatal("a prefix changed its words")
|
|
}
|
|
}
|
|
|
|
// A key whose module's lock names a version of the group's package not yet published waits, queued, saying which
|
|
// (ADR 0500 clause 6): an older reader reads it as queued, and only a queued key waits.
|
|
func TestAKeyWaitsQueuedForAPackageVersion(t *testing.T) {
|
|
b := BuilderBuild{State: BuildQueued, Manifest: digestOf('4'), Waits: "@novox/mesh-sdk@0.1.15"}
|
|
data, err := EncodeBuilderBuild(b)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
back, err := DecodeBuilderBuild(data)
|
|
if err != nil || back.Waits != b.Waits || back.State != BuildQueued {
|
|
t.Fatalf("decoded %+v, %v", back, err)
|
|
}
|
|
building := BuilderBuild{State: BuildBuilding, By: "x", Waits: "@novox/mesh-sdk@0.1.15"}
|
|
if _, err := EncodeBuilderBuild(building); err == nil {
|
|
t.Fatal("a building key that waits was accepted")
|
|
}
|
|
if _, err := EncodeBuilderBuild(BuilderBuild{State: BuildQueued, Waits: "mesh-sdk"}); err == nil {
|
|
t.Fatal("a wait naming no version was accepted")
|
|
}
|
|
}
|