diff --git a/internal/k8s/job_helpers_test.go b/internal/k8s/job_helpers_test.go index c7dec1d..b732499 100644 --- a/internal/k8s/job_helpers_test.go +++ b/internal/k8s/job_helpers_test.go @@ -46,6 +46,12 @@ func TestJobSupportHelpersCoverFallbackAndFormattingBranches(t *testing.T) { if got := parseBoolWithDefault("yes", false); got != true { t.Fatalf("expected explicit true parse, got %v", got) } + if got := parseBoolWithDefault("0", true); got != false { + t.Fatalf("expected numeric false parse, got %v", got) + } + if got := parseBoolWithDefault("maybe", false); got != false { + t.Fatalf("expected unknown value to fall back, got %v", got) + } } func TestJobNameBackupCommandAndResticEnvCoverRemainingBranches(t *testing.T) { diff --git a/internal/k8s/jobs_test.go b/internal/k8s/jobs_test.go index 877ba9f..1d4bd93 100644 --- a/internal/k8s/jobs_test.go +++ b/internal/k8s/jobs_test.go @@ -167,6 +167,15 @@ func TestResolvePVCMountedNodeIgnoresDeadPodsAndFindsMountedClaim(t *testing.T) if err != nil || nodeName != "" { t.Fatalf("expected missing pvc mount to return empty node, got %q %v", nodeName, err) } + + clientset := k8sfake.NewSimpleClientset() + clientset.PrependReactor("list", "pods", func(action k8stesting.Action) (bool, runtime.Object, error) { + return true, nil, errors.New("resolve pods exploded") + }) + client = &Client{Clientset: clientset} + if _, err := client.resolvePVCMountedNode(context.Background(), "apps", "data"); err == nil || !strings.Contains(err.Error(), "resolve pods exploded") { + t.Fatalf("expected pod list error, got %v", err) + } } func TestReadBackupJobLogCoversSuccessAndListFailures(t *testing.T) { diff --git a/internal/server/restore_handlers_test.go b/internal/server/restore_handlers_test.go index 354910d..eebeec4 100644 --- a/internal/server/restore_handlers_test.go +++ b/internal/server/restore_handlers_test.go @@ -528,6 +528,9 @@ func TestExecuteRestoreResticAndHelperFunctions(t *testing.T) { if got := targetPVCName("", "Data_PVC"); got != "restore-data-pvc" { t.Fatalf("expected default restore prefix, got %q", got) } + if got := targetPVCName("___", "Data_PVC"); got != "restore-data-pvc" { + t.Fatalf("expected sanitized-empty prefix to fall back to restore, got %q", got) + } if got := targetPVCName("drill", "cache"); got != "drill-cache" { t.Fatalf("expected explicit prefix, got %q", got) } diff --git a/internal/server/server_test.go b/internal/server/server_test.go index ecac3eb..0eeaa4a 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -1097,6 +1097,55 @@ func TestParseResticStoredBytesFromJSONSummary(t *testing.T) { } } +func TestParseResticStoredBytesRejectsEmptyAndInvalidSummaries(t *testing.T) { + testCases := []string{ + "", + `{"message_type":"summary","data_added":"not-a-number"}`, + `Added to the repository: 120.500 MiB (not-a-size stored)`, + } + + for _, logBody := range testCases { + if value, ok := parseResticStoredBytes(logBody); ok || value != 0 { + t.Fatalf("expected invalid summary to fail parse, got value=%f ok=%v for %q", value, ok, logBody) + } + } +} + +func TestHandleUICoversMethodNilRendererAndIndexErrors(t *testing.T) { + t.Run("method not allowed", func(t *testing.T) { + srv := &Server{} + req := httptest.NewRequest(http.MethodPost, "/", nil) + res := httptest.NewRecorder() + + srv.handleUI(res, req) + if res.Code != http.StatusMethodNotAllowed { + t.Fatalf("expected method not allowed, got %d", res.Code) + } + }) + + t.Run("nil renderer", func(t *testing.T) { + srv := &Server{} + req := httptest.NewRequest(http.MethodGet, "/", nil) + res := httptest.NewRecorder() + + srv.handleUI(res, req) + if res.Code != http.StatusInternalServerError || !strings.Contains(res.Body.String(), "UI renderer is unavailable") { + t.Fatalf("expected nil renderer error, got %d %q", res.Code, res.Body.String()) + } + }) + + t.Run("index render failure", func(t *testing.T) { + srv := &Server{ui: &uiRenderer{}} + req := httptest.NewRequest(http.MethodGet, "/", nil) + res := httptest.NewRecorder() + + srv.handleUI(res, req) + if res.Code != http.StatusInternalServerError || !strings.Contains(res.Body.String(), "UI assets are not available") { + t.Fatalf("expected ui index error, got %d %q", res.Code, res.Body.String()) + } + }) +} + func TestMetricsStayPublic(t *testing.T) { srv := &Server{ cfg: &config.Config{AuthRequired: true, AllowedGroups: []string{"admin"}},