FileBrowser is published only after its default login is checked (R-1126); the memory refusal says what to do (R-1125)
R-1126 (D11 = A): FileBrowser starts off traefik-public, on its own network felhom-filebrowser; the controller joins it there, checks this run's default login, and only then puts FileBrowser on traefik-public (files.<domain> served). FileBrowser's own admin-password setting re-applies at every start (1.5.6 cmd/user.go:50-57, measured on 9202), so it cannot carry the box's password without overwriting the household's own. Tests red-proved. R-1125 (D10 = A): err.stacks.not_enough_memory says the memory is held by the installed apps and to remove one or use a machine with more memory (HU + EN, reworded on purpose). TestR1125_NotEnoughMemorySaysWhatToDo, red-proved. Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
@@ -244,3 +245,54 @@ func TestFileBrowserAdmin_R977_NewRunIsWaitedForInTheSameTick(t *testing.T) {
|
||||
t.Fatalf("state %q, want generated", s)
|
||||
}
|
||||
}
|
||||
|
||||
// R-1126 (D11 = A): files.<domain> is published (FileBrowser joined to traefik-public) only AFTER this run's default
|
||||
// login was checked; a check that cannot finish leaves it unpublished; a later run already published is not touched.
|
||||
// RED-PROOF (2026-10-17): ensureFileBrowserPublic without the „this run was checked" test → the unreachable case fails.
|
||||
func TestFileBrowserGate_PublishedOnlyAfterTheCheck(t *testing.T) {
|
||||
var events []string
|
||||
fb := &fakeFB{password: "admin"}
|
||||
inner := fb.handler()
|
||||
down := false
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if down {
|
||||
w.WriteHeader(http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
if r.Method == http.MethodPut {
|
||||
events = append(events, "password replaced")
|
||||
}
|
||||
inner.ServeHTTP(w, r)
|
||||
}))
|
||||
defer srv.Close()
|
||||
m, _, _ := fbManager(t, srv.URL)
|
||||
run := "run-1"
|
||||
m.fbStarted = func() string { return run }
|
||||
nets := map[string]bool{}
|
||||
m.fbNetOnFn = func(c, n string) bool { return nets[c+"@"+n] }
|
||||
m.fbNetConnectFn = func(c, n string) error {
|
||||
nets[c+"@"+n] = true
|
||||
events = append(events, "connect "+c+" "+n)
|
||||
return nil
|
||||
}
|
||||
|
||||
// A new run whose FileBrowser does not answer: nothing is published.
|
||||
down = true
|
||||
m.fileBrowserGateLocked()
|
||||
if nets["filebrowser@traefik-public"] {
|
||||
t.Fatal("published while this run's default login was never checked")
|
||||
}
|
||||
// It answers, on its default: replaced first, published after.
|
||||
down = false
|
||||
m.fileBrowserGateLocked()
|
||||
want := []string{"connect felhom-controller felhom-filebrowser", "password replaced", "connect filebrowser traefik-public"}
|
||||
if strings.Join(events, " | ") != strings.Join(want, " | ") {
|
||||
t.Fatalf("order:\n got %v\n want %v", events, want)
|
||||
}
|
||||
// A new run (a restart) on the box's own password: checked, nothing changes, nothing connected twice.
|
||||
run = "run-2"
|
||||
m.fileBrowserGateLocked()
|
||||
if len(events) != 3 {
|
||||
t.Fatalf("a checked restart did more: %v", events)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user