From 4db44f7a263308f36ef0dcfff3691d71857b2d90 Mon Sep 17 00:00:00 2001 From: rcourtman <8825017+rcourtman@users.noreply.github.com> Date: Tue, 1 Sep 2026 18:59:01 +0100 Subject: [PATCH] Handle unloaded user manager teardown --- ...ure_runtime_rootless_qualification_test.go | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/scripts/installtests/secure_runtime_rootless_qualification_test.go b/scripts/installtests/secure_runtime_rootless_qualification_test.go index f8e85ccb8..3d9540773 100644 --- a/scripts/installtests/secure_runtime_rootless_qualification_test.go +++ b/scripts/installtests/secure_runtime_rootless_qualification_test.go @@ -1183,9 +1183,43 @@ func rootlessQualStopUnit(t *testing.T, unit string) { if stateErr == nil && strings.TrimSpace(loadState) == "not-found" { return } + activeState, activeErr := rootlessQualCommandError(30*time.Second, "systemctl", "show", "--property=ActiveState", "--value", unit) + if rootlessQualResetFailureIsAlreadyUnloaded(resetOutput, activeState, activeErr) { + return + } t.Fatalf("systemctl reset-failed %s: %v\n%s", unit, resetErr, resetOutput) } +func rootlessQualResetFailureIsAlreadyUnloaded(resetOutput, activeState string, activeErr error) bool { + if activeErr != nil || strings.TrimSpace(activeState) != "inactive" { + return false + } + message := strings.ToLower(resetOutput) + return strings.Contains(message, "unit not loaded") || strings.Contains(message, "unit not found") +} + +func TestRootlessQualificationAcceptsAlreadyUnloadedUnitAfterSuccessfulStop(t *testing.T) { + if !rootlessQualResetFailureIsAlreadyUnloaded("Failed to reset failed state: Unit not loaded.", "inactive\n", nil) { + t.Fatal("already-unloaded inactive unit was not accepted") + } + for _, test := range []struct { + name string + output string + activeState string + err error + }{ + {name: "still active", output: "Unit not loaded", activeState: "active"}, + {name: "different failure", output: "Access denied", activeState: "inactive"}, + {name: "state unavailable", output: "Unit not loaded", activeState: "", err: errors.New("show failed")}, + } { + t.Run(test.name, func(t *testing.T) { + if rootlessQualResetFailureIsAlreadyUnloaded(test.output, test.activeState, test.err) { + t.Fatal("unsafe reset failure was accepted") + } + }) + } +} + func rootlessQualBestEffortStop(units ...string) { for _, unit := range units { if unit != "" {