github.com/klaytn/klaytn@v1.12.1/storage/statedb/print_trie_test.go (about)

     1  // Copyright 2018 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn 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 klaytn 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 klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package statedb
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"testing"
    23  )
    24  
    25  ////////////////////////////////////////////////////////////////////////////////
    26  // Additional member functions of Iterator (defined in iterator.go)
    27  ////////////////////////////////////////////////////////////////////////////////
    28  func (it *Iterator) NextAny() bool {
    29  	if it.nodeIt.Next(true) {
    30  		return true
    31  	}
    32  	it.Err = it.nodeIt.Error()
    33  	return false
    34  }
    35  
    36  ////////////////////////////////////////////////////////////////////////////////
    37  // Additional member functions of nodeIterator (defined in iterator.go)
    38  ////////////////////////////////////////////////////////////////////////////////
    39  func (it *nodeIterator) GetType() string {
    40  	if len(it.stack) == 0 {
    41  		return ""
    42  	}
    43  	return reflect.TypeOf(it.stack[len(it.stack)-1].node).String()
    44  }
    45  
    46  func (it *nodeIterator) GetKeyNibbles() (key, key_nibbles string) {
    47  	k := it.path
    48  	k = k[:len(k)-(len(k)&1)]
    49  
    50  	for i, n := range it.path {
    51  		if i == len(it.path)-1 && n == 16 {
    52  			key_nibbles += "T"
    53  		} else {
    54  			key_nibbles += indices[n]
    55  		}
    56  	}
    57  
    58  	return string(hexToKeybytes(k)), key_nibbles
    59  }
    60  
    61  ////////////////////////////////////////////////////////////////////////////////
    62  // NodeIntMap
    63  //
    64  // Stores a mapping between node* and int
    65  // This is required to make an integer ID of a node object for id in vis.js.
    66  ////////////////////////////////////////////////////////////////////////////////
    67  type NodeIntMap struct {
    68  	hashMap map[*node]int
    69  	counter int
    70  }
    71  
    72  func NewHashIntMap() *NodeIntMap {
    73  	return &NodeIntMap{
    74  		hashMap: map[*node]int{},
    75  		counter: 1,
    76  	}
    77  }
    78  
    79  func (m *NodeIntMap) Get(h *node) int {
    80  	if _, ok := m.hashMap[h]; !ok {
    81  		m.hashMap[h] = m.counter
    82  		m.counter++
    83  	}
    84  
    85  	return m.hashMap[h]
    86  }
    87  
    88  ////////////////////////////////////////////////////////////////////////////////
    89  // VisNode
    90  //
    91  // Describes a node object in vis.js.
    92  ////////////////////////////////////////////////////////////////////////////////
    93  type VisNode struct {
    94  	id       int
    95  	label    string
    96  	level    int
    97  	addr     *node
    98  	str      string
    99  	typename string
   100  }
   101  
   102  func (v *VisNode) String() string {
   103  	return fmt.Sprintf("{id:%d, label:'%s', level:%d, addr:'%p', typename:'%s', x:%d, y:%d}",
   104  		v.id, v.label, v.level, v.addr, v.typename, v.id, v.id)
   105  }
   106  
   107  func SerializeNodes(nodes []VisNode) (ret string) {
   108  	for _, n := range nodes {
   109  		ret += fmt.Sprintf("%s, \n", n.String())
   110  	}
   111  
   112  	return
   113  }
   114  
   115  ////////////////////////////////////////////////////////////////////////////////
   116  // VisEdge
   117  //
   118  // Describes an edge object in vis.js.
   119  ////////////////////////////////////////////////////////////////////////////////
   120  type VisEdge struct {
   121  	from  int
   122  	to    int
   123  	label string
   124  }
   125  
   126  func (e *VisEdge) String() string {
   127  	return fmt.Sprintf("{from:%d, to:%d, label:'%s'}", e.from, e.to, e.label)
   128  }
   129  
   130  func SerializeEdges(edges []VisEdge) (ret string) {
   131  	for _, e := range edges {
   132  		ret += fmt.Sprintf("%s, \n", e.String())
   133  	}
   134  
   135  	return
   136  }
   137  
   138  ////////////////////////////////////////////////////////////////////////////////
   139  // TestPrintTrie
   140  //
   141  // You can execute only this test by `go test -run TestPrintTrie`
   142  ////////////////////////////////////////////////////////////////////////////////
   143  func TestPrintTrie(t *testing.T) {
   144  	trie := newEmptyTrie()
   145  	vals := []struct{ k, v string }{
   146  		//{"klaytn", "wookiedoo"},
   147  		//{"horse", "stallion"},
   148  		//{"shaman", "horse"},
   149  		//{"doge", "coin"},
   150  		//{"dog", "puppy"},
   151  		{"do", "verb"},
   152  		{"dok", "puppyuyyy"},
   153  		{"somethingveryoddindeedthis is", "myothernodedata"},
   154  		{"barb", "ba"},
   155  		{"bard", "bc"},
   156  		{"bars", "bb"},
   157  		{"bar", "b"},
   158  		{"fab", "z"},
   159  		{"food", "ab"},
   160  		{"foos", "aa"},
   161  		{"foo", "a"},
   162  		{"aardvark", "c"},
   163  		//{"bar", "b"},
   164  		//{"barb", "bd"},
   165  		//{"bars", "be"},
   166  		//{"fab", "z"},
   167  		//{"foo", "a"},
   168  		//{"foos", "aa"},
   169  		//{"food", "ab"},
   170  		{"jars", "d"},
   171  	}
   172  	all := make(map[string]string)
   173  	for _, val := range vals {
   174  		all[val.k] = val.v
   175  		trie.Update([]byte(val.k), []byte(val.v))
   176  	}
   177  	trie.Commit(nil)
   178  
   179  	nodeIntMap := NewHashIntMap()
   180  	var visNodes []VisNode
   181  	var visEdges []VisEdge
   182  
   183  	it := NewIterator(trie.NodeIterator(nil))
   184  	for it.NextAny() {
   185  		nodeIt, _ := it.nodeIt.(*nodeIterator)
   186  
   187  		key, key_nibbles := nodeIt.GetKeyNibbles()
   188  
   189  		edgeLabel := ""
   190  
   191  		myId := nodeIntMap.Get(&nodeIt.stack[len(nodeIt.stack)-1].node)
   192  		pId := 0
   193  		if len(nodeIt.stack) > 1 {
   194  			parent := &nodeIt.stack[len(nodeIt.stack)-2].node
   195  			pId = nodeIntMap.Get(parent)
   196  			switch (*parent).(type) {
   197  			case *fullNode:
   198  				edgeLabel = key_nibbles[len(key_nibbles)-1:]
   199  			default:
   200  			}
   201  		}
   202  
   203  		label := string("ROOT")
   204  		if len(key_nibbles) > 0 {
   205  			label = fmt.Sprintf("%s\\n%s", key, key_nibbles)
   206  			if key_nibbles[len(key_nibbles)-1:] == "T" {
   207  				label += fmt.Sprintf("\\nValue:%s", string(nodeIt.LeafBlob()))
   208  			}
   209  		}
   210  
   211  		visNodes = append(visNodes, VisNode{
   212  			id:       myId,
   213  			addr:     &nodeIt.stack[len(nodeIt.stack)-1].node,
   214  			str:      nodeIt.stack[len(nodeIt.stack)-1].node.fstring("0"),
   215  			label:    label,
   216  			level:    len(nodeIt.stack),
   217  			typename: nodeIt.GetType(),
   218  		})
   219  
   220  		if pId > 0 {
   221  			visEdges = append(visEdges, VisEdge{
   222  				from:  pId,
   223  				to:    myId,
   224  				label: edgeLabel,
   225  			})
   226  		}
   227  	}
   228  
   229  	serNodes := SerializeNodes(visNodes)
   230  	serEdges := SerializeEdges(visEdges)
   231  	t.Logf("var nodes = new vis.DataSet([%s]);\n", serNodes)
   232  	t.Logf("var edges = new vis.DataSet([%s]);\n", serEdges)
   233  }