controller v0.72.0: FileBrowser converges on boot-recreate
processGuestBootChange recreated the drive-backed app stacks but never re-synced FileBrowser (base-infra, no HDD_PATH), so its drive mounts went stale after a reboot. Now, AFTER pollLiveBinds confirms the live binds and the apps are recreated, trigger go s.SyncFileBrowserMounts() so FileBrowser converges against the now-live drives. Refactored into pure recreateDriveBackedApps(stacks, present, recreate, syncFB). Tests: FB sync runs once after recreate (red-proofed companion); runs even when nothing recreated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -139,6 +139,43 @@ func TestPollLiveBinds_TimeoutLeavesAbsent(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestRecreateDriveBackedApps_SyncsFileBrowserAfterRecreate (Task B): FileBrowser must be re-synced
|
||||
// AFTER the drive-backed apps are recreated (so it syncs against live binds). COMPANION: the pre-fix
|
||||
// boot-recreate path never synced FileBrowser — red-proofed by dropping the syncFB() call.
|
||||
func TestRecreateDriveBackedApps_SyncsFileBrowserAfterRecreate(t *testing.T) {
|
||||
flash := "/mnt/felhom-drives/felhom-flash"
|
||||
present := map[string]bool{flash: true}
|
||||
stacks := []bootStack{
|
||||
{name: "romm", deployed: true, hdd: flash}, // drive-backed, live → recreate
|
||||
{name: "actualbudget", deployed: true, hdd: "/mnt/sys_drive/felhom-data"}, // SSD → not recreated
|
||||
{name: "stranded", deployed: true, hdd: "/mnt/felhom-drives/felhom-usb"}, // drive-backed, bind NOT live → skipped
|
||||
}
|
||||
var seq []string
|
||||
recreate := func(bs bootStack) { seq = append(seq, "recreate:"+bs.name) }
|
||||
syncFB := func() { seq = append(seq, "syncFB") }
|
||||
|
||||
recreated, skipped := recreateDriveBackedApps(stacks, present, recreate, syncFB)
|
||||
|
||||
if recreated != 1 || skipped != 1 {
|
||||
t.Fatalf("recreated=%d skipped=%d, want 1/1", recreated, skipped)
|
||||
}
|
||||
// FileBrowser sync MUST be invoked, and AFTER every recreate.
|
||||
if len(seq) != 2 || seq[0] != "recreate:romm" || seq[len(seq)-1] != "syncFB" {
|
||||
t.Fatalf("FileBrowser sync must run once, AFTER the recreate; seq=%v", seq)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRecreateDriveBackedApps_SyncsEvenWithNoRecreate: FileBrowser is re-synced to reflect the live
|
||||
// binds even when no app needed recreating (so its mounts never go stale).
|
||||
func TestRecreateDriveBackedApps_SyncsEvenWithNoRecreate(t *testing.T) {
|
||||
stacks := []bootStack{{name: "x", deployed: true, hdd: "/mnt/sys_drive/felhom-data"}} // SSD only
|
||||
synced := false
|
||||
recreateDriveBackedApps(stacks, map[string]bool{}, func(bootStack) { t.Fatal("should not recreate") }, func() { synced = true })
|
||||
if !synced {
|
||||
t.Fatal("FileBrowser sync must run even when nothing was recreated")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStablePathForName(t *testing.T) {
|
||||
if got := stablePathForName("felhom-usb"); got != "/mnt/felhom-drives/felhom-usb" {
|
||||
t.Errorf("stablePathForName = %q", got)
|
||||
|
||||
Reference in New Issue
Block a user