Support exhaustive comparison of tries
package trie_manager
import (
+ "bytes"
+ "reflect"
+
"github.com/icon-project/goloop/common/db"
"github.com/icon-project/goloop/common/trie"
- "reflect"
)
type trieManager struct {
@@ -29,3 +31,79 @@ func (m *trieManager) NewMutableForObject(h []byte, t reflect.Type) trie.Mutable
func New(database db.Database) trie.Manager {
return &trieManager{database}
}
+
+type BytesDifferenceHandler func(diff int, key, expect, real []byte)
+
+func CompareImmutable(exp, real trie.Immutable, handler BytesDifferenceHandler) error {
+ for ie, ir := exp.Iterator(), real.Iterator(); ie.Has() || ir.Has(); {
+ ve, ke, err := ie.Get()
+ if err != nil {
+ return err
+ }
+ vr, kr, err := ir.Get()
+ if err != nil {
+ return err
+ }
+ switch bytes.Compare(ke, kr) {
+ case -1:
+ handler(-1, ke, ve, nil)
+ if err := ie.Next(); err != nil {
+ return err
+ }
+ case 0:
+ if !bytes.Equal(ve, vr) {
+ handler(0, ke, ve, vr)
+ }
+ if err := ie.Next(); err != nil {
+ return err
+ }
+ if err := ir.Next(); err != nil {
+ return err
+ }
+ case 1:
+ handler(1, kr, nil, vr)
+ if err := ir.Next(); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+type ObjectDifferenceHandler func(op int, key []byte, expect, real trie.Object)
+
+func CompareImmutableForObject(exp, real trie.ImmutableForObject, handler ObjectDifferenceHandler) error {
+ for ie, ir := exp.Iterator(), real.Iterator(); ie.Has() || ir.Has(); {
+ ve, ke, err := ie.Get()
+ if err != nil {
+ return err
+ }
+ vr, kr, err := ir.Get()
+ if err != nil {
+ return err
+ }
+ switch bytes.Compare(ke, kr) {
+ case -1:
+ handler(-1, ke, ve, nil)
+ if err := ie.Next(); err != nil {
+ return err
+ }
+ case 0:
+ if !ve.Equal(vr) {
+ handler(0, ke, ve, vr)
+ }
+ if err := ie.Next(); err != nil {
+ return err
+ }
+ if err := ir.Next(); err != nil {
+ return err
+ }
+ case 1:
+ handler(1, kr, nil, vr)
+ if err := ir.Next(); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
