Remove unused second part of the expiry counter
This commit is contained in:
@@ -89,6 +89,29 @@ func TestFormatRoundTrips(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The spellings themselves, not just their round trip: Duration.String() pads
|
||||||
|
// out the units below the largest one, and trimming that tail is easy to get
|
||||||
|
// wrong in a way that eats a real digit ("1m30s" must not become "1m3").
|
||||||
|
func TestFormatDurationSpelling(t *testing.T) {
|
||||||
|
for _, c := range []struct {
|
||||||
|
in time.Duration
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{Unlimited, "never"},
|
||||||
|
{30 * time.Second, "30s"},
|
||||||
|
{time.Minute, "1m"},
|
||||||
|
{90 * time.Second, "1m30s"},
|
||||||
|
{90 * time.Minute, "1h30m"},
|
||||||
|
{2 * time.Hour, "2h"},
|
||||||
|
{25 * time.Hour, "25h"},
|
||||||
|
{72 * time.Hour, "3d"},
|
||||||
|
} {
|
||||||
|
if got := FormatDuration(c.in); got != c.want {
|
||||||
|
t.Errorf("FormatDuration(%s) = %q, want %q", c.in, got, c.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The convention is: one hyphen for a letter, two for a word. It is enforced
|
// The convention is: one hyphen for a letter, two for a word. It is enforced
|
||||||
// here because the stdlib flag package treats both forms as the same.
|
// here because the stdlib flag package treats both forms as the same.
|
||||||
func TestHyphenConvention(t *testing.T) {
|
func TestHyphenConvention(t *testing.T) {
|
||||||
|
|||||||
@@ -123,6 +123,13 @@ func FormatDuration(d time.Duration) string {
|
|||||||
case d%time.Hour == 0:
|
case d%time.Hour == 0:
|
||||||
return fmt.Sprintf("%dh", d/time.Hour)
|
return fmt.Sprintf("%dh", d/time.Hour)
|
||||||
default:
|
default:
|
||||||
return d.String()
|
// Duration.String() spells out every unit below the largest one, so a
|
||||||
|
// whole number of minutes arrives as "1m0s". Drop that tail, but only
|
||||||
|
// when the seconds really are zero: "1m30s" has to keep them.
|
||||||
|
s := d.String()
|
||||||
|
if strings.HasSuffix(s, "m0s") {
|
||||||
|
s = strings.TrimSuffix(s, "0s")
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,10 +169,16 @@ func describeExpiry(t *time.Time, now time.Time) string {
|
|||||||
if t == nil {
|
if t == nil {
|
||||||
return "never"
|
return "never"
|
||||||
}
|
}
|
||||||
|
at := t.UTC().Format("2006-01-02 15:04 MST")
|
||||||
d := t.Sub(now).Round(time.Minute)
|
d := t.Sub(now).Round(time.Minute)
|
||||||
if d < 0 {
|
switch {
|
||||||
|
case d < 0:
|
||||||
return "expired"
|
return "expired"
|
||||||
|
case d == 0:
|
||||||
|
// Rounded away to nothing, and a zero duration is how this program
|
||||||
|
// spells "unlimited": saying "in never" of a file about to go would
|
||||||
|
// be exactly backwards.
|
||||||
|
return at + " (in under a minute)"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s (in %s)", t.UTC().Format("2006-01-02 15:04 MST"),
|
return fmt.Sprintf("%s (in %s)", at, config.FormatDuration(d))
|
||||||
config.FormatDuration(d))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1686,6 +1686,32 @@ func TestCustomNameFieldIsAlwaysUsable(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The share page's expiry line is rounded to the minute, so it must not offer
|
||||||
|
// a seconds tail it is not counting - nor, when the remainder rounds away to
|
||||||
|
// nothing, claim the file is kept forever.
|
||||||
|
func TestDescribeExpiryReadsAsWritten(t *testing.T) {
|
||||||
|
at := func(d time.Duration) *time.Time {
|
||||||
|
when := clock.Add(d)
|
||||||
|
return &when
|
||||||
|
}
|
||||||
|
for _, c := range []struct {
|
||||||
|
name string
|
||||||
|
in *time.Time
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"no deadline", nil, "never"},
|
||||||
|
{"already gone", at(-time.Hour), "expired"},
|
||||||
|
{"about to go", at(20 * time.Second), "(in under a minute)"},
|
||||||
|
{"a minute off", at(time.Minute), "(in 1m)"},
|
||||||
|
{"an hour and a half", at(90 * time.Minute), "(in 1h30m)"},
|
||||||
|
{"three days", at(72 * time.Hour), "(in 3d)"},
|
||||||
|
} {
|
||||||
|
if got := describeExpiry(c.in, clock); !strings.Contains(got, c.want) {
|
||||||
|
t.Errorf("%s: describeExpiry = %q, want it to contain %q", c.name, got, c.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// A chosen passphrase has to work everywhere a generated token does: at the
|
// A chosen passphrase has to work everywhere a generated token does: at the
|
||||||
// login form, on an upload, and as a session.
|
// login form, on an upload, and as a session.
|
||||||
func TestChosenPassphraseWorksEndToEnd(t *testing.T) {
|
func TestChosenPassphraseWorksEndToEnd(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user