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  }