package store import ( "path/filepath" "testing" "time" ) // Defends the node's record across processes: a `reconcile` run by hand beside the link service, // or the installer beside either, waits for the other's apply rather than saving over it. func TestASecondApplyWaitsForTheFirst(t *testing.T) { state := filepath.Join(t.TempDir(), "state.json") release, err := Lock(state, nil) if err != nil { t.Fatal(err) } waited := make(chan struct{}, 1) got := make(chan struct{}) go func() { unlock, err := Lock(state, func() { waited <- struct{}{} }) if err != nil { t.Error(err) } close(got) unlock() }() select { case <-waited: case <-time.After(5 * time.Second): t.Fatal("the second apply was not told it is waiting") } select { case <-got: t.Fatal("the second apply took the lock while the first held it") case <-time.After(50 * time.Millisecond): } release() select { case <-got: case <-time.After(5 * time.Second): t.Fatal("the second apply never got the lock once the first let go") } }