From a37ca160aa8a382d4f34912087a1bf2290cdcb7b Mon Sep 17 00:00:00 2001 From: ROKUMATE Date: Thu, 20 Aug 2026 00:51:08 +0530 Subject: [PATCH] pkg/util: add tests for ParseRestartPolicy ParseRestartPolicy parses the value of the --restart flag and had no unit test. It handles several distinct cases: bare policy names, the "never" -> "no" normalization (case-insensitive), on-failure with a retry count, and a number of error paths (retries specified on a non-on-failure policy, non-numeric or negative retry counts, and too many colon-separated fields). Add a table-driven unit test covering the happy paths and each error branch. Signed-off-by: ROKUMATE --- pkg/util/utils_test.go | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/pkg/util/utils_test.go b/pkg/util/utils_test.go index e3e377612c..3f15cfe870 100644 --- a/pkg/util/utils_test.go +++ b/pkg/util/utils_test.go @@ -13,6 +13,8 @@ import ( ruser "github.com/moby/sys/user" "github.com/opencontainers/runtime-spec/specs-go" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.podman.io/podman/v6/libpod/define" "go.podman.io/storage/pkg/idtools" stypes "go.podman.io/storage/types" ) @@ -894,3 +896,44 @@ func TestParseDockerignoreLeadingTrailingSlashes(t *testing.T) { }) } } + +func TestParseRestartPolicy(t *testing.T) { + tests := []struct { + name string + policy string + wantPolicy string + wantRetries uint + wantErr string // substring to match; empty means no error expected + }{ + {"empty policy", "", "", 0, ""}, + {"no", "no", "no", 0, ""}, + {"always", "always", "always", 0, ""}, + {"unless-stopped", "unless-stopped", "unless-stopped", 0, ""}, + {"on-failure without retries", "on-failure", "on-failure", 0, ""}, + {"never is normalized to no", "never", define.RestartPolicyNo, 0, ""}, + {"never is case-insensitive", "Never", define.RestartPolicyNo, 0, ""}, + {"on-failure with retries", "on-failure:5", "on-failure", 5, ""}, + {"on-failure with zero retries", "on-failure:0", "on-failure", 0, ""}, + {"on-failure preserves original case", "ON-FAILURE:3", "ON-FAILURE", 3, ""}, + {"retries with non on-failure policy", "always:5", "", 0, "can only be specified with on-failure"}, + {"non-numeric retries", "on-failure:abc", "", 0, "parsing restart policy retry count"}, + {"empty retries", "on-failure:", "", 0, "parsing restart policy retry count"}, + {"negative retries", "on-failure:-1", "", 0, "greater than 0"}, + {"too many fields", "on-failure:5:3", "", 0, "may specify retries at most once"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + policy, retries, err := ParseRestartPolicy(tt.policy) + if tt.wantErr != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.wantErr) + assert.Empty(t, policy) + assert.Zero(t, retries) + return + } + assert.NoError(t, err) + assert.Equal(t, tt.wantPolicy, policy) + assert.Equal(t, tt.wantRetries, retries) + }) + } +}