Skip to content

Commit

Permalink
add basic operation tests
Browse files Browse the repository at this point in the history
  • Loading branch information
weiihann committed Oct 21, 2024
1 parent 1e2aaa4 commit a5c3119
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 1 deletion.
2 changes: 1 addition & 1 deletion encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func ParseNode(serializedNode []byte, depth byte) (VerkleNode, error) {
return parseEoAccountNode(serializedNode, depth)
case singleSlotType:
return parseSingleSlotNode(serializedNode, depth)
case expiredLeafType: // TODO(weiihann)
case expiredLeafType:
return parseExpiredLeafNode(serializedNode)
default:
return nil, ErrInvalidNodeEncoding
Expand Down
223 changes: 223 additions & 0 deletions expired_tree_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
package verkle

import (
"bytes"
"errors"
"testing"
)

func TestInsertSameLeafNoExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

if err := root.Insert(oneKeyTest, testValue, 1, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

leaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

if !bytes.Equal(leaf.values[zeroKeyTest[StemSize]], testValue) {
t.Fatalf("expected value %x, got %x", testValue, leaf.values[zeroKeyTest[StemSize]])
}

if !bytes.Equal(leaf.values[oneKeyTest[StemSize]], testValue) {
t.Fatalf("expected value %x, got %x", testValue, leaf.values[oneKeyTest[StemSize]])
}

if leaf.lastTs != 1 {
t.Fatalf("expected last accessed to be 1, got %d", leaf.lastTs)
}
}

func TestInsertSameLeafExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

err := root.Insert(oneKeyTest, testValue, 2, nil)
if !errors.Is(err, errEpochExpired) {
t.Fatalf("expected epoch expired error when inserting, got %v", err)
}

leaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

if !bytes.Equal(leaf.values[zeroKeyTest[StemSize]], testValue) {
t.Fatalf("expected value %x, got %x", testValue, leaf.values[zeroKeyTest[StemSize]])
}

if leaf.lastTs != 0 {
t.Fatalf("expected last accessed to be 0, got %d", leaf.lastTs)
}
}

func TestInsertDiffLeaf(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

if err := root.Insert(ffx32KeyTest, testValue, 2, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

leaf0, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

leaff, ok := root.(*InternalNode).children[255].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[255])
}

if !bytes.Equal(leaf0.values[zeroKeyTest[StemSize]], testValue) {
t.Fatalf("expected value %x, got %x", testValue, leaf0.values[zeroKeyTest[StemSize]])
}

if !bytes.Equal(leaff.values[ffx32KeyTest[StemSize]], testValue) {
t.Fatalf("expected value %x, got %x", testValue, leaff.values[ffx32KeyTest[StemSize]])
}

if leaf0.lastTs != 0 {
t.Fatalf("expected last accessed to be 0, got %d", leaf0.lastTs)
}

if leaff.lastTs != 2 {
t.Fatalf("expected last accessed to be 2, got %d", leaff.lastTs)
}
}

func TestGetNoExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

val, err := root.Get(zeroKeyTest, 1, nil)
if err != nil {
t.Fatalf("error getting: %v", err)
}

leaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

if !bytes.Equal(val, testValue) {
t.Fatalf("expected value %x, got %x", testValue, val)
}

if leaf.lastTs != 0 {
t.Fatalf("expected last accessed to be 0, got %d", leaf.lastTs)
}
}

func TestGetExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

val, err := root.Get(zeroKeyTest, 2, nil)
if !errors.Is(err, errEpochExpired) {
t.Fatalf("expected epoch expired error when getting, got %v", err)
}

if val != nil {
t.Fatalf("expected value to be nil, got %x", val)
}

leaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

if leaf.lastTs != 0 {
t.Fatalf("expected last accessed to be 0, got %d", leaf.lastTs)
}
}

func TestDelLeafNoExpired(t *testing.T) { // skipcq: GO-R1005
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

if _, err := root.Delete(zeroKeyTest, 1, nil); err != nil {
t.Fatalf("error deleting: %v", err)
}

_, ok := root.(*InternalNode).children[0].(Empty)
if !ok {
t.Fatalf("expected empty node, got %T", root.(*InternalNode).children[0])
}
}

func TestDelLeafExpired(t *testing.T) { // skipcq: GO-R1005
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

_, err := root.Delete(zeroKeyTest, 2, nil)
if !errors.Is(err, errEpochExpired) {
t.Fatalf("expected epoch expired error when deleting, got %v", err)
}

leaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected empty node, got %T", root.(*InternalNode).children[0])
}

if leaf.lastTs != 0 {
t.Fatalf("expected last accessed to be 0, got %d", leaf.lastTs)
}
}

func TestRootCommitExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

leaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

var init Point
init.Set(root.Commit())

expiredLeaf := NewExpiredLeafNode(leaf.stem, leaf.commitment)
root.(*InternalNode).children[0] = expiredLeaf

comm := root.Commit()
if !comm.Equal(&init) {
t.Fatalf("expected commitment to be %x, got %x", &init, comm)
}
}
5 changes: 5 additions & 0 deletions tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,7 @@ func (n *InternalNode) Delete(key []byte, curTs AccessTimestamp, resolver NodeRe
// DeleteAtStem delete a full stem. Unlike Delete, it will error out if the stem that is to
// be deleted does not exist in the tree, because it's meant to be used by rollback code,
// that should only delete things that exist.
// TODO(weiihann): check if need to compare access timestamp
func (n *InternalNode) DeleteAtStem(key []byte, resolver NodeResolverFn) (bool, error) {
nChild := offset2key(key, n.depth)
switch child := n.children[nChild].(type) {
Expand Down Expand Up @@ -1198,6 +1199,10 @@ func (n *LeafNode) insertMultiple(stem Stem, values [][]byte, curTs AccessTimest
return errInsertIntoOtherStem
}

if IsExpired(n.lastTs, curTs) {
return errEpochExpired
}

if err := n.updateMultipleLeaves(values, curTs); err != nil {
return err
}
Expand Down

0 comments on commit a5c3119

Please sign in to comment.