From b7f5cdf90a902513bcf21766cfdf4b23989fa64c Mon Sep 17 00:00:00 2001 From: Qiang Huang Date: Tue, 21 Mar 2017 07:48:17 +0800 Subject: [PATCH] Use uint64 for parseSize Functions like RAMInBytes offen used to parse memory set to cgroup, while Linux kernel take cgroup memory value as uint64, so we need the return value of RAMInBytes also be uint64, otherwise we are not able to set memory larger than MAX(int64) and smaller than MAX(uint64). This'll somewhat break compatibility since parseSize returns 0 when input is not parseable, but I doubt people actually depend on that because we already return error, so I don't think this'll be a problem. Signed-off-by: Qiang Huang --- size.go | 17 +++++++++-------- size_test.go | 8 ++++---- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/size.go b/size.go index 44616c2..23cdd6b 100644 --- a/size.go +++ b/size.go @@ -26,7 +26,7 @@ const ( PiB = 1024 * TiB ) -type unitMap map[string]int64 +type unitMap map[string]uint64 var ( decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB} @@ -75,28 +75,29 @@ func BytesSize(size float64) string { // FromHumanSize returns an integer from a human-readable specification of a // size using SI standard (eg. "44kB", "17MB"). -func FromHumanSize(size string) (int64, error) { +func FromHumanSize(size string) (uint64, error) { return parseSize(size, decimalMap) } // RAMInBytes parses a human-readable string representing an amount of RAM // in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and -// returns the number of bytes, or -1 if the string is unparseable. +// returns the number of bytes, or 0 and corresponding error if the string +// is unparseable. // Units are case-insensitive, and the 'b' suffix is optional. -func RAMInBytes(size string) (int64, error) { +func RAMInBytes(size string) (uint64, error) { return parseSize(size, binaryMap) } // Parses the human-readable size string into the amount it represents. -func parseSize(sizeStr string, uMap unitMap) (int64, error) { +func parseSize(sizeStr string, uMap unitMap) (uint64, error) { matches := sizeRegex.FindStringSubmatch(sizeStr) if len(matches) != 4 { - return -1, fmt.Errorf("invalid size: '%s'", sizeStr) + return 0, fmt.Errorf("invalid size: '%s'", sizeStr) } size, err := strconv.ParseFloat(matches[1], 64) if err != nil { - return -1, err + return 0, err } unitPrefix := strings.ToLower(matches[3]) @@ -104,5 +105,5 @@ func parseSize(sizeStr string, uMap unitMap) (int64, error) { size *= float64(mul) } - return int64(size), nil + return uint64(size), nil } diff --git a/size_test.go b/size_test.go index 8923e50..cf9a44b 100644 --- a/size_test.go +++ b/size_test.go @@ -125,7 +125,7 @@ func TestRAMInBytes(t *testing.T) { assertSuccessEquals(t, 32, RAMInBytes, "32.3") tmp := 32.3 * MiB - assertSuccessEquals(t, int64(tmp), RAMInBytes, "32.3 mb") + assertSuccessEquals(t, uint64(tmp), RAMInBytes, "32.3 mb") assertError(t, RAMInBytes, "") assertError(t, RAMInBytes, "hello") @@ -142,7 +142,7 @@ func assertEquals(t *testing.T, expected, actual interface{}) { } // func that maps to the parse function signatures as testing abstraction -type parseFn func(string) (int64, error) +type parseFn func(string) (uint64, error) // Define 'String()' for pretty-print func (fn parseFn) String() string { @@ -150,7 +150,7 @@ func (fn parseFn) String() string { return fnName[strings.LastIndex(fnName, ".")+1:] } -func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) { +func assertSuccessEquals(t *testing.T, expected uint64, fn parseFn, arg string) { res, err := fn(arg) if err != nil || res != expected { t.Errorf("%s(\"%s\") -> expected '%d' but got '%d' with error '%v'", fn, arg, expected, res, err) @@ -159,7 +159,7 @@ func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) { func assertError(t *testing.T, fn parseFn, arg string) { res, err := fn(arg) - if err == nil && res != -1 { + if err == nil && res != 0 { t.Errorf("%s(\"%s\") -> expected error but got '%d'", fn, arg, res) } }