mirror of https://github.com/XTLS/Xray-core
Browse Source
Occasional error is observed when we execute long test Print time and memory for better troubleshooting in the future Co-authored-by: Jebbs <qjebbs@gmail.com>pull/854/head
yuhan6665
3 years ago
3 changed files with 179 additions and 1 deletions
@ -0,0 +1,100 @@
|
||||
package units |
||||
|
||||
import ( |
||||
"errors" |
||||
"strconv" |
||||
"strings" |
||||
"unicode" |
||||
) |
||||
|
||||
var ( |
||||
errInvalidSize = errors.New("invalid size") |
||||
errInvalidUnit = errors.New("invalid or unsupported unit") |
||||
) |
||||
|
||||
// ByteSize is the size of bytes
|
||||
type ByteSize uint64 |
||||
|
||||
const ( |
||||
_ = iota |
||||
// KB = 1KB
|
||||
KB ByteSize = 1 << (10 * iota) |
||||
// MB = 1MB
|
||||
MB |
||||
// GB = 1GB
|
||||
GB |
||||
// TB = 1TB
|
||||
TB |
||||
// PB = 1PB
|
||||
PB |
||||
// EB = 1EB
|
||||
EB |
||||
) |
||||
|
||||
func (b ByteSize) String() string { |
||||
unit := "" |
||||
value := float64(0) |
||||
switch { |
||||
case b == 0: |
||||
return "0" |
||||
case b < KB: |
||||
unit = "B" |
||||
value = float64(b) |
||||
case b < MB: |
||||
unit = "KB" |
||||
value = float64(b) / float64(KB) |
||||
case b < GB: |
||||
unit = "MB" |
||||
value = float64(b) / float64(MB) |
||||
case b < TB: |
||||
unit = "GB" |
||||
value = float64(b) / float64(GB) |
||||
case b < PB: |
||||
unit = "TB" |
||||
value = float64(b) / float64(TB) |
||||
case b < EB: |
||||
unit = "PB" |
||||
value = float64(b) / float64(PB) |
||||
default: |
||||
unit = "EB" |
||||
value = float64(b) / float64(EB) |
||||
} |
||||
result := strconv.FormatFloat(value, 'f', 2, 64) |
||||
result = strings.TrimSuffix(result, ".0") |
||||
return result + unit |
||||
} |
||||
|
||||
// Parse parses ByteSize from string
|
||||
func (b *ByteSize) Parse(s string) error { |
||||
s = strings.TrimSpace(s) |
||||
s = strings.ToUpper(s) |
||||
i := strings.IndexFunc(s, unicode.IsLetter) |
||||
if i == -1 { |
||||
return errInvalidUnit |
||||
} |
||||
|
||||
bytesString, multiple := s[:i], s[i:] |
||||
bytes, err := strconv.ParseFloat(bytesString, 64) |
||||
if err != nil || bytes <= 0 { |
||||
return errInvalidSize |
||||
} |
||||
switch multiple { |
||||
case "B": |
||||
*b = ByteSize(bytes) |
||||
case "K", "KB", "KIB": |
||||
*b = ByteSize(bytes * float64(KB)) |
||||
case "M", "MB", "MIB": |
||||
*b = ByteSize(bytes * float64(MB)) |
||||
case "G", "GB", "GIB": |
||||
*b = ByteSize(bytes * float64(GB)) |
||||
case "T", "TB", "TIB": |
||||
*b = ByteSize(bytes * float64(TB)) |
||||
case "P", "PB", "PIB": |
||||
*b = ByteSize(bytes * float64(PB)) |
||||
case "E", "EB", "EIB": |
||||
*b = ByteSize(bytes * float64(EB)) |
||||
default: |
||||
return errInvalidUnit |
||||
} |
||||
return nil |
||||
} |
@ -0,0 +1,66 @@
|
||||
package units_test |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"github.com/xtls/xray-core/common/units" |
||||
) |
||||
|
||||
func TestByteSizes(t *testing.T) { |
||||
size := units.ByteSize(0) |
||||
assertSizeString(t, size, "0") |
||||
size++ |
||||
assertSizeValue(t, |
||||
assertSizeString(t, size, "1.00B"), |
||||
size, |
||||
) |
||||
size <<= 10 |
||||
assertSizeValue(t, |
||||
assertSizeString(t, size, "1.00KB"), |
||||
size, |
||||
) |
||||
size <<= 10 |
||||
assertSizeValue(t, |
||||
assertSizeString(t, size, "1.00MB"), |
||||
size, |
||||
) |
||||
size <<= 10 |
||||
assertSizeValue(t, |
||||
assertSizeString(t, size, "1.00GB"), |
||||
size, |
||||
) |
||||
size <<= 10 |
||||
assertSizeValue(t, |
||||
assertSizeString(t, size, "1.00TB"), |
||||
size, |
||||
) |
||||
size <<= 10 |
||||
assertSizeValue(t, |
||||
assertSizeString(t, size, "1.00PB"), |
||||
size, |
||||
) |
||||
size <<= 10 |
||||
assertSizeValue(t, |
||||
assertSizeString(t, size, "1.00EB"), |
||||
size, |
||||
) |
||||
} |
||||
|
||||
func assertSizeValue(t *testing.T, size string, expected units.ByteSize) { |
||||
actual := units.ByteSize(0) |
||||
err := actual.Parse(size) |
||||
if err != nil { |
||||
t.Error(err) |
||||
} |
||||
if actual != expected { |
||||
t.Errorf("expect %s, but got %s", expected, actual) |
||||
} |
||||
} |
||||
|
||||
func assertSizeString(t *testing.T, size units.ByteSize, expected string) string { |
||||
actual := size.String() |
||||
if actual != expected { |
||||
t.Errorf("expect %s, but got %s", expected, actual) |
||||
} |
||||
return expected |
||||
} |
Loading…
Reference in new issue