github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/kbfsblock/id_test.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package kbfsblock 6 7 import ( 8 "encoding/binary" 9 "math" 10 "math/rand" 11 "testing" 12 13 "github.com/keybase/client/go/kbfs/kbfscodec" 14 "github.com/keybase/client/go/kbfs/kbfshash" 15 "github.com/stretchr/testify/require" 16 ) 17 18 // Make sure ID encodes and decodes properly with minimal overhead. 19 func TestIDEncodeDecode(t *testing.T) { 20 codec := kbfscodec.NewMsgpack() 21 22 id := FakeID(1) 23 24 encodedID, err := codec.Encode(id) 25 require.NoError(t, err) 26 27 // See 28 // https://github.com/msgpack/msgpack/blob/master/spec.md#formats-bin 29 // for why there are two bytes of overhead. 30 const overhead = 2 31 require.Equal(t, kbfshash.DefaultHashByteLength+overhead, 32 len(encodedID)) 33 34 var id2 ID 35 err = codec.Decode(encodedID, &id2) 36 require.NoError(t, err) 37 require.Equal(t, id, id2) 38 } 39 40 // Make sure the zero ID value encodes and decodes properly. 41 func TestIDEncodeDecodeZero(t *testing.T) { 42 codec := kbfscodec.NewMsgpack() 43 encodedID, err := codec.Encode(ID{}) 44 require.NoError(t, err) 45 require.Equal(t, []byte{0xc0}, encodedID) 46 47 var id ID 48 err = codec.Decode(encodedID, &id) 49 require.NoError(t, err) 50 require.Equal(t, ID{}, id) 51 } 52 53 // Test (very superficially) that MakeTemporaryID() returns non-zero 54 // values that aren't equal. 55 func TestTemporaryIDRandom(t *testing.T) { 56 b1, err := MakeTemporaryID() 57 require.NoError(t, err) 58 require.NotEqual(t, ID{}, b1) 59 60 b2, err := MakeTemporaryID() 61 require.NoError(t, err) 62 require.NotEqual(t, ID{}, b2) 63 64 require.NotEqual(t, b1, b2) 65 } 66 67 // Test that MakeRandomIDInRange returns items in the range specified. 68 func TestRandomIDInRange(t *testing.T) { 69 rand.Seed(1) 70 idToInt := func(id ID) uint64 { 71 idBytes := id.Bytes()[1:9] 72 return binary.BigEndian.Uint64(idBytes) 73 } 74 t.Log("Test that the random IDs are within the range specified.") 75 const maxUintFloat = float64(math.MaxUint64) 76 for i := uint64(0x1000); i < (math.MaxUint64 / 4); i *= 2 { 77 for j := i * 2; j < (math.MaxUint64 / 2); j *= 2 { 78 iAsFloat := float64(i) / maxUintFloat 79 jAsFloat := float64(j) / maxUintFloat 80 id, err := MakeRandomIDInRange(iAsFloat, jAsFloat, 81 UseMathRandForTest) 82 require.NoError(t, err) 83 asInt := idToInt(id) 84 require.True(t, asInt >= i) 85 require.True(t, asInt < j) 86 } 87 } 88 89 t.Log("Test that the distribution of IDs is roughly uniform.") 90 buckets := make([]int, 16) 91 numIds := 100000 92 for i := 0; i < numIds; i++ { 93 id, err := MakeRandomIDInRange(0, 1.0, UseMathRandForTest) 94 require.NoError(t, err) 95 asInt := idToInt(id) 96 buckets[asInt>>60]++ 97 } 98 t.Log("Buckets:") 99 for i, v := range buckets { 100 t.Logf("Bucket %x: %d", i, v) 101 // They should all be around 100,000/16 = 6250. This tests that they're 102 // within 10% in either direction. 103 require.InEpsilon(t, numIds/16, v, .10) 104 } 105 }