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  }