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 }