package cli import ( "testing" "time" "github.com/stretchr/testify/assert" ) func TestParseDuration(t *testing.T) { tests := []struct { name string input string expected time.Duration wantErr bool }{ // Standard Go durations { name: "standard seconds", input: "30s", expected: 30 * time.Second, }, { name: "standard minutes", input: "45m", expected: 45 * time.Minute, }, { name: "standard hours", input: "2h", expected: 2 * time.Hour, }, { name: "standard combined", input: "3h30m", expected: 3*time.Hour + 30*time.Minute, }, { name: "standard complex", input: "1h45m30s", expected: 1*time.Hour + 45*time.Minute + 30*time.Second, }, { name: "standard with milliseconds", input: "1s500ms", expected: 1*time.Second + 500*time.Millisecond, }, // Extended units - days { name: "single day", input: "1d", expected: 24 * time.Hour, }, { name: "multiple days", input: "7d", expected: 7 * 24 * time.Hour, }, { name: "fractional days", input: "1.5d", expected: 36 * time.Hour, }, { name: "days spelled out", input: "3days", expected: 3 * 24 * time.Hour, }, // Extended units - weeks { name: "single week", input: "1w", expected: 7 * 24 * time.Hour, }, { name: "multiple weeks", input: "4w", expected: 4 * 7 * 24 * time.Hour, }, { name: "weeks spelled out", input: "2weeks", expected: 2 * 7 * 24 * time.Hour, }, // Extended units - months { name: "single month", input: "1mo", expected: 30 * 24 * time.Hour, }, { name: "multiple months", input: "6mo", expected: 6 * 30 * 24 * time.Hour, }, { name: "months spelled out", input: "3months", expected: 3 * 30 * 24 * time.Hour, }, // Extended units - years { name: "single year", input: "1y", expected: 365 * 24 * time.Hour, }, { name: "multiple years", input: "2y", expected: 2 * 365 * 24 * time.Hour, }, { name: "years spelled out", input: "1year", expected: 365 * 24 * time.Hour, }, // Combined extended units { name: "weeks and days", input: "2w3d", expected: 2*7*24*time.Hour + 3*24*time.Hour, }, { name: "years and months", input: "1y6mo", expected: 365*24*time.Hour + 6*30*24*time.Hour, }, { name: "days and hours", input: "1d12h", expected: 24*time.Hour + 12*time.Hour, }, { name: "complex combination", input: "1y2mo3w4d5h6m7s", expected: 365*24*time.Hour + 2*30*24*time.Hour + 3*7*24*time.Hour + 4*24*time.Hour + 5*time.Hour + 6*time.Minute + 7*time.Second, }, { name: "with spaces", input: "1d 12h 30m", expected: 24*time.Hour + 12*time.Hour + 30*time.Minute, }, // Edge cases { name: "zero duration", input: "0s", expected: 0, }, { name: "large duration", input: "10y", expected: 10 * 365 * 24 * time.Hour, }, // Error cases { name: "empty string", input: "", wantErr: true, }, { name: "invalid format", input: "abc", wantErr: true, }, { name: "unknown unit", input: "5x", wantErr: true, }, { name: "invalid number", input: "xyzd", wantErr: true, }, { name: "negative not supported", input: "-5d", wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := parseDuration(tt.input) if tt.wantErr { assert.Error(t, err, "expected error for input %q", tt.input) return } assert.NoError(t, err, "unexpected error for input %q", tt.input) assert.Equal(t, tt.expected, got, "duration mismatch for input %q", tt.input) }) } } func TestParseDurationSpecialCases(t *testing.T) { // Test that standard Go durations work exactly as expected standardDurations := []string{ "300ms", "1.5h", "2h45m", "72h", "1us", "1µs", "1ns", } for _, d := range standardDurations { expected, err := time.ParseDuration(d) assert.NoError(t, err) got, err := parseDuration(d) assert.NoError(t, err) assert.Equal(t, expected, got, "standard duration %q should parse identically", d) } } func TestParseDurationRealWorldExamples(t *testing.T) { // Test real-world snapshot purge scenarios tests := []struct { description string input string olderThan time.Duration }{ { description: "keep snapshots from last 30 days", input: "30d", olderThan: 30 * 24 * time.Hour, }, { description: "keep snapshots from last 6 months", input: "6mo", olderThan: 6 * 30 * 24 * time.Hour, }, { description: "keep snapshots from last year", input: "1y", olderThan: 365 * 24 * time.Hour, }, { description: "keep snapshots from last week and a half", input: "1w3d", olderThan: 10 * 24 * time.Hour, }, { description: "keep snapshots from last 90 days", input: "90d", olderThan: 90 * 24 * time.Hour, }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { got, err := parseDuration(tt.input) assert.NoError(t, err) assert.Equal(t, tt.olderThan, got) // Verify the duration makes sense for snapshot purging assert.Greater(t, got, time.Hour, "snapshot purge duration should be at least an hour") }) } }