Add message-{size|delay}-limit
This commit is contained in:
16
util/time.go
16
util/time.go
@@ -83,6 +83,22 @@ func ParseDuration(s string) (time.Duration, error) {
|
||||
return 0, errUnparsableTime
|
||||
}
|
||||
|
||||
func FormatDuration(d time.Duration) string {
|
||||
if d >= 24*time.Hour {
|
||||
return strconv.Itoa(int(d/(24*time.Hour))) + "d"
|
||||
}
|
||||
if d >= time.Hour {
|
||||
return strconv.Itoa(int(d/time.Hour)) + "h"
|
||||
}
|
||||
if d >= time.Minute {
|
||||
return strconv.Itoa(int(d/time.Minute)) + "m"
|
||||
}
|
||||
if d >= time.Second {
|
||||
return strconv.Itoa(int(d/time.Second)) + "s"
|
||||
}
|
||||
return "0s"
|
||||
}
|
||||
|
||||
func parseFromDuration(s string, now time.Time) (time.Time, error) {
|
||||
d, err := ParseDuration(s)
|
||||
if err == nil {
|
||||
|
||||
@@ -92,3 +92,27 @@ func TestParseDuration(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, time.Duration(0), d)
|
||||
}
|
||||
|
||||
func TestFormatDuration(t *testing.T) {
|
||||
values := []struct {
|
||||
duration time.Duration
|
||||
expected string
|
||||
}{
|
||||
{24 * time.Second, "24s"},
|
||||
{56 * time.Minute, "56m"},
|
||||
{time.Hour, "1h"},
|
||||
{2 * time.Hour, "2h"},
|
||||
{24 * time.Hour, "1d"},
|
||||
{3 * 24 * time.Hour, "3d"},
|
||||
}
|
||||
for _, value := range values {
|
||||
require.Equal(t, value.expected, FormatDuration(value.duration))
|
||||
d, err := ParseDuration(FormatDuration(value.duration))
|
||||
require.Nil(t, err)
|
||||
require.Equalf(t, value.duration, d, "duration does not match: %v != %v", value.duration, d)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatDuration_Rounded(t *testing.T) {
|
||||
require.Equal(t, "1d", FormatDuration(47*time.Hour))
|
||||
}
|
||||
|
||||
22
util/util.go
22
util/util.go
@@ -7,6 +7,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net/netip"
|
||||
"os"
|
||||
@@ -215,6 +216,8 @@ func ParseSize(s string) (int64, error) {
|
||||
return -1, fmt.Errorf("cannot convert number %s", matches[1])
|
||||
}
|
||||
switch strings.ToUpper(matches[2]) {
|
||||
case "T":
|
||||
return int64(value) * 1024 * 1024 * 1024 * 1024, nil
|
||||
case "G":
|
||||
return int64(value) * 1024 * 1024 * 1024, nil
|
||||
case "M":
|
||||
@@ -226,8 +229,23 @@ func ParseSize(s string) (int64, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// FormatSize formats bytes into a human-readable notation, e.g. 2.1 MB
|
||||
// FormatSize formats the size in a way that it can be parsed by ParseSize.
|
||||
// It does not include decimal places. Uneven sizes are rounded down.
|
||||
func FormatSize(b int64) string {
|
||||
const unit = 1024
|
||||
if b < unit {
|
||||
return fmt.Sprintf("%d", b)
|
||||
}
|
||||
div, exp := int64(unit), 0
|
||||
for n := b / unit; n >= unit; n /= unit {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
return fmt.Sprintf("%d%c", int(math.Floor(float64(b)/float64(div))), "KMGT"[exp])
|
||||
}
|
||||
|
||||
// FormatSizeHuman formats bytes into a human-readable notation, e.g. 2.1 MB
|
||||
func FormatSizeHuman(b int64) string {
|
||||
const unit = 1024
|
||||
if b < unit {
|
||||
return fmt.Sprintf("%d bytes", b)
|
||||
@@ -237,7 +255,7 @@ func FormatSize(b int64) string {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "KMGTPE"[exp])
|
||||
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "KMGT"[exp])
|
||||
}
|
||||
|
||||
// ReadPassword will read a password from STDIN. If the terminal supports it, it will not print the
|
||||
|
||||
@@ -110,33 +110,47 @@ func TestShortTopicURL(t *testing.T) {
|
||||
|
||||
func TestParseSize_10GSuccess(t *testing.T) {
|
||||
s, err := ParseSize("10G")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, int64(10*1024*1024*1024), s)
|
||||
}
|
||||
|
||||
func TestParseSize_10MUpperCaseSuccess(t *testing.T) {
|
||||
s, err := ParseSize("10M")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, int64(10*1024*1024), s)
|
||||
}
|
||||
|
||||
func TestParseSize_10kLowerCaseSuccess(t *testing.T) {
|
||||
s, err := ParseSize("10k")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, int64(10*1024), s)
|
||||
}
|
||||
|
||||
func TestParseSize_FailureInvalid(t *testing.T) {
|
||||
_, err := ParseSize("not a size")
|
||||
if err == nil {
|
||||
t.Fatalf("expected error, but got none")
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestFormatSize(t *testing.T) {
|
||||
values := []struct {
|
||||
size int64
|
||||
expected string
|
||||
}{
|
||||
{10, "10"},
|
||||
{10 * 1024, "10K"},
|
||||
{10 * 1024 * 1024, "10M"},
|
||||
{10 * 1024 * 1024 * 1024, "10G"},
|
||||
}
|
||||
for _, value := range values {
|
||||
require.Equal(t, value.expected, FormatSize(value.size))
|
||||
s, err := ParseSize(FormatSize(value.size))
|
||||
require.Nil(t, err)
|
||||
require.Equalf(t, value.size, s, "size does not match: %d != %d", value.size, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatSize_Rounded(t *testing.T) {
|
||||
require.Equal(t, "10K", FormatSize(10*1024+999))
|
||||
}
|
||||
|
||||
func TestSplitKV(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user