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:
@@ -1,10 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -19,63 +17,6 @@ import (
|
||||
"github.com/novox/mesh-controller/internal/outward"
|
||||
)
|
||||
|
||||
// **Every condition this suite raises says itself in machine names and words** (novox/hq issue 277,
|
||||
// ADR 0234 §6). Every observation a keeper takes in any test of this package — every signals row
|
||||
// suppressed past its bound, every probe's finding, every event's condition — is held to the operator
|
||||
// channel's content rule; one whose summary or key carries an address, a domain, a path or a secret's
|
||||
// shape fails the suite, naming its source. The keeper would say such a summary in words at run time;
|
||||
// this is where the producer is made to say it rightly in the first place.
|
||||
func TestMain(m *testing.M) {
|
||||
// **A command line this suite runs ends when it is done** (novox/hq issue 591). Many tests run this test
|
||||
// binary as a verb's command line, and a binary built with the race detector sleeps a second before it
|
||||
// exits (GORACE's atexit_sleep_ms), which was more than the rest of each such test. The children still
|
||||
// run under the race detector and still fail on a race they find; they only stop waiting at their end.
|
||||
// Set before any child starts, and only where nobody chose GORACE.
|
||||
if _, chosen := os.LookupEnv("GORACE"); !chosen {
|
||||
_ = os.Setenv("GORACE", "atexit_sleep_ms=0")
|
||||
}
|
||||
// The process a mesh-cli test runs as a command line: it says the verb and the caller it was given, and
|
||||
// ends (meshcli_test.go).
|
||||
// The process a mesh-cli test runs as `secret accept`: it reads its value exactly as `secret accept` does
|
||||
// (valueFor) and says whether it is the one the test gave, never the value (meshcli_stdin_test.go).
|
||||
if want := os.Getenv(secretAcceptWants); want != "" {
|
||||
os.Exit(readAsSecretAccept(want, os.Args[1:]))
|
||||
}
|
||||
if os.Getenv(echoEnvironment) != "" {
|
||||
fmt.Printf("verb=%q caller=%q terminal=%v\n", os.Getenv("MESH_VERB"), os.Getenv("MESH_CALLER"), startedAtTheTerminal())
|
||||
if os.Getenv(echoFails) != "" {
|
||||
os.Exit(3)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
conditions.Unsayable = func(o conditions.Observation, field string, r outward.Refusal) {
|
||||
unsaid.note(o, field, r)
|
||||
}
|
||||
conditions.Unworded = func(o conditions.Observation, why string) {
|
||||
if o.Source != "test" { // a kind a test makes up to exercise the keeper
|
||||
unworded.add(o, why)
|
||||
}
|
||||
}
|
||||
code := m.Run()
|
||||
if said := unworded.all(); len(said) > 0 {
|
||||
fmt.Fprintf(os.Stderr, "FAIL: %d condition(s) raised in these tests have no plain words of their own, or "+
|
||||
"words that are not plain (novox/hq ADR 0253: a headline, an explanation and a resolved line the operator "+
|
||||
"reads at a glance — plain_words.go):\n %s\n", len(said), strings.Join(said, "\n "))
|
||||
if code == 0 {
|
||||
code = 1
|
||||
}
|
||||
}
|
||||
if said := unsaid.all(); len(said) > 0 {
|
||||
fmt.Fprintf(os.Stderr, "FAIL: %d condition(s) raised in these tests say what the operator's channel withholds "+
|
||||
"(an address, a domain, a path or a secret's shape belongs in the evidence, not the summary):\n %s\n",
|
||||
len(said), strings.Join(said, "\n "))
|
||||
if code == 0 {
|
||||
code = 1
|
||||
}
|
||||
}
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
// unsaid collects, across the suite, every finding whose words the operator's channel would withhold.
|
||||
var unsaid unsayable
|
||||
|
||||
@@ -284,79 +225,3 @@ func TestAResolverAnsweringWronglyIsSaidAtOnceInMachineNames(t *testing.T) {
|
||||
// **The self-check raises a finding one look can be wrong about on the second run in a row**, keeps it
|
||||
// open while it is seen, and clears it when it is not — and a probe that cannot run is said as a
|
||||
// condition only when the next run cannot run it either. Neither is ever a pass in the verdict.
|
||||
func TestASingleLookIsHeldAndTheSecondInARowRaises(t *testing.T) {
|
||||
var unanswered, broken atomic.Bool
|
||||
held := conditions.Observation{Scope: conditions.ScopeSeat, ID: "mesh-dns-resolver.anchor", Token: "wrong",
|
||||
Machine: "anchor", Severity: conditions.Urgent, Confirm: true,
|
||||
Summary: "the mesh's resolver on anchor does not answer", Said: "no answer from 10.77.0.1"}
|
||||
withProbes(t,
|
||||
probe{ID: "P1", Asserts: "asks over the network", Kind: "resolver-wrong", Phase: 1,
|
||||
run: func(context.Context, *doctor) ([]conditions.Observation, error) {
|
||||
if unanswered.Load() {
|
||||
return []conditions.Observation{held}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}},
|
||||
probe{ID: "P2", Asserts: "sometimes cannot run", Kind: "x", Phase: 1,
|
||||
run: func(context.Context, *doctor) ([]conditions.Observation, error) {
|
||||
if broken.Load() {
|
||||
return nil, fmt.Errorf("a question timed out")
|
||||
}
|
||||
return nil, nil
|
||||
}},
|
||||
)
|
||||
store := conditions.NewInMemory()
|
||||
k := conditions.NewKeeper(t.Context(), conditions.Options{Store: store, History: store})
|
||||
defer k.Close(context.Background())
|
||||
d := &doctor{keeper: k, host: "anchor"}
|
||||
keys := func() []string {
|
||||
open, err := k.Open(t.Context())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var out []string
|
||||
for _, c := range open {
|
||||
out = append(out, c.Key)
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
|
||||
unanswered.Store(true)
|
||||
broken.Store(true)
|
||||
run := d.runOnce(t.Context(), "a test")
|
||||
if open := keys(); len(open) != 0 {
|
||||
t.Fatalf("one look raised %v", open)
|
||||
}
|
||||
if run.Probes[0].Verdict != verdictPass || len(run.Probes[0].Unconfirmed) != 1 || run.Probes[1].Verdict != verdictFailedToRun {
|
||||
t.Fatalf("the first run's verdict hides what it saw: %+v", run.Probes)
|
||||
}
|
||||
|
||||
// Seen twice in a row: raised, and so is the probe that could not run twice.
|
||||
run = d.runOnce(t.Context(), "a test")
|
||||
if open := keys(); strings.Join(open, " ") != "probe.P2.failed seat.mesh-dns-resolver.anchor.wrong" {
|
||||
t.Fatalf("two looks in a row left open %v", open)
|
||||
}
|
||||
if run.Probes[0].Verdict != verdictFail {
|
||||
t.Fatalf("%+v", run.Probes[0])
|
||||
}
|
||||
|
||||
// Open, and seen again: kept, never cleared and raised again.
|
||||
d.runOnce(t.Context(), "a test")
|
||||
if c, open, _ := k.Get(t.Context(), "seat.mesh-dns-resolver.anchor.wrong"); !open || c.Count != 1 || c.Observations != 2 {
|
||||
t.Fatalf("the open condition was not kept as it was: %+v", c)
|
||||
}
|
||||
|
||||
// Answered again: cleared. Then one look alone raises nothing again.
|
||||
unanswered.Store(false)
|
||||
broken.Store(false)
|
||||
d.runOnce(t.Context(), "a test")
|
||||
if open := keys(); len(open) != 0 {
|
||||
t.Fatalf("a passing run left open %v", open)
|
||||
}
|
||||
unanswered.Store(true)
|
||||
d.runOnce(t.Context(), "a test")
|
||||
if open := keys(); len(open) != 0 {
|
||||
t.Fatalf("one look after a pass raised %v", open)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user