Unify trunk on main: initialization → main #3
@@ -1298,3 +1298,65 @@ func TestAContainerGivenNoNamesIsRunAsBefore(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Defends the ordering half of novox/hq work breakdown 1.3: resources are applied in the order
|
||||
// the module declared them.
|
||||
//
|
||||
// **Already true, and untested until now** — the apply loop walks `d.Resources` and sorts nothing,
|
||||
// so a module that needs one thing before another says so by writing it first. Worth an assertion
|
||||
// because it is the kind of property a later change would break silently: sorting the resources
|
||||
// for any good reason at all — by type, by identity, for a tidier report — would still pass every
|
||||
// other test in this package.
|
||||
//
|
||||
// It is sequence, not readiness. A container started is not a container ready, and nothing here
|
||||
// waits: what depends on something being *usable* retries, which is what both example
|
||||
// provisioners do and is more robust than start ordering, because a dependency can also restart
|
||||
// long after everything was applied.
|
||||
func TestResourcesAreAppliedInTheOrderTheyWereDeclared(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
var order []string
|
||||
done := map[string]bool{}
|
||||
run := func(_ context.Context, name string, args ...string) (string, error) {
|
||||
order = append(order, name+" "+strings.Join(args, " "))
|
||||
// `verify` is the idempotency check, so it has to fail before the step and pass after —
|
||||
// a stub that always succeeds means every action is already done and nothing ever runs,
|
||||
// which is what the first version of this test measured.
|
||||
if name == "check" {
|
||||
if !done[args[0]] {
|
||||
return "", fmt.Errorf("not yet")
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
done[args[0]] = true
|
||||
return "", nil
|
||||
}
|
||||
|
||||
_ = dir
|
||||
// Trusted, because the link may not carry an action and only a bundle may (novox/hq ADR 0005).
|
||||
// Actions are used here because they are the one shape whose execution is observable through
|
||||
// the runner, which is what makes the order visible at all.
|
||||
d, err := declaration.ParseTrusted([]byte(`{"declaration":1,"resources":[` +
|
||||
`{"id":"first","type":"action","command":["step","one"],"verify":["check","one"]},` +
|
||||
`{"id":"second","type":"action","command":["step","two"],"verify":["check","two"]},` +
|
||||
`{"id":"third","type":"action","command":["step","three"],"verify":["check","three"]}]}`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, _, err := Apply(context.Background(), archHost(t), d, store.State{},
|
||||
store.OriginCarried, run, nil, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var ran []string
|
||||
for _, line := range order {
|
||||
if strings.HasPrefix(line, "step ") {
|
||||
ran = append(ran, strings.TrimPrefix(line, "step "))
|
||||
}
|
||||
}
|
||||
want := []string{"one", "two", "three"}
|
||||
if strings.Join(ran, ",") != strings.Join(want, ",") {
|
||||
t.Fatalf("declared one, two, three and ran %v — a module that needs one thing before "+
|
||||
"another has no way to say so", ran)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user