github.com/ledgerwatch/erigon-lib@v1.0.0/kv/mdbx/kv_mdbx_test.go (about)

     1  /*
     2     Copyright 2022 Erigon contributors
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package mdbx
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"github.com/c2h5oh/datasize"
    24  	"github.com/ledgerwatch/erigon-lib/kv"
    25  	"github.com/ledgerwatch/erigon-lib/kv/order"
    26  	"github.com/ledgerwatch/log/v3"
    27  	"github.com/stretchr/testify/assert"
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  func BaseCase(t *testing.T) (kv.RwDB, kv.RwTx, kv.RwCursorDupSort) {
    32  	t.Helper()
    33  	path := t.TempDir()
    34  	logger := log.New()
    35  	table := "Table"
    36  	db := NewMDBX(logger).InMem(path).WithTableCfg(func(defaultBuckets kv.TableCfg) kv.TableCfg {
    37  		return kv.TableCfg{
    38  			table:       kv.TableCfgItem{Flags: kv.DupSort},
    39  			kv.Sequence: kv.TableCfgItem{},
    40  		}
    41  	}).MapSize(128 * datasize.MB).MustOpen()
    42  	t.Cleanup(db.Close)
    43  
    44  	tx, err := db.BeginRw(context.Background())
    45  	require.NoError(t, err)
    46  	t.Cleanup(tx.Rollback)
    47  
    48  	c, err := tx.RwCursorDupSort(table)
    49  	require.NoError(t, err)
    50  	t.Cleanup(c.Close)
    51  
    52  	// Insert some dupsorted records
    53  	require.NoError(t, c.Put([]byte("key1"), []byte("value1.1")))
    54  	require.NoError(t, c.Put([]byte("key3"), []byte("value3.1")))
    55  	require.NoError(t, c.Put([]byte("key1"), []byte("value1.3")))
    56  	require.NoError(t, c.Put([]byte("key3"), []byte("value3.3")))
    57  
    58  	return db, tx, c
    59  }
    60  
    61  func iteration(t *testing.T, c kv.RwCursorDupSort, start []byte, val []byte) ([]string, []string) {
    62  	t.Helper()
    63  	var keys []string
    64  	var values []string
    65  	var err error
    66  	i := 0
    67  	for k, v, err := start, val, err; k != nil; k, v, err = c.Next() {
    68  		require.Nil(t, err)
    69  		keys = append(keys, string(k))
    70  		values = append(values, string(v))
    71  		i += 1
    72  	}
    73  	for ind := i; ind > 1; ind-- {
    74  		c.Prev()
    75  	}
    76  
    77  	return keys, values
    78  }
    79  
    80  func TestSeekBothRange(t *testing.T) {
    81  	_, _, c := BaseCase(t)
    82  
    83  	v, err := c.SeekBothRange([]byte("key2"), []byte("value1.2"))
    84  	require.NoError(t, err)
    85  	// SeekBothRange does exact match of the key, but range match of the value, so we get nil here
    86  	require.Nil(t, v)
    87  
    88  	v, err = c.SeekBothRange([]byte("key3"), []byte("value3.2"))
    89  	require.NoError(t, err)
    90  	require.Equal(t, "value3.3", string(v))
    91  }
    92  
    93  func TestRange(t *testing.T) {
    94  	t.Run("Asc", func(t *testing.T) {
    95  		_, tx, _ := BaseCase(t)
    96  
    97  		//[from, to)
    98  		it, err := tx.Range("Table", []byte("key1"), []byte("key3"))
    99  		require.NoError(t, err)
   100  		require.True(t, it.HasNext())
   101  		k, v, err := it.Next()
   102  		require.NoError(t, err)
   103  		require.Equal(t, "key1", string(k))
   104  		require.Equal(t, "value1.1", string(v))
   105  
   106  		require.True(t, it.HasNext())
   107  		k, v, err = it.Next()
   108  		require.NoError(t, err)
   109  		require.Equal(t, "key1", string(k))
   110  		require.Equal(t, "value1.3", string(v))
   111  
   112  		require.False(t, it.HasNext())
   113  		require.False(t, it.HasNext())
   114  
   115  		// [from, nil) means [from, INF)
   116  		it, err = tx.Range("Table", []byte("key1"), nil)
   117  		require.NoError(t, err)
   118  		cnt := 0
   119  		for it.HasNext() {
   120  			_, _, err := it.Next()
   121  			require.NoError(t, err)
   122  			cnt++
   123  		}
   124  		require.Equal(t, 4, cnt)
   125  	})
   126  	t.Run("Desc", func(t *testing.T) {
   127  		_, tx, _ := BaseCase(t)
   128  
   129  		//[from, to)
   130  		it, err := tx.RangeDescend("Table", []byte("key3"), []byte("key1"), kv.Unlim)
   131  		require.NoError(t, err)
   132  		require.True(t, it.HasNext())
   133  		k, v, err := it.Next()
   134  		require.NoError(t, err)
   135  		require.Equal(t, "key3", string(k))
   136  		require.Equal(t, "value3.3", string(v))
   137  
   138  		require.True(t, it.HasNext())
   139  		k, v, err = it.Next()
   140  		require.NoError(t, err)
   141  		require.Equal(t, "key3", string(k))
   142  		require.Equal(t, "value3.1", string(v))
   143  
   144  		require.False(t, it.HasNext())
   145  
   146  		it, err = tx.RangeDescend("Table", nil, nil, 2)
   147  		require.NoError(t, err)
   148  
   149  		cnt := 0
   150  		for it.HasNext() {
   151  			_, _, err := it.Next()
   152  			require.NoError(t, err)
   153  			cnt++
   154  		}
   155  		require.Equal(t, 2, cnt)
   156  	})
   157  }
   158  
   159  func TestRangeDupSort(t *testing.T) {
   160  	t.Run("Asc", func(t *testing.T) {
   161  		_, tx, _ := BaseCase(t)
   162  
   163  		//[from, to)
   164  		it, err := tx.RangeDupSort("Table", []byte("key1"), nil, nil, order.Asc, -1)
   165  		require.NoError(t, err)
   166  		require.True(t, it.HasNext())
   167  		k, v, err := it.Next()
   168  		require.NoError(t, err)
   169  		require.Equal(t, "key1", string(k))
   170  		require.Equal(t, "value1.1", string(v))
   171  
   172  		require.True(t, it.HasNext())
   173  		k, v, err = it.Next()
   174  		require.NoError(t, err)
   175  		require.Equal(t, "key1", string(k))
   176  		require.Equal(t, "value1.3", string(v))
   177  
   178  		require.False(t, it.HasNext())
   179  		require.False(t, it.HasNext())
   180  
   181  		// [from, nil) means [from, INF)
   182  		it, err = tx.Range("Table", []byte("key1"), nil)
   183  		require.NoError(t, err)
   184  		cnt := 0
   185  		for it.HasNext() {
   186  			_, _, err := it.Next()
   187  			require.NoError(t, err)
   188  			cnt++
   189  		}
   190  		require.Equal(t, 4, cnt)
   191  	})
   192  	t.Run("Desc", func(t *testing.T) {
   193  		_, tx, _ := BaseCase(t)
   194  
   195  		//[from, to)
   196  		it, err := tx.RangeDupSort("Table", []byte("key3"), nil, nil, order.Desc, -1)
   197  		require.NoError(t, err)
   198  		require.True(t, it.HasNext())
   199  		k, v, err := it.Next()
   200  		require.NoError(t, err)
   201  		require.Equal(t, "key3", string(k))
   202  		require.Equal(t, "value3.3", string(v))
   203  
   204  		require.True(t, it.HasNext())
   205  		k, v, err = it.Next()
   206  		require.NoError(t, err)
   207  		require.Equal(t, "key3", string(k))
   208  		require.Equal(t, "value3.1", string(v))
   209  
   210  		require.False(t, it.HasNext())
   211  
   212  		it, err = tx.RangeDescend("Table", nil, nil, 2)
   213  		require.NoError(t, err)
   214  
   215  		cnt := 0
   216  		for it.HasNext() {
   217  			_, _, err := it.Next()
   218  			require.NoError(t, err)
   219  			cnt++
   220  		}
   221  		require.Equal(t, 2, cnt)
   222  	})
   223  }
   224  
   225  func TestLastDup(t *testing.T) {
   226  	db, tx, _ := BaseCase(t)
   227  
   228  	err := tx.Commit()
   229  	require.NoError(t, err)
   230  	roTx, err := db.BeginRo(context.Background())
   231  	require.NoError(t, err)
   232  	defer roTx.Rollback()
   233  
   234  	roC, err := roTx.CursorDupSort("Table")
   235  	require.NoError(t, err)
   236  	defer roC.Close()
   237  
   238  	var keys, vals []string
   239  	var k, v []byte
   240  	for k, _, err = roC.First(); err == nil && k != nil; k, _, err = roC.NextNoDup() {
   241  		v, err = roC.LastDup()
   242  		require.NoError(t, err)
   243  		keys = append(keys, string(k))
   244  		vals = append(vals, string(v))
   245  	}
   246  	require.NoError(t, err)
   247  	require.Equal(t, []string{"key1", "key3"}, keys)
   248  	require.Equal(t, []string{"value1.3", "value3.3"}, vals)
   249  }
   250  
   251  func TestPutGet(t *testing.T) {
   252  	_, tx, c := BaseCase(t)
   253  
   254  	require.NoError(t, c.Put([]byte(""), []byte("value1.1")))
   255  
   256  	var v []byte
   257  	v, err := tx.GetOne("Table", []byte("key1"))
   258  	require.Nil(t, err)
   259  	require.Equal(t, v, []byte("value1.1"))
   260  
   261  	v, err = tx.GetOne("RANDOM", []byte("key1"))
   262  	require.Error(t, err) // Error from non-existent bucket returns error
   263  	require.Nil(t, v)
   264  }
   265  
   266  func TestIncrementRead(t *testing.T) {
   267  	_, tx, _ := BaseCase(t)
   268  
   269  	table := "Table"
   270  
   271  	_, err := tx.IncrementSequence(table, uint64(12))
   272  	require.Nil(t, err)
   273  	chaV, err := tx.ReadSequence(table)
   274  	require.Nil(t, err)
   275  	require.Equal(t, chaV, uint64(12))
   276  	_, err = tx.IncrementSequence(table, uint64(240))
   277  	require.Nil(t, err)
   278  	chaV, err = tx.ReadSequence(table)
   279  	require.Nil(t, err)
   280  	require.Equal(t, chaV, uint64(252))
   281  }
   282  
   283  func TestHasDelete(t *testing.T) {
   284  	_, tx, _ := BaseCase(t)
   285  
   286  	table := "Table"
   287  
   288  	require.NoError(t, tx.Put(table, []byte("key2"), []byte("value2.1")))
   289  	require.NoError(t, tx.Put(table, []byte("key4"), []byte("value4.1")))
   290  	require.NoError(t, tx.Put(table, []byte("key5"), []byte("value5.1")))
   291  
   292  	c, err := tx.RwCursorDupSort(table)
   293  	require.NoError(t, err)
   294  	defer c.Close()
   295  	require.NoError(t, c.DeleteExact([]byte("key1"), []byte("value1.1")))
   296  	require.NoError(t, c.DeleteExact([]byte("key1"), []byte("value1.3")))
   297  	require.NoError(t, c.DeleteExact([]byte("key1"), []byte("value1.1"))) //valid but already deleted
   298  	require.NoError(t, c.DeleteExact([]byte("key2"), []byte("value1.1"))) //valid key but wrong value
   299  
   300  	res, err := tx.Has(table, []byte("key1"))
   301  	require.Nil(t, err)
   302  	require.False(t, res)
   303  
   304  	res, err = tx.Has(table, []byte("key2"))
   305  	require.Nil(t, err)
   306  	require.True(t, res)
   307  
   308  	res, err = tx.Has(table, []byte("key3"))
   309  	require.Nil(t, err)
   310  	require.True(t, res) //There is another key3 left
   311  
   312  	res, err = tx.Has(table, []byte("k"))
   313  	require.Nil(t, err)
   314  	require.False(t, res)
   315  }
   316  
   317  func TestForAmount(t *testing.T) {
   318  	_, tx, _ := BaseCase(t)
   319  
   320  	table := "Table"
   321  
   322  	require.NoError(t, tx.Put(table, []byte("key2"), []byte("value2.1")))
   323  	require.NoError(t, tx.Put(table, []byte("key4"), []byte("value4.1")))
   324  	require.NoError(t, tx.Put(table, []byte("key5"), []byte("value5.1")))
   325  
   326  	var keys []string
   327  
   328  	err := tx.ForAmount(table, []byte("key3"), uint32(2), func(k, v []byte) error {
   329  		keys = append(keys, string(k))
   330  		return nil
   331  	})
   332  	require.Nil(t, err)
   333  	require.Equal(t, []string{"key3", "key3"}, keys)
   334  
   335  	var keys1 []string
   336  
   337  	err1 := tx.ForAmount(table, []byte("key1"), 100, func(k, v []byte) error {
   338  		keys1 = append(keys1, string(k))
   339  		return nil
   340  	})
   341  	require.Nil(t, err1)
   342  	require.Equal(t, []string{"key1", "key1", "key2", "key3", "key3", "key4", "key5"}, keys1)
   343  
   344  	var keys2 []string
   345  
   346  	err2 := tx.ForAmount(table, []byte("value"), 100, func(k, v []byte) error {
   347  		keys2 = append(keys2, string(k))
   348  		return nil
   349  	})
   350  	require.Nil(t, err2)
   351  	require.Nil(t, keys2)
   352  
   353  	var keys3 []string
   354  
   355  	err3 := tx.ForAmount(table, []byte("key1"), 0, func(k, v []byte) error {
   356  		keys3 = append(keys3, string(k))
   357  		return nil
   358  	})
   359  	require.Nil(t, err3)
   360  	require.Nil(t, keys3)
   361  }
   362  
   363  func TestForPrefix(t *testing.T) {
   364  	_, tx, _ := BaseCase(t)
   365  
   366  	table := "Table"
   367  
   368  	var keys []string
   369  
   370  	err := tx.ForPrefix(table, []byte("key"), func(k, v []byte) error {
   371  		keys = append(keys, string(k))
   372  		return nil
   373  	})
   374  	require.Nil(t, err)
   375  	require.Equal(t, []string{"key1", "key1", "key3", "key3"}, keys)
   376  
   377  	var keys1 []string
   378  
   379  	err = tx.ForPrefix(table, []byte("key1"), func(k, v []byte) error {
   380  		keys1 = append(keys1, string(k))
   381  		return nil
   382  	})
   383  	require.Nil(t, err)
   384  	require.Equal(t, []string{"key1", "key1"}, keys1)
   385  
   386  	var keys2 []string
   387  
   388  	err = tx.ForPrefix(table, []byte("e"), func(k, v []byte) error {
   389  		keys2 = append(keys2, string(k))
   390  		return nil
   391  	})
   392  	require.Nil(t, err)
   393  	require.Nil(t, keys2)
   394  }
   395  
   396  func TestAppendFirstLast(t *testing.T) {
   397  	_, tx, c := BaseCase(t)
   398  
   399  	table := "Table"
   400  
   401  	require.Error(t, tx.Append(table, []byte("key2"), []byte("value2.1")))
   402  	require.NoError(t, tx.Append(table, []byte("key6"), []byte("value6.1")))
   403  	require.Error(t, tx.Append(table, []byte("key4"), []byte("value4.1")))
   404  	require.NoError(t, tx.AppendDup(table, []byte("key2"), []byte("value1.11")))
   405  
   406  	k, v, err := c.First()
   407  	require.Nil(t, err)
   408  	require.Equal(t, k, []byte("key1"))
   409  	require.Equal(t, v, []byte("value1.1"))
   410  
   411  	keys, values := iteration(t, c, k, v)
   412  	require.Equal(t, []string{"key1", "key1", "key2", "key3", "key3", "key6"}, keys)
   413  	require.Equal(t, []string{"value1.1", "value1.3", "value1.11", "value3.1", "value3.3", "value6.1"}, values)
   414  
   415  	k, v, err = c.Last()
   416  	require.Nil(t, err)
   417  	require.Equal(t, k, []byte("key6"))
   418  	require.Equal(t, v, []byte("value6.1"))
   419  
   420  	keys, values = iteration(t, c, k, v)
   421  	require.Equal(t, []string{"key6"}, keys)
   422  	require.Equal(t, []string{"value6.1"}, values)
   423  }
   424  
   425  func TestNextPrevCurrent(t *testing.T) {
   426  	_, _, c := BaseCase(t)
   427  
   428  	k, v, err := c.First()
   429  	require.Nil(t, err)
   430  	keys, values := iteration(t, c, k, v)
   431  	require.Equal(t, []string{"key1", "key1", "key3", "key3"}, keys)
   432  	require.Equal(t, []string{"value1.1", "value1.3", "value3.1", "value3.3"}, values)
   433  
   434  	k, v, err = c.Next()
   435  	require.Equal(t, []byte("key1"), k)
   436  	require.Nil(t, err)
   437  	keys, values = iteration(t, c, k, v)
   438  	require.Equal(t, []string{"key1", "key3", "key3"}, keys)
   439  	require.Equal(t, []string{"value1.3", "value3.1", "value3.3"}, values)
   440  
   441  	k, v, err = c.Current()
   442  	require.Nil(t, err)
   443  	keys, values = iteration(t, c, k, v)
   444  	require.Equal(t, []string{"key1", "key3", "key3"}, keys)
   445  	require.Equal(t, []string{"value1.3", "value3.1", "value3.3"}, values)
   446  	require.Equal(t, k, []byte("key1"))
   447  	require.Equal(t, v, []byte("value1.3"))
   448  
   449  	k, v, err = c.Next()
   450  	require.Nil(t, err)
   451  	keys, values = iteration(t, c, k, v)
   452  	require.Equal(t, []string{"key3", "key3"}, keys)
   453  	require.Equal(t, []string{"value3.1", "value3.3"}, values)
   454  
   455  	k, v, err = c.Prev()
   456  	require.Nil(t, err)
   457  	keys, values = iteration(t, c, k, v)
   458  	require.Equal(t, []string{"key1", "key3", "key3"}, keys)
   459  	require.Equal(t, []string{"value1.3", "value3.1", "value3.3"}, values)
   460  
   461  	k, v, err = c.Current()
   462  	require.Nil(t, err)
   463  	keys, values = iteration(t, c, k, v)
   464  	require.Equal(t, []string{"key1", "key3", "key3"}, keys)
   465  	require.Equal(t, []string{"value1.3", "value3.1", "value3.3"}, values)
   466  
   467  	k, v, err = c.Prev()
   468  	require.Nil(t, err)
   469  	keys, values = iteration(t, c, k, v)
   470  	require.Equal(t, []string{"key1", "key1", "key3", "key3"}, keys)
   471  	require.Equal(t, []string{"value1.1", "value1.3", "value3.1", "value3.3"}, values)
   472  
   473  	err = c.DeleteCurrent()
   474  	require.Nil(t, err)
   475  	k, v, err = c.Current()
   476  	require.Nil(t, err)
   477  	keys, values = iteration(t, c, k, v)
   478  	require.Equal(t, []string{"key1", "key3", "key3"}, keys)
   479  	require.Equal(t, []string{"value1.3", "value3.1", "value3.3"}, values)
   480  
   481  }
   482  
   483  func TestSeek(t *testing.T) {
   484  	_, _, c := BaseCase(t)
   485  
   486  	k, v, err := c.Seek([]byte("k"))
   487  	require.Nil(t, err)
   488  	keys, values := iteration(t, c, k, v)
   489  	require.Equal(t, []string{"key1", "key1", "key3", "key3"}, keys)
   490  	require.Equal(t, []string{"value1.1", "value1.3", "value3.1", "value3.3"}, values)
   491  
   492  	k, v, err = c.Seek([]byte("key3"))
   493  	require.Nil(t, err)
   494  	keys, values = iteration(t, c, k, v)
   495  	require.Equal(t, []string{"key3", "key3"}, keys)
   496  	require.Equal(t, []string{"value3.1", "value3.3"}, values)
   497  
   498  	k, v, err = c.Seek([]byte("xyz"))
   499  	require.Nil(t, err)
   500  	keys, values = iteration(t, c, k, v)
   501  	require.Nil(t, keys)
   502  	require.Nil(t, values)
   503  }
   504  
   505  func TestSeekExact(t *testing.T) {
   506  	_, _, c := BaseCase(t)
   507  
   508  	k, v, err := c.SeekExact([]byte("key3"))
   509  	require.Nil(t, err)
   510  	keys, values := iteration(t, c, k, v)
   511  	require.Equal(t, []string{"key3", "key3"}, keys)
   512  	require.Equal(t, []string{"value3.1", "value3.3"}, values)
   513  
   514  	k, v, err = c.SeekExact([]byte("key"))
   515  	require.Nil(t, err)
   516  	keys, values = iteration(t, c, k, v)
   517  	require.Nil(t, keys)
   518  	require.Nil(t, values)
   519  }
   520  
   521  func TestSeekBothExact(t *testing.T) {
   522  	_, _, c := BaseCase(t)
   523  
   524  	k, v, err := c.SeekBothExact([]byte("key1"), []byte("value1.2"))
   525  	require.Nil(t, err)
   526  	keys, values := iteration(t, c, k, v)
   527  	require.Nil(t, keys)
   528  	require.Nil(t, values)
   529  
   530  	k, v, err = c.SeekBothExact([]byte("key2"), []byte("value1.1"))
   531  	require.Nil(t, err)
   532  	keys, values = iteration(t, c, k, v)
   533  	require.Nil(t, keys)
   534  	require.Nil(t, values)
   535  
   536  	k, v, err = c.SeekBothExact([]byte("key1"), []byte("value1.1"))
   537  	require.Nil(t, err)
   538  	keys, values = iteration(t, c, k, v)
   539  	require.Equal(t, []string{"key1", "key1", "key3", "key3"}, keys)
   540  	require.Equal(t, []string{"value1.1", "value1.3", "value3.1", "value3.3"}, values)
   541  
   542  	k, v, err = c.SeekBothExact([]byte("key3"), []byte("value3.3"))
   543  	require.Nil(t, err)
   544  	keys, values = iteration(t, c, k, v)
   545  	require.Equal(t, []string{"key3"}, keys)
   546  	require.Equal(t, []string{"value3.3"}, values)
   547  }
   548  
   549  func TestNextDups(t *testing.T) {
   550  	_, tx, _ := BaseCase(t)
   551  
   552  	table := "Table"
   553  
   554  	c, err := tx.RwCursorDupSort(table)
   555  	require.NoError(t, err)
   556  	defer c.Close()
   557  	require.NoError(t, c.DeleteExact([]byte("key1"), []byte("value1.1")))
   558  	require.NoError(t, c.DeleteExact([]byte("key1"), []byte("value1.3")))
   559  	require.NoError(t, c.DeleteExact([]byte("key3"), []byte("value3.1"))) //valid but already deleted
   560  	require.NoError(t, c.DeleteExact([]byte("key3"), []byte("value3.3"))) //valid key but wrong value
   561  
   562  	require.NoError(t, tx.Put(table, []byte("key2"), []byte("value1.1")))
   563  	require.NoError(t, c.Put([]byte("key2"), []byte("value1.2")))
   564  	require.NoError(t, c.Put([]byte("key3"), []byte("value1.6")))
   565  	require.NoError(t, c.Put([]byte("key"), []byte("value1.7")))
   566  
   567  	k, v, err := c.Current()
   568  	require.Nil(t, err)
   569  	keys, values := iteration(t, c, k, v)
   570  	require.Equal(t, []string{"key", "key2", "key2", "key3"}, keys)
   571  	require.Equal(t, []string{"value1.7", "value1.1", "value1.2", "value1.6"}, values)
   572  
   573  	v, err = c.FirstDup()
   574  	require.Nil(t, err)
   575  	keys, values = iteration(t, c, k, v)
   576  	require.Equal(t, []string{"key", "key2", "key2", "key3"}, keys)
   577  	require.Equal(t, []string{"value1.7", "value1.1", "value1.2", "value1.6"}, values)
   578  
   579  	k, v, err = c.NextNoDup()
   580  	require.Nil(t, err)
   581  	keys, values = iteration(t, c, k, v)
   582  	require.Equal(t, []string{"key2", "key2", "key3"}, keys)
   583  	require.Equal(t, []string{"value1.1", "value1.2", "value1.6"}, values)
   584  
   585  	k, v, err = c.NextDup()
   586  	require.Nil(t, err)
   587  	keys, values = iteration(t, c, k, v)
   588  	require.Equal(t, []string{"key2", "key3"}, keys)
   589  	require.Equal(t, []string{"value1.2", "value1.6"}, values)
   590  
   591  	v, err = c.LastDup()
   592  	require.Nil(t, err)
   593  	keys, values = iteration(t, c, k, v)
   594  	require.Equal(t, []string{"key2", "key3"}, keys)
   595  	require.Equal(t, []string{"value1.2", "value1.6"}, values)
   596  
   597  	k, v, err = c.NextDup()
   598  	require.Nil(t, err)
   599  	keys, values = iteration(t, c, k, v)
   600  	require.Nil(t, keys)
   601  	require.Nil(t, values)
   602  
   603  	k, v, err = c.NextNoDup()
   604  	require.Nil(t, err)
   605  	keys, values = iteration(t, c, k, v)
   606  	require.Equal(t, []string{"key3"}, keys)
   607  	require.Equal(t, []string{"value1.6"}, values)
   608  }
   609  
   610  func TestCurrentDup(t *testing.T) {
   611  	_, _, c := BaseCase(t)
   612  
   613  	count, err := c.CountDuplicates()
   614  	require.Nil(t, err)
   615  	require.Equal(t, count, uint64(2))
   616  
   617  	require.Error(t, c.PutNoDupData([]byte("key3"), []byte("value3.3")))
   618  	require.NoError(t, c.DeleteCurrentDuplicates())
   619  
   620  	k, v, err := c.SeekExact([]byte("key1"))
   621  	require.Nil(t, err)
   622  	keys, values := iteration(t, c, k, v)
   623  	require.Equal(t, []string{"key1", "key1"}, keys)
   624  	require.Equal(t, []string{"value1.1", "value1.3"}, values)
   625  
   626  	require.Equal(t, []string{"key1", "key1"}, keys)
   627  	require.Equal(t, []string{"value1.1", "value1.3"}, values)
   628  }
   629  
   630  func TestDupDelete(t *testing.T) {
   631  	_, _, c := BaseCase(t)
   632  
   633  	k, _, err := c.Current()
   634  	require.Nil(t, err)
   635  	require.Equal(t, []byte("key3"), k)
   636  
   637  	err = c.DeleteCurrentDuplicates()
   638  	require.Nil(t, err)
   639  
   640  	err = c.Delete([]byte("key1"))
   641  	require.Nil(t, err)
   642  
   643  	count, err := c.Count()
   644  	require.Nil(t, err)
   645  	assert.Zero(t, count)
   646  }
   647  
   648  func baseAutoConversion(t *testing.T) (kv.RwDB, kv.RwTx, kv.RwCursor) {
   649  	t.Helper()
   650  	path := t.TempDir()
   651  	logger := log.New()
   652  	db := NewMDBX(logger).InMem(path).MustOpen()
   653  
   654  	tx, err := db.BeginRw(context.Background())
   655  	require.NoError(t, err)
   656  
   657  	c, err := tx.RwCursor(kv.PlainState)
   658  	require.NoError(t, err)
   659  
   660  	// Insert some records
   661  	require.NoError(t, c.Put([]byte("A"), []byte("0")))
   662  	require.NoError(t, c.Put([]byte("A..........................._______________________________A"), []byte("1")))
   663  	require.NoError(t, c.Put([]byte("A..........................._______________________________C"), []byte("2")))
   664  	require.NoError(t, c.Put([]byte("B"), []byte("8")))
   665  	require.NoError(t, c.Put([]byte("C"), []byte("9")))
   666  	require.NoError(t, c.Put([]byte("D..........................._______________________________A"), []byte("3")))
   667  	require.NoError(t, c.Put([]byte("D..........................._______________________________C"), []byte("4")))
   668  
   669  	return db, tx, c
   670  }
   671  
   672  func TestAutoConversion(t *testing.T) {
   673  	db, tx, c := baseAutoConversion(t)
   674  	defer db.Close()
   675  	defer tx.Rollback()
   676  	defer c.Close()
   677  
   678  	// key length conflict
   679  	require.Error(t, c.Put([]byte("A..........................."), []byte("?")))
   680  
   681  	require.NoError(t, c.Delete([]byte("A..........................._______________________________A")))
   682  	require.NoError(t, c.Put([]byte("B"), []byte("7")))
   683  	require.NoError(t, c.Delete([]byte("C")))
   684  	require.NoError(t, c.Put([]byte("D..........................._______________________________C"), []byte("6")))
   685  	require.NoError(t, c.Put([]byte("D..........................._______________________________E"), []byte("5")))
   686  
   687  	k, v, err := c.First()
   688  	require.NoError(t, err)
   689  	assert.Equal(t, []byte("A"), k)
   690  	assert.Equal(t, []byte("0"), v)
   691  
   692  	k, v, err = c.Next()
   693  	require.NoError(t, err)
   694  	assert.Equal(t, []byte("A..........................._______________________________C"), k)
   695  	assert.Equal(t, []byte("2"), v)
   696  
   697  	k, v, err = c.Next()
   698  	require.NoError(t, err)
   699  	assert.Equal(t, []byte("B"), k)
   700  	assert.Equal(t, []byte("7"), v)
   701  
   702  	k, v, err = c.Next()
   703  	require.NoError(t, err)
   704  	assert.Equal(t, []byte("D..........................._______________________________A"), k)
   705  	assert.Equal(t, []byte("3"), v)
   706  
   707  	k, v, err = c.Next()
   708  	require.NoError(t, err)
   709  	assert.Equal(t, []byte("D..........................._______________________________C"), k)
   710  	assert.Equal(t, []byte("6"), v)
   711  
   712  	k, v, err = c.Next()
   713  	require.NoError(t, err)
   714  	assert.Equal(t, []byte("D..........................._______________________________E"), k)
   715  	assert.Equal(t, []byte("5"), v)
   716  
   717  	k, v, err = c.Next()
   718  	require.NoError(t, err)
   719  	assert.Nil(t, k)
   720  	assert.Nil(t, v)
   721  }
   722  
   723  func TestAutoConversionSeekBothRange(t *testing.T) {
   724  	db, tx, nonDupC := baseAutoConversion(t)
   725  	nonDupC.Close()
   726  	defer db.Close()
   727  	defer tx.Rollback()
   728  
   729  	c, err := tx.RwCursorDupSort(kv.PlainState)
   730  	require.NoError(t, err)
   731  
   732  	require.NoError(t, c.Delete([]byte("A..........................._______________________________A")))
   733  	require.NoError(t, c.Put([]byte("D..........................._______________________________C"), []byte("6")))
   734  	require.NoError(t, c.Put([]byte("D..........................._______________________________E"), []byte("5")))
   735  
   736  	v, err := c.SeekBothRange([]byte("A..........................."), []byte("_______________________________A"))
   737  	require.NoError(t, err)
   738  	assert.Equal(t, []byte("_______________________________C2"), v)
   739  
   740  	_, v, err = c.NextDup()
   741  	require.NoError(t, err)
   742  	assert.Nil(t, v)
   743  
   744  	v, err = c.SeekBothRange([]byte("A..........................."), []byte("_______________________________X"))
   745  	require.NoError(t, err)
   746  	assert.Nil(t, v)
   747  
   748  	v, err = c.SeekBothRange([]byte("B..........................."), []byte(""))
   749  	require.NoError(t, err)
   750  	assert.Nil(t, v)
   751  
   752  	v, err = c.SeekBothRange([]byte("C..........................."), []byte(""))
   753  	require.NoError(t, err)
   754  	assert.Nil(t, v)
   755  
   756  	v, err = c.SeekBothRange([]byte("D..........................."), []byte(""))
   757  	require.NoError(t, err)
   758  	assert.Equal(t, []byte("_______________________________A3"), v)
   759  
   760  	_, v, err = c.NextDup()
   761  	require.NoError(t, err)
   762  	assert.Equal(t, []byte("_______________________________C6"), v)
   763  
   764  	_, v, err = c.NextDup()
   765  	require.NoError(t, err)
   766  	assert.Equal(t, []byte("_______________________________E5"), v)
   767  
   768  	_, v, err = c.NextDup()
   769  	require.NoError(t, err)
   770  	assert.Nil(t, v)
   771  
   772  	v, err = c.SeekBothRange([]byte("X..........................."), []byte("_______________________________Y"))
   773  	require.NoError(t, err)
   774  	assert.Nil(t, v)
   775  }