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 }