github.com/koko1123/flow-go-1@v0.29.6/model/flow/identifier_test.go (about) 1 package flow_test 2 3 import ( 4 "encoding/binary" 5 "encoding/json" 6 "fmt" 7 "math/rand" 8 "testing" 9 10 blocks "github.com/ipfs/go-block-format" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 14 "github.com/koko1123/flow-go-1/model/flow" 15 "github.com/koko1123/flow-go-1/storage/merkle" 16 "github.com/koko1123/flow-go-1/utils/unittest" 17 ) 18 19 func TestIdentifierFormat(t *testing.T) { 20 id := unittest.IdentifierFixture() 21 22 // should print hex representation with %x formatting verb 23 t.Run("%x", func(t *testing.T) { 24 formatted := fmt.Sprintf("%x", id) 25 assert.Equal(t, id.String(), formatted) 26 }) 27 28 // should print hex representation with %s formatting verb 29 t.Run("%s", func(t *testing.T) { 30 formatted := fmt.Sprintf("%s", id) //nolint:gosimple 31 assert.Equal(t, id.String(), formatted) 32 }) 33 34 // should print hex representation with default formatting verb 35 t.Run("%v", func(t *testing.T) { 36 formatted := fmt.Sprintf("%v", id) 37 assert.Equal(t, id.String(), formatted) 38 }) 39 40 // should handle unsupported verbs 41 t.Run("unsupported formatting verb", func(t *testing.T) { 42 formatted := fmt.Sprintf("%d", id) 43 expected := fmt.Sprintf("%%!d(flow.Identifier=%s)", id) 44 assert.Equal(t, expected, formatted) 45 }) 46 } 47 48 func TestIdentifierJSON(t *testing.T) { 49 id := unittest.IdentifierFixture() 50 bz, err := json.Marshal(id) 51 assert.NoError(t, err) 52 assert.Equal(t, fmt.Sprintf("\"%v\"", id), string(bz)) 53 var actual flow.Identifier 54 err = json.Unmarshal(bz, &actual) 55 assert.NoError(t, err) 56 assert.Equal(t, id, actual) 57 } 58 59 func TestIdentifierSample(t *testing.T) { 60 61 total := 10 62 ids := make([]flow.Identifier, total) 63 for i := range ids { 64 ids[i] = unittest.IdentifierFixture() 65 } 66 67 t.Run("Sample creates a random sample", func(t *testing.T) { 68 sampleSize := uint(5) 69 sample := flow.Sample(sampleSize, ids...) 70 require.Len(t, sample, int(sampleSize)) 71 require.NotEqual(t, sample, ids[:sampleSize]) 72 }) 73 74 t.Run("sample size greater than total size results in the original list", func(t *testing.T) { 75 sampleSize := uint(len(ids) + 1) 76 sample := flow.Sample(sampleSize, ids...) 77 require.Equal(t, sample, ids) 78 }) 79 80 t.Run("sample size of zero results in an empty list", func(t *testing.T) { 81 sampleSize := uint(0) 82 sample := flow.Sample(sampleSize, ids...) 83 require.Empty(t, sample) 84 }) 85 } 86 87 func TestMerkleRoot(t *testing.T) { 88 total := 10 89 ids := make([]flow.Identifier, total) 90 for i := range ids { 91 ids[i] = unittest.IdentifierFixture() 92 } 93 94 idsBad := make([]flow.Identifier, total) 95 for i := range idsBad { 96 idsBad[i] = ids[len(ids)-1] 97 } 98 fmt.Println(ids) 99 fmt.Println(idsBad) 100 101 require.NotEqual(t, flow.MerkleRoot(ids...), flow.MerkleRoot(idsBad...)) 102 require.Equal(t, referenceMerkleRoot(t, ids...), flow.MerkleRoot(ids...)) 103 } 104 105 // We should ideally replace this with a completely different reference implementation 106 // Possibly written in another language, such as python, similar to the Ledger Trie Implementation 107 func referenceMerkleRoot(t *testing.T, ids ...flow.Identifier) flow.Identifier { 108 var root flow.Identifier 109 tree, err := merkle.NewTree(flow.IdentifierLen) 110 assert.NoError(t, err) 111 for idx, id := range ids { 112 idxVal := make([]byte, 8) 113 binary.BigEndian.PutUint64(idxVal, uint64(idx)) 114 _, err := tree.Put(id[:], idxVal) 115 assert.NoError(t, err) 116 } 117 hash := tree.Hash() 118 copy(root[:], hash) 119 return root 120 } 121 122 // TestCIDConversion tests that the CID conversion functions are working as expected 123 // It generates Flow ID / CID fixtures and converts them back and forth to check that 124 // the conversion is correct. 125 func TestCIDConversion(t *testing.T) { 126 id := unittest.IdentifierFixture() 127 cid := flow.IdToCid(id) 128 id2, err := flow.CidToId(cid) 129 assert.NoError(t, err) 130 assert.Equal(t, id, id2) 131 132 // generate random CID 133 data := make([]byte, 4) 134 rand.Read(data) 135 cid = blocks.NewBlock(data).Cid() 136 137 id, err = flow.CidToId(cid) 138 cid2 := flow.IdToCid(id) 139 assert.NoError(t, err) 140 assert.Equal(t, cid, cid2) 141 } 142 143 // TestByteConversionRoundTrip evaluates the round trip of conversion of identifiers to bytes, and back. 144 // The original identifiers must be recovered from the converted bytes. 145 func TestByteConversionRoundTrip(t *testing.T) { 146 ids := unittest.IdentifierListFixture(10) 147 148 converted, err := flow.ByteSlicesToIds(flow.IdsToBytes(ids)) 149 require.NoError(t, err) 150 151 require.Equal(t, len(ids), len(converted)) 152 require.ElementsMatch(t, ids, converted) 153 }