github.com/klaytn/klaytn@v1.12.1/blockchain/state/iterator_test.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // This file is derived from ethdb/iterator_test.go (2020/05/20).
    18  // Modified and improved for the klaytn development.
    19  
    20  package state
    21  
    22  import (
    23  	"bytes"
    24  	"testing"
    25  
    26  	"github.com/klaytn/klaytn/common"
    27  	"github.com/klaytn/klaytn/log"
    28  	"github.com/klaytn/klaytn/storage/database"
    29  )
    30  
    31  // Tests that the node iterator indeed walks over the entire database contents.
    32  func TestNodeIteratorCoverage(t *testing.T) {
    33  	log.EnableLogForTest(log.LvlCrit, log.LvlCrit)
    34  	// Create some arbitrary test state to iterate
    35  	db, root, _ := makeTestState(t)
    36  	db.TrieDB().Commit(root, false, 0)
    37  
    38  	state, err := New(root, db, nil, nil)
    39  	if err != nil {
    40  		t.Fatalf("failed to create state trie at %x: %v", root, err)
    41  	}
    42  	// Gather all the node hashes found by the iterator
    43  	iterated := make(map[common.Hash]struct{})
    44  	for it := NewNodeIterator(state); it.Next(); {
    45  		if it.Hash != (common.Hash{}) {
    46  			iterated[it.Hash] = struct{}{}
    47  		}
    48  	}
    49  
    50  	// Cross check the iterated hashes and the database/nodepool content
    51  	// (TrieDB.Node + ContractCode) contains all iterated hashes
    52  	for itHash := range iterated {
    53  		_, err1 := db.TrieDB().Node(itHash.ExtendZero())
    54  		_, err2 := db.ContractCode(itHash)
    55  		if err1 != nil && err2 != nil { // both failed
    56  			t.Errorf("failed to retrieve reported node %x", itHash)
    57  		}
    58  	}
    59  	// iterated hashes contains all TrieDB.Nodes
    60  	for _, exthash := range db.TrieDB().Nodes() {
    61  		hash := exthash.Unextend()
    62  		if hash == emptyCode {
    63  			continue // skip emptyCode
    64  		}
    65  		if _, ok := iterated[hash]; !ok {
    66  			t.Errorf("state entry not reported %x", hash)
    67  		}
    68  	}
    69  	// iterated hashes contains all DiskDB keys
    70  	// StateTrieDB contains preimages, codes and nodes
    71  	it := db.TrieDB().DiskDB().GetMemDB().NewIterator(nil, nil)
    72  	for it.Next() {
    73  		key := it.Key()
    74  		if bytes.HasPrefix(key, []byte("secure-key-")) {
    75  			continue // skip preimages
    76  		}
    77  		if isCode, _ := database.IsCodeKey(key); isCode {
    78  			continue // skip codes
    79  		}
    80  		hash := common.BytesToExtHash(key).Unextend()
    81  		if hash == emptyCode {
    82  			continue // skip emptyCode
    83  		}
    84  		if _, ok := iterated[hash]; !ok {
    85  			t.Errorf("state entry not reported %x", hash)
    86  		}
    87  	}
    88  	it.Release()
    89  }