NewUsageValue exists to clip an oversized quota to the maximum value of an
int64, which is what dc95f36bc added it for when Box raised the Enterprise
space_amount to 1e+18 and started returning it as a float.
For the float64 instantiation the guard misses its own boundary.
float64(math.MaxInt64) is not 2**63-1, it rounds up to 2**63, so a quota of
exactly 2**63 fails the comparison and falls through to the int64 conversion,
which the spec leaves implementation dependent for an unrepresentable value.
On linux/amd64 it wraps:
Before: rclone about -> Total=-9223372036854775808
After: rclone about -> Total=9223372036854775807
A negative total is not just a wrong number. vfs.Statfs documents -1 as "not
known", vfs.fillInMissingSizes branches on total < 0, and serve sftp only
computes its usage percentage when total > 0, so the value is read back as a
missing quota.
The int64 and uint64 instantiations are unaffected, since for them
T(int64(math.MaxInt64)) is exact and clipping MaxInt64 to MaxInt64 is a no-op.
54 lines
1.2 KiB
Go
54 lines
1.2 KiB
Go
package fs
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestNewUsageValueInt64(t *testing.T) {
|
|
for _, test := range []struct {
|
|
in int64
|
|
want int64
|
|
}{
|
|
{0, 0},
|
|
{1 << 60, 1 << 60},
|
|
{math.MaxInt64, math.MaxInt64},
|
|
} {
|
|
assert.Equal(t, test.want, *NewUsageValue(test.in), "in=%d", test.in)
|
|
}
|
|
}
|
|
|
|
func TestNewUsageValueUint64(t *testing.T) {
|
|
for _, test := range []struct {
|
|
in uint64
|
|
want int64
|
|
}{
|
|
{0, 0},
|
|
{math.MaxInt64, math.MaxInt64},
|
|
{math.MaxInt64 + 1, math.MaxInt64},
|
|
{math.MaxUint64, math.MaxInt64},
|
|
} {
|
|
assert.Equal(t, test.want, *NewUsageValue(test.in), "in=%d", test.in)
|
|
}
|
|
}
|
|
|
|
func TestNewUsageValueFloat64(t *testing.T) {
|
|
// Largest float64 strictly below 2**63 - this still fits in an int64.
|
|
const belowMax = float64(9223372036854773760)
|
|
for _, test := range []struct {
|
|
in float64
|
|
want int64
|
|
}{
|
|
{0, 0},
|
|
{1e18, 1000000000000000000}, // Box reports space_amount like this
|
|
{belowMax, 9223372036854773760},
|
|
{float64(math.MaxInt64), math.MaxInt64}, // rounds up to 2**63
|
|
{1e19, math.MaxInt64},
|
|
{math.Inf(1), math.MaxInt64},
|
|
} {
|
|
assert.Equal(t, test.want, *NewUsageValue(test.in), "in=%v", test.in)
|
|
}
|
|
}
|