142 lines
5.2 KiB
Go
142 lines
5.2 KiB
Go
package view
|
|
|
|
import (
|
|
"bytes"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
const (
|
|
hA = "0123456789abcdef0123456789abcdef01234567"
|
|
hB = "89abcdef0123456789abcdef0123456789abcdef"
|
|
fF = "src1:1111111111111111111111111111111111111111111111111111111111111111"
|
|
fG = "src1:2222222222222222222222222222222222222222222222222222222222222222"
|
|
)
|
|
|
|
func candidate(t *testing.T, group string, pulls ...delivery.CandidatePull) Entry {
|
|
t.Helper()
|
|
heads := make([]delivery.Head, len(pulls))
|
|
for i, p := range pulls {
|
|
heads[i] = p.Head
|
|
}
|
|
hash, err := delivery.HeadsHash(heads)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
b, err := delivery.EncodeCandidate(delivery.Candidate{Group: group, HeadsHash: hash, Pulls: pulls})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return Entry{Bucket: delivery.CandidatesBucket, Key: group, Value: b, At: t0}
|
|
}
|
|
|
|
func pullOf(repo string, n int, head string, modules ...string) delivery.CandidatePull {
|
|
if modules == nil {
|
|
modules = []string{}
|
|
}
|
|
return delivery.CandidatePull{Head: delivery.Head{Repository: repo, Number: n, Head: head}, Modules: modules}
|
|
}
|
|
|
|
func modEntry(t *testing.T, name string, m delivery.Module) Entry {
|
|
t.Helper()
|
|
b, err := delivery.EncodeModule(m)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return Entry{Bucket: delivery.ModulesBucket, Key: name, Value: b, At: t0}
|
|
}
|
|
|
|
func fpRow(t *testing.T, s Snapshot, module string) FingerprintRow {
|
|
t.Helper()
|
|
for _, f := range s.Fingerprints {
|
|
if f.Module == module {
|
|
return f
|
|
}
|
|
}
|
|
t.Fatalf("no fingerprint row for %s in %+v", module, s.Fingerprints)
|
|
return FingerprintRow{}
|
|
}
|
|
|
|
func TestSnapshotListsTheCandidateGroups(t *testing.T) { // 1241/AC1
|
|
m := New()
|
|
fill(m,
|
|
candidate(t, "feat/x", pullOf("novox/mesh-delivery", 12, hA, "a", "b"), pullOf("novox/mesh-catalog", 300, hB, "c")),
|
|
candidate(t, "feat/y", pullOf("novox/mesh-delivery", 13, hB)))
|
|
g := m.Snapshot().Groups
|
|
if len(g) != 2 || g[0].Group != "feat/x" || g[1].Group != "feat/y" {
|
|
t.Fatalf("groups = %+v", g)
|
|
}
|
|
// sorted by repository: mesh-catalog before mesh-delivery
|
|
if len(g[0].Pulls) != 2 || g[0].Pulls[0].Repository != "novox/mesh-catalog" || g[0].Pulls[0].Number != 300 {
|
|
t.Fatalf("pulls = %+v", g[0].Pulls)
|
|
}
|
|
p := g[0].Pulls[1]
|
|
if p.Repository != "novox/mesh-delivery" || p.Number != 12 || p.Head != hA[:12] || strings.Join(p.Modules, ",") != "a,b" {
|
|
t.Errorf("pull = %+v, want #12 with head %s and modules a,b", p, hA[:12])
|
|
}
|
|
if len(g[1].Pulls) != 1 || len(g[1].Pulls[0].Modules) != 0 {
|
|
t.Errorf("feat/y = %+v", g[1])
|
|
}
|
|
m.Apply(Entry{Bucket: delivery.CandidatesBucket, Key: "feat/x", Deleted: true})
|
|
if g := m.Snapshot().Groups; len(g) != 1 || g[0].Group != "feat/y" {
|
|
t.Errorf("after the delete: %+v", g)
|
|
}
|
|
}
|
|
|
|
// 1955/L7 (ADR 0571 §1): the view reads no build record of the controller's: a module with no fingerprint of the new
|
|
// form is said so, never compared with the controller's builds.
|
|
func TestAModuleOfTheOldFormIsComparedWithNoBuild(t *testing.T) {
|
|
m := New()
|
|
fill(m,
|
|
modEntry(t, "a", delivery.Module{FP: fF, Repository: "novox/mesh-delivery", Commit: hA}),
|
|
modEntry(t, "b", delivery.Module{None: "an artifact compiles a Go program from a build source that git trees do not pin: no fingerprint before release 4", Repository: "novox/mesh-delivery", Commit: hA}))
|
|
s := m.Snapshot()
|
|
for _, name := range []string{"a", "b"} {
|
|
if r := fpRow(t, s, name); r.State != FPNone || !(strings.Contains(r.Reason, "new form") || strings.Contains(r.Reason, "release 4")) || r.Build != "" {
|
|
t.Errorf("%s = %+v, want none: no build of the builder's is compared", name, r)
|
|
}
|
|
}
|
|
}
|
|
|
|
func shown(t *testing.T) *Model {
|
|
m := New()
|
|
fill(m,
|
|
candidate(t, "feat/x", pullOf("novox/mesh-delivery", 12, hA, "a"), pullOf("novox/mesh-catalog", 300, hB, "c")),
|
|
modEntry(t, "a", delivery.Module{FP2: fp2A, Repository: "novox/mesh-delivery", Commit: hA}),
|
|
builderKey(t, "a", fp2A, delivery.BuilderBuild{State: delivery.BuildFailed, Error: "the compile failed"}),
|
|
modEntry(t, "b", delivery.Module{None: "no tree", Repository: "novox/mesh-delivery", Commit: hA}))
|
|
return m
|
|
}
|
|
|
|
func TestTableAndPagePrintTheGroupsAndTheComparison(t *testing.T) { // 1241/AC6
|
|
m := shown(t)
|
|
var out bytes.Buffer
|
|
Table(&out, m.Snapshot())
|
|
for _, want := range []string{"CANDIDATES", "feat/x", "novox/mesh-delivery#12", hA[:12], "novox/mesh-catalog#300", "FINGERPRINT", "the compile failed", fp2A, "no tree"} {
|
|
if !strings.Contains(out.String(), want) {
|
|
t.Errorf("the table lacks %q:\n%s", want, out.String())
|
|
}
|
|
}
|
|
rec := httptest.NewRecorder()
|
|
Web(m).ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil))
|
|
for _, want := range []string{"CANDIDATES", "feat/x", "novox/mesh-delivery#12", hA[:12], "FINGERPRINTS", "the compile failed", fp2A, "no tree"} {
|
|
if !strings.Contains(rec.Body.String(), want) {
|
|
t.Errorf("the page lacks %q:\n%s", want, rec.Body.String())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUnreadableIndexerValuesAreNamed(t *testing.T) { // never dropped silently
|
|
m := New()
|
|
fill(m, Entry{Bucket: delivery.CandidatesBucket, Key: "feat/x", Value: []byte("{"), At: t0},
|
|
Entry{Bucket: delivery.ModulesBucket, Key: "a", Value: []byte("{"), At: t0})
|
|
s := m.Snapshot()
|
|
if len(s.Unreadable) != 2 || len(s.Groups) != 0 || len(s.Fingerprints) != 0 {
|
|
t.Errorf("snapshot = %+v", s)
|
|
}
|
|
}
|