95 lines
3.1 KiB
Go
95 lines
3.1 KiB
Go
|
package mpt
|
||
|
|
||
|
import (
|
||
|
"testing"
|
||
|
|
||
|
"github.com/nspcc-dev/neo-go/pkg/internal/random"
|
||
|
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
|
||
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||
|
"github.com/stretchr/testify/require"
|
||
|
)
|
||
|
|
||
|
func getTestFuncEncode(ok bool, expected, actual Node) func(t *testing.T) {
|
||
|
return func(t *testing.T) {
|
||
|
bs, err := testserdes.EncodeBinary(expected)
|
||
|
require.NoError(t, err)
|
||
|
err = testserdes.DecodeBinary(bs, actual)
|
||
|
if !ok {
|
||
|
require.Error(t, err)
|
||
|
return
|
||
|
}
|
||
|
require.NoError(t, err)
|
||
|
require.Equal(t, expected.Type(), actual.Type())
|
||
|
require.Equal(t, expected.Hash(), actual.Hash())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestNode_Serializable(t *testing.T) {
|
||
|
t.Run("Leaf", func(t *testing.T) {
|
||
|
t.Run("Good", func(t *testing.T) {
|
||
|
l := NewLeafNode(random.Bytes(123))
|
||
|
t.Run("Raw", getTestFuncEncode(true, l, new(LeafNode)))
|
||
|
t.Run("WithType", getTestFuncEncode(true, &NodeObject{l}, new(NodeObject)))
|
||
|
})
|
||
|
t.Run("BigValue", getTestFuncEncode(false,
|
||
|
NewLeafNode(random.Bytes(MaxValueLength+1)), new(LeafNode)))
|
||
|
})
|
||
|
|
||
|
t.Run("Extension", func(t *testing.T) {
|
||
|
t.Run("Good", func(t *testing.T) {
|
||
|
e := NewExtensionNode(random.Bytes(42), NewLeafNode(random.Bytes(10)))
|
||
|
t.Run("Raw", getTestFuncEncode(true, e, new(ExtensionNode)))
|
||
|
t.Run("WithType", getTestFuncEncode(true, &NodeObject{e}, new(NodeObject)))
|
||
|
})
|
||
|
t.Run("BigKey", getTestFuncEncode(false,
|
||
|
NewExtensionNode(random.Bytes(MaxKeyLength+1), NewLeafNode(random.Bytes(10))), new(ExtensionNode)))
|
||
|
})
|
||
|
|
||
|
t.Run("Branch", func(t *testing.T) {
|
||
|
b := NewBranchNode()
|
||
|
b.Children[0] = NewLeafNode(random.Bytes(10))
|
||
|
b.Children[lastChild] = NewHashNode(random.Uint256())
|
||
|
t.Run("Raw", getTestFuncEncode(true, b, new(BranchNode)))
|
||
|
t.Run("WithType", getTestFuncEncode(true, &NodeObject{b}, new(NodeObject)))
|
||
|
})
|
||
|
|
||
|
t.Run("Hash", func(t *testing.T) {
|
||
|
t.Run("Good", func(t *testing.T) {
|
||
|
h := NewHashNode(random.Uint256())
|
||
|
t.Run("Raw", getTestFuncEncode(true, h, new(HashNode)))
|
||
|
t.Run("WithType", getTestFuncEncode(true, &NodeObject{h}, new(NodeObject)))
|
||
|
})
|
||
|
t.Run("Empty", func(t *testing.T) { // compare nodes, not hashes
|
||
|
testserdes.EncodeDecodeBinary(t, new(HashNode), new(HashNode))
|
||
|
})
|
||
|
t.Run("InvalidSize", func(t *testing.T) {
|
||
|
buf := io.NewBufBinWriter()
|
||
|
buf.BinWriter.WriteVarBytes(make([]byte, 13))
|
||
|
require.Error(t, testserdes.DecodeBinary(buf.Bytes(), new(HashNode)))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
t.Run("Invalid", func(t *testing.T) {
|
||
|
require.Error(t, testserdes.DecodeBinary([]byte{0xFF}, new(NodeObject)))
|
||
|
})
|
||
|
}
|
||
|
|
||
|
// C# interoperability test
|
||
|
// https://github.com/neo-project/neo/blob/neox-2.x/neo.UnitTests/UT_MPTTrie.cs#L135
|
||
|
func TestRootHash(t *testing.T) {
|
||
|
b := NewBranchNode()
|
||
|
r := NewExtensionNode([]byte{0x0A, 0x0C}, b)
|
||
|
|
||
|
v1 := NewLeafNode([]byte{0xAB, 0xCD})
|
||
|
l1 := NewExtensionNode([]byte{0x01}, v1)
|
||
|
b.Children[0] = l1
|
||
|
|
||
|
v2 := NewLeafNode([]byte{0x22, 0x22})
|
||
|
l2 := NewExtensionNode([]byte{0x09}, v2)
|
||
|
b.Children[9] = l2
|
||
|
|
||
|
r1 := NewExtensionNode([]byte{0x0A, 0x0C, 0x00, 0x01}, v1)
|
||
|
require.Equal(t, "dea3ab46e9461e885ed7091c1e533e0a8030b248d39cbc638962394eaca0fbb3", r1.Hash().StringLE())
|
||
|
require.Equal(t, "93e8e1ffe2f83dd92fca67330e273bcc811bf64b8f8d9d1b25d5e7366b47d60d", r.Hash().StringLE())
|
||
|
}
|