github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/iavl/tree_test.go (about)

     1  package iavl
     2  
     3  import (
     4  	"bytes"
     5  	"flag"
     6  	"fmt"
     7  	"os"
     8  	"runtime"
     9  	"strconv"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/gnolang/gno/tm2/pkg/db"
    16  	"github.com/gnolang/gno/tm2/pkg/db/goleveldb"
    17  	"github.com/gnolang/gno/tm2/pkg/db/memdb"
    18  	"github.com/gnolang/gno/tm2/pkg/random"
    19  )
    20  
    21  var (
    22  	testLevelDB        bool
    23  	testFuzzIterations int
    24  	rnd                *random.Rand
    25  )
    26  
    27  // NOTE see https://github.com/golang/go/issues/31859
    28  var _ = func() bool {
    29  	testing.Init()
    30  	return true
    31  }()
    32  
    33  func init() {
    34  	rnd = random.NewRand()
    35  	rnd.Seed(0) // for determinism
    36  	flag.BoolVar(&testLevelDB, "test.leveldb", false, "test leveldb backend")
    37  	flag.IntVar(&testFuzzIterations, "test.fuzz-iterations", 100000, "number of fuzz testing iterations")
    38  	flag.Parse()
    39  }
    40  
    41  func getTestDB() (db.DB, func()) {
    42  	if testLevelDB {
    43  		d, err := goleveldb.NewGoLevelDB("test", ".")
    44  		if err != nil {
    45  			panic(err)
    46  		}
    47  		return d, func() {
    48  			d.Close()
    49  			os.RemoveAll("./test.db")
    50  		}
    51  	}
    52  	return memdb.NewMemDB(), func() {}
    53  }
    54  
    55  func TestVersionedRandomTree(t *testing.T) {
    56  	t.Parallel()
    57  
    58  	require := require.New(t)
    59  
    60  	d, closeDB := getTestDB()
    61  	defer closeDB()
    62  
    63  	tree := NewMutableTree(d, 100)
    64  	versions := 50
    65  	keysPerVersion := 30
    66  
    67  	// Create a tree of size 1000 with 100 versions.
    68  	for i := 1; i <= versions; i++ {
    69  		for j := 0; j < keysPerVersion; j++ {
    70  			k := []byte(rnd.Str(8))
    71  			v := []byte(rnd.Str(8))
    72  			tree.Set(k, v)
    73  		}
    74  		tree.SaveVersion()
    75  	}
    76  	require.Equal(versions, len(tree.ndb.roots()), "wrong number of roots")
    77  	require.Equal(versions*keysPerVersion, len(tree.ndb.leafNodes()), "wrong number of nodes")
    78  
    79  	// Before deleting old versions, we should have equal or more nodes in the
    80  	// db than in the current tree version.
    81  	require.True(len(tree.ndb.nodes()) >= tree.nodeSize())
    82  
    83  	// Ensure it returns all versions in sorted order
    84  	available := zip(tree.AvailableVersions())
    85  	assert.Equal(t, versions, len(available))
    86  	assert.Equal(t, int64(1), available[0])
    87  	assert.Equal(t, int64(versions), available[len(available)-1])
    88  
    89  	for i := 1; i < versions; i++ {
    90  		tree.DeleteVersion(int64(i))
    91  	}
    92  	available = zip(tree.AvailableVersions())
    93  
    94  	require.Len(available, 1, "tree must have one version left")
    95  	tr, err := tree.GetImmutable(int64(versions))
    96  	require.NoError(err, "GetImmutable should not error for version %d", versions)
    97  	require.Equal(tr.root, tree.root)
    98  
    99  	// we should only have one available version now
   100  	available = zip(tree.AvailableVersions())
   101  	assert.Equal(t, 1, len(available))
   102  	assert.Equal(t, int64(versions), available[0])
   103  
   104  	// After cleaning up all previous versions, we should have as many nodes
   105  	// in the db as in the current tree version.
   106  	require.Len(tree.ndb.leafNodes(), int(tree.Size()))
   107  
   108  	require.Equal(tree.nodeSize(), len(tree.ndb.nodes()))
   109  }
   110  
   111  func TestVersionedRandomTreeSmallKeys(t *testing.T) {
   112  	t.Parallel()
   113  
   114  	require := require.New(t)
   115  	d, closeDB := getTestDB()
   116  	defer closeDB()
   117  
   118  	tree := NewMutableTree(d, 100)
   119  	singleVersionTree := NewMutableTree(memdb.NewMemDB(), 0)
   120  	versions := 20
   121  	keysPerVersion := 50
   122  
   123  	for i := 1; i <= versions; i++ {
   124  		for j := 0; j < keysPerVersion; j++ {
   125  			// Keys of size one are likely to be overwritten.
   126  			k := []byte(rnd.Str(1))
   127  			v := []byte(rnd.Str(8))
   128  			tree.Set(k, v)
   129  			singleVersionTree.Set(k, v)
   130  		}
   131  		tree.SaveVersion()
   132  	}
   133  	singleVersionTree.SaveVersion()
   134  
   135  	for i := 1; i < versions; i++ {
   136  		tree.DeleteVersion(int64(i))
   137  	}
   138  
   139  	// After cleaning up all previous versions, we should have as many nodes
   140  	// in the db as in the current tree version. The simple tree must be equal
   141  	// too.
   142  	require.Len(tree.ndb.leafNodes(), int(tree.Size()))
   143  	require.Len(tree.ndb.nodes(), tree.nodeSize())
   144  	require.Len(tree.ndb.nodes(), singleVersionTree.nodeSize())
   145  
   146  	// Try getting random keys.
   147  	for i := 0; i < keysPerVersion; i++ {
   148  		_, val := tree.Get([]byte(rnd.Str(1)))
   149  		require.NotNil(val)
   150  		require.NotEmpty(val)
   151  	}
   152  }
   153  
   154  func TestVersionedRandomTreeSmallKeysRandomDeletes(t *testing.T) {
   155  	t.Parallel()
   156  
   157  	require := require.New(t)
   158  	d, closeDB := getTestDB()
   159  	defer closeDB()
   160  
   161  	tree := NewMutableTree(d, 100)
   162  	singleVersionTree := NewMutableTree(memdb.NewMemDB(), 0)
   163  	versions := 30
   164  	keysPerVersion := 50
   165  
   166  	for i := 1; i <= versions; i++ {
   167  		for j := 0; j < keysPerVersion; j++ {
   168  			// Keys of size one are likely to be overwritten.
   169  			k := []byte(rnd.Str(1))
   170  			v := []byte(rnd.Str(8))
   171  			tree.Set(k, v)
   172  			singleVersionTree.Set(k, v)
   173  		}
   174  		tree.SaveVersion()
   175  	}
   176  	singleVersionTree.SaveVersion()
   177  
   178  	for _, i := range rnd.Perm(versions - 1) {
   179  		tree.DeleteVersion(int64(i + 1))
   180  	}
   181  
   182  	// After cleaning up all previous versions, we should have as many nodes
   183  	// in the db as in the current tree version. The simple tree must be equal
   184  	// too.
   185  	require.Len(tree.ndb.leafNodes(), int(tree.Size()))
   186  	require.Len(tree.ndb.nodes(), tree.nodeSize())
   187  	require.Len(tree.ndb.nodes(), singleVersionTree.nodeSize())
   188  
   189  	// Try getting random keys.
   190  	for i := 0; i < keysPerVersion; i++ {
   191  		_, val := tree.Get([]byte(rnd.Str(1)))
   192  		require.NotNil(val)
   193  		require.NotEmpty(val)
   194  	}
   195  }
   196  
   197  func TestVersionedTreeSpecial1(t *testing.T) {
   198  	t.Parallel()
   199  
   200  	tree := NewMutableTree(memdb.NewMemDB(), 100)
   201  
   202  	tree.Set([]byte("C"), []byte("so43QQFN"))
   203  	tree.SaveVersion()
   204  
   205  	tree.Set([]byte("A"), []byte("ut7sTTAO"))
   206  	tree.SaveVersion()
   207  
   208  	tree.Set([]byte("X"), []byte("AoWWC1kN"))
   209  	tree.SaveVersion()
   210  
   211  	tree.Set([]byte("T"), []byte("MhkWjkVy"))
   212  	tree.SaveVersion()
   213  
   214  	tree.DeleteVersion(1)
   215  	tree.DeleteVersion(2)
   216  	tree.DeleteVersion(3)
   217  
   218  	require.Equal(t, tree.nodeSize(), len(tree.ndb.nodes()))
   219  }
   220  
   221  func TestVersionedRandomTreeSpecial2(t *testing.T) {
   222  	t.Parallel()
   223  
   224  	require := require.New(t)
   225  	tree := NewMutableTree(memdb.NewMemDB(), 100)
   226  
   227  	tree.Set([]byte("OFMe2Yvm"), []byte("ez2OtQtE"))
   228  	tree.Set([]byte("WEN4iN7Y"), []byte("kQNyUalI"))
   229  	tree.SaveVersion()
   230  
   231  	tree.Set([]byte("1yY3pXHr"), []byte("udYznpII"))
   232  	tree.Set([]byte("7OSHNE7k"), []byte("ff181M2d"))
   233  	tree.SaveVersion()
   234  
   235  	tree.DeleteVersion(1)
   236  	require.Len(tree.ndb.nodes(), tree.nodeSize())
   237  }
   238  
   239  func TestVersionedEmptyTree(t *testing.T) {
   240  	t.Parallel()
   241  
   242  	require := require.New(t)
   243  	d, closeDB := getTestDB()
   244  	defer closeDB()
   245  
   246  	tree := NewMutableTree(d, 0)
   247  
   248  	hash, v, err := tree.SaveVersion()
   249  	require.Nil(hash)
   250  	require.EqualValues(1, v)
   251  	require.NoError(err)
   252  
   253  	hash, v, err = tree.SaveVersion()
   254  	require.Nil(hash)
   255  	require.EqualValues(2, v)
   256  	require.NoError(err)
   257  
   258  	hash, v, err = tree.SaveVersion()
   259  	require.Nil(hash)
   260  	require.EqualValues(3, v)
   261  	require.NoError(err)
   262  
   263  	hash, v, err = tree.SaveVersion()
   264  	require.Nil(hash)
   265  	require.EqualValues(4, v)
   266  	require.NoError(err)
   267  
   268  	require.EqualValues(4, tree.Version())
   269  
   270  	require.True(tree.VersionExists(1))
   271  	require.True(tree.VersionExists(3))
   272  
   273  	require.NoError(tree.DeleteVersion(1))
   274  	require.NoError(tree.DeleteVersion(3))
   275  
   276  	require.False(tree.VersionExists(1))
   277  	require.False(tree.VersionExists(3))
   278  
   279  	tree.Set([]byte("k"), []byte("v"))
   280  	require.EqualValues(5, tree.root.version)
   281  
   282  	// Now reload the tree.
   283  
   284  	tree = NewMutableTree(d, 0)
   285  	tree.Load()
   286  
   287  	require.False(tree.VersionExists(1))
   288  	require.True(tree.VersionExists(2))
   289  	require.False(tree.VersionExists(3))
   290  
   291  	t2, err := tree.GetImmutable(2)
   292  	require.NoError(err, "GetImmutable should not fail for version 2")
   293  
   294  	require.Empty(t2.root)
   295  }
   296  
   297  func TestVersionedTree(t *testing.T) {
   298  	t.Parallel()
   299  
   300  	require := require.New(t)
   301  	d, closeDB := getTestDB()
   302  	defer closeDB()
   303  
   304  	tree := NewMutableTree(d, 0)
   305  
   306  	// We start with zero keys in the databse.
   307  	require.Equal(0, tree.ndb.size())
   308  	require.True(tree.IsEmpty())
   309  
   310  	// version 0
   311  
   312  	tree.Set([]byte("key1"), []byte("val0"))
   313  	tree.Set([]byte("key2"), []byte("val0"))
   314  
   315  	// Still zero keys, since we haven't written them.
   316  	require.Len(tree.ndb.leafNodes(), 0)
   317  	require.False(tree.IsEmpty())
   318  
   319  	// Now let's write the keys to storage.
   320  	hash1, v, err := tree.SaveVersion()
   321  	require.NoError(err)
   322  	require.False(tree.IsEmpty())
   323  	require.EqualValues(1, v)
   324  
   325  	// -----1-----
   326  	// key1 = val0  version=1
   327  	// key2 = val0  version=1
   328  	// key2 (root)  version=1
   329  	// -----------
   330  
   331  	nodes1 := tree.ndb.leafNodes()
   332  	require.Len(nodes1, 2, "db should have a size of 2")
   333  
   334  	// version  1
   335  
   336  	tree.Set([]byte("key1"), []byte("val1"))
   337  	tree.Set([]byte("key2"), []byte("val1"))
   338  	tree.Set([]byte("key3"), []byte("val1"))
   339  	require.Len(tree.ndb.leafNodes(), len(nodes1))
   340  
   341  	hash2, v2, err := tree.SaveVersion()
   342  	require.NoError(err)
   343  	require.False(bytes.Equal(hash1, hash2))
   344  	require.EqualValues(v+1, v2)
   345  
   346  	// Recreate a new tree and load it, to make sure it works in this
   347  	// scenario.
   348  	tree = NewMutableTree(d, 100)
   349  	_, err = tree.Load()
   350  	require.NoError(err)
   351  	available := zip(tree.AvailableVersions())
   352  
   353  	require.Len(available, 2, "wrong number of versions")
   354  	require.EqualValues(v2, tree.Version())
   355  
   356  	// -----1-----
   357  	// key1 = val0  <orphaned>
   358  	// key2 = val0  <orphaned>
   359  	// -----2-----
   360  	// key1 = val1
   361  	// key2 = val1
   362  	// key3 = val1
   363  	// -----------
   364  
   365  	nodes2 := tree.ndb.leafNodes()
   366  	require.Len(nodes2, 5, "db should have grown in size")
   367  	require.Len(tree.ndb.orphans(), 3, "db should have three orphans")
   368  
   369  	// Create two more orphans.
   370  	tree.Remove([]byte("key1"))
   371  	tree.Set([]byte("key2"), []byte("val2"))
   372  
   373  	hash3, v3, _ := tree.SaveVersion()
   374  	require.EqualValues(3, v3)
   375  
   376  	// -----1-----
   377  	// key1 = val0  <orphaned> (replaced)
   378  	// key2 = val0  <orphaned> (replaced)
   379  	// -----2-----
   380  	// key1 = val1  <orphaned> (removed)
   381  	// key2 = val1  <orphaned> (replaced)
   382  	// key3 = val1
   383  	// -----3-----
   384  	// key2 = val2
   385  	// -----------
   386  
   387  	nodes3 := tree.ndb.leafNodes()
   388  	require.Len(nodes3, 6, "wrong number of nodes")
   389  	require.Len(tree.ndb.orphans(), 6, "wrong number of orphans")
   390  
   391  	hash4, _, _ := tree.SaveVersion()
   392  	require.EqualValues(hash3, hash4)
   393  	require.NotNil(hash4)
   394  
   395  	tree = NewMutableTree(d, 100)
   396  	_, err = tree.Load()
   397  	require.NoError(err)
   398  
   399  	// ------------
   400  	// DB UNCHANGED
   401  	// ------------
   402  
   403  	nodes4 := tree.ndb.leafNodes()
   404  	require.Len(nodes4, len(nodes3), "db should not have changed in size")
   405  
   406  	tree.Set([]byte("key1"), []byte("val0"))
   407  
   408  	// "key2"
   409  	_, val := tree.GetVersioned([]byte("key2"), 0)
   410  	require.Nil(val)
   411  
   412  	_, val = tree.GetVersioned([]byte("key2"), 1)
   413  	require.Equal("val0", string(val))
   414  
   415  	_, val = tree.GetVersioned([]byte("key2"), 2)
   416  	require.Equal("val1", string(val))
   417  
   418  	_, val = tree.Get([]byte("key2"))
   419  	require.Equal("val2", string(val))
   420  
   421  	// "key1"
   422  	_, val = tree.GetVersioned([]byte("key1"), 1)
   423  	require.Equal("val0", string(val))
   424  
   425  	_, val = tree.GetVersioned([]byte("key1"), 2)
   426  	require.Equal("val1", string(val))
   427  
   428  	_, val = tree.GetVersioned([]byte("key1"), 3)
   429  	require.Nil(val)
   430  
   431  	_, val = tree.GetVersioned([]byte("key1"), 4)
   432  	require.Nil(val)
   433  
   434  	_, val = tree.Get([]byte("key1"))
   435  	require.Equal("val0", string(val))
   436  
   437  	// "key3"
   438  	_, val = tree.GetVersioned([]byte("key3"), 0)
   439  	require.Nil(val)
   440  
   441  	_, val = tree.GetVersioned([]byte("key3"), 2)
   442  	require.Equal("val1", string(val))
   443  
   444  	_, val = tree.GetVersioned([]byte("key3"), 3)
   445  	require.Equal("val1", string(val))
   446  
   447  	// Delete a version. After this the keys in that version should not be found.
   448  
   449  	tree.DeleteVersion(2)
   450  
   451  	// -----1-----
   452  	// key1 = val0
   453  	// key2 = val0
   454  	// -----2-----
   455  	// key3 = val1
   456  	// -----3-----
   457  	// key2 = val2
   458  	// -----------
   459  
   460  	nodes5 := tree.ndb.leafNodes()
   461  	require.True(len(nodes5) < len(nodes4), "db should have shrunk after delete %d !< %d", len(nodes5), len(nodes4))
   462  
   463  	_, val = tree.GetVersioned([]byte("key2"), 2)
   464  	require.Nil(val)
   465  
   466  	_, val = tree.GetVersioned([]byte("key3"), 2)
   467  	require.Nil(val)
   468  
   469  	// But they should still exist in the latest version.
   470  
   471  	_, val = tree.Get([]byte("key2"))
   472  	require.Equal("val2", string(val))
   473  
   474  	_, val = tree.Get([]byte("key3"))
   475  	require.Equal("val1", string(val))
   476  
   477  	// Version 1 should still be available.
   478  
   479  	_, val = tree.GetVersioned([]byte("key1"), 1)
   480  	require.Equal("val0", string(val))
   481  
   482  	_, val = tree.GetVersioned([]byte("key2"), 1)
   483  	require.Equal("val0", string(val))
   484  }
   485  
   486  func TestVersionedTreeVersionDeletingEfficiency(t *testing.T) {
   487  	t.Parallel()
   488  
   489  	d, closeDB := getTestDB()
   490  	defer closeDB()
   491  
   492  	tree := NewMutableTree(d, 0)
   493  
   494  	tree.Set([]byte("key0"), []byte("val0"))
   495  	tree.Set([]byte("key1"), []byte("val0"))
   496  	tree.Set([]byte("key2"), []byte("val0"))
   497  	tree.SaveVersion()
   498  
   499  	require.Len(t, tree.ndb.leafNodes(), 3)
   500  
   501  	tree.Set([]byte("key1"), []byte("val1"))
   502  	tree.Set([]byte("key2"), []byte("val1"))
   503  	tree.Set([]byte("key3"), []byte("val1"))
   504  	tree.SaveVersion()
   505  
   506  	require.Len(t, tree.ndb.leafNodes(), 6)
   507  
   508  	tree.Set([]byte("key0"), []byte("val2"))
   509  	tree.Remove([]byte("key1"))
   510  	tree.Set([]byte("key2"), []byte("val2"))
   511  	tree.SaveVersion()
   512  
   513  	require.Len(t, tree.ndb.leafNodes(), 8)
   514  
   515  	tree.DeleteVersion(2)
   516  
   517  	require.Len(t, tree.ndb.leafNodes(), 6)
   518  
   519  	tree.DeleteVersion(1)
   520  
   521  	require.Len(t, tree.ndb.leafNodes(), 3)
   522  
   523  	tree2 := NewMutableTree(memdb.NewMemDB(), 0)
   524  	tree2.Set([]byte("key0"), []byte("val2"))
   525  	tree2.Set([]byte("key2"), []byte("val2"))
   526  	tree2.Set([]byte("key3"), []byte("val1"))
   527  	tree2.SaveVersion()
   528  
   529  	require.Equal(t, tree2.nodeSize(), tree.nodeSize())
   530  }
   531  
   532  func TestVersionedTreeOrphanDeleting(t *testing.T) {
   533  	t.Parallel()
   534  
   535  	mdb := memdb.NewMemDB()
   536  	tree := NewMutableTree(mdb, 0)
   537  
   538  	tree.Set([]byte("key0"), []byte("val0"))
   539  	tree.Set([]byte("key1"), []byte("val0"))
   540  	tree.Set([]byte("key2"), []byte("val0"))
   541  	tree.SaveVersion()
   542  
   543  	tree.Set([]byte("key1"), []byte("val1"))
   544  	tree.Set([]byte("key2"), []byte("val1"))
   545  	tree.Set([]byte("key3"), []byte("val1"))
   546  	tree.SaveVersion()
   547  
   548  	tree.Set([]byte("key0"), []byte("val2"))
   549  	tree.Remove([]byte("key1"))
   550  	tree.Set([]byte("key2"), []byte("val2"))
   551  	tree.SaveVersion()
   552  
   553  	tree.DeleteVersion(2)
   554  
   555  	_, val := tree.Get([]byte("key0"))
   556  	require.Equal(t, val, []byte("val2"))
   557  
   558  	_, val = tree.Get([]byte("key1"))
   559  	require.Nil(t, val)
   560  
   561  	_, val = tree.Get([]byte("key2"))
   562  	require.Equal(t, val, []byte("val2"))
   563  
   564  	_, val = tree.Get([]byte("key3"))
   565  	require.Equal(t, val, []byte("val1"))
   566  
   567  	tree.DeleteVersion(1)
   568  
   569  	require.Len(t, tree.ndb.leafNodes(), 3)
   570  }
   571  
   572  func TestVersionedTreeSpecialCase(t *testing.T) {
   573  	t.Parallel()
   574  
   575  	require := require.New(t)
   576  	tree := NewMutableTree(memdb.NewMemDB(), 100)
   577  
   578  	tree.Set([]byte("key1"), []byte("val0"))
   579  	tree.Set([]byte("key2"), []byte("val0"))
   580  	tree.SaveVersion()
   581  
   582  	tree.Set([]byte("key1"), []byte("val1"))
   583  	tree.Set([]byte("key2"), []byte("val1"))
   584  	tree.SaveVersion()
   585  
   586  	tree.Set([]byte("key2"), []byte("val2"))
   587  	tree.SaveVersion()
   588  
   589  	tree.DeleteVersion(2)
   590  
   591  	_, val := tree.GetVersioned([]byte("key2"), 1)
   592  	require.Equal("val0", string(val))
   593  }
   594  
   595  func TestVersionedTreeSpecialCase2(t *testing.T) {
   596  	t.Parallel()
   597  
   598  	require := require.New(t)
   599  	d := memdb.NewMemDB()
   600  
   601  	tree := NewMutableTree(d, 100)
   602  
   603  	tree.Set([]byte("key1"), []byte("val0"))
   604  	tree.Set([]byte("key2"), []byte("val0"))
   605  	tree.SaveVersion()
   606  
   607  	tree.Set([]byte("key1"), []byte("val1"))
   608  	tree.Set([]byte("key2"), []byte("val1"))
   609  	tree.SaveVersion()
   610  
   611  	tree.Set([]byte("key2"), []byte("val2"))
   612  	tree.SaveVersion()
   613  
   614  	tree = NewMutableTree(d, 100)
   615  	_, err := tree.Load()
   616  	require.NoError(err)
   617  
   618  	require.NoError(tree.DeleteVersion(2))
   619  
   620  	_, val := tree.GetVersioned([]byte("key2"), 1)
   621  	require.Equal("val0", string(val))
   622  }
   623  
   624  func TestVersionedTreeSpecialCase3(t *testing.T) {
   625  	t.Parallel()
   626  
   627  	require := require.New(t)
   628  	tree := NewMutableTree(memdb.NewMemDB(), 0)
   629  
   630  	tree.Set([]byte("m"), []byte("liWT0U6G"))
   631  	tree.Set([]byte("G"), []byte("7PxRXwUA"))
   632  	tree.SaveVersion()
   633  
   634  	tree.Set([]byte("7"), []byte("XRLXgf8C"))
   635  	tree.SaveVersion()
   636  
   637  	tree.Set([]byte("r"), []byte("bBEmIXBU"))
   638  	tree.SaveVersion()
   639  
   640  	tree.Set([]byte("i"), []byte("kkIS35te"))
   641  	tree.SaveVersion()
   642  
   643  	tree.Set([]byte("k"), []byte("CpEnpzKJ"))
   644  	tree.SaveVersion()
   645  
   646  	tree.DeleteVersion(1)
   647  	tree.DeleteVersion(2)
   648  	tree.DeleteVersion(3)
   649  	tree.DeleteVersion(4)
   650  
   651  	require.Equal(tree.nodeSize(), len(tree.ndb.nodes()))
   652  }
   653  
   654  func TestVersionedTreeSaveAndLoad(t *testing.T) {
   655  	t.Parallel()
   656  
   657  	require := require.New(t)
   658  	d := memdb.NewMemDB()
   659  	tree := NewMutableTree(d, 0)
   660  
   661  	// Loading with an empty root is a no-op.
   662  	tree.Load()
   663  
   664  	tree.Set([]byte("C"), []byte("so43QQFN"))
   665  	tree.SaveVersion()
   666  
   667  	tree.Set([]byte("A"), []byte("ut7sTTAO"))
   668  	tree.SaveVersion()
   669  
   670  	tree.Set([]byte("X"), []byte("AoWWC1kN"))
   671  	tree.SaveVersion()
   672  
   673  	tree.SaveVersion()
   674  	tree.SaveVersion()
   675  	tree.SaveVersion()
   676  
   677  	preHash := tree.Hash()
   678  	require.NotNil(preHash)
   679  
   680  	require.Equal(int64(6), tree.Version())
   681  
   682  	// Reload the tree, to test that roots and orphans are properly loaded.
   683  	ntree := NewMutableTree(d, 0)
   684  	ntree.Load()
   685  
   686  	require.False(ntree.IsEmpty())
   687  	require.Equal(int64(6), ntree.Version())
   688  
   689  	postHash := ntree.Hash()
   690  	require.Equal(preHash, postHash)
   691  
   692  	ntree.Set([]byte("T"), []byte("MhkWjkVy"))
   693  	ntree.SaveVersion()
   694  
   695  	ntree.DeleteVersion(6)
   696  	ntree.DeleteVersion(5)
   697  	ntree.DeleteVersion(1)
   698  	ntree.DeleteVersion(2)
   699  	ntree.DeleteVersion(4)
   700  	ntree.DeleteVersion(3)
   701  
   702  	require.False(ntree.IsEmpty())
   703  	require.Equal(int64(4), ntree.Size())
   704  	require.Len(ntree.ndb.nodes(), ntree.nodeSize())
   705  }
   706  
   707  func TestVersionedTreeErrors(t *testing.T) {
   708  	t.Parallel()
   709  
   710  	require := require.New(t)
   711  	tree := NewMutableTree(memdb.NewMemDB(), 100)
   712  
   713  	// Can't delete non-existent versions.
   714  	require.Error(tree.DeleteVersion(1))
   715  	require.Error(tree.DeleteVersion(99))
   716  
   717  	tree.Set([]byte("key"), []byte("val"))
   718  
   719  	// Saving with content is ok.
   720  	_, _, err := tree.SaveVersion()
   721  	require.NoError(err)
   722  
   723  	// Can't delete current version.
   724  	require.Error(tree.DeleteVersion(1))
   725  
   726  	// Trying to get a key from a version which doesn't exist.
   727  	_, val := tree.GetVersioned([]byte("key"), 404)
   728  	require.Nil(val)
   729  
   730  	// Same thing with proof. We get an error because a proof couldn't be
   731  	// constructed.
   732  	val, proof, err := tree.GetVersionedWithProof([]byte("key"), 404)
   733  	require.Nil(val)
   734  	require.Empty(proof)
   735  	require.Error(err)
   736  }
   737  
   738  func TestVersionedCheckpoints(t *testing.T) {
   739  	t.Parallel()
   740  
   741  	require := require.New(t)
   742  	d, closeDB := getTestDB()
   743  	defer closeDB()
   744  
   745  	tree := NewMutableTree(d, 100)
   746  	versions := 50
   747  	keysPerVersion := 10
   748  	versionsPerCheckpoint := 5
   749  	keys := map[int64]([][]byte){}
   750  
   751  	for i := 1; i <= versions; i++ {
   752  		for j := 0; j < keysPerVersion; j++ {
   753  			k := []byte(rnd.Str(1))
   754  			v := []byte(rnd.Str(8))
   755  			keys[int64(i)] = append(keys[int64(i)], k)
   756  			tree.Set(k, v)
   757  		}
   758  		tree.SaveVersion()
   759  	}
   760  
   761  	for i := 1; i <= versions; i++ {
   762  		if i%versionsPerCheckpoint != 0 {
   763  			tree.DeleteVersion(int64(i))
   764  		}
   765  	}
   766  
   767  	// Make sure all keys exist at least once.
   768  	for _, ks := range keys {
   769  		for _, k := range ks {
   770  			_, val := tree.Get(k)
   771  			require.NotEmpty(val)
   772  		}
   773  	}
   774  
   775  	// Make sure all keys from deleted versions aren't present.
   776  	for i := 1; i <= versions; i++ {
   777  		if i%versionsPerCheckpoint != 0 {
   778  			for _, k := range keys[int64(i)] {
   779  				_, val := tree.GetVersioned(k, int64(i))
   780  				require.Nil(val)
   781  			}
   782  		}
   783  	}
   784  
   785  	// Make sure all keys exist at all checkpoints.
   786  	for i := 1; i <= versions; i++ {
   787  		for _, k := range keys[int64(i)] {
   788  			if i%versionsPerCheckpoint == 0 {
   789  				_, val := tree.GetVersioned(k, int64(i))
   790  				require.NotEmpty(val)
   791  			}
   792  		}
   793  	}
   794  }
   795  
   796  func TestVersionedCheckpointsSpecialCase(t *testing.T) {
   797  	t.Parallel()
   798  
   799  	require := require.New(t)
   800  	tree := NewMutableTree(memdb.NewMemDB(), 0)
   801  	key := []byte("k")
   802  
   803  	tree.Set(key, []byte("val1"))
   804  
   805  	tree.SaveVersion()
   806  	// ...
   807  	tree.SaveVersion()
   808  	// ...
   809  	tree.SaveVersion()
   810  	// ...
   811  	// This orphans "k" at version 1.
   812  	tree.Set(key, []byte("val2"))
   813  	tree.SaveVersion()
   814  
   815  	// When version 1 is deleted, the orphans should move to the next
   816  	// checkpoint, which is version 10.
   817  	tree.DeleteVersion(1)
   818  
   819  	_, val := tree.GetVersioned(key, 2)
   820  	require.NotEmpty(val)
   821  	require.Equal([]byte("val1"), val)
   822  }
   823  
   824  func TestVersionedCheckpointsSpecialCase2(t *testing.T) {
   825  	t.Parallel()
   826  
   827  	tree := NewMutableTree(memdb.NewMemDB(), 0)
   828  
   829  	tree.Set([]byte("U"), []byte("XamDUtiJ"))
   830  	tree.Set([]byte("A"), []byte("UkZBuYIU"))
   831  	tree.Set([]byte("H"), []byte("7a9En4uw"))
   832  	tree.Set([]byte("V"), []byte("5HXU3pSI"))
   833  	tree.SaveVersion()
   834  
   835  	tree.Set([]byte("U"), []byte("Replaced"))
   836  	tree.Set([]byte("A"), []byte("Replaced"))
   837  	tree.SaveVersion()
   838  
   839  	tree.Set([]byte("X"), []byte("New"))
   840  	tree.SaveVersion()
   841  
   842  	tree.DeleteVersion(1)
   843  	tree.DeleteVersion(2)
   844  }
   845  
   846  func TestVersionedCheckpointsSpecialCase3(t *testing.T) {
   847  	t.Parallel()
   848  
   849  	tree := NewMutableTree(memdb.NewMemDB(), 0)
   850  
   851  	tree.Set([]byte("n"), []byte("2wUCUs8q"))
   852  	tree.Set([]byte("l"), []byte("WQ7mvMbc"))
   853  	tree.SaveVersion()
   854  
   855  	tree.Set([]byte("N"), []byte("ved29IqU"))
   856  	tree.Set([]byte("v"), []byte("01jquVXU"))
   857  	tree.SaveVersion()
   858  
   859  	tree.Set([]byte("l"), []byte("bhIpltPM"))
   860  	tree.Set([]byte("B"), []byte("rj97IKZh"))
   861  	tree.SaveVersion()
   862  
   863  	tree.DeleteVersion(2)
   864  
   865  	tree.GetVersioned([]byte("m"), 1)
   866  }
   867  
   868  func TestVersionedCheckpointsSpecialCase4(t *testing.T) {
   869  	t.Parallel()
   870  
   871  	tree := NewMutableTree(memdb.NewMemDB(), 0)
   872  
   873  	tree.Set([]byte("U"), []byte("XamDUtiJ"))
   874  	tree.Set([]byte("A"), []byte("UkZBuYIU"))
   875  	tree.Set([]byte("H"), []byte("7a9En4uw"))
   876  	tree.Set([]byte("V"), []byte("5HXU3pSI"))
   877  	tree.SaveVersion()
   878  
   879  	tree.Remove([]byte("U"))
   880  	tree.Remove([]byte("A"))
   881  	tree.SaveVersion()
   882  
   883  	tree.Set([]byte("X"), []byte("New"))
   884  	tree.SaveVersion()
   885  
   886  	_, val := tree.GetVersioned([]byte("A"), 2)
   887  	require.Nil(t, val)
   888  
   889  	_, val = tree.GetVersioned([]byte("A"), 1)
   890  	require.NotEmpty(t, val)
   891  
   892  	tree.DeleteVersion(1)
   893  	tree.DeleteVersion(2)
   894  
   895  	_, val = tree.GetVersioned([]byte("A"), 2)
   896  	require.Nil(t, val)
   897  
   898  	_, val = tree.GetVersioned([]byte("A"), 1)
   899  	require.Nil(t, val)
   900  }
   901  
   902  func TestVersionedCheckpointsSpecialCase5(t *testing.T) {
   903  	t.Parallel()
   904  
   905  	tree := NewMutableTree(memdb.NewMemDB(), 0)
   906  
   907  	tree.Set([]byte("R"), []byte("ygZlIzeW"))
   908  	tree.SaveVersion()
   909  
   910  	tree.Set([]byte("j"), []byte("ZgmCWyo2"))
   911  	tree.SaveVersion()
   912  
   913  	tree.Set([]byte("R"), []byte("vQDaoz6Z"))
   914  	tree.SaveVersion()
   915  
   916  	tree.DeleteVersion(1)
   917  
   918  	tree.GetVersioned([]byte("R"), 2)
   919  }
   920  
   921  func TestVersionedCheckpointsSpecialCase6(t *testing.T) {
   922  	t.Parallel()
   923  
   924  	tree := NewMutableTree(memdb.NewMemDB(), 0)
   925  
   926  	tree.Set([]byte("Y"), []byte("MW79JQeV"))
   927  	tree.Set([]byte("7"), []byte("Kp0ToUJB"))
   928  	tree.Set([]byte("Z"), []byte("I26B1jPG"))
   929  	tree.Set([]byte("6"), []byte("ZG0iXq3h"))
   930  	tree.Set([]byte("2"), []byte("WOR27LdW"))
   931  	tree.Set([]byte("4"), []byte("MKMvc6cn"))
   932  	tree.SaveVersion()
   933  
   934  	tree.Set([]byte("1"), []byte("208dOu40"))
   935  	tree.Set([]byte("G"), []byte("7isI9OQH"))
   936  	tree.Set([]byte("8"), []byte("zMC1YwpH"))
   937  	tree.SaveVersion()
   938  
   939  	tree.Set([]byte("7"), []byte("bn62vWbq"))
   940  	tree.Set([]byte("5"), []byte("wZuLGDkZ"))
   941  	tree.SaveVersion()
   942  
   943  	tree.DeleteVersion(1)
   944  	tree.DeleteVersion(2)
   945  
   946  	tree.GetVersioned([]byte("Y"), 1)
   947  	tree.GetVersioned([]byte("7"), 1)
   948  	tree.GetVersioned([]byte("Z"), 1)
   949  	tree.GetVersioned([]byte("6"), 1)
   950  	tree.GetVersioned([]byte("s"), 1)
   951  	tree.GetVersioned([]byte("2"), 1)
   952  	tree.GetVersioned([]byte("4"), 1)
   953  }
   954  
   955  func TestVersionedCheckpointsSpecialCase7(t *testing.T) {
   956  	t.Parallel()
   957  
   958  	tree := NewMutableTree(memdb.NewMemDB(), 100)
   959  
   960  	tree.Set([]byte("n"), []byte("OtqD3nyn"))
   961  	tree.Set([]byte("W"), []byte("kMdhJjF5"))
   962  	tree.Set([]byte("A"), []byte("BM3BnrIb"))
   963  	tree.Set([]byte("I"), []byte("QvtCH970"))
   964  	tree.Set([]byte("L"), []byte("txKgOTqD"))
   965  	tree.Set([]byte("Y"), []byte("NAl7PC5L"))
   966  	tree.SaveVersion()
   967  
   968  	tree.Set([]byte("7"), []byte("qWcEAlyX"))
   969  	tree.SaveVersion()
   970  
   971  	tree.Set([]byte("M"), []byte("HdQwzA64"))
   972  	tree.Set([]byte("3"), []byte("2Naa77fo"))
   973  	tree.Set([]byte("A"), []byte("SRuwKOTm"))
   974  	tree.Set([]byte("I"), []byte("oMX4aAOy"))
   975  	tree.Set([]byte("4"), []byte("dKfvbEOc"))
   976  	tree.SaveVersion()
   977  
   978  	tree.Set([]byte("D"), []byte("3U4QbXCC"))
   979  	tree.Set([]byte("B"), []byte("FxExhiDq"))
   980  	tree.SaveVersion()
   981  
   982  	tree.Set([]byte("A"), []byte("tWQgbFCY"))
   983  	tree.SaveVersion()
   984  
   985  	tree.DeleteVersion(4)
   986  
   987  	tree.GetVersioned([]byte("A"), 3)
   988  }
   989  
   990  func TestVersionedTreeEfficiency(t *testing.T) {
   991  	t.Parallel()
   992  
   993  	require := require.New(t)
   994  	tree := NewMutableTree(memdb.NewMemDB(), 0)
   995  	versions := 20
   996  	keysPerVersion := 100
   997  	keysAddedPerVersion := map[int]int{}
   998  
   999  	keysAdded := 0
  1000  	for i := 1; i <= versions; i++ {
  1001  		for j := 0; j < keysPerVersion; j++ {
  1002  			// Keys of size one are likely to be overwritten.
  1003  			tree.Set([]byte(rnd.Str(1)), []byte(rnd.Str(8)))
  1004  		}
  1005  		sizeBefore := len(tree.ndb.nodes())
  1006  		tree.SaveVersion()
  1007  		sizeAfter := len(tree.ndb.nodes())
  1008  		change := sizeAfter - sizeBefore
  1009  		keysAddedPerVersion[i] = change
  1010  		keysAdded += change
  1011  	}
  1012  
  1013  	keysDeleted := 0
  1014  	for i := 1; i < versions; i++ {
  1015  		sizeBefore := len(tree.ndb.nodes())
  1016  		tree.DeleteVersion(int64(i))
  1017  		sizeAfter := len(tree.ndb.nodes())
  1018  
  1019  		change := sizeBefore - sizeAfter
  1020  		keysDeleted += change
  1021  
  1022  		require.InDelta(change, keysAddedPerVersion[i], float64(keysPerVersion)/5)
  1023  	}
  1024  	require.Equal(keysAdded-tree.nodeSize(), keysDeleted)
  1025  }
  1026  
  1027  func TestVersionedTreeProofs(t *testing.T) {
  1028  	t.Parallel()
  1029  
  1030  	require := require.New(t)
  1031  	tree := NewMutableTree(memdb.NewMemDB(), 0)
  1032  
  1033  	tree.Set([]byte("k1"), []byte("v1"))
  1034  	tree.Set([]byte("k2"), []byte("v1"))
  1035  	tree.Set([]byte("k3"), []byte("v1"))
  1036  	tree.SaveVersion()
  1037  
  1038  	// fmt.Println("TREE VERSION 1")
  1039  	// printNode(tree.ndb, tree.root, 0)
  1040  	// fmt.Println("TREE VERSION 1 END")
  1041  
  1042  	root1 := tree.Hash()
  1043  
  1044  	tree.Set([]byte("k2"), []byte("v2"))
  1045  	tree.Set([]byte("k4"), []byte("v2"))
  1046  	tree.SaveVersion()
  1047  
  1048  	// fmt.Println("TREE VERSION 2")
  1049  	// printNode(tree.ndb, tree.root, 0)
  1050  	// fmt.Println("TREE VERSION END")
  1051  
  1052  	root2 := tree.Hash()
  1053  	require.NotEqual(root1, root2)
  1054  
  1055  	tree.Remove([]byte("k2"))
  1056  	tree.SaveVersion()
  1057  
  1058  	// fmt.Println("TREE VERSION 3")
  1059  	// printNode(tree.ndb, tree.root, 0)
  1060  	// fmt.Println("TREE VERSION END")
  1061  
  1062  	root3 := tree.Hash()
  1063  	require.NotEqual(root2, root3)
  1064  
  1065  	val, proof, err := tree.GetVersionedWithProof([]byte("k2"), 1)
  1066  	require.NoError(err)
  1067  	require.EqualValues(val, []byte("v1"))
  1068  	require.NoError(proof.Verify(root1), proof.String())
  1069  	require.NoError(proof.VerifyItem([]byte("k2"), val))
  1070  
  1071  	val, proof, err = tree.GetVersionedWithProof([]byte("k4"), 1)
  1072  	require.NoError(err)
  1073  	require.Nil(val)
  1074  	require.NoError(proof.Verify(root1))
  1075  	require.NoError(proof.VerifyAbsence([]byte("k4")))
  1076  
  1077  	val, proof, err = tree.GetVersionedWithProof([]byte("k2"), 2)
  1078  	require.NoError(err)
  1079  	require.EqualValues(val, []byte("v2"))
  1080  	require.NoError(proof.Verify(root2), proof.String())
  1081  	require.NoError(proof.VerifyItem([]byte("k2"), val))
  1082  
  1083  	val, proof, err = tree.GetVersionedWithProof([]byte("k1"), 2)
  1084  	require.NoError(err)
  1085  	require.EqualValues(val, []byte("v1"))
  1086  	require.NoError(proof.Verify(root2))
  1087  	require.NoError(proof.VerifyItem([]byte("k1"), val))
  1088  
  1089  	val, proof, err = tree.GetVersionedWithProof([]byte("k2"), 3)
  1090  
  1091  	require.NoError(err)
  1092  	require.Nil(val)
  1093  	require.NoError(proof.Verify(root3))
  1094  	require.NoError(proof.VerifyAbsence([]byte("k2")))
  1095  	require.Error(proof.Verify(root1))
  1096  	require.Error(proof.Verify(root2))
  1097  }
  1098  
  1099  func TestOrphans(t *testing.T) {
  1100  	t.Parallel()
  1101  
  1102  	// If you create a sequence of saved versions
  1103  	// Then randomly delete versions other than the first and last until only those two remain
  1104  	// Any remaining orphan nodes should be constrained to just the first version
  1105  	require := require.New(t)
  1106  	tree := NewMutableTree(memdb.NewMemDB(), 100)
  1107  
  1108  	NUMVERSIONS := 100
  1109  	NUMUPDATES := 100
  1110  
  1111  	for i := 0; i < NUMVERSIONS; i++ {
  1112  		for j := 1; j < NUMUPDATES; j++ {
  1113  			tree.Set(randBytes(2), randBytes(2))
  1114  		}
  1115  		_, _, err := tree.SaveVersion()
  1116  		require.NoError(err, "SaveVersion should not error")
  1117  	}
  1118  
  1119  	idx := rnd.Perm(NUMVERSIONS - 2)
  1120  	for i := range idx {
  1121  		err := tree.DeleteVersion(int64(i + 2))
  1122  		require.NoError(err, "DeleteVersion should not error")
  1123  	}
  1124  
  1125  	tree.ndb.traverseOrphans(func(k, v []byte) {
  1126  		var fromVersion, toVersion int64
  1127  		orphanKeyFormat.Scan(k, &toVersion, &fromVersion)
  1128  		require.Equal(fromVersion, int64(1), "fromVersion should be 1")
  1129  		require.Equal(toVersion, int64(1), "toVersion should be 1")
  1130  	})
  1131  }
  1132  
  1133  func TestVersionedTreeHash(t *testing.T) {
  1134  	t.Parallel()
  1135  
  1136  	require := require.New(t)
  1137  	tree := NewMutableTree(memdb.NewMemDB(), 0)
  1138  
  1139  	require.Nil(tree.Hash())
  1140  	tree.Set([]byte("I"), []byte("D"))
  1141  	require.Nil(tree.Hash())
  1142  
  1143  	hash1, _, _ := tree.SaveVersion()
  1144  
  1145  	tree.Set([]byte("I"), []byte("F"))
  1146  	require.EqualValues(hash1, tree.Hash())
  1147  
  1148  	hash2, _, _ := tree.SaveVersion()
  1149  
  1150  	val, proof, err := tree.GetVersionedWithProof([]byte("I"), 2)
  1151  	require.NoError(err)
  1152  	require.EqualValues(val, []byte("F"))
  1153  	require.NoError(proof.Verify(hash2))
  1154  	require.NoError(proof.VerifyItem([]byte("I"), val))
  1155  }
  1156  
  1157  func TestNilValueSemantics(t *testing.T) {
  1158  	t.Parallel()
  1159  
  1160  	require := require.New(t)
  1161  	tree := NewMutableTree(memdb.NewMemDB(), 0)
  1162  
  1163  	require.Panics(func() {
  1164  		tree.Set([]byte("k"), nil)
  1165  	})
  1166  }
  1167  
  1168  func TestCopyValueSemantics(t *testing.T) {
  1169  	t.Parallel()
  1170  
  1171  	require := require.New(t)
  1172  
  1173  	tree := NewMutableTree(memdb.NewMemDB(), 0)
  1174  
  1175  	val := []byte("v1")
  1176  
  1177  	tree.Set([]byte("k"), val)
  1178  	_, v := tree.Get([]byte("k"))
  1179  	require.Equal([]byte("v1"), v)
  1180  
  1181  	val[1] = '2'
  1182  
  1183  	_, val = tree.Get([]byte("k"))
  1184  	require.Equal([]byte("v2"), val)
  1185  }
  1186  
  1187  func TestRollback(t *testing.T) {
  1188  	t.Parallel()
  1189  
  1190  	require := require.New(t)
  1191  
  1192  	tree := NewMutableTree(memdb.NewMemDB(), 0)
  1193  
  1194  	tree.Set([]byte("k"), []byte("v"))
  1195  	tree.SaveVersion()
  1196  
  1197  	tree.Set([]byte("r"), []byte("v"))
  1198  	tree.Set([]byte("s"), []byte("v"))
  1199  
  1200  	tree.Rollback()
  1201  
  1202  	tree.Set([]byte("t"), []byte("v"))
  1203  
  1204  	tree.SaveVersion()
  1205  
  1206  	require.Equal(int64(2), tree.Size())
  1207  
  1208  	_, val := tree.Get([]byte("r"))
  1209  	require.Nil(val)
  1210  
  1211  	_, val = tree.Get([]byte("s"))
  1212  	require.Nil(val)
  1213  
  1214  	_, val = tree.Get([]byte("t"))
  1215  	require.Equal([]byte("v"), val)
  1216  }
  1217  
  1218  func TestLazyLoadVersion(t *testing.T) {
  1219  	t.Parallel()
  1220  
  1221  	mdb := memdb.NewMemDB()
  1222  	tree := NewMutableTree(mdb, 0)
  1223  	maxVersions := 10
  1224  
  1225  	version, err := tree.LazyLoadVersion(0)
  1226  	require.NoError(t, err, "unexpected error")
  1227  	require.Equal(t, version, int64(0), "expected latest version to be zero")
  1228  
  1229  	for i := 0; i < maxVersions; i++ {
  1230  		tree.Set([]byte(fmt.Sprintf("key_%d", i+1)), []byte(fmt.Sprintf("value_%d", i+1)))
  1231  
  1232  		_, _, err := tree.SaveVersion()
  1233  		require.NoError(t, err, "SaveVersion should not fail")
  1234  	}
  1235  
  1236  	// require the ability to lazy load the latest version
  1237  	version, err = tree.LazyLoadVersion(int64(maxVersions))
  1238  	require.NoError(t, err, "unexpected error when lazy loading version")
  1239  	require.Equal(t, version, int64(maxVersions))
  1240  
  1241  	_, value := tree.Get([]byte(fmt.Sprintf("key_%d", maxVersions)))
  1242  	require.Equal(t, value, []byte(fmt.Sprintf("value_%d", maxVersions)), "unexpected value")
  1243  
  1244  	// require the ability to lazy load an older version
  1245  	version, err = tree.LazyLoadVersion(int64(maxVersions - 1))
  1246  	require.NoError(t, err, "unexpected error when lazy loading version")
  1247  	require.Equal(t, version, int64(maxVersions-1))
  1248  
  1249  	_, value = tree.Get([]byte(fmt.Sprintf("key_%d", maxVersions-1)))
  1250  	require.Equal(t, value, []byte(fmt.Sprintf("value_%d", maxVersions-1)), "unexpected value")
  1251  
  1252  	// require the inability to lazy load a non-valid version
  1253  	version, err = tree.LazyLoadVersion(int64(maxVersions + 1))
  1254  	require.Error(t, err, "expected error when lazy loading version")
  1255  	require.Equal(t, version, int64(maxVersions))
  1256  }
  1257  
  1258  func TestOverwrite(t *testing.T) {
  1259  	t.Parallel()
  1260  
  1261  	require := require.New(t)
  1262  
  1263  	mdb := memdb.NewMemDB()
  1264  	tree := NewMutableTree(mdb, 0)
  1265  
  1266  	// Set one kv pair and save version 1
  1267  	tree.Set([]byte("key1"), []byte("value1"))
  1268  	_, _, err := tree.SaveVersion()
  1269  	require.NoError(err, "SaveVersion should not fail")
  1270  
  1271  	// Set another kv pair and save version 2
  1272  	tree.Set([]byte("key2"), []byte("value2"))
  1273  	_, _, err = tree.SaveVersion()
  1274  	require.NoError(err, "SaveVersion should not fail")
  1275  
  1276  	// Reload tree at version 1
  1277  	tree = NewMutableTree(mdb, 0)
  1278  	_, err = tree.LoadVersion(int64(1))
  1279  	require.NoError(err, "LoadVersion should not fail")
  1280  
  1281  	// Attempt to put a different kv pair into the tree and save
  1282  	tree.Set([]byte("key2"), []byte("different value 2"))
  1283  	_, _, err = tree.SaveVersion()
  1284  	require.Error(err, "SaveVersion should fail because of changed value")
  1285  
  1286  	// Replay the original transition from version 1 to version 2 and attempt to save
  1287  	tree.Set([]byte("key2"), []byte("value2"))
  1288  	_, _, err = tree.SaveVersion()
  1289  	require.NoError(err, "SaveVersion should not fail, overwrite was idempotent")
  1290  }
  1291  
  1292  func TestLoadVersionForOverwriting(t *testing.T) {
  1293  	t.Parallel()
  1294  
  1295  	require := require.New(t)
  1296  
  1297  	mdb := memdb.NewMemDB()
  1298  	tree := NewMutableTree(mdb, 0)
  1299  
  1300  	maxLength := 100
  1301  	for count := 1; count <= maxLength; count++ {
  1302  		countStr := strconv.Itoa(count)
  1303  		// Set one kv pair and save version
  1304  		tree.Set([]byte("key"+countStr), []byte("value"+countStr))
  1305  		_, _, err := tree.SaveVersion()
  1306  		require.NoError(err, "SaveVersion should not fail")
  1307  	}
  1308  
  1309  	tree = NewMutableTree(mdb, 0)
  1310  	targetVersion, _ := tree.LoadVersionForOverwriting(int64(maxLength * 2))
  1311  	require.Equal(targetVersion, int64(maxLength), "targetVersion shouldn't larger than the actual tree latest version")
  1312  
  1313  	tree = NewMutableTree(mdb, 0)
  1314  	_, err := tree.LoadVersionForOverwriting(int64(maxLength / 2))
  1315  	require.NoError(err, "LoadVersion should not fail")
  1316  
  1317  	for version := 1; version <= maxLength/2; version++ {
  1318  		exist := tree.VersionExists(int64(version))
  1319  		require.True(exist, "versions no more than 50 should exist")
  1320  	}
  1321  
  1322  	for version := (maxLength / 2) + 1; version <= maxLength; version++ {
  1323  		exist := tree.VersionExists(int64(version))
  1324  		require.False(exist, "versions more than 50 should have been deleted")
  1325  	}
  1326  
  1327  	tree.Set([]byte("key49"), []byte("value49 different"))
  1328  	_, _, err = tree.SaveVersion()
  1329  	require.NoError(err, "SaveVersion should not fail, overwrite was allowed")
  1330  
  1331  	tree.Set([]byte("key50"), []byte("value50 different"))
  1332  	_, _, err = tree.SaveVersion()
  1333  	require.NoError(err, "SaveVersion should not fail, overwrite was allowed")
  1334  
  1335  	// Reload tree at version 50, the latest tree version is 52
  1336  	tree = NewMutableTree(mdb, 0)
  1337  	_, err = tree.LoadVersion(int64(maxLength / 2))
  1338  	require.NoError(err, "LoadVersion should not fail")
  1339  
  1340  	tree.Set([]byte("key49"), []byte("value49 different"))
  1341  	_, _, err = tree.SaveVersion()
  1342  	require.NoError(err, "SaveVersion should not fail, write the same value")
  1343  
  1344  	tree.Set([]byte("key50"), []byte("value50 different different"))
  1345  	_, _, err = tree.SaveVersion()
  1346  	require.Error(err, "SaveVersion should fail, overwrite was not allowed")
  1347  
  1348  	tree.Set([]byte("key50"), []byte("value50 different"))
  1349  	_, _, err = tree.SaveVersion()
  1350  	require.NoError(err, "SaveVersion should not fail, write the same value")
  1351  
  1352  	// The tree version now is 52 which is equal to latest version.
  1353  	// Now any key value can be written into the tree
  1354  	tree.Set([]byte("key any value"), []byte("value any value"))
  1355  	_, _, err = tree.SaveVersion()
  1356  	require.NoError(err, "SaveVersion should not fail.")
  1357  }
  1358  
  1359  // ----------- BENCHMARKS // -----------
  1360  
  1361  func BenchmarkTreeLoadAndDelete(b *testing.B) {
  1362  	if testing.Short() {
  1363  		b.Skip("skipping testing in short mode")
  1364  	}
  1365  
  1366  	numVersions := 5000
  1367  	numKeysPerVersion := 10
  1368  
  1369  	d, err := goleveldb.NewGoLevelDB("bench", ".")
  1370  	if err != nil {
  1371  		panic(err)
  1372  	}
  1373  	defer d.Close()
  1374  	defer os.RemoveAll("./bench.db")
  1375  
  1376  	tree := NewMutableTree(d, 0)
  1377  	for v := 1; v < numVersions; v++ {
  1378  		for i := 0; i < numKeysPerVersion; i++ {
  1379  			tree.Set([]byte(rnd.Str(16)), rnd.Bytes(32))
  1380  		}
  1381  		tree.SaveVersion()
  1382  	}
  1383  
  1384  	b.Run("LoadAndDelete", func(b *testing.B) {
  1385  		for n := 0; n < b.N; n++ {
  1386  			b.StopTimer()
  1387  			tree = NewMutableTree(d, 0)
  1388  			runtime.GC()
  1389  			b.StartTimer()
  1390  
  1391  			// Load the tree from disk.
  1392  			tree.Load()
  1393  
  1394  			// Delete about 10% of the versions randomly.
  1395  			// The trade-off is usually between load efficiency and delete
  1396  			// efficiency, which is why we do both in this benchmark.
  1397  			// If we can load quickly into a data-structure that allows for
  1398  			// efficient deletes, we are golden.
  1399  			for v := 0; v < numVersions/10; v++ {
  1400  				version := (rnd.Int() % numVersions) + 1
  1401  				tree.DeleteVersion(int64(version))
  1402  			}
  1403  		}
  1404  	})
  1405  }
  1406  
  1407  func zip(av <-chan int64) []int64 {
  1408  	res := []int64{}
  1409  	for ver := range av {
  1410  		res = append(res, ver)
  1411  	}
  1412  	return res
  1413  }