github.com/flower-corp/rosedb@v1.1.2-0.20230117132829-21dc4f7b319a/sets_test.go (about) 1 package rosedb 2 3 import ( 4 "fmt" 5 "github.com/stretchr/testify/assert" 6 "path/filepath" 7 "sort" 8 "testing" 9 ) 10 11 func TestRoseDB_SAdd(t *testing.T) { 12 t.Run("fileio", func(t *testing.T) { 13 testRoseDBSAdd(t, FileIO, KeyValueMemMode) 14 }) 15 t.Run("mmap", func(t *testing.T) { 16 testRoseDBSAdd(t, MMap, KeyOnlyMemMode) 17 }) 18 } 19 20 func testRoseDBSAdd(t *testing.T, ioType IOType, mode DataIndexMode) { 21 path := filepath.Join("/tmp", "rosedb") 22 opts := DefaultOptions(path) 23 opts.IoType = ioType 24 opts.IndexMode = mode 25 db, err := Open(opts) 26 assert.Nil(t, err) 27 defer destroyDB(db) 28 29 type args struct { 30 key []byte 31 members [][]byte 32 } 33 tests := []struct { 34 name string 35 db *RoseDB 36 args args 37 wantErr bool 38 }{ 39 { 40 "normal-1", db, args{key: GetKey(1), members: [][]byte{GetValue16B()}}, false, 41 }, 42 { 43 "normal-2", db, args{key: GetKey(1), members: [][]byte{GetValue16B()}}, false, 44 }, 45 } 46 for _, tt := range tests { 47 if err := tt.db.SAdd(tt.args.key, tt.args.members...); (err != nil) != tt.wantErr { 48 t.Errorf("SAdd() error = %v, wantErr %v", err, tt.wantErr) 49 } 50 } 51 } 52 53 func TestRoseDB_SPop(t *testing.T) { 54 t.Run("fileio", func(t *testing.T) { 55 testRoseDBSPop(t, FileIO, KeyOnlyMemMode) 56 }) 57 t.Run("mmap", func(t *testing.T) { 58 testRoseDBSPop(t, MMap, KeyValueMemMode) 59 }) 60 } 61 62 func testRoseDBSPop(t *testing.T, ioType IOType, mode DataIndexMode) { 63 path := filepath.Join("/tmp", "rosedb") 64 opts := DefaultOptions(path) 65 opts.IoType = ioType 66 opts.IndexMode = mode 67 db, err := Open(opts) 68 assert.Nil(t, err) 69 defer destroyDB(db) 70 71 setKey := []byte("my_set") 72 err = db.SAdd(setKey, GetKey(1), GetKey(2), GetKey(3)) 73 assert.Nil(t, err) 74 75 c1 := db.SCard(setKey) 76 assert.Equal(t, 3, c1) 77 78 p1, err := db.SPop(setKey, 4) 79 assert.Nil(t, err) 80 assert.Equal(t, 3, len(p1)) 81 p2, err := db.SPop(setKey, 1) 82 assert.Nil(t, err) 83 assert.Equal(t, 0, len(p2)) 84 85 c2 := db.SCard(setKey) 86 assert.Equal(t, 0, c2) 87 } 88 89 func TestRoseDB_SRem(t *testing.T) { 90 t.Run("fileio", func(t *testing.T) { 91 testRoseDBSRem(t, FileIO, KeyOnlyMemMode) 92 }) 93 t.Run("mmap", func(t *testing.T) { 94 testRoseDBSRem(t, MMap, KeyValueMemMode) 95 }) 96 } 97 98 func testRoseDBSRem(t *testing.T, ioType IOType, mode DataIndexMode) { 99 path := filepath.Join("/tmp", "rosedb") 100 opts := DefaultOptions(path) 101 opts.IoType = ioType 102 opts.IndexMode = mode 103 db, err := Open(opts) 104 assert.Nil(t, err) 105 defer destroyDB(db) 106 107 setKey := []byte("my_set") 108 err = db.SAdd(setKey, GetKey(1), GetKey(2), GetKey(3)) 109 assert.Nil(t, err) 110 111 err = db.SRem(setKey, GetKey(1)) 112 assert.Nil(t, err) 113 114 ok1 := db.SIsMember(setKey, GetKey(1)) 115 assert.False(t, ok1) 116 117 ok2 := db.SIsMember(setKey, GetKey(2)) 118 assert.True(t, ok2) 119 } 120 121 func TestRoseDB_SIsMember(t *testing.T) { 122 t.Run("fileio", func(t *testing.T) { 123 testRoseDBSIsMember(t, FileIO, KeyOnlyMemMode) 124 }) 125 t.Run("mmap", func(t *testing.T) { 126 testRoseDBSIsMember(t, MMap, KeyValueMemMode) 127 }) 128 } 129 130 func testRoseDBSIsMember(t *testing.T, ioType IOType, mode DataIndexMode) { 131 path := filepath.Join("/tmp", "rosedb") 132 opts := DefaultOptions(path) 133 opts.IoType = ioType 134 opts.IndexMode = mode 135 db, err := Open(opts) 136 assert.Nil(t, err) 137 defer destroyDB(db) 138 139 setKey := []byte("my_set") 140 ok1 := db.SIsMember(setKey, GetKey(1)) 141 assert.False(t, ok1) 142 143 err = db.SAdd(setKey, GetKey(1), GetKey(2), GetKey(3)) 144 assert.Nil(t, err) 145 146 ok2 := db.SIsMember(setKey, GetKey(3)) 147 assert.True(t, ok2) 148 } 149 150 func TestRoseDB_SMembers(t *testing.T) { 151 t.Run("fileio", func(t *testing.T) { 152 testRoseDBSMembers(t, FileIO, KeyOnlyMemMode) 153 }) 154 t.Run("mmap", func(t *testing.T) { 155 testRoseDBSMembers(t, MMap, KeyValueMemMode) 156 }) 157 } 158 159 func testRoseDBSMembers(t *testing.T, ioType IOType, mode DataIndexMode) { 160 path := filepath.Join("/tmp", "rosedb") 161 opts := DefaultOptions(path) 162 opts.IoType = ioType 163 opts.IndexMode = mode 164 db, err := Open(opts) 165 assert.Nil(t, err) 166 defer destroyDB(db) 167 168 setKey := []byte("my_set") 169 mems1, err := db.SMembers(setKey) 170 assert.Nil(t, err) 171 assert.Equal(t, 0, len(mems1)) 172 173 err = db.SAdd(setKey, GetKey(0), GetKey(1), GetKey(2)) 174 assert.Nil(t, err) 175 mems2, err := db.SMembers(setKey) 176 assert.Nil(t, err) 177 assert.Equal(t, 3, len(mems2)) 178 179 err = db.SRem(setKey, GetKey(2)) 180 assert.Nil(t, err) 181 mems3, err := db.SMembers(setKey) 182 assert.Nil(t, err) 183 assert.Equal(t, 2, len(mems3)) 184 } 185 186 func TestRoseDB_SCard(t *testing.T) { 187 path := filepath.Join("/tmp", "rosedb") 188 opts := DefaultOptions(path) 189 db, err := Open(opts) 190 assert.Nil(t, err) 191 defer destroyDB(db) 192 193 setKey := []byte("my_set") 194 c1 := db.SCard(setKey) 195 assert.Equal(t, 0, c1) 196 197 err = db.SAdd(setKey, GetKey(0), GetKey(1), GetKey(2)) 198 assert.Nil(t, err) 199 200 c2 := db.SCard(setKey) 201 assert.Equal(t, 3, c2) 202 203 err = db.Close() 204 assert.Nil(t, err) 205 db2, err := Open(opts) 206 assert.Nil(t, err) 207 defer func() { 208 _ = db2.Close() 209 }() 210 c3 := db2.SCard(setKey) 211 assert.Equal(t, 3, c3) 212 } 213 214 func TestRoseDB_DiscardStat_Sets(t *testing.T) { 215 helper := func(isDelete bool) { 216 path := filepath.Join("/tmp", "rosedb") 217 opts := DefaultOptions(path) 218 opts.LogFileSizeThreshold = 64 << 20 219 db, err := Open(opts) 220 assert.Nil(t, err) 221 defer destroyDB(db) 222 223 setKey := []byte("my_set") 224 writeCount := 500000 225 for i := 0; i < writeCount; i++ { 226 err := db.SAdd(setKey, GetKey(i)) 227 assert.Nil(t, err) 228 } 229 230 if isDelete { 231 for i := 0; i < writeCount/2; i++ { 232 err := db.SRem(setKey, GetKey(i)) 233 assert.Nil(t, err) 234 } 235 } else { 236 for i := 0; i < writeCount/2; i++ { 237 err := db.SAdd(setKey, GetKey(i)) 238 assert.Nil(t, err) 239 } 240 } 241 _ = db.Sync() 242 ccl, err := db.discards[Set].getCCL(10, 0.1) 243 assert.Nil(t, err) 244 assert.Equal(t, 1, len(ccl)) 245 } 246 247 t.Run("rewrite", func(t *testing.T) { 248 helper(false) 249 }) 250 251 t.Run("delete", func(t *testing.T) { 252 helper(true) 253 }) 254 } 255 256 func TestRoseDB_SetGC(t *testing.T) { 257 path := filepath.Join("/tmp", "rosedb") 258 opts := DefaultOptions(path) 259 opts.LogFileSizeThreshold = 64 << 20 260 db, err := Open(opts) 261 assert.Nil(t, err) 262 defer destroyDB(db) 263 264 setKey := []byte("my_set") 265 writeCount := 500000 266 for i := 0; i < writeCount; i++ { 267 err := db.SAdd(setKey, GetValue16B()) 268 assert.Nil(t, err) 269 } 270 271 _, err = db.SPop(setKey, uint(writeCount/2)) 272 assert.Nil(t, err) 273 274 err = db.RunLogFileGC(Set, 0, 0.1) 275 assert.Nil(t, err) 276 277 c1 := db.SCard(setKey) 278 assert.Equal(t, writeCount/2, c1) 279 } 280 281 func TestRoseDB_SDiff(t *testing.T) { 282 path := filepath.Join("/tmp", "rosedb") 283 opts := DefaultOptions(path) 284 db, err := Open(opts) 285 assert.Nil(t, err) 286 defer destroyDB(db) 287 288 _ = db.SAdd([]byte("key-1"), []byte("value-1"), []byte("value-2"), []byte("value-3")) 289 _ = db.SAdd([]byte("key-2"), []byte("value-4"), []byte("value-5"), []byte("value-6"), []byte("value-7")) 290 _ = db.SAdd([]byte("key-3"), []byte("value-2"), []byte("value-5"), []byte("value-8"), []byte("value-9")) 291 _ = db.SAdd([]byte("key-4"), []byte("value-1"), []byte("value-2"), []byte("value-3")) 292 testCases := []struct { 293 name string 294 db *RoseDB 295 keys [][]byte 296 expDiffSet [][]byte 297 expErr error 298 }{ 299 { 300 name: "empty key parameters", 301 db: db, 302 keys: [][]byte{}, 303 expDiffSet: nil, 304 expErr: ErrWrongNumberOfArgs, 305 }, 306 { 307 name: "one key parameter", 308 db: db, 309 keys: [][]byte{[]byte("key-2")}, 310 expDiffSet: [][]byte{[]byte("value-5"), []byte("value-4"), []byte("value-6"), []byte("value-7")}, // todo check 311 expErr: nil, 312 }, 313 { 314 name: "two key parameters", 315 db: db, 316 keys: [][]byte{[]byte("key-1"), []byte("key-3")}, 317 expDiffSet: [][]byte{[]byte("value-3"), []byte("value-1")}, 318 expErr: nil, 319 }, 320 { 321 name: "multiple key parameters", 322 db: db, 323 keys: [][]byte{[]byte("key-1"), []byte("key-2"), []byte("key-3")}, 324 expDiffSet: [][]byte{[]byte("value-3"), []byte("value-1")}, 325 expErr: nil, 326 }, 327 { 328 name: "no diff", 329 db: db, 330 keys: [][]byte{[]byte("key-1"), []byte("key-4")}, 331 expDiffSet: [][]byte{}, 332 expErr: nil, 333 }, 334 } 335 336 for _, tc := range testCases { 337 t.Run(tc.name, func(t *testing.T) { 338 diffSet, err := db.SDiff(tc.keys...) 339 assert.Equal(t, tc.expErr, err) 340 assert.Equal(t, tc.expDiffSet, diffSet) 341 }) 342 } 343 } 344 345 func TestRoseDB_SDiffStore(t *testing.T) { 346 path := filepath.Join("/tmp", "rosedb") 347 opts := DefaultOptions(path) 348 db, err := Open(opts) 349 assert.Nil(t, err) 350 defer destroyDB(db) 351 352 _ = db.SAdd([]byte("key-1"), []byte("value-1"), []byte("value-2"), []byte("value-3")) 353 _ = db.SAdd([]byte("key-2"), []byte("value-4"), []byte("value-5"), []byte("value-6"), []byte("value-7")) 354 _ = db.SAdd([]byte("key-3"), []byte("value-2"), []byte("value-5"), []byte("value-8"), []byte("value-9")) 355 _ = db.SAdd([]byte("key-4"), []byte("value-1"), []byte("value-2"), []byte("value-3")) 356 testCases := []struct { 357 name string 358 db *RoseDB 359 keys [][]byte 360 expDiffSet [][]byte 361 expErr error 362 }{ 363 { 364 name: "two key parameter", 365 db: db, 366 keys: [][]byte{[]byte("destination1"), []byte("key-2")}, 367 expDiffSet: [][]byte{[]byte("value-5"), []byte("value-4"), []byte("value-6"), []byte("value-7")}, // todo check 368 expErr: nil, 369 }, 370 { 371 name: "three key parameters", 372 db: db, 373 keys: [][]byte{[]byte("destination2"), []byte("key-1"), []byte("key-3")}, 374 expDiffSet: [][]byte{[]byte("value-3"), []byte("value-1")}, 375 expErr: nil, 376 }, 377 { 378 name: "four key parameters", 379 db: db, 380 keys: [][]byte{[]byte("destination3"), []byte("key-1"), []byte("key-2"), []byte("key-3")}, 381 expDiffSet: [][]byte{[]byte("value-3"), []byte("value-1")}, 382 expErr: nil, 383 }, 384 { 385 name: "no diff", 386 db: db, 387 keys: [][]byte{[]byte("destination4"), []byte("key-1"), []byte("key-4")}, 388 expDiffSet: nil, 389 expErr: nil, 390 }, 391 } 392 393 for _, tc := range testCases { 394 t.Run(tc.name, func(t *testing.T) { 395 count, err := db.SDiffStore(tc.keys...) 396 assert.Nil(t, err) 397 actual, err := db.sMembers(tc.keys[0]) 398 assert.Equal(t, tc.expErr, err) 399 assert.Equal(t, tc.expDiffSet, actual) 400 assert.Equal(t, len(actual), count) 401 }) 402 } 403 } 404 405 func TestRoseDB_SUnion(t *testing.T) { 406 path := filepath.Join("/tmp", "rosedb") 407 opts := DefaultOptions(path) 408 db, err := Open(opts) 409 assert.Nil(t, err) 410 defer destroyDB(db) 411 412 _ = db.SAdd([]byte("key-1"), []byte("value-1"), []byte("value-2"), []byte("value-3")) 413 _ = db.SAdd([]byte("key-2"), []byte("value-4"), []byte("value-5"), []byte("value-6"), []byte("value-7")) 414 _ = db.SAdd([]byte("key-3"), []byte("value-2"), []byte("value-5"), []byte("value-8"), []byte("value-9")) 415 testCases := []struct { 416 name string 417 db *RoseDB 418 keys [][]byte 419 expUnionSet [][]byte 420 expErr error 421 }{ 422 { 423 name: "empty key parameters", 424 db: db, 425 keys: [][]byte{}, 426 expUnionSet: nil, 427 expErr: ErrWrongNumberOfArgs, 428 }, 429 { 430 name: "one key parameter", 431 db: db, 432 keys: [][]byte{[]byte("key-1")}, 433 expUnionSet: [][]byte{[]byte("value-3"), []byte("value-2"), []byte("value-1")}, 434 expErr: nil, 435 }, 436 { 437 name: "two key parameters", 438 db: db, 439 keys: [][]byte{[]byte("key-1"), []byte("key-2")}, 440 expUnionSet: [][]byte{[]byte("value-3"), []byte("value-2"), []byte("value-1"), 441 []byte("value-5"), []byte("value-4"), []byte("value-6"), []byte("value-7")}, 442 expErr: nil, 443 }, 444 { 445 name: "multiple key parameters", 446 db: db, 447 keys: [][]byte{[]byte("key-1"), []byte("key-2"), []byte("key-3")}, 448 expUnionSet: [][]byte{[]byte("value-3"), []byte("value-2"), []byte("value-1"), 449 []byte("value-5"), []byte("value-4"), []byte("value-6"), []byte("value-7"), 450 []byte("value-8"), []byte("value-9")}, 451 expErr: nil, 452 }, 453 { 454 name: "no union", 455 db: db, 456 keys: [][]byte{[]byte("key-10"), []byte("key-20")}, 457 expUnionSet: [][]byte{}, 458 expErr: nil, 459 }, 460 } 461 462 for _, tc := range testCases { 463 t.Run(tc.name, func(t *testing.T) { 464 unionSet, err := db.SUnion(tc.keys...) 465 assert.Equal(t, tc.expErr, err) 466 assert.Equal(t, tc.expUnionSet, unionSet) 467 }) 468 } 469 } 470 471 func TestRoseDB_SUnionStore(t *testing.T) { 472 path := filepath.Join("/tmp", "rosedb") 473 opts := DefaultOptions(path) 474 db, err := Open(opts) 475 assert.Nil(t, err) 476 defer destroyDB(db) 477 478 _ = db.SAdd([]byte("key-1"), []byte("value-1"), []byte("value-2"), []byte("value-3")) 479 _ = db.SAdd([]byte("key-2"), []byte("value-4"), []byte("value-5"), []byte("value-6"), []byte("value-7")) 480 _ = db.SAdd([]byte("key-3"), []byte("value-2"), []byte("value-5"), []byte("value-8"), []byte("value-9")) 481 _ = db.SAdd([]byte("key-4"), []byte("value-1"), []byte("value-2"), []byte("value-3")) 482 testCases := []struct { 483 name string 484 db *RoseDB 485 keys [][]byte 486 expUnionSet [][]byte 487 expErr error 488 }{ 489 { 490 name: "two key parameter", 491 db: db, 492 keys: [][]byte{[]byte("destination1"), []byte("key-2")}, 493 expUnionSet: [][]byte{[]byte("value-5"), []byte("value-4"), []byte("value-6"), []byte("value-7")}, // todo check 494 expErr: nil, 495 }, 496 { 497 name: "three key parameters", 498 db: db, 499 keys: [][]byte{[]byte("destination2"), []byte("key-1"), []byte("key-3")}, 500 expUnionSet: [][]byte{[]byte("value-3"), []byte("value-1"), []byte("value-2"), []byte("value-5"), []byte("value-8"), []byte("value-9")}, 501 expErr: nil, 502 }, 503 { 504 name: "four key parameters", 505 db: db, 506 keys: [][]byte{[]byte("destination3"), []byte("key-1"), []byte("key-2"), []byte("key-3")}, 507 expUnionSet: [][]byte{[]byte("value-1"), []byte("value-2"), []byte("value-3"), []byte("value-5"), []byte("value-4"), []byte("value-6"), []byte("value-7"), []byte("value-8"), []byte("value-9")}, 508 expErr: nil, 509 }, 510 { 511 name: "no union", 512 db: db, 513 keys: [][]byte{[]byte("destination4"), []byte("key-10"), []byte("key-40")}, 514 expUnionSet: nil, 515 expErr: nil, 516 }, 517 } 518 519 for _, tc := range testCases { 520 t.Run(tc.name, func(t *testing.T) { 521 count, err := db.SUnionStore(tc.keys...) 522 assert.Nil(t, err) 523 524 actual, err := db.sMembers(tc.keys[0]) 525 var expectString []string 526 var actualString []string 527 for exp := range tc.expUnionSet { 528 expectString = append(expectString, fmt.Sprintf("%x", exp)) 529 } 530 for act := range actual { 531 actualString = append(actualString, fmt.Sprintf("%x", act)) 532 } 533 534 sort.Strings(expectString) 535 sort.Strings(actualString) 536 assert.Equal(t, tc.expErr, err) 537 assert.Equal(t, expectString, actualString) 538 assert.Equal(t, len(actual), count) 539 }) 540 } 541 } 542 543 func TestRoseDB_SInter(t *testing.T) { 544 path := filepath.Join("/tmp", "rosedb") 545 opts := DefaultOptions(path) 546 db, err := Open(opts) 547 assert.Nil(t, err) 548 defer destroyDB(db) 549 550 _ = db.SAdd([]byte("key-1"), []byte("value-1"), []byte("value-2"), []byte("value-3")) 551 _ = db.SAdd([]byte("key-2"), []byte("value-1"), []byte("value-2"), []byte("value-3"), []byte("value-4")) 552 _ = db.SAdd([]byte("key-3"), []byte("value-4"), []byte("value-5"), []byte("value-6"), []byte("value-7")) 553 _ = db.SAdd([]byte("key-4"), []byte("value-4"), []byte("value-5")) 554 testCases := []struct { 555 name string 556 db *RoseDB 557 keys [][]byte 558 expInterSet [][]byte 559 expErr error 560 }{ 561 { 562 name: "empty key parameters", 563 db: db, 564 keys: [][]byte{}, 565 expInterSet: nil, 566 expErr: ErrWrongNumberOfArgs, 567 }, 568 { 569 name: "one key parameter", 570 db: db, 571 keys: [][]byte{[]byte("key-1")}, 572 expInterSet: [][]byte{[]byte("value-3"), []byte("value-2"), []byte("value-1")}, 573 expErr: nil, 574 }, 575 { 576 name: "two key parameters key-1 key-2", 577 db: db, 578 keys: [][]byte{[]byte("key-1"), []byte("key-2")}, 579 expInterSet: [][]byte{[]byte("value-3"), []byte("value-2"), []byte("value-1")}, 580 expErr: nil, 581 }, 582 { 583 name: "two key parameters key-1 key-3", 584 db: db, 585 keys: [][]byte{[]byte("key-1"), []byte("key-3")}, 586 expInterSet: [][]byte{}, 587 expErr: nil, 588 }, 589 { 590 name: "multiple key parameters key-1 key-2 key-3", 591 db: db, 592 keys: [][]byte{[]byte("key-1"), []byte("key-2"), []byte("key-3")}, 593 expInterSet: [][]byte{}, 594 expErr: nil, 595 }, 596 { 597 name: "multiple key parameters key-2 key-3 key-4", 598 db: db, 599 keys: [][]byte{[]byte("key-4"), []byte("key-2"), []byte("key-3")}, 600 expInterSet: [][]byte{[]byte("value-4")}, 601 expErr: nil, 602 }, 603 { 604 name: "no Inter", 605 db: db, 606 keys: [][]byte{[]byte("key-10"), []byte("key-20")}, 607 expInterSet: [][]byte{}, 608 expErr: nil, 609 }, 610 } 611 612 for _, tc := range testCases { 613 t.Run(tc.name, func(t *testing.T) { 614 unionSet, err := db.SInter(tc.keys...) 615 assert.Equal(t, tc.expErr, err) 616 assert.Equal(t, tc.expInterSet, unionSet) 617 }) 618 } 619 } 620 621 func TestRoseDB_SInterStore(t *testing.T) { 622 path := filepath.Join("/tmp", "rosedb") 623 opts := DefaultOptions(path) 624 db, err := Open(opts) 625 assert.Nil(t, err) 626 defer destroyDB(db) 627 628 _ = db.SAdd([]byte("key-1"), []byte("value-1"), []byte("value-2"), []byte("value-3")) 629 _ = db.SAdd([]byte("key-2"), []byte("value-4"), []byte("value-5"), []byte("value-6"), []byte("value-7")) 630 _ = db.SAdd([]byte("key-3"), []byte("value-2"), []byte("value-5"), []byte("value-8"), []byte("value-9")) 631 _ = db.SAdd([]byte("key-4"), []byte("value-1"), []byte("value-2"), []byte("value-3")) 632 testCases := []struct { 633 name string 634 db *RoseDB 635 keys [][]byte 636 expInterSet [][]byte 637 expErr error 638 }{ 639 { 640 name: "two key parameter", 641 db: db, 642 keys: [][]byte{[]byte("destination1"), []byte("key-2")}, 643 expInterSet: [][]byte{[]byte("value-5"), []byte("value-4"), []byte("value-6"), []byte("value-7")}, // todo check 644 expErr: nil, 645 }, 646 { 647 name: "three key parameters", 648 db: db, 649 keys: [][]byte{[]byte("destination2"), []byte("key-1"), []byte("key-3")}, 650 expInterSet: [][]byte{[]byte("value-2")}, 651 expErr: nil, 652 }, 653 { 654 name: "four key parameters", 655 db: db, 656 keys: [][]byte{[]byte("destination3"), []byte("key-1"), []byte("key-3"), []byte("key-4")}, 657 expInterSet: [][]byte{[]byte("value-2")}, 658 expErr: nil, 659 }, 660 { 661 name: "no inter", 662 db: db, 663 keys: [][]byte{[]byte("destination4"), []byte("key-1"), []byte("key-2")}, 664 expInterSet: nil, 665 expErr: nil, 666 }, 667 } 668 669 for _, tc := range testCases { 670 t.Run(tc.name, func(t *testing.T) { 671 count, err := db.SInterStore(tc.keys...) 672 assert.Nil(t, err) 673 674 actual, err := db.sMembers(tc.keys[0]) 675 var expectString []string 676 var actualString []string 677 for exp := range tc.expInterSet { 678 expectString = append(expectString, fmt.Sprintf("%x", exp)) 679 } 680 for act := range actual { 681 actualString = append(actualString, fmt.Sprintf("%x", act)) 682 } 683 684 sort.Strings(expectString) 685 sort.Strings(actualString) 686 assert.Equal(t, tc.expErr, err) 687 assert.Equal(t, expectString, actualString) 688 assert.Equal(t, len(actual), count) 689 }) 690 } 691 }