Split the unit level from the integration level in cmd, builder, link, catalogue, inventory; cheap fixtures for the archive-entry bound, the registry waits and the catalogue copy (issue 895)
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
//go:build integration
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/novox/mesh-controller/internal/catalogue"
|
||||
)
|
||||
|
||||
func TestAnAssignmentWithoutItsHolderIsRefusedAndNotKept(t *testing.T) {
|
||||
open := aMesh(t)
|
||||
ctx := t.Context()
|
||||
register(t, open, serviceManagerHolder())
|
||||
register(t, open, packageManagerHolder())
|
||||
register(t, open, aDaemon())
|
||||
|
||||
_, err := assign(ctx, open, "laptop", "sshd")
|
||||
if err == nil {
|
||||
t.Fatal("sshd went onto a machine nothing holds the service manager of")
|
||||
}
|
||||
for _, want := range []string{catalogue.ServiceManagerSeat, "systemd", "ADR 0207"} {
|
||||
if !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("the refusal does not say %q:\n%v", want, err)
|
||||
}
|
||||
}
|
||||
assigned, err := open.inventory.Assigned(ctx, "laptop")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if contains(assigned, "sshd") {
|
||||
t.Fatalf("a refused assignment was kept: %v", assigned)
|
||||
}
|
||||
|
||||
// The holders depend on each other, so neither goes on alone — and both go on in one act.
|
||||
if _, err := assign(ctx, open, "laptop", "systemd"); err == nil {
|
||||
t.Fatal("systemd went on alone though its package needs a package manager")
|
||||
}
|
||||
if said, err := assign(ctx, open, "laptop", "systemd", "pacman"); err != nil {
|
||||
t.Fatalf("the two holders assigned together were refused: %v\n%s", err, said)
|
||||
}
|
||||
if said, err := assign(ctx, open, "laptop", "sshd"); err != nil {
|
||||
t.Fatalf("sshd beside its holder was refused: %v\n%s", err, said)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnassigningTheLastHolderUnderItsDependentsIsRefused(t *testing.T) {
|
||||
open := aMesh(t)
|
||||
ctx := t.Context()
|
||||
register(t, open, serviceManagerHolder())
|
||||
register(t, open, packageManagerHolder())
|
||||
register(t, open, aDaemon())
|
||||
if _, err := assign(ctx, open, "laptop", "systemd", "pacman", "sshd"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err := unassign(ctx, open, "laptop", "systemd")
|
||||
if err == nil {
|
||||
t.Fatal("the service manager came off a machine still running services")
|
||||
}
|
||||
for _, want := range []string{catalogue.ServiceManagerSeat, "sshd", "pacman"} {
|
||||
if !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("the refusal does not name %q:\n%v", want, err)
|
||||
}
|
||||
}
|
||||
assigned, _ := open.inventory.Assigned(ctx, "laptop")
|
||||
if !contains(assigned, "systemd") {
|
||||
t.Fatalf("a refused unassignment took the module off anyway: %v", assigned)
|
||||
}
|
||||
if _, err := unassign(ctx, open, "laptop", "sshd"); err != nil {
|
||||
t.Fatalf("a dependent could not come off: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatusReportsAnUnheldDependencyWithoutRefusingTheMachine(t *testing.T) {
|
||||
// The mesh as it ran before the switch (novox/hq ADR 0207 §4).
|
||||
defer catalogue.EnforcingSeatDependencies(false)()
|
||||
open := aMesh(t)
|
||||
ctx := t.Context()
|
||||
register(t, open, serviceManagerHolder())
|
||||
register(t, open, aDaemon())
|
||||
// Assigned straight into the store: a machine whose modules predate the rule, which is every
|
||||
// machine on the day it ships.
|
||||
if _, err := open.inventory.Assign(ctx, "laptop", "sshd"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
asked, err := theThreeQuestions(ctx, open)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, refused := asked.refused["laptop"]; refused {
|
||||
t.Fatalf("an unmet dependency refused the machine before the switch: %s", asked.refused["laptop"])
|
||||
}
|
||||
if asked.well() {
|
||||
t.Error("a mesh with an unheld dependency reads as all well")
|
||||
}
|
||||
got := printed(t, func() error { return printStatus(asked) })
|
||||
for _, want := range []string{"unheld", "laptop", "sshd", catalogue.ServiceManagerSeat, "systemd"} {
|
||||
if !strings.Contains(got, want) {
|
||||
t.Errorf("status does not say %q:\n%s", want, got)
|
||||
}
|
||||
}
|
||||
body, err := statusAsJSON(asked)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var doc struct {
|
||||
Unheld []catalogue.Unheld `json:"unheld"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &doc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(doc.Unheld) != 1 || doc.Unheld[0].Module != "sshd" || doc.Unheld[0].Seat != catalogue.ServiceManagerSeat {
|
||||
t.Errorf("the document's unheld is %+v", doc.Unheld)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user