github.com/rosedblabs/rosedb/v2@v2.3.7-0.20240423093736-a89ea823e5b9/db_test.go (about) 1 package rosedb 2 3 import ( 4 "errors" 5 "io" 6 "math/rand" 7 "os" 8 "sync" 9 "testing" 10 "time" 11 12 "github.com/rosedblabs/rosedb/v2/utils" 13 "github.com/stretchr/testify/assert" 14 ) 15 16 func TestDB_Put_Normal(t *testing.T) { 17 options := DefaultOptions 18 db, err := Open(options) 19 assert.Nil(t, err) 20 defer destroyDB(db) 21 22 for i := 0; i < 100; i++ { 23 err := db.Put(utils.GetTestKey(rand.Int()), utils.RandomValue(128)) 24 assert.Nil(t, err) 25 err = db.Put(utils.GetTestKey(rand.Int()), utils.RandomValue(KB)) 26 assert.Nil(t, err) 27 err = db.Put(utils.GetTestKey(rand.Int()), utils.RandomValue(5*KB)) 28 assert.Nil(t, err) 29 } 30 31 // reopen 32 err = db.Close() 33 assert.Nil(t, err) 34 db2, err := Open(options) 35 assert.Nil(t, err) 36 defer func() { 37 _ = db2.Close() 38 }() 39 stat := db2.Stat() 40 assert.Equal(t, 300, stat.KeysNum) 41 } 42 43 func TestDB_Get_Normal(t *testing.T) { 44 options := DefaultOptions 45 db, err := Open(options) 46 assert.Nil(t, err) 47 defer destroyDB(db) 48 49 // not exist 50 val1, err := db.Get([]byte("not-exist")) 51 assert.Nil(t, val1) 52 assert.Equal(t, ErrKeyNotFound, err) 53 54 generateData(t, db, 1, 100, 128) 55 for i := 1; i < 100; i++ { 56 val, err := db.Get(utils.GetTestKey(i)) 57 assert.Nil(t, err) 58 assert.Equal(t, len(val), len(utils.RandomValue(128))) 59 } 60 generateData(t, db, 200, 300, KB) 61 for i := 200; i < 300; i++ { 62 val, err := db.Get(utils.GetTestKey(i)) 63 assert.Nil(t, err) 64 assert.Equal(t, len(val), len(utils.RandomValue(KB))) 65 } 66 generateData(t, db, 400, 500, 4*KB) 67 for i := 400; i < 500; i++ { 68 val, err := db.Get(utils.GetTestKey(i)) 69 assert.Nil(t, err) 70 assert.Equal(t, len(val), len(utils.RandomValue(4*KB))) 71 } 72 } 73 74 func TestDB_Close_Sync(t *testing.T) { 75 options := DefaultOptions 76 db, err := Open(options) 77 assert.Nil(t, err) 78 defer destroyDB(db) 79 80 err = db.Sync() 81 assert.Nil(t, err) 82 } 83 84 func TestDB_Concurrent_Put(t *testing.T) { 85 options := DefaultOptions 86 db, err := Open(options) 87 assert.Nil(t, err) 88 defer destroyDB(db) 89 90 wg := sync.WaitGroup{} 91 m := sync.Map{} 92 wg.Add(10) 93 for i := 0; i < 10; i++ { 94 go func() { 95 defer wg.Done() 96 for i := 0; i < 10000; i++ { 97 key := utils.GetTestKey(rand.Int()) 98 m.Store(string(key), struct{}{}) 99 e := db.Put(key, utils.RandomValue(128)) 100 assert.Nil(t, e) 101 } 102 }() 103 } 104 wg.Wait() 105 106 var count int 107 m.Range(func(key, value any) bool { 108 count++ 109 return true 110 }) 111 assert.Equal(t, count, db.index.Size()) 112 } 113 114 func TestDB_Ascend(t *testing.T) { 115 // Create a test database instance 116 options := DefaultOptions 117 db, err := Open(options) 118 assert.Nil(t, err) 119 defer destroyDB(db) 120 121 // Insert some test data 122 data := []struct { 123 key []byte 124 value []byte 125 }{ 126 {[]byte("key1"), []byte("value1")}, 127 {[]byte("key2"), []byte("value2")}, 128 {[]byte("key3"), []byte("value3")}, 129 } 130 131 for _, d := range data { 132 if err := db.Put(d.key, d.value); err != nil { 133 t.Fatalf("Failed to put data: %v", err) 134 } 135 } 136 137 // Test Ascend function 138 var result []string 139 db.Ascend(func(k []byte, v []byte) (bool, error) { 140 result = append(result, string(k)) 141 return true, nil // No error here 142 }) 143 144 if err != nil { 145 t.Errorf("Ascend returned an error: %v", err) 146 } 147 148 expected := []string{"key1", "key2", "key3"} 149 if len(result) != len(expected) { 150 t.Errorf("Unexpected number of results. Expected: %v, Got: %v", expected, result) 151 } else { 152 for i, val := range expected { 153 if result[i] != val { 154 t.Errorf("Unexpected result at index %d. Expected: %v, Got: %v", i, val, result[i]) 155 } 156 } 157 } 158 } 159 160 func TestDB_Descend(t *testing.T) { 161 // Create a test database instance 162 options := DefaultOptions 163 db, err := Open(options) 164 assert.Nil(t, err) 165 defer destroyDB(db) 166 167 // Insert some test data 168 data := []struct { 169 key []byte 170 value []byte 171 }{ 172 {[]byte("key1"), []byte("value1")}, 173 {[]byte("key2"), []byte("value2")}, 174 {[]byte("key3"), []byte("value3")}, 175 } 176 177 for _, d := range data { 178 if err := db.Put(d.key, d.value); err != nil { 179 t.Fatalf("Failed to put data: %v", err) 180 } 181 } 182 183 // Test Descend function 184 var result []string 185 db.Descend(func(k []byte, v []byte) (bool, error) { 186 result = append(result, string(k)) 187 return true, nil 188 }) 189 190 if err != nil { 191 t.Errorf("Descend returned an error: %v", err) 192 } 193 194 expected := []string{"key3", "key2", "key1"} 195 if len(result) != len(expected) { 196 t.Errorf("Unexpected number of results. Expected: %v, Got: %v", expected, result) 197 } else { 198 for i, val := range expected { 199 if result[i] != val { 200 t.Errorf("Unexpected result at index %d. Expected: %v, Got: %v", i, val, result[i]) 201 } 202 } 203 } 204 } 205 206 func TestDB_AscendRange(t *testing.T) { 207 // Create a test database instance 208 options := DefaultOptions 209 db, err := Open(options) 210 assert.Nil(t, err) 211 defer destroyDB(db) 212 213 // Insert some test data 214 data := []struct { 215 key []byte 216 value []byte 217 }{ 218 {[]byte("apple"), []byte("value1")}, 219 {[]byte("banana"), []byte("value2")}, 220 {[]byte("cherry"), []byte("value3")}, 221 {[]byte("date"), []byte("value4")}, 222 {[]byte("grape"), []byte("value5")}, 223 {[]byte("kiwi"), []byte("value6")}, 224 } 225 226 for _, d := range data { 227 if err := db.Put(d.key, d.value); err != nil { 228 t.Fatalf("Failed to put data: %v", err) 229 } 230 } 231 232 // Test AscendRange 233 var resultAscendRange []string 234 db.AscendRange([]byte("banana"), []byte("grape"), func(k []byte, v []byte) (bool, error) { 235 resultAscendRange = append(resultAscendRange, string(k)) 236 return true, nil 237 }) 238 assert.Equal(t, []string{"banana", "cherry", "date"}, resultAscendRange) 239 } 240 241 func TestDB_DescendRange(t *testing.T) { 242 // Create a test database instance 243 options := DefaultOptions 244 db, err := Open(options) 245 assert.Nil(t, err) 246 defer destroyDB(db) 247 248 // Insert some test data 249 data := []struct { 250 key []byte 251 value []byte 252 }{ 253 {[]byte("apple"), []byte("value1")}, 254 {[]byte("banana"), []byte("value2")}, 255 {[]byte("cherry"), []byte("value3")}, 256 {[]byte("date"), []byte("value4")}, 257 {[]byte("grape"), []byte("value5")}, 258 {[]byte("kiwi"), []byte("value6")}, 259 } 260 261 for _, d := range data { 262 if err := db.Put(d.key, d.value); err != nil { 263 t.Fatalf("Failed to put data: %v", err) 264 } 265 } 266 267 // Test DescendRange 268 var resultDescendRange []string 269 db.DescendRange([]byte("grape"), []byte("cherry"), func(k []byte, v []byte) (bool, error) { 270 resultDescendRange = append(resultDescendRange, string(k)) 271 return true, nil 272 }) 273 assert.Equal(t, []string{"grape", "date"}, resultDescendRange) 274 } 275 276 func TestDB_AscendGreaterOrEqual(t *testing.T) { 277 // Create a test database instance 278 options := DefaultOptions 279 db, err := Open(options) 280 assert.Nil(t, err) 281 defer destroyDB(db) 282 283 // Insert some test data 284 data := []struct { 285 key []byte 286 value []byte 287 }{ 288 {[]byte("apple"), []byte("value1")}, 289 {[]byte("banana"), []byte("value2")}, 290 {[]byte("cherry"), []byte("value3")}, 291 {[]byte("date"), []byte("value4")}, 292 {[]byte("grape"), []byte("value5")}, 293 {[]byte("kiwi"), []byte("value6")}, 294 } 295 296 for _, d := range data { 297 if err := db.Put(d.key, d.value); err != nil { 298 t.Fatalf("Failed to put data: %v", err) 299 } 300 } 301 302 // Test AscendGreaterOrEqual 303 var resultAscendGreaterOrEqual []string 304 db.AscendGreaterOrEqual([]byte("date"), func(k []byte, v []byte) (bool, error) { 305 resultAscendGreaterOrEqual = append(resultAscendGreaterOrEqual, string(k)) 306 return true, nil 307 }) 308 assert.Equal(t, []string{"date", "grape", "kiwi"}, resultAscendGreaterOrEqual) 309 } 310 311 func TestDB_DescendLessOrEqual(t *testing.T) { 312 // Create a test database instance 313 options := DefaultOptions 314 db, err := Open(options) 315 assert.Nil(t, err) 316 defer destroyDB(db) 317 318 // Insert some test data 319 data := []struct { 320 key []byte 321 value []byte 322 }{ 323 {[]byte("apple"), []byte("value1")}, 324 {[]byte("banana"), []byte("value2")}, 325 {[]byte("cherry"), []byte("value3")}, 326 {[]byte("date"), []byte("value4")}, 327 {[]byte("grape"), []byte("value5")}, 328 {[]byte("kiwi"), []byte("value6")}, 329 } 330 331 for _, d := range data { 332 if err := db.Put(d.key, d.value); err != nil { 333 t.Fatalf("Failed to put data: %v", err) 334 } 335 } 336 337 // Test DescendLessOrEqual 338 var resultDescendLessOrEqual []string 339 db.DescendLessOrEqual([]byte("grape"), func(k []byte, v []byte) (bool, error) { 340 resultDescendLessOrEqual = append(resultDescendLessOrEqual, string(k)) 341 return true, nil 342 }) 343 assert.Equal(t, []string{"grape", "date", "cherry", "banana", "apple"}, resultDescendLessOrEqual) 344 } 345 346 func TestDB_AscendKeys(t *testing.T) { 347 options := DefaultOptions 348 db, err := Open(options) 349 assert.Nil(t, err) 350 defer destroyDB(db) 351 352 err = db.Put([]byte("aacd"), utils.RandomValue(10)) 353 assert.Nil(t, err) 354 355 validate := func(target [][]byte, pattern []byte) { 356 var keys [][]byte 357 db.AscendKeys(pattern, false, func(k []byte) (bool, error) { 358 keys = append(keys, k) 359 return true, nil 360 }) 361 assert.Equal(t, keys, target) 362 } 363 364 validate([][]byte{[]byte("aacd")}, nil) 365 366 err = db.Put([]byte("bbde"), utils.RandomValue(10)) 367 assert.Nil(t, err) 368 err = db.Put([]byte("cdea"), utils.RandomValue(10)) 369 assert.Nil(t, err) 370 err = db.Put([]byte("bcae"), utils.RandomValue(10)) 371 assert.Nil(t, err) 372 373 validate([][]byte{[]byte("aacd"), []byte("bbde"), []byte("bcae"), []byte("cdea")}, nil) 374 } 375 376 func TestDB_AscendKeysExpired(t *testing.T) { 377 options := DefaultOptions 378 db, err := Open(options) 379 assert.Nil(t, err) 380 defer destroyDB(db) 381 382 validate := func(target [][]byte, pattern []byte) { 383 var keys [][]byte 384 db.AscendKeys(pattern, true, func(k []byte) (bool, error) { 385 keys = append(keys, k) 386 return true, nil 387 }) 388 assert.Equal(t, keys, target) 389 } 390 391 err = db.PutWithTTL([]byte("bbde"), utils.RandomValue(10), time.Millisecond*500) 392 assert.Nil(t, err) 393 err = db.Put([]byte("cdea"), utils.RandomValue(10)) 394 assert.Nil(t, err) 395 err = db.Put([]byte("bcae"), utils.RandomValue(10)) 396 assert.Nil(t, err) 397 time.Sleep(time.Millisecond * 600) 398 399 validate([][]byte{[]byte("bcae"), []byte("cdea")}, nil) 400 } 401 402 func TestDB_DescendKeys(t *testing.T) { 403 options := DefaultOptions 404 db, err := Open(options) 405 assert.Nil(t, err) 406 defer destroyDB(db) 407 408 err = db.Put([]byte("aacd"), utils.RandomValue(10)) 409 assert.Nil(t, err) 410 411 validate := func(target [][]byte, pattern []byte) { 412 var keys [][]byte 413 db.DescendKeys(pattern, false, func(k []byte) (bool, error) { 414 keys = append(keys, k) 415 return true, nil 416 }) 417 assert.Equal(t, keys, target) 418 } 419 420 validate([][]byte{[]byte("aacd")}, nil) 421 422 err = db.Put([]byte("bbde"), utils.RandomValue(10)) 423 assert.Nil(t, err) 424 err = db.Put([]byte("cdea"), utils.RandomValue(10)) 425 assert.Nil(t, err) 426 err = db.Put([]byte("bcae"), utils.RandomValue(10)) 427 assert.Nil(t, err) 428 429 validate([][]byte{[]byte("cdea"), []byte("bcae"), []byte("bbde"), []byte("aacd")}, nil) 430 } 431 432 func TestDB_DescendKeysExpired(t *testing.T) { 433 options := DefaultOptions 434 db, err := Open(options) 435 assert.Nil(t, err) 436 defer destroyDB(db) 437 438 validate := func(target [][]byte, pattern []byte) { 439 var keys [][]byte 440 db.DescendKeys(pattern, true, func(k []byte) (bool, error) { 441 keys = append(keys, k) 442 return true, nil 443 }) 444 assert.Equal(t, keys, target) 445 } 446 447 err = db.Put([]byte("bbde"), utils.RandomValue(10)) 448 assert.Nil(t, err) 449 err = db.PutWithTTL([]byte("cdea"), utils.RandomValue(10), time.Millisecond*500) 450 assert.Nil(t, err) 451 err = db.PutWithTTL([]byte("bcae"), utils.RandomValue(10), time.Millisecond*500) 452 assert.Nil(t, err) 453 454 time.Sleep(time.Millisecond * 600) 455 456 validate([][]byte{[]byte("bbde")}, nil) 457 } 458 459 func TestDB_PutWithTTL(t *testing.T) { 460 options := DefaultOptions 461 db, err := Open(options) 462 assert.Nil(t, err) 463 defer destroyDB(db) 464 465 err = db.PutWithTTL(utils.GetTestKey(1), utils.RandomValue(128), time.Millisecond*100) 466 assert.Nil(t, err) 467 val1, err := db.Get(utils.GetTestKey(1)) 468 assert.Nil(t, err) 469 assert.NotNil(t, val1) 470 time.Sleep(time.Millisecond * 200) 471 val2, err := db.Get(utils.GetTestKey(1)) 472 assert.Equal(t, err, ErrKeyNotFound) 473 assert.Nil(t, val2) 474 475 err = db.PutWithTTL(utils.GetTestKey(2), utils.RandomValue(128), time.Millisecond*200) 476 assert.Nil(t, err) 477 // rewrite 478 err = db.Put(utils.GetTestKey(2), utils.RandomValue(128)) 479 assert.Nil(t, err) 480 time.Sleep(time.Millisecond * 200) 481 val3, err := db.Get(utils.GetTestKey(2)) 482 assert.Nil(t, err) 483 assert.NotNil(t, val3) 484 485 err = db.Close() 486 assert.Nil(t, err) 487 488 db2, err := Open(options) 489 assert.Nil(t, err) 490 491 val4, err := db2.Get(utils.GetTestKey(1)) 492 assert.Equal(t, err, ErrKeyNotFound) 493 assert.Nil(t, val4) 494 495 val5, err := db2.Get(utils.GetTestKey(2)) 496 assert.Nil(t, err) 497 assert.NotNil(t, val5) 498 499 _ = db2.Close() 500 } 501 502 func TestDB_RePutWithTTL(t *testing.T) { 503 options := DefaultOptions 504 db, err := Open(options) 505 assert.Nil(t, err) 506 defer destroyDB(db) 507 508 err = db.Put(utils.GetTestKey(10), utils.RandomValue(10)) 509 assert.Nil(t, err) 510 err = db.PutWithTTL(utils.GetTestKey(10), utils.RandomValue(10), time.Millisecond*100) 511 assert.Nil(t, err) 512 time.Sleep(time.Second * 1) // wait for expired 513 514 val1, err := db.Get(utils.GetTestKey(10)) 515 assert.Equal(t, err, ErrKeyNotFound) 516 assert.Nil(t, val1) 517 518 err = db.Merge(true) 519 assert.Nil(t, err) 520 521 val2, err := db.Get(utils.GetTestKey(10)) 522 assert.Equal(t, err, ErrKeyNotFound) 523 assert.Nil(t, val2) 524 } 525 526 func TestDB_PutWithTTL_Merge(t *testing.T) { 527 options := DefaultOptions 528 db, err := Open(options) 529 assert.Nil(t, err) 530 defer destroyDB(db) 531 for i := 0; i < 100; i++ { 532 err = db.PutWithTTL(utils.GetTestKey(i), utils.RandomValue(10), time.Second*2) 533 assert.Nil(t, err) 534 } 535 for i := 100; i < 150; i++ { 536 err = db.PutWithTTL(utils.GetTestKey(i), utils.RandomValue(10), time.Second*20) 537 assert.Nil(t, err) 538 } 539 time.Sleep(time.Second * 3) 540 541 err = db.Merge(true) 542 assert.Nil(t, err) 543 544 for i := 0; i < 100; i++ { 545 val, err := db.Get(utils.GetTestKey(i)) 546 assert.Nil(t, val) 547 assert.Equal(t, err, ErrKeyNotFound) 548 } 549 for i := 100; i < 150; i++ { 550 val, err := db.Get(utils.GetTestKey(i)) 551 assert.Nil(t, err) 552 assert.NotNil(t, val) 553 } 554 } 555 556 func TestDB_Expire(t *testing.T) { 557 options := DefaultOptions 558 db, err := Open(options) 559 assert.Nil(t, err) 560 defer destroyDB(db) 561 562 err = db.Put(utils.GetTestKey(1), utils.RandomValue(10)) 563 assert.Nil(t, err) 564 565 err = db.Expire(utils.GetTestKey(1), time.Second*100) 566 assert.Nil(t, err) 567 tt1, err := db.TTL(utils.GetTestKey(1)) 568 assert.Nil(t, err) 569 assert.True(t, tt1.Seconds() > 90) 570 571 err = db.PutWithTTL(utils.GetTestKey(2), utils.RandomValue(10), time.Second*1) 572 assert.Nil(t, err) 573 574 tt2, err := db.TTL(utils.GetTestKey(2)) 575 assert.Nil(t, err) 576 assert.True(t, tt2.Microseconds() > 500) 577 578 err = db.Close() 579 assert.Nil(t, err) 580 581 db2, err := Open(options) 582 assert.Nil(t, err) 583 defer func() { 584 _ = db2.Close() 585 }() 586 587 tt3, err := db2.TTL(utils.GetTestKey(1)) 588 assert.Nil(t, err) 589 assert.True(t, tt3.Seconds() > 90) 590 591 time.Sleep(time.Second) 592 tt4, err := db2.TTL(utils.GetTestKey(2)) 593 assert.Equal(t, tt4, time.Duration(-1)) 594 assert.Equal(t, err, ErrKeyNotFound) 595 } 596 597 func TestDB_Expire2(t *testing.T) { 598 options := DefaultOptions 599 db, err := Open(options) 600 assert.Nil(t, err) 601 defer destroyDB(db) 602 603 // expire an expired key 604 _ = db.PutWithTTL(utils.GetTestKey(1), utils.RandomValue(10), time.Second*1) 605 _ = db.Put(utils.GetTestKey(2), utils.RandomValue(10)) 606 err = db.Expire(utils.GetTestKey(2), time.Second*2) 607 assert.Nil(t, err) 608 609 time.Sleep(time.Second * 2) 610 _ = db.Close() 611 612 db2, err := Open(options) 613 assert.Nil(t, err) 614 defer func() { 615 _ = db2.Close() 616 }() 617 err = db2.Expire(utils.GetTestKey(1), time.Second) 618 assert.Equal(t, err, ErrKeyNotFound) 619 err = db2.Expire(utils.GetTestKey(2), time.Second) 620 assert.Equal(t, err, ErrKeyNotFound) 621 } 622 623 func TestDB_DeleteExpiredKeys(t *testing.T) { 624 options := DefaultOptions 625 db, err := Open(options) 626 assert.Nil(t, err) 627 defer destroyDB(db) 628 629 for i := 0; i < 100001; i++ { 630 err = db.PutWithTTL(utils.GetTestKey(i), utils.RandomValue(10), time.Second*1) 631 assert.Nil(t, err) 632 } 633 634 // wait for key to expire 635 time.Sleep(time.Second * 2) 636 637 err = db.DeleteExpiredKeys(time.Second * 2) 638 assert.Nil(t, err) 639 assert.Equal(t, 0, db.Stat().KeysNum) 640 641 } 642 643 func TestDB_Multi_DeleteExpiredKeys(t *testing.T) { 644 options := DefaultOptions 645 db, err := Open(options) 646 assert.Nil(t, err) 647 defer destroyDB(db) 648 649 for i := 0; i < 3; i++ { 650 for i := 0; i < 10000; i++ { 651 err = db.Put(utils.GetTestKey(i), utils.RandomValue(10)) 652 assert.Nil(t, err) 653 } 654 for i := 10000; i < 100001; i++ { 655 err = db.PutWithTTL(utils.GetTestKey(i), utils.RandomValue(10), time.Second*1) 656 assert.Nil(t, err) 657 } 658 659 // wait for key to expire 660 time.Sleep(time.Second * 2) 661 662 err = db.DeleteExpiredKeys(time.Second * 2) 663 assert.Nil(t, err) 664 assert.Equal(t, 10000, db.Stat().KeysNum) 665 } 666 } 667 668 func TestDB_Persist(t *testing.T) { 669 options := DefaultOptions 670 db, err := Open(options) 671 assert.Nil(t, err) 672 defer destroyDB(db) 673 674 // not exist 675 err = db.Persist(utils.GetTestKey(1)) 676 assert.Equal(t, err, ErrKeyNotFound) 677 678 err = db.PutWithTTL(utils.GetTestKey(1), utils.RandomValue(10), time.Second*1) 679 assert.Nil(t, err) 680 681 // exist 682 err = db.Persist(utils.GetTestKey(1)) 683 assert.Nil(t, err) 684 time.Sleep(time.Second * 2) 685 // check ttl 686 ttl, err := db.TTL(utils.GetTestKey(1)) 687 assert.Nil(t, err) 688 assert.Equal(t, ttl, time.Duration(-1)) 689 val1, err := db.Get(utils.GetTestKey(1)) 690 assert.Nil(t, err) 691 assert.NotNil(t, val1) 692 693 // restart 694 err = db.Close() 695 assert.Nil(t, err) 696 697 db2, err := Open(options) 698 assert.Nil(t, err) 699 defer func() { 700 _ = db2.Close() 701 }() 702 703 ttl2, err := db2.TTL(utils.GetTestKey(1)) 704 assert.Nil(t, err) 705 assert.Equal(t, ttl2, time.Duration(-1)) 706 val2, err := db2.Get(utils.GetTestKey(1)) 707 assert.Nil(t, err) 708 assert.NotNil(t, val2) 709 } 710 711 func TestDB_Invalid_Cron_Expression(t *testing.T) { 712 options := DefaultOptions 713 options.AutoMergeCronExpr = "*/1 * * * * * *" 714 _, err := Open(options) 715 assert.NotNil(t, err) 716 } 717 718 func TestDB_Valid_Cron_Expression(t *testing.T) { 719 options := DefaultOptions 720 { 721 options.AutoMergeCronExpr = "* */1 * * * *" 722 db, err := Open(options) 723 assert.Nil(t, err) 724 destroyDB(db) 725 } 726 727 { 728 options.AutoMergeCronExpr = "*/1 * * * *" 729 db, err := Open(options) 730 assert.Nil(t, err) 731 destroyDB(db) 732 } 733 734 { 735 options.AutoMergeCronExpr = "5 0 * 8 *" 736 db, err := Open(options) 737 assert.Nil(t, err) 738 destroyDB(db) 739 } 740 741 { 742 options.AutoMergeCronExpr = "*/2 14 1 * *" 743 db, err := Open(options) 744 assert.Nil(t, err) 745 destroyDB(db) 746 } 747 748 { 749 options.AutoMergeCronExpr = "@hourly" 750 db, err := Open(options) 751 assert.Nil(t, err) 752 destroyDB(db) 753 } 754 } 755 756 func TestDB_Auto_Merge(t *testing.T) { 757 options := DefaultOptions 758 db, err := Open(options) 759 assert.Nil(t, err) 760 defer destroyDB(db) 761 762 for i := 0; i < 2000; i++ { 763 delKey := utils.GetTestKey(rand.Int()) 764 err := db.Put(delKey, utils.RandomValue(128)) 765 assert.Nil(t, err) 766 err = db.Put(utils.GetTestKey(rand.Int()), utils.RandomValue(2*KB)) 767 assert.Nil(t, err) 768 err = db.Delete(delKey) 769 assert.Nil(t, err) 770 } 771 772 { 773 reader := db.dataFiles.NewReader() 774 var keyCnt int 775 for { 776 if _, _, err := reader.Next(); errors.Is(err, io.EOF) { 777 break 778 } 779 keyCnt++ 780 } 781 // each record has one data wal and commit at end of batch with wal 782 // so totally is 2000 * 3 * 2 = 12000 783 assert.Equal(t, 12000, keyCnt) 784 } 785 786 mergeDirPath := mergeDirPath(options.DirPath) 787 if _, err := os.Stat(mergeDirPath); err != nil { 788 assert.True(t, os.IsNotExist(err)) 789 } 790 assert.NoError(t, db.Close()) 791 792 { 793 options.AutoMergeCronExpr = "* * * * * *" // every second 794 db, err := Open(options) 795 assert.Nil(t, err) 796 { 797 <-time.After(time.Second * 2) 798 reader := db.dataFiles.NewReader() 799 var keyCnt int 800 for { 801 if _, _, err := reader.Next(); errors.Is(err, io.EOF) { 802 break 803 } 804 keyCnt++ 805 } 806 // after merge records are only valid data, so totally is 2000 807 assert.Equal(t, 2000, keyCnt) 808 } 809 destroyDB(db) 810 } 811 }