diff --git a/weed/util/bytes.go b/weed/util/bytes.go index 4e9ce1d15..b3217a195 100644 --- a/weed/util/bytes.go +++ b/weed/util/bytes.go @@ -13,6 +13,8 @@ import ( "unicode" ) +var randomRead = rand.Read + // BytesToHumanReadable returns the converted human readable representation of the bytes. func BytesToHumanReadable(b uint64) string { const unit = 1024 @@ -156,10 +158,12 @@ func RandomInt32() int32 { return int32(BytesToUint32(buf)) } -func RandomUint64() int32 { +func RandomUint64() uint64 { buf := make([]byte, 8) - rand.Read(buf) - return int32(BytesToUint64(buf)) + if _, err := randomRead(buf); err != nil { + panic(err) + } + return BytesToUint64(buf) } func RandomBytes(byteCount int) []byte { diff --git a/weed/util/bytes_test.go b/weed/util/bytes_test.go index d9269cadb..31c7af40c 100644 --- a/weed/util/bytes_test.go +++ b/weed/util/bytes_test.go @@ -1,6 +1,45 @@ package util -import "testing" +import ( + "errors" + "testing" +) + +func TestRandomUint64ReturnsFullRandomValue(t *testing.T) { + useRandomRead(t, func(p []byte) (int, error) { + copy(p, []byte{0x80, 0, 0, 0, 0, 0, 0, 1}) + return len(p), nil + }) + + const want uint64 = 0x8000000000000001 + if got := RandomUint64(); got != want { + t.Fatalf("RandomUint64() = %d, want %d", got, want) + } +} + +func TestRandomUint64PanicsOnRandomReadError(t *testing.T) { + useRandomRead(t, func([]byte) (int, error) { + return 0, errors.New("random read failed") + }) + + defer func() { + if recover() == nil { + t.Fatal("RandomUint64() did not panic on random read error") + } + }() + + RandomUint64() +} + +func useRandomRead(t *testing.T, read func([]byte) (int, error)) { + t.Helper() + + original := randomRead + randomRead = read + t.Cleanup(func() { + randomRead = original + }) +} func TestByteParsing(t *testing.T) { tests := []struct {