Skip to content

Commit

Permalink
chore,pkg/utils: remove named return, refactor, add tests for ByteFormat
Browse files Browse the repository at this point in the history
  • Loading branch information
mkcp committed Sep 9, 2024
1 parent 9a8cbc9 commit a04af22
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 21 deletions.
70 changes: 49 additions & 21 deletions src/pkg/utils/bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,73 @@ import (
"github.com/zarf-dev/zarf/src/pkg/message"
)

type Unit struct {
name string
size float64
}

var (
gigabyte = Unit{
name: "GB",
size: 1000000000,
}
megabyte = Unit{
name: "MB",
size: 1000000,
}
kilobyte = Unit{
name: "KB",
size: 1000,
}
unitByte = Unit{
name: "Byte",
}
)

// RoundUp rounds a float64 to the given number of decimal places.
func RoundUp(input float64, places int) (newVal float64) {
var round float64
func RoundUp(input float64, places int) float64 {
pow := math.Pow(10, float64(places))
digit := pow * input
round = math.Ceil(digit)
newVal = round / pow
return
round := math.Ceil(digit)
return round / pow
}

// ByteFormat formats a number of bytes into a human readable string.
func ByteFormat(inputNum float64, precision int) string {
func ByteFormat(in float64, precision int) string {
if precision <= 0 {
precision = 1
}

var unit string
var returnVal float64
var val float64

// https://www.techtarget.com/searchstorage/definition/mebibyte-MiB
if inputNum >= 1000000000 {
returnVal = RoundUp(inputNum/1000000000, precision)
unit = " GB" // gigabyte
} else if inputNum >= 1000000 {
returnVal = RoundUp(inputNum/1000000, precision)
unit = " MB" // megabyte
} else if inputNum >= 1000 {
returnVal = RoundUp(inputNum/1000, precision)
unit = " KB" // kilobyte
} else {
returnVal = inputNum
unit = " Byte" // byte
switch {
case gigabyte.size <= in:
val = RoundUp(in/gigabyte.size, precision)
unit = gigabyte.name
break
case 1000000 <= in:
val = RoundUp(in/1000000, precision)
unit = megabyte.name
break
case 1000 <= in:
val = RoundUp(in/1000, precision)
unit = kilobyte.name
break
default:
val = in
unit = unitByte.name
break
}

if returnVal > 1 {
// NOTE(mkcp): Negative bytes are nonsense, but it's more robust for inputs without erroring.
if val < -1 || 1 < val {
unit += "s"
}

return strconv.FormatFloat(returnVal, 'f', precision, 64) + unit
vFmt := strconv.FormatFloat(val, 'f', precision, 64)
return vFmt + " " + unit
}

// RenderProgressBarForLocalDirWrite creates a progress bar that continuously tracks the progress of writing files to a local directory and all of its subdirectories.
Expand Down
78 changes: 78 additions & 0 deletions src/pkg/utils/bytes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2024-Present The Zarf Authors

// Package utils provides generic utility functions.
package utils

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestByteFormat(t *testing.T) {
t.Parallel()
tt := []struct {
name string
in float64
precision int
expect string
}{
{
name: "accepts empty",
expect: "0.0 Byte",
},
{
name: "accepts empty bytes with precision",
precision: 1,
expect: "0.0 Byte",
},
{
name: "accepts empty bytes with meaningful precision",
precision: 3,
expect: "0.000 Byte",
},
{
name: "formats negative byte with empty precision",
in: -1,
expect: "-1.0 Byte",
},
{
name: "formats negative bytes with empty precision",
in: -2,
expect: "-2.0 Bytes",
},
{
name: "formats kilobyte",
in: 1000,
expect: "1.0 KB",
},
{
name: "formats kilobytes",
in: 1100,
expect: "1.1 KBs",
},
{
name: "formats megabytes",
in: 10000000,
expect: "10.0 MBs",
},
{
name: "formats gigabytes",
in: 100000000000,
expect: "100.0 GBs",
},
{
name: "formats arbitrary in",
in: 4238970784923,
precision: 99,
expect: "4238.970784922999882837757468223571777343750000000000000000000000000000000000000000000000000000000000000 GBs",
},
}
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
actual := ByteFormat(tc.in, tc.precision)
require.Equal(t, tc.expect, actual)
})
}
}

0 comments on commit a04af22

Please sign in to comment.