Let go of a hold whose resource is no longer declared, touching nothing on disk (hq ADR 0100)
This commit is contained in:
+135
-2
@@ -332,8 +332,141 @@ func TestAHeldFileIsNeverRemovedWhenItsModuleIsUnassigned(t *testing.T) {
|
||||
if m.removed("hello-web") {
|
||||
t.Fatal("a held container was removed when its module left")
|
||||
}
|
||||
if _, still := state.HeldAt("hello-web.page"); !still {
|
||||
t.Error("the hold was forgotten, so a return of the module would read the file as the mesh's")
|
||||
if _, still := state.HeldAt("hello-web.page"); still {
|
||||
t.Error("a hold outlived its resource leaving the declaration, so the node reports it for ever")
|
||||
}
|
||||
if _, recorded := state.Find("hello-web.page"); recorded {
|
||||
t.Error("a file let go was recorded as the mesh's")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAHoldNoLongerDeclaredIsLetGoAndFoundAgainIfItsModuleReturns(t *testing.T) {
|
||||
dir, page, m := predecessor(t)
|
||||
_, state := applyAdopted(t, adopted(t, untakenWeb, webResources(page)), store.State{}, m, dir)
|
||||
first, _ := state.HeldAt("hello-web.page")
|
||||
|
||||
report, state := applyAdopted(t, adopted(t, `{"taken":[]}`, withConf(dir)), state, m, dir)
|
||||
if o := outcomeOf(report, "hello-web.page"); o.Action != "forgotten" || o.Detail != "no longer declared; left as found" {
|
||||
t.Errorf("letting a hold go was not reported: %+v", o)
|
||||
}
|
||||
if len(state.Held) != 0 {
|
||||
t.Errorf("holds outlived their resources: %+v", state.Held)
|
||||
}
|
||||
|
||||
// The module comes back: what is there is found again, and the original first kept stays.
|
||||
if err := os.WriteFile(page, []byte("the predecessor wrote again\n"), 0o640); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
report, state = applyAdopted(t, adopted(t, untakenWeb, webResources(page)), state, m, dir)
|
||||
if o := outcomeOf(report, "hello-web.page"); o.Action != "held" {
|
||||
t.Fatalf("a returning module's found file was not held again: %+v", o)
|
||||
}
|
||||
again, _ := state.HeldAt("hello-web.page")
|
||||
if kept, _ := os.ReadFile(again.Kept); again.Kept != first.Kept || string(kept) != "the predecessor's page\n" {
|
||||
t.Errorf("the first kept original was lost: %s %q", again.Kept, kept)
|
||||
}
|
||||
if got, _ := os.ReadFile(page); string(got) != "the predecessor wrote again\n" {
|
||||
t.Errorf("the found file was touched: %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestACarriedApplyLetsNoHoldGo(t *testing.T) {
|
||||
dir, page, m := predecessor(t)
|
||||
_, state := applyAdopted(t, adopted(t, untakenWeb, webResources(page)), store.State{}, m, dir)
|
||||
carried := parse(t, `{"declaration":1,"resources":[`+withConf(dir)+`]}`)
|
||||
_, state, err := ApplyKeeping(context.Background(), archHost(t), carried, state, store.OriginCarried,
|
||||
m.run, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(state.Held) != 2 {
|
||||
t.Errorf("a carried apply let holds go: %+v", state.Held)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAHeldFileRewrittenIsReportedAndNotReverted(t *testing.T) {
|
||||
dir, page, m := predecessor(t)
|
||||
d := adopted(t, untakenWeb, webResources(page))
|
||||
_, state := applyAdopted(t, d, store.State{}, m, dir)
|
||||
|
||||
if err := os.WriteFile(page, []byte("the predecessor wrote again\n"), 0o640); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
report, state := applyAdopted(t, d, state, m, dir)
|
||||
if got, _ := os.ReadFile(page); string(got) != "the predecessor wrote again\n" {
|
||||
t.Fatalf("a held file was reverted: %q", got)
|
||||
}
|
||||
if h, _ := state.HeldAt("hello-web.page"); h.Changed != "rewritten" || h.ChangedAt.IsZero() {
|
||||
t.Errorf("a rewrite was not recorded: %+v", h)
|
||||
}
|
||||
if o := outcomeOf(report, "hello-web.page"); !strings.Contains(o.Detail, "rewritten") {
|
||||
t.Errorf("a rewrite was not reported: %+v", o)
|
||||
}
|
||||
h, _ := state.HeldAt("hello-web.page")
|
||||
if kept, _ := os.ReadFile(h.Kept); string(kept) != "the predecessor's page\n" {
|
||||
t.Errorf("the kept original was overwritten by a later write: %q", kept)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAHeldContainerStoppedOrReplacedIsReportedAndNotRestarted(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
change func(*machine)
|
||||
want string
|
||||
}{
|
||||
{func(m *machine) { m.containers["hello-web"].running = false }, "stopped"},
|
||||
{func(m *machine) { m.containers["hello-web"].id = "another" }, "replaced"},
|
||||
{func(m *machine) { delete(m.containers, "hello-web") }, "gone"},
|
||||
} {
|
||||
dir, page, m := predecessor(t)
|
||||
d := adopted(t, untakenWeb, webResources(page))
|
||||
_, state := applyAdopted(t, d, store.State{}, m, dir)
|
||||
c.change(m)
|
||||
m.asked = nil
|
||||
_, state = applyAdopted(t, d, state, m, dir)
|
||||
if h, _ := state.HeldAt("hello-web.server"); h.Changed != c.want {
|
||||
t.Errorf("%s: recorded as %q", c.want, h.Changed)
|
||||
}
|
||||
for _, a := range m.asked {
|
||||
if strings.HasPrefix(a, "docker run") || strings.HasPrefix(a, "docker rm") ||
|
||||
strings.HasPrefix(a, "docker start") {
|
||||
t.Errorf("%s: the held container was acted on: %s", c.want, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAHeldFileThatVanishesIsNotCreated(t *testing.T) {
|
||||
dir, page, m := predecessor(t)
|
||||
d := adopted(t, untakenWeb, webResources(page))
|
||||
_, state := applyAdopted(t, d, store.State{}, m, dir)
|
||||
if err := os.Remove(page); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, state = applyAdopted(t, d, state, m, dir)
|
||||
if _, err := os.Stat(page); !errors.Is(err, os.ErrNotExist) {
|
||||
t.Fatal("a held file that vanished was created before its module was taken")
|
||||
}
|
||||
if h, _ := state.HeldAt("hello-web.page"); h.Changed != "gone" {
|
||||
t.Errorf("a vanished held file was not reported gone: %+v", h)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAConvergedNodeStillReplacesWhatItFinds(t *testing.T) {
|
||||
// No adoption, no holds: byte for byte what a converged node did before ADR 0100.
|
||||
dir, page, m := predecessor(t)
|
||||
d := parse(t, `{"declaration":1,"resources":[`+webResources(page)+`]}`)
|
||||
report, state := applyAdopted(t, d, store.State{}, m, dir)
|
||||
if got, _ := os.ReadFile(page); string(got) != "the mesh's page\n" {
|
||||
t.Errorf("a converged node kept a found file: %q", got)
|
||||
}
|
||||
if !m.removed("hello-web") {
|
||||
t.Error("a converged node kept a found container")
|
||||
}
|
||||
if len(state.Held) != 0 || outcomeOf(report, "hello-web.page").Action == "held" {
|
||||
t.Errorf("a converged node held something: %+v", state.Held)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(dir, "kept")); !errors.Is(err, os.ErrNotExist) {
|
||||
t.Error("a converged node kept originals")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user