github.com/ava-labs/avalanchego@v1.11.11/ids/bits_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package ids 5 6 import ( 7 "fmt" 8 "math" 9 "math/rand" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/stretchr/testify/require" 15 ) 16 17 func flip(b uint8) uint8 { 18 b = b>>4 | b<<4 19 b = (b&0xCC)>>2 | (b&0x33)<<2 20 b = (b&0xAA)>>1 | (b&0x55)<<1 21 return b 22 } 23 24 func BitString(id ID) string { 25 sb := strings.Builder{} 26 for _, b := range id { 27 sb.WriteString(fmt.Sprintf("%08b", flip(b))) 28 } 29 return sb.String() 30 } 31 32 func Check(start, stop int, id1, id2 ID) bool { 33 s1 := BitString(id1) 34 s2 := BitString(id2) 35 36 shorts1 := s1[start:stop] 37 shorts2 := s2[start:stop] 38 39 return shorts1 == shorts2 40 } 41 42 func TestEqualSubsetEarlyStop(t *testing.T) { 43 require := require.New(t) 44 45 id1 := ID{0xf0, 0x0f} 46 id2 := ID{0xf0, 0x1f} 47 48 require.True(EqualSubset(0, 12, id1, id2)) 49 require.False(EqualSubset(0, 13, id1, id2)) 50 } 51 52 func TestEqualSubsetLateStart(t *testing.T) { 53 id1 := ID{0x1f, 0xf8} 54 id2 := ID{0x10, 0x08} 55 56 require.True(t, EqualSubset(4, 12, id1, id2)) 57 } 58 59 func TestEqualSubsetSameByte(t *testing.T) { 60 id1 := ID{0x18} 61 id2 := ID{0xfc} 62 63 require.True(t, EqualSubset(3, 5, id1, id2)) 64 } 65 66 func TestEqualSubsetBadMiddle(t *testing.T) { 67 id1 := ID{0x18, 0xe8, 0x55} 68 id2 := ID{0x18, 0x8e, 0x55} 69 70 require.False(t, EqualSubset(0, 8*3, id1, id2)) 71 } 72 73 func TestEqualSubsetAll3Bytes(t *testing.T) { 74 rand.Seed(time.Now().UnixNano()) 75 seed := uint64(rand.Int63()) // #nosec G404 76 t.Logf("seed: %d", seed) 77 id1 := ID{}.Prefix(seed) 78 79 for i := 0; i < BitsPerByte; i++ { 80 for j := i; j < BitsPerByte; j++ { 81 for k := j; k < BitsPerByte; k++ { 82 id2 := ID{uint8(i), uint8(j), uint8(k)} 83 84 for start := 0; start < BitsPerByte*3; start++ { 85 for end := start; end <= BitsPerByte*3; end++ { 86 require.Equal(t, Check(start, end, id1, id2), EqualSubset(start, end, id1, id2)) 87 } 88 } 89 } 90 } 91 } 92 } 93 94 func TestEqualSubsetOutOfBounds(t *testing.T) { 95 id1 := ID{0x18, 0xe8, 0x55} 96 id2 := ID{0x18, 0x8e, 0x55} 97 98 require.False(t, EqualSubset(0, math.MaxInt32, id1, id2)) 99 } 100 101 func TestFirstDifferenceSubsetEarlyStop(t *testing.T) { 102 require := require.New(t) 103 104 id1 := ID{0xf0, 0x0f} 105 id2 := ID{0xf0, 0x1f} 106 107 _, found := FirstDifferenceSubset(0, 12, id1, id2) 108 require.False(found) 109 110 index, found := FirstDifferenceSubset(0, 13, id1, id2) 111 require.True(found) 112 require.Equal(12, index) 113 } 114 115 func TestFirstDifferenceEqualByte4(t *testing.T) { 116 require := require.New(t) 117 118 id1 := ID{0x10} 119 id2 := ID{0x00} 120 121 _, found := FirstDifferenceSubset(0, 4, id1, id2) 122 require.False(found) 123 124 index, found := FirstDifferenceSubset(0, 5, id1, id2) 125 require.True(found) 126 require.Equal(4, index) 127 } 128 129 func TestFirstDifferenceEqualByte5(t *testing.T) { 130 require := require.New(t) 131 132 id1 := ID{0x20} 133 id2 := ID{0x00} 134 135 _, found := FirstDifferenceSubset(0, 5, id1, id2) 136 require.False(found) 137 138 index, found := FirstDifferenceSubset(0, 6, id1, id2) 139 require.True(found) 140 require.Equal(5, index) 141 } 142 143 func TestFirstDifferenceSubsetMiddle(t *testing.T) { 144 require := require.New(t) 145 146 id1 := ID{0xf0, 0x0f, 0x11} 147 id2 := ID{0xf0, 0x1f, 0xff} 148 149 index, found := FirstDifferenceSubset(0, 24, id1, id2) 150 require.True(found) 151 require.Equal(12, index) 152 } 153 154 func TestFirstDifferenceStartMiddle(t *testing.T) { 155 require := require.New(t) 156 157 id1 := ID{0x1f, 0x0f, 0x11} 158 id2 := ID{0x0f, 0x1f, 0xff} 159 160 index, found := FirstDifferenceSubset(0, 24, id1, id2) 161 require.True(found) 162 require.Equal(4, index) 163 } 164 165 func TestFirstDifferenceVacuous(t *testing.T) { 166 id1 := ID{0xf0, 0x0f, 0x11} 167 id2 := ID{0xf0, 0x1f, 0xff} 168 169 _, found := FirstDifferenceSubset(0, 0, id1, id2) 170 require.False(t, found) 171 }