github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/ledger/complete/wal/checkpointer_serialization_test.go (about) 1 package wal 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/assert" 7 "github.com/stretchr/testify/require" 8 9 "github.com/onflow/flow-go/ledger" 10 "github.com/onflow/flow-go/ledger/common/hash" 11 "github.com/onflow/flow-go/ledger/common/testutils" 12 "github.com/onflow/flow-go/ledger/complete/mtrie/node" 13 "github.com/onflow/flow-go/ledger/complete/mtrie/trie" 14 ) 15 16 func TestGetNodesAtLevel(t *testing.T) { 17 18 t.Run("nil node", func(t *testing.T) { 19 n := (*node.Node)(nil) 20 for level := uint(0); level < 6; level++ { 21 nodes := getNodesAtLevel(n, level) 22 assert.Equal(t, 1<<level, len(nodes)) 23 for _, nAtLevel := range nodes { 24 require.Nil(t, nAtLevel) 25 } 26 } 27 }) 28 29 t.Run("leaf node", func(t *testing.T) { 30 path := testutils.PathByUint8(1) 31 payload := testutils.LightPayload8('A', 'a') 32 hashValue := hash.Hash([32]byte{1, 1, 1}) 33 leafNode := node.NewNode(255, nil, nil, path, payload, hashValue) 34 35 nodes := getNodesAtLevel(leafNode, 0) 36 require.Equal(t, []*node.Node{leafNode}, nodes) 37 38 for level := uint(1); level < 6; level++ { 39 nodes := getNodesAtLevel(leafNode, level) 40 require.Equal(t, 1<<level, len(nodes)) 41 for _, nAtLevel := range nodes { 42 require.Nil(t, nAtLevel) 43 } 44 } 45 }) 46 47 t.Run("interim node with left child", func(t *testing.T) { 48 emptyTrie := trie.NewEmptyMTrie() 49 50 // key: 0000... 51 p1 := testutils.PathByUint8(0) 52 v1 := testutils.LightPayload8('A', 'a') 53 54 // key: 0100.... 55 p2 := testutils.PathByUint8(64) 56 v2 := testutils.LightPayload8('B', 'b') 57 58 paths := []ledger.Path{p1, p2} 59 payloads := []ledger.Payload{*v1, *v2} 60 61 updatedTrie, _, err := trie.NewTrieWithUpdatedRegisters(emptyTrie, paths, payloads, true) 62 require.NoError(t, err) 63 64 // n4 65 // / 66 // / 67 // n3 68 // / \ 69 // / \ 70 // n1 (p1/v1) n2 (p2/v2) 71 72 rootNode := updatedTrie.RootNode() 73 74 nodes := getNodesAtLevel(rootNode, 0) 75 require.Equal(t, []*node.Node{updatedTrie.RootNode()}, nodes) 76 77 nodes = getNodesAtLevel(rootNode, 1) 78 require.Equal(t, []*node.Node{rootNode.LeftChild(), nil}, nodes) 79 80 nodes = getNodesAtLevel(rootNode, 2) 81 require.Equal(t, []*node.Node{rootNode.LeftChild().LeftChild(), rootNode.LeftChild().RightChild(), nil, nil}, nodes) 82 83 for level := uint(3); level < 6; level++ { 84 nodes := getNodesAtLevel(rootNode, level) 85 require.Equal(t, 1<<level, len(nodes)) 86 for _, nAtLevel := range nodes { 87 require.Nil(t, nAtLevel) 88 } 89 } 90 }) 91 92 t.Run("interim node with right child", func(t *testing.T) { 93 emptyTrie := trie.NewEmptyMTrie() 94 95 // key: 1000... 96 p3 := testutils.PathByUint8(128) 97 v3 := testutils.LightPayload8('C', 'c') 98 99 // key: 1100.... 100 p4 := testutils.PathByUint8(192) 101 v4 := testutils.LightPayload8('D', 'd') 102 103 paths := []ledger.Path{p3, p4} 104 payloads := []ledger.Payload{*v3, *v4} 105 106 updatedTrie, _, err := trie.NewTrieWithUpdatedRegisters(emptyTrie, paths, payloads, true) 107 require.NoError(t, err) 108 109 // n8 110 // \ 111 // \ 112 // n7 113 // / \ 114 // / \ 115 // n5 n6 116 // (p3/v3) (p4/v4) 117 118 rootNode := updatedTrie.RootNode() 119 120 nodes := getNodesAtLevel(rootNode, 0) 121 require.Equal(t, []*node.Node{rootNode}, nodes) 122 123 nodes = getNodesAtLevel(rootNode, 1) 124 require.Equal(t, []*node.Node{nil, rootNode.RightChild()}, nodes) 125 126 nodes = getNodesAtLevel(rootNode, 2) 127 require.Equal(t, []*node.Node{nil, nil, rootNode.RightChild().LeftChild(), rootNode.RightChild().RightChild()}, nodes) 128 129 for level := uint(3); level < 6; level++ { 130 nodes := getNodesAtLevel(rootNode, level) 131 require.Equal(t, 1<<level, len(nodes)) 132 for _, nAtLevel := range nodes { 133 require.Nil(t, nAtLevel) 134 } 135 } 136 }) 137 138 t.Run("interim node with 2 children", func(t *testing.T) { 139 emptyTrie := trie.NewEmptyMTrie() 140 141 // key: 0000... 142 p1 := testutils.PathByUint8(0) 143 v1 := testutils.LightPayload8('A', 'a') 144 145 // key: 0100.... 146 p2 := testutils.PathByUint8(64) 147 v2 := testutils.LightPayload8('B', 'b') 148 149 // key: 1000... 150 p3 := testutils.PathByUint8(128) 151 v3 := testutils.LightPayload8('C', 'c') 152 153 // key: 1100.... 154 p4 := testutils.PathByUint8(192) 155 v4 := testutils.LightPayload8('D', 'd') 156 157 paths := []ledger.Path{p1, p2, p3, p4} 158 payloads := []ledger.Payload{*v1, *v2, *v3, *v4} 159 160 updatedTrie, _, err := trie.NewTrieWithUpdatedRegisters(emptyTrie, paths, payloads, true) 161 require.NoError(t, err) 162 163 // n4 164 // / \ 165 // / \ 166 // n3 n5 167 // / \ / \ 168 // / \ / \ 169 // n1 n2 n6 n7 170 // (p1) (p2) (p3) (p4) 171 172 rootNode := updatedTrie.RootNode() 173 174 nodes := getNodesAtLevel(rootNode, 0) 175 require.Equal(t, []*node.Node{rootNode}, nodes) 176 177 nodes = getNodesAtLevel(rootNode, 1) 178 require.Equal(t, []*node.Node{rootNode.LeftChild(), rootNode.RightChild()}, nodes) 179 180 nodes = getNodesAtLevel(rootNode, 2) 181 require.Equal(t, []*node.Node{rootNode.LeftChild().LeftChild(), rootNode.LeftChild().RightChild(), rootNode.RightChild().LeftChild(), rootNode.RightChild().RightChild()}, nodes) 182 183 for level := uint(3); level < 6; level++ { 184 nodes := getNodesAtLevel(rootNode, level) 185 require.Equal(t, 1<<level, len(nodes)) 186 for _, nAtLevel := range nodes { 187 require.Nil(t, nAtLevel) 188 } 189 } 190 }) 191 192 t.Run("sparse trie with 8 levels", func(t *testing.T) { 193 194 emptyTrie := trie.NewEmptyMTrie() 195 196 // key: 0000 0000 197 p1 := testutils.PathByUint8(0) 198 v1 := testutils.LightPayload8('A', 'a') 199 200 // key: 0000 0001 201 p2 := testutils.PathByUint8(1) 202 v2 := testutils.LightPayload8('B', 'b') 203 204 // key: 1111 1110 205 p3 := testutils.PathByUint8(254) 206 v3 := testutils.LightPayload8('C', 'c') 207 208 // key: 1111 1111 209 p4 := testutils.PathByUint8(255) 210 v4 := testutils.LightPayload8('D', 'd') 211 212 paths := []ledger.Path{p1, p2, p3, p4} 213 payloads := []ledger.Payload{*v1, *v2, *v3, *v4} 214 215 updatedTrie, _, err := trie.NewTrieWithUpdatedRegisters(emptyTrie, paths, payloads, true) 216 require.NoError(t, err) 217 218 // n0 219 // / \ 220 // n1a n1b 221 // / \ 222 // n2a n2b 223 // / \ 224 // n3a n3b 225 // / \ 226 // n4a n4b 227 // / \ 228 // n5a n5b 229 // / \ 230 // n6a n6b 231 // / \ 232 // n7a n7b 233 // / \ / \ 234 // n8a n8b n8d n8d 235 // (p1) (p2) (p3) (p4) 236 237 n0 := updatedTrie.RootNode() 238 239 n1a := n0.LeftChild() 240 require.NotNil(t, n1a) 241 n1b := n0.RightChild() 242 require.NotNil(t, n1b) 243 244 n2a := n1a.LeftChild() 245 require.NotNil(t, n2a) 246 n2b := n1b.RightChild() 247 require.NotNil(t, n2b) 248 249 n3a := n2a.LeftChild() 250 require.NotNil(t, n3a) 251 n3b := n2b.RightChild() 252 require.NotNil(t, n3b) 253 254 n4a := n3a.LeftChild() 255 require.NotNil(t, n4a) 256 n4b := n3b.RightChild() 257 require.NotNil(t, n4b) 258 259 n5a := n4a.LeftChild() 260 require.NotNil(t, n5a) 261 n5b := n4b.RightChild() 262 require.NotNil(t, n5b) 263 264 n6a := n5a.LeftChild() 265 require.NotNil(t, n6a) 266 n6b := n5b.RightChild() 267 require.NotNil(t, n6b) 268 269 n7a := n6a.LeftChild() 270 require.NotNil(t, n7a) 271 n7b := n6b.RightChild() 272 require.NotNil(t, n7b) 273 274 n8a := n7a.LeftChild() 275 require.NotNil(t, n8a) 276 n8b := n7a.RightChild() 277 require.NotNil(t, n8b) 278 n8c := n7b.LeftChild() 279 require.NotNil(t, n8c) 280 n8d := n7b.RightChild() 281 require.NotNil(t, n8d) 282 283 testcases := []struct { 284 level uint 285 expectedNodes []*node.Node 286 }{ 287 {0, []*node.Node{n0}}, 288 {1, []*node.Node{n1a, n1b}}, 289 {2, []*node.Node{0: n2a, 3: n2b}}, 290 {3, []*node.Node{0: n3a, 7: n3b}}, 291 {4, []*node.Node{0: n4a, 15: n4b}}, 292 {5, []*node.Node{0: n5a, 31: n5b}}, 293 {6, []*node.Node{0: n6a, 63: n6b}}, 294 {7, []*node.Node{0: n7a, 127: n7b}}, 295 {8, []*node.Node{0: n8a, 1: n8b, 254: n8c, 255: n8d}}, 296 } 297 298 rootNode := updatedTrie.RootNode() 299 for _, tc := range testcases { 300 nodes := getNodesAtLevel(rootNode, tc.level) 301 require.Equal(t, len(tc.expectedNodes), len(nodes)) 302 require.Equal(t, tc.expectedNodes, nodes) 303 } 304 }) 305 }