more changes for test file and function namings

This commit is contained in:
samuel 2025-09-02 20:26:56 +01:00 committed by Gary Rong
parent 9a72c83e6f
commit 6a812bcab0
4 changed files with 133 additions and 141 deletions

View file

@ -148,8 +148,8 @@ type nodeIterator struct {
pool []*nodeIteratorState // local pool for iterator states pool []*nodeIteratorState // local pool for iterator states
// Fields for subtree iteration // Fields for subtree iteration
prefix []byte // Prefix for subtree iteration (nil for full trie) startKey []byte // Start key for subtree iteration (nil for full trie)
stop []byte // Stop boundary for subtree iteration (nil for full trie) stopKey []byte // Stop key for subtree iteration (nil for full trie)
} }
// errIteratorEnd is stored in nodeIterator.err when iteration is done. // errIteratorEnd is stored in nodeIterator.err when iteration is done.
@ -303,23 +303,23 @@ func (it *nodeIterator) Next(descend bool) bool {
// Check if we're still within the subtree boundaries // Check if we're still within the subtree boundaries
// Note: path is already hex-encoded by the iterator // Note: path is already hex-encoded by the iterator
if it.prefix != nil && len(path) > 0 { if it.startKey != nil && len(path) > 0 {
prefixHex := keybytesToHex(it.prefix) startKeyHex := keybytesToHex(it.startKey)
// Remove terminator from prefix hex if present // Remove terminator from startKey hex if present
if hasTerm(prefixHex) { if hasTerm(startKeyHex) {
prefixHex = prefixHex[:len(prefixHex)-1] startKeyHex = startKeyHex[:len(startKeyHex)-1]
} }
if !bytes.HasPrefix(path, prefixHex) { if !bytes.HasPrefix(path, startKeyHex) {
it.err = errIteratorEnd it.err = errIteratorEnd
return false return false
} }
} }
if it.stop != nil && len(path) > 0 { if it.stopKey != nil && len(path) > 0 {
stopHex := keybytesToHex(it.stop) stopKeyHex := keybytesToHex(it.stopKey)
if hasTerm(stopHex) { if hasTerm(stopKeyHex) {
stopHex = stopHex[:len(stopHex)-1] stopKeyHex = stopKeyHex[:len(stopKeyHex)-1]
} }
if bytes.Compare(path, stopHex) >= 0 { if bytes.Compare(path, stopKeyHex) >= 0 {
it.err = errIteratorEnd it.err = errIteratorEnd
return false return false
} }
@ -867,25 +867,25 @@ func (it *unionIterator) Error() error {
} }
// NewSubtreeIterator creates an iterator that only traverses nodes within a subtree // NewSubtreeIterator creates an iterator that only traverses nodes within a subtree
// defined by the given prefix and stopping point. The prefix defines where iteration // defined by the given startKey and stopKey. The startKey defines where iteration
// starts, and stop defines where it ends (exclusive). // starts, and stopKey defines where it ends (exclusive).
func NewSubtreeIterator(trie *Trie, prefix []byte, stop []byte) NodeIterator { func NewSubtreeIterator(trie *Trie, startKey, stopKey []byte) NodeIterator {
if trie.Hash() == types.EmptyRootHash { if trie.Hash() == types.EmptyRootHash {
return &nodeIterator{ return &nodeIterator{
trie: trie, trie: trie,
err: errIteratorEnd, err: errIteratorEnd,
prefix: prefix, startKey: startKey,
stop: stop, stopKey: stopKey,
} }
} }
it := &nodeIterator{ it := &nodeIterator{
trie: trie, trie: trie,
prefix: prefix, startKey: startKey,
stop: stop, stopKey: stopKey,
} }
// Seek to the starting position if prefix is provided // Seek to the starting position if startKey is provided
if prefix != nil && len(prefix) > 0 { if startKey != nil && len(startKey) > 0 {
it.err = it.seek(prefix) it.err = it.seek(startKey)
} else { } else {
state, err := it.init() state, err := it.init()
if err != nil { if err != nil {

View file

@ -676,6 +676,112 @@ func TestSubtreeIterator(t *testing.T) {
} }
} }
func TestPrefixIterator(t *testing.T) {
// Create a new trie
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
// Insert test data
testData := map[string]string{
"key1": "value1",
"key2": "value2",
"key10": "value10",
"key11": "value11",
"different": "value_different",
}
for key, value := range testData {
trie.Update([]byte(key), []byte(value))
}
// Test prefix iteration for "key1" prefix
prefix := []byte("key1")
iter, err := trie.NodeIteratorWithPrefix(prefix)
if err != nil {
t.Fatalf("Failed to create prefix iterator: %v", err)
}
var foundKeys [][]byte
for iter.Next(true) {
if iter.Leaf() {
foundKeys = append(foundKeys, iter.LeafKey())
}
}
if err := iter.Error(); err != nil {
t.Fatalf("Iterator error: %v", err)
}
// Verify only keys starting with "key1" were found
expectedCount := 3 // "key1", "key10", "key11"
if len(foundKeys) != expectedCount {
t.Errorf("Expected %d keys, found %d", expectedCount, len(foundKeys))
}
for _, key := range foundKeys {
keyStr := string(key)
if !bytes.HasPrefix(key, prefix) {
t.Errorf("Found key %s doesn't have prefix %s", keyStr, string(prefix))
}
}
}
func TestPrefixIteratorVsFullIterator(t *testing.T) {
// Create a new trie with more structured data
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
// Insert structured test data
testData := map[string]string{
"aaa": "value_aaa",
"aab": "value_aab",
"aba": "value_aba",
"bbb": "value_bbb",
}
for key, value := range testData {
trie.Update([]byte(key), []byte(value))
}
// Test that prefix iterator stops at boundary
prefix := []byte("aa")
prefixIter, err := trie.NodeIteratorWithPrefix(prefix)
if err != nil {
t.Fatalf("Failed to create prefix iterator: %v", err)
}
var prefixKeys [][]byte
for prefixIter.Next(true) {
if prefixIter.Leaf() {
prefixKeys = append(prefixKeys, prefixIter.LeafKey())
}
}
// Should only find "aaa" and "aab", not "aba" or "bbb"
if len(prefixKeys) != 2 {
t.Errorf("Expected 2 keys with prefix 'aa', found %d", len(prefixKeys))
}
// Verify no keys outside prefix were found
for _, key := range prefixKeys {
if !bytes.HasPrefix(key, prefix) {
t.Errorf("Prefix iterator returned key %s outside prefix %s", string(key), string(prefix))
}
}
}
func TestEmptyPrefixIterator(t *testing.T) {
// Test with empty trie
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
iter, err := trie.NodeIteratorWithPrefix([]byte("nonexistent"))
if err != nil {
t.Fatalf("Failed to create iterator: %v", err)
}
if iter.Next(true) {
t.Error("Expected no results from empty trie")
}
}
func BenchmarkIterator(b *testing.B) { func BenchmarkIterator(b *testing.B) {
diskDb, srcDb, tr, _ := makeTestTrie(rawdb.HashScheme) diskDb, srcDb, tr, _ := makeTestTrie(rawdb.HashScheme)
root := tr.Hash() root := tr.Hash()

View file

@ -1,114 +0,0 @@
package trie
import (
"bytes"
"testing"
"github.com/ethereum/go-ethereum/core/rawdb"
)
func TestPrefixIterator(t *testing.T) {
// Create a new trie
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
// Insert test data
testData := map[string]string{
"key1": "value1",
"key2": "value2",
"key10": "value10",
"key11": "value11",
"different": "value_different",
}
for key, value := range testData {
trie.Update([]byte(key), []byte(value))
}
// Test prefix iteration for "key1" prefix
prefix := []byte("key1")
iter, err := trie.NodeIteratorWithPrefix(prefix)
if err != nil {
t.Fatalf("Failed to create prefix iterator: %v", err)
}
var foundKeys [][]byte
for iter.Next(true) {
if iter.Leaf() {
foundKeys = append(foundKeys, iter.LeafKey())
}
}
if err := iter.Error(); err != nil {
t.Fatalf("Iterator error: %v", err)
}
// Verify only keys starting with "key1" were found
expectedCount := 3 // "key1", "key10", "key11"
if len(foundKeys) != expectedCount {
t.Errorf("Expected %d keys, found %d", expectedCount, len(foundKeys))
}
for _, key := range foundKeys {
keyStr := string(key)
if !bytes.HasPrefix(key, prefix) {
t.Errorf("Found key %s doesn't have prefix %s", keyStr, string(prefix))
}
}
}
func TestPrefixIteratorVsFullIterator(t *testing.T) {
// Create a new trie with more structured data
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
// Insert structured test data
testData := map[string]string{
"aaa": "value_aaa",
"aab": "value_aab",
"aba": "value_aba",
"bbb": "value_bbb",
}
for key, value := range testData {
trie.Update([]byte(key), []byte(value))
}
// Test that prefix iterator stops at boundary
prefix := []byte("aa")
prefixIter, err := trie.NodeIteratorWithPrefix(prefix)
if err != nil {
t.Fatalf("Failed to create prefix iterator: %v", err)
}
var prefixKeys [][]byte
for prefixIter.Next(true) {
if prefixIter.Leaf() {
prefixKeys = append(prefixKeys, prefixIter.LeafKey())
}
}
// Should only find "aaa" and "aab", not "aba" or "bbb"
if len(prefixKeys) != 2 {
t.Errorf("Expected 2 keys with prefix 'aa', found %d", len(prefixKeys))
}
// Verify no keys outside prefix were found
for _, key := range prefixKeys {
if !bytes.HasPrefix(key, prefix) {
t.Errorf("Prefix iterator returned key %s outside prefix %s", string(key), string(prefix))
}
}
}
func TestEmptyPrefixIterator(t *testing.T) {
// Test with empty trie
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
iter, err := trie.NodeIteratorWithPrefix([]byte("nonexistent"))
if err != nil {
t.Fatalf("Failed to create iterator: %v", err)
}
if iter.Next(true) {
t.Error("Expected no results from empty trie")
}
}

View file

@ -141,7 +141,7 @@ func (t *Trie) NodeIteratorWithPrefix(prefix []byte) (NodeIterator, error) {
if t.committed { if t.committed {
return nil, ErrCommitted return nil, ErrCommitted
} }
// Use NewSubtreeIterator with just a prefix and no stop boundary // Use NewSubtreeIterator with just a startKey and no stopKey boundary
return NewSubtreeIterator(t, prefix, nil), nil return NewSubtreeIterator(t, prefix, nil), nil
} }