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

     1  /*
     2     Copyright 2021 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 iter_test
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"fmt"
    23  	"testing"
    24  
    25  	"github.com/ledgerwatch/erigon-lib/kv"
    26  	"github.com/ledgerwatch/erigon-lib/kv/iter"
    27  	"github.com/ledgerwatch/erigon-lib/kv/memdb"
    28  	"github.com/ledgerwatch/erigon-lib/kv/order"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestUnion(t *testing.T) {
    33  	t.Run("arrays", func(t *testing.T) {
    34  		s1 := iter.Array[uint64]([]uint64{1, 3, 6, 7})
    35  		s2 := iter.Array[uint64]([]uint64{2, 3, 7, 8})
    36  		s3 := iter.Union[uint64](s1, s2, order.Asc, -1)
    37  		res, err := iter.ToArr[uint64](s3)
    38  		require.NoError(t, err)
    39  		require.Equal(t, []uint64{1, 2, 3, 6, 7, 8}, res)
    40  
    41  		s1 = iter.ReverseArray[uint64]([]uint64{1, 3, 6, 7})
    42  		s2 = iter.ReverseArray[uint64]([]uint64{2, 3, 7, 8})
    43  		s3 = iter.Union[uint64](s1, s2, order.Desc, -1)
    44  		res, err = iter.ToArr[uint64](s3)
    45  		require.NoError(t, err)
    46  		require.Equal(t, []uint64{8, 7, 6, 3, 2, 1}, res)
    47  
    48  		s1 = iter.ReverseArray[uint64]([]uint64{1, 3, 6, 7})
    49  		s2 = iter.ReverseArray[uint64]([]uint64{2, 3, 7, 8})
    50  		s3 = iter.Union[uint64](s1, s2, order.Desc, 2)
    51  		res, err = iter.ToArr[uint64](s3)
    52  		require.NoError(t, err)
    53  		require.Equal(t, []uint64{8, 7}, res)
    54  
    55  	})
    56  	t.Run("empty left", func(t *testing.T) {
    57  		s1 := iter.EmptyU64
    58  		s2 := iter.Array[uint64]([]uint64{2, 3, 7, 8})
    59  		s3 := iter.Union[uint64](s1, s2, order.Asc, -1)
    60  		res, err := iter.ToArr[uint64](s3)
    61  		require.NoError(t, err)
    62  		require.Equal(t, []uint64{2, 3, 7, 8}, res)
    63  	})
    64  	t.Run("empty right", func(t *testing.T) {
    65  		s1 := iter.Array[uint64]([]uint64{1, 3, 4, 5, 6, 7})
    66  		s2 := iter.EmptyU64
    67  		s3 := iter.Union[uint64](s1, s2, order.Asc, -1)
    68  		res, err := iter.ToArr[uint64](s3)
    69  		require.NoError(t, err)
    70  		require.Equal(t, []uint64{1, 3, 4, 5, 6, 7}, res)
    71  	})
    72  	t.Run("empty", func(t *testing.T) {
    73  		s1 := iter.EmptyU64
    74  		s2 := iter.EmptyU64
    75  		s3 := iter.Union[uint64](s1, s2, order.Asc, -1)
    76  		res, err := iter.ToArr[uint64](s3)
    77  		require.NoError(t, err)
    78  		require.Nil(t, res)
    79  	})
    80  }
    81  func TestUnionPairs(t *testing.T) {
    82  	db := memdb.NewTestDB(t)
    83  	ctx := context.Background()
    84  	t.Run("simple", func(t *testing.T) {
    85  		require := require.New(t)
    86  		tx, _ := db.BeginRw(ctx)
    87  		defer tx.Rollback()
    88  		_ = tx.Put(kv.E2AccountsHistory, []byte{1}, []byte{1})
    89  		_ = tx.Put(kv.E2AccountsHistory, []byte{3}, []byte{1})
    90  		_ = tx.Put(kv.E2AccountsHistory, []byte{4}, []byte{1})
    91  		_ = tx.Put(kv.PlainState, []byte{2}, []byte{9})
    92  		_ = tx.Put(kv.PlainState, []byte{3}, []byte{9})
    93  		it, _ := tx.Range(kv.E2AccountsHistory, nil, nil)
    94  		it2, _ := tx.Range(kv.PlainState, nil, nil)
    95  		keys, values, err := iter.ToKVArray(iter.UnionKV(it, it2, -1))
    96  		require.NoError(err)
    97  		require.Equal([][]byte{{1}, {2}, {3}, {4}}, keys)
    98  		require.Equal([][]byte{{1}, {9}, {1}, {1}}, values)
    99  	})
   100  	t.Run("empty 1st", func(t *testing.T) {
   101  		require := require.New(t)
   102  		tx, _ := db.BeginRw(ctx)
   103  		defer tx.Rollback()
   104  		_ = tx.Put(kv.PlainState, []byte{2}, []byte{9})
   105  		_ = tx.Put(kv.PlainState, []byte{3}, []byte{9})
   106  		it, _ := tx.Range(kv.E2AccountsHistory, nil, nil)
   107  		it2, _ := tx.Range(kv.PlainState, nil, nil)
   108  		keys, _, err := iter.ToKVArray(iter.UnionKV(it, it2, -1))
   109  		require.NoError(err)
   110  		require.Equal([][]byte{{2}, {3}}, keys)
   111  	})
   112  	t.Run("empty 2nd", func(t *testing.T) {
   113  		require := require.New(t)
   114  		tx, _ := db.BeginRw(ctx)
   115  		defer tx.Rollback()
   116  		_ = tx.Put(kv.E2AccountsHistory, []byte{1}, []byte{1})
   117  		_ = tx.Put(kv.E2AccountsHistory, []byte{3}, []byte{1})
   118  		_ = tx.Put(kv.E2AccountsHistory, []byte{4}, []byte{1})
   119  		it, _ := tx.Range(kv.E2AccountsHistory, nil, nil)
   120  		it2, _ := tx.Range(kv.PlainState, nil, nil)
   121  		keys, _, err := iter.ToKVArray(iter.UnionKV(it, it2, -1))
   122  		require.NoError(err)
   123  		require.Equal([][]byte{{1}, {3}, {4}}, keys)
   124  	})
   125  	t.Run("empty both", func(t *testing.T) {
   126  		require := require.New(t)
   127  		tx, _ := db.BeginRw(ctx)
   128  		defer tx.Rollback()
   129  		it, _ := tx.Range(kv.E2AccountsHistory, nil, nil)
   130  		it2, _ := tx.Range(kv.PlainState, nil, nil)
   131  		m := iter.UnionKV(it, it2, -1)
   132  		require.False(m.HasNext())
   133  	})
   134  	t.Run("error handling", func(t *testing.T) {
   135  		require := require.New(t)
   136  		tx, _ := db.BeginRw(ctx)
   137  		defer tx.Rollback()
   138  		it := iter.PairsWithError(10)
   139  		it2 := iter.PairsWithError(12)
   140  		keys, _, err := iter.ToKVArray(iter.UnionKV(it, it2, -1))
   141  		require.Equal("expected error at iteration: 10", err.Error())
   142  		require.Equal(10, len(keys))
   143  	})
   144  }
   145  
   146  func TestIntersect(t *testing.T) {
   147  	t.Run("intersect", func(t *testing.T) {
   148  		s1 := iter.Array[uint64]([]uint64{1, 3, 4, 5, 6, 7})
   149  		s2 := iter.Array[uint64]([]uint64{2, 3, 7})
   150  		s3 := iter.Intersect[uint64](s1, s2, -1)
   151  		res, err := iter.ToArr[uint64](s3)
   152  		require.NoError(t, err)
   153  		require.Equal(t, []uint64{3, 7}, res)
   154  
   155  		s1 = iter.Array[uint64]([]uint64{1, 3, 4, 5, 6, 7})
   156  		s2 = iter.Array[uint64]([]uint64{2, 3, 7})
   157  		s3 = iter.Intersect[uint64](s1, s2, 1)
   158  		res, err = iter.ToArr[uint64](s3)
   159  		require.NoError(t, err)
   160  		require.Equal(t, []uint64{3}, res)
   161  	})
   162  	t.Run("empty left", func(t *testing.T) {
   163  		s1 := iter.EmptyU64
   164  		s2 := iter.Array[uint64]([]uint64{2, 3, 7, 8})
   165  		s3 := iter.Intersect[uint64](s1, s2, -1)
   166  		res, err := iter.ToArr[uint64](s3)
   167  		require.NoError(t, err)
   168  		require.Nil(t, res)
   169  
   170  		s2 = iter.Array[uint64]([]uint64{2, 3, 7, 8})
   171  		s3 = iter.Intersect[uint64](nil, s2, -1)
   172  		res, err = iter.ToArr[uint64](s3)
   173  		require.NoError(t, err)
   174  		require.Nil(t, res)
   175  	})
   176  	t.Run("empty right", func(t *testing.T) {
   177  		s1 := iter.Array[uint64]([]uint64{1, 3, 4, 5, 6, 7})
   178  		s2 := iter.EmptyU64
   179  		s3 := iter.Intersect[uint64](s1, s2, -1)
   180  		res, err := iter.ToArr[uint64](s3)
   181  		require.NoError(t, err)
   182  		require.Nil(t, nil, res)
   183  
   184  		s1 = iter.Array[uint64]([]uint64{1, 3, 4, 5, 6, 7})
   185  		s3 = iter.Intersect[uint64](s1, nil, -1)
   186  		res, err = iter.ToArr[uint64](s3)
   187  		require.NoError(t, err)
   188  		require.Nil(t, res)
   189  	})
   190  	t.Run("empty", func(t *testing.T) {
   191  		s1 := iter.EmptyU64
   192  		s2 := iter.EmptyU64
   193  		s3 := iter.Intersect[uint64](s1, s2, -1)
   194  		res, err := iter.ToArr[uint64](s3)
   195  		require.NoError(t, err)
   196  		require.Nil(t, res)
   197  
   198  		s3 = iter.Intersect[uint64](nil, nil, -1)
   199  		res, err = iter.ToArr[uint64](s3)
   200  		require.NoError(t, err)
   201  		require.Nil(t, res)
   202  	})
   203  }
   204  
   205  func TestRange(t *testing.T) {
   206  	t.Run("range", func(t *testing.T) {
   207  		s1 := iter.Range[uint64](1, 4)
   208  		res, err := iter.ToArr[uint64](s1)
   209  		require.NoError(t, err)
   210  		require.Equal(t, []uint64{1, 2, 3}, res)
   211  	})
   212  	t.Run("empty", func(t *testing.T) {
   213  		s1 := iter.Range[uint64](1, 1)
   214  		res, err := iter.ToArr[uint64](s1)
   215  		require.NoError(t, err)
   216  		require.Equal(t, []uint64{1}, res)
   217  	})
   218  }
   219  
   220  func TestPaginated(t *testing.T) {
   221  	t.Run("paginated", func(t *testing.T) {
   222  		i := 0
   223  		s1 := iter.Paginate[uint64](func(pageToken string) (arr []uint64, nextPageToken string, err error) {
   224  			i++
   225  			switch i {
   226  			case 1:
   227  				return []uint64{1, 2, 3}, "test", nil
   228  			case 2:
   229  				return []uint64{4, 5, 6}, "test", nil
   230  			case 3:
   231  				return []uint64{7}, "", nil
   232  			case 4:
   233  				panic("must not happen")
   234  			}
   235  			return
   236  		})
   237  		res, err := iter.ToArr[uint64](s1)
   238  		require.NoError(t, err)
   239  		require.Equal(t, []uint64{1, 2, 3, 4, 5, 6, 7}, res)
   240  
   241  		//idempotency
   242  		require.False(t, s1.HasNext())
   243  		require.False(t, s1.HasNext())
   244  	})
   245  	t.Run("error", func(t *testing.T) {
   246  		i := 0
   247  		testErr := fmt.Errorf("test")
   248  		s1 := iter.Paginate[uint64](func(pageToken string) (arr []uint64, nextPageToken string, err error) {
   249  			i++
   250  			switch i {
   251  			case 1:
   252  				return []uint64{1, 2, 3}, "test", nil
   253  			case 2:
   254  				return nil, "test", testErr
   255  			case 3:
   256  				panic("must not happen")
   257  			}
   258  			return
   259  		})
   260  		res, err := iter.ToArr[uint64](s1)
   261  		require.ErrorIs(t, err, testErr)
   262  		require.Equal(t, []uint64{1, 2, 3}, res)
   263  
   264  		//idempotency
   265  		require.True(t, s1.HasNext())
   266  		require.True(t, s1.HasNext())
   267  		_, err = s1.Next()
   268  		require.ErrorIs(t, err, testErr)
   269  	})
   270  	t.Run("empty", func(t *testing.T) {
   271  		s1 := iter.Paginate[uint64](func(pageToken string) (arr []uint64, nextPageToken string, err error) {
   272  			return []uint64{}, "", nil
   273  		})
   274  		res, err := iter.ToArr[uint64](s1)
   275  		require.NoError(t, err)
   276  		require.Nil(t, res)
   277  
   278  		//idempotency
   279  		require.False(t, s1.HasNext())
   280  		require.False(t, s1.HasNext())
   281  	})
   282  }
   283  
   284  func TestPaginatedDual(t *testing.T) {
   285  	t.Run("paginated", func(t *testing.T) {
   286  		i := 0
   287  		s1 := iter.PaginateKV(func(pageToken string) (keys, values [][]byte, nextPageToken string, err error) {
   288  			i++
   289  			switch i {
   290  			case 1:
   291  				return [][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}}, "test", nil
   292  			case 2:
   293  				return [][]byte{{4}, {5}, {6}}, [][]byte{{4}, {5}, {6}}, "test", nil
   294  			case 3:
   295  				return [][]byte{{7}}, [][]byte{{7}}, "", nil
   296  			case 4:
   297  				panic("must not happen")
   298  			}
   299  			return
   300  		})
   301  
   302  		keys, values, err := iter.ToKVArray(s1)
   303  		require.NoError(t, err)
   304  		require.Equal(t, [][]byte{{1}, {2}, {3}, {4}, {5}, {6}, {7}}, keys)
   305  		require.Equal(t, [][]byte{{1}, {2}, {3}, {4}, {5}, {6}, {7}}, values)
   306  
   307  		//idempotency
   308  		require.False(t, s1.HasNext())
   309  		require.False(t, s1.HasNext())
   310  	})
   311  	t.Run("error", func(t *testing.T) {
   312  		i := 0
   313  		testErr := fmt.Errorf("test")
   314  		s1 := iter.PaginateKV(func(pageToken string) (keys, values [][]byte, nextPageToken string, err error) {
   315  			i++
   316  			switch i {
   317  			case 1:
   318  				return [][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}}, "test", nil
   319  			case 2:
   320  				return nil, nil, "test", testErr
   321  			case 3:
   322  				panic("must not happen")
   323  			}
   324  			return
   325  		})
   326  		keys, values, err := iter.ToKVArray(s1)
   327  		require.ErrorIs(t, err, testErr)
   328  		require.Equal(t, [][]byte{{1}, {2}, {3}}, keys)
   329  		require.Equal(t, [][]byte{{1}, {2}, {3}}, values)
   330  
   331  		//idempotency
   332  		require.True(t, s1.HasNext())
   333  		require.True(t, s1.HasNext())
   334  		_, _, err = s1.Next()
   335  		require.ErrorIs(t, err, testErr)
   336  	})
   337  	t.Run("empty", func(t *testing.T) {
   338  		s1 := iter.PaginateKV(func(pageToken string) (keys, values [][]byte, nextPageToken string, err error) {
   339  			return [][]byte{}, [][]byte{}, "", nil
   340  		})
   341  		keys, values, err := iter.ToKVArray(s1)
   342  		require.NoError(t, err)
   343  		require.Nil(t, keys)
   344  		require.Nil(t, values)
   345  
   346  		//idempotency
   347  		require.False(t, s1.HasNext())
   348  		require.False(t, s1.HasNext())
   349  	})
   350  }
   351  
   352  func TestFiler(t *testing.T) {
   353  	createKVIter := func() iter.KV {
   354  		i := 0
   355  		return iter.PaginateKV(func(pageToken string) (keys, values [][]byte, nextPageToken string, err error) {
   356  			i++
   357  			switch i {
   358  			case 1:
   359  				return [][]byte{{1}, {2}, {3}}, [][]byte{{1}, {2}, {3}}, "test", nil
   360  			case 2:
   361  				return nil, nil, "", nil
   362  			}
   363  			return
   364  		})
   365  
   366  	}
   367  	t.Run("dual", func(t *testing.T) {
   368  		s2 := iter.FilterKV(createKVIter(), func(k, v []byte) bool { return bytes.Equal(k, []byte{1}) })
   369  		keys, values, err := iter.ToKVArray(s2)
   370  		require.NoError(t, err)
   371  		require.Equal(t, [][]byte{{1}}, keys)
   372  		require.Equal(t, [][]byte{{1}}, values)
   373  
   374  		s2 = iter.FilterKV(createKVIter(), func(k, v []byte) bool { return bytes.Equal(k, []byte{3}) })
   375  		keys, values, err = iter.ToKVArray(s2)
   376  		require.NoError(t, err)
   377  		require.Equal(t, [][]byte{{3}}, keys)
   378  		require.Equal(t, [][]byte{{3}}, values)
   379  
   380  		s2 = iter.FilterKV(createKVIter(), func(k, v []byte) bool { return bytes.Equal(k, []byte{4}) })
   381  		keys, values, err = iter.ToKVArray(s2)
   382  		require.NoError(t, err)
   383  		require.Nil(t, keys)
   384  		require.Nil(t, values)
   385  
   386  		s2 = iter.FilterKV(iter.EmptyKV, func(k, v []byte) bool { return bytes.Equal(k, []byte{4}) })
   387  		keys, values, err = iter.ToKVArray(s2)
   388  		require.NoError(t, err)
   389  		require.Nil(t, keys)
   390  		require.Nil(t, values)
   391  	})
   392  	t.Run("unary", func(t *testing.T) {
   393  		s1 := iter.Array[uint64]([]uint64{1, 2, 3})
   394  		s2 := iter.FilterU64(s1, func(k uint64) bool { return k == 1 })
   395  		res, err := iter.ToU64Arr(s2)
   396  		require.NoError(t, err)
   397  		require.Equal(t, []uint64{1}, res)
   398  
   399  		s1 = iter.Array[uint64]([]uint64{1, 2, 3})
   400  		s2 = iter.FilterU64(s1, func(k uint64) bool { return k == 3 })
   401  		res, err = iter.ToU64Arr(s2)
   402  		require.NoError(t, err)
   403  		require.Equal(t, []uint64{3}, res)
   404  
   405  		s1 = iter.Array[uint64]([]uint64{1, 2, 3})
   406  		s2 = iter.FilterU64(s1, func(k uint64) bool { return k == 4 })
   407  		res, err = iter.ToU64Arr(s2)
   408  		require.NoError(t, err)
   409  		require.Nil(t, res)
   410  
   411  		s2 = iter.FilterU64(iter.EmptyU64, func(k uint64) bool { return k == 4 })
   412  		res, err = iter.ToU64Arr(s2)
   413  		require.NoError(t, err)
   414  		require.Nil(t, res)
   415  	})
   416  }