1package miniredis 2 3import ( 4 "sort" 5 "testing" 6 7 "github.com/gomodule/redigo/redis" 8) 9 10// Test SADD / SMEMBERS. 11func TestSadd(t *testing.T) { 12 s, err := Run() 13 ok(t, err) 14 defer s.Close() 15 c, err := redis.Dial("tcp", s.Addr()) 16 ok(t, err) 17 18 { 19 b, err := redis.Int(c.Do("SADD", "s", "aap", "noot", "mies")) 20 ok(t, err) 21 equals(t, 3, b) // New elements. 22 23 members, err := s.Members("s") 24 ok(t, err) 25 equals(t, []string{"aap", "mies", "noot"}, members) 26 27 m, err := redis.Strings(c.Do("SMEMBERS", "s")) 28 ok(t, err) 29 equals(t, []string{"aap", "mies", "noot"}, m) 30 } 31 32 { 33 b, err := redis.String(c.Do("TYPE", "s")) 34 ok(t, err) 35 equals(t, "set", b) 36 } 37 38 // SMEMBERS on an nonexisting key 39 { 40 m, err := redis.Strings(c.Do("SMEMBERS", "nosuch")) 41 ok(t, err) 42 equals(t, []string{}, m) 43 } 44 45 { 46 b, err := redis.Int(c.Do("SADD", "s", "new", "noot", "mies")) 47 ok(t, err) 48 equals(t, 1, b) // Only one new field. 49 50 members, err := s.Members("s") 51 ok(t, err) 52 equals(t, []string{"aap", "mies", "new", "noot"}, members) 53 } 54 55 // Direct usage 56 { 57 added, err := s.SetAdd("s1", "aap") 58 ok(t, err) 59 equals(t, 1, added) 60 61 members, err := s.Members("s1") 62 ok(t, err) 63 equals(t, []string{"aap"}, members) 64 } 65 66 // Wrong type of key 67 { 68 _, err := redis.String(c.Do("SET", "str", "value")) 69 ok(t, err) 70 _, err = redis.Int(c.Do("SADD", "str", "hi")) 71 assert(t, err != nil, "SADD error") 72 _, err = redis.Int(c.Do("SMEMBERS", "str")) 73 assert(t, err != nil, "MEMBERS error") 74 // Wrong argument counts 75 _, err = redis.String(c.Do("SADD")) 76 assert(t, err != nil, "SADD error") 77 _, err = redis.String(c.Do("SADD", "set")) 78 assert(t, err != nil, "SADD error") 79 _, err = redis.String(c.Do("SMEMBERS")) 80 assert(t, err != nil, "SMEMBERS error") 81 _, err = redis.String(c.Do("SMEMBERS", "set", "spurious")) 82 assert(t, err != nil, "SMEMBERS error") 83 } 84 85} 86 87// Test SISMEMBER 88func TestSismember(t *testing.T) { 89 s, err := Run() 90 ok(t, err) 91 defer s.Close() 92 c, err := redis.Dial("tcp", s.Addr()) 93 ok(t, err) 94 95 s.SetAdd("s", "aap", "noot", "mies") 96 97 { 98 b, err := redis.Int(c.Do("SISMEMBER", "s", "aap")) 99 ok(t, err) 100 equals(t, 1, b) 101 102 b, err = redis.Int(c.Do("SISMEMBER", "s", "nosuch")) 103 ok(t, err) 104 equals(t, 0, b) 105 } 106 107 // a nonexisting key 108 { 109 b, err := redis.Int(c.Do("SISMEMBER", "nosuch", "nosuch")) 110 ok(t, err) 111 equals(t, 0, b) 112 } 113 114 // Direct usage 115 { 116 isMember, err := s.IsMember("s", "noot") 117 ok(t, err) 118 equals(t, true, isMember) 119 } 120 121 // Wrong type of key 122 { 123 _, err := redis.String(c.Do("SET", "str", "value")) 124 ok(t, err) 125 _, err = redis.Int(c.Do("SISMEMBER", "str")) 126 assert(t, err != nil, "SISMEMBER error") 127 // Wrong argument counts 128 _, err = redis.String(c.Do("SISMEMBER")) 129 assert(t, err != nil, "SISMEMBER error") 130 _, err = redis.String(c.Do("SISMEMBER", "set")) 131 assert(t, err != nil, "SISMEMBER error") 132 _, err = redis.String(c.Do("SISMEMBER", "set", "spurious", "args")) 133 assert(t, err != nil, "SISMEMBER error") 134 } 135 136} 137 138// Test SREM 139func TestSrem(t *testing.T) { 140 s, err := Run() 141 ok(t, err) 142 defer s.Close() 143 c, err := redis.Dial("tcp", s.Addr()) 144 ok(t, err) 145 146 s.SetAdd("s", "aap", "noot", "mies", "vuur") 147 148 { 149 b, err := redis.Int(c.Do("SREM", "s", "aap", "noot")) 150 ok(t, err) 151 equals(t, 2, b) 152 153 members, err := s.Members("s") 154 ok(t, err) 155 equals(t, []string{"mies", "vuur"}, members) 156 } 157 158 // a nonexisting field 159 { 160 b, err := redis.Int(c.Do("SREM", "s", "nosuch")) 161 ok(t, err) 162 equals(t, 0, b) 163 } 164 165 // a nonexisting key 166 { 167 b, err := redis.Int(c.Do("SREM", "nosuch", "nosuch")) 168 ok(t, err) 169 equals(t, 0, b) 170 } 171 172 // Direct usage 173 { 174 b, err := s.SRem("s", "mies") 175 ok(t, err) 176 equals(t, 1, b) 177 178 members, err := s.Members("s") 179 ok(t, err) 180 equals(t, []string{"vuur"}, members) 181 } 182 183 // Wrong type of key 184 { 185 _, err := redis.String(c.Do("SET", "str", "value")) 186 ok(t, err) 187 _, err = redis.Int(c.Do("SREM", "str", "value")) 188 assert(t, err != nil, "SREM error") 189 // Wrong argument counts 190 _, err = redis.String(c.Do("SREM")) 191 assert(t, err != nil, "SREM error") 192 _, err = redis.String(c.Do("SREM", "set")) 193 assert(t, err != nil, "SREM error") 194 _, err = redis.String(c.Do("SREM", "set", "spurious", "args")) 195 assert(t, err != nil, "SREM error") 196 } 197} 198 199// Test SMOVE 200func TestSmove(t *testing.T) { 201 s, err := Run() 202 ok(t, err) 203 defer s.Close() 204 c, err := redis.Dial("tcp", s.Addr()) 205 ok(t, err) 206 207 s.SetAdd("s", "aap", "noot") 208 209 { 210 b, err := redis.Int(c.Do("SMOVE", "s", "s2", "aap")) 211 ok(t, err) 212 equals(t, 1, b) 213 214 m, err := s.IsMember("s", "aap") 215 ok(t, err) 216 equals(t, false, m) 217 m, err = s.IsMember("s2", "aap") 218 ok(t, err) 219 equals(t, true, m) 220 } 221 222 // Move away the last member 223 { 224 b, err := redis.Int(c.Do("SMOVE", "s", "s2", "noot")) 225 ok(t, err) 226 equals(t, 1, b) 227 228 equals(t, false, s.Exists("s")) 229 230 m, err := s.IsMember("s2", "noot") 231 ok(t, err) 232 equals(t, true, m) 233 } 234 235 // a nonexisting member 236 { 237 b, err := redis.Int(c.Do("SMOVE", "s", "s2", "nosuch")) 238 ok(t, err) 239 equals(t, 0, b) 240 } 241 242 // a nonexisting key 243 { 244 b, err := redis.Int(c.Do("SMOVE", "nosuch", "nosuch2", "nosuch")) 245 ok(t, err) 246 equals(t, 0, b) 247 } 248 249 // Wrong type of key 250 { 251 _, err := redis.String(c.Do("SET", "str", "value")) 252 ok(t, err) 253 _, err = redis.Int(c.Do("SMOVE", "str", "dst", "value")) 254 assert(t, err != nil, "SMOVE error") 255 _, err = redis.Int(c.Do("SMOVE", "s2", "str", "value")) 256 assert(t, err != nil, "SMOVE error") 257 // Wrong argument counts 258 _, err = redis.String(c.Do("SMOVE")) 259 assert(t, err != nil, "SMOVE error") 260 _, err = redis.String(c.Do("SMOVE", "set")) 261 assert(t, err != nil, "SMOVE error") 262 _, err = redis.String(c.Do("SMOVE", "set", "set2")) 263 assert(t, err != nil, "SMOVE error") 264 _, err = redis.String(c.Do("SMOVE", "set", "set2", "spurious", "args")) 265 assert(t, err != nil, "SMOVE error") 266 } 267} 268 269// Test SPOP 270func TestSpop(t *testing.T) { 271 s, err := Run() 272 ok(t, err) 273 defer s.Close() 274 c, err := redis.Dial("tcp", s.Addr()) 275 ok(t, err) 276 277 s.SetAdd("s", "aap", "noot") 278 279 { 280 el, err := redis.String(c.Do("SPOP", "s")) 281 ok(t, err) 282 assert(t, el == "aap" || el == "noot", "spop got something") 283 284 el, err = redis.String(c.Do("SPOP", "s")) 285 ok(t, err) 286 assert(t, el == "aap" || el == "noot", "spop got something") 287 288 assert(t, !s.Exists("s"), "all spopped away") 289 } 290 291 // a nonexisting key 292 { 293 b, err := c.Do("SPOP", "nosuch") 294 ok(t, err) 295 equals(t, nil, b) 296 } 297 298 // various errors 299 { 300 s.SetAdd("chk", "aap", "noot") 301 s.Set("str", "value") 302 303 _, err = redis.String(c.Do("SMOVE")) 304 assert(t, err != nil, "SMOVE error") 305 _, err = redis.String(c.Do("SMOVE", "chk", "set2")) 306 assert(t, err != nil, "SMOVE error") 307 308 _, err = c.Do("SPOP", "str") 309 assert(t, err != nil, "SPOP error") 310 } 311 312 // count argument 313 { 314 s.SetAdd("s", "aap", "noot", "mies", "vuur") 315 el, err := redis.Strings(c.Do("SPOP", "s", 2)) 316 ok(t, err) 317 assert(t, len(el) == 2, "SPOP s 2") 318 members, err := s.Members("s") 319 ok(t, err) 320 assert(t, len(members) == 2, "SPOP s 2") 321 } 322} 323 324// Test SRANDMEMBER 325func TestSrandmember(t *testing.T) { 326 s, err := Run() 327 ok(t, err) 328 defer s.Close() 329 c, err := redis.Dial("tcp", s.Addr()) 330 ok(t, err) 331 332 s.SetAdd("s", "aap", "noot", "mies") 333 334 // No count 335 { 336 el, err := redis.String(c.Do("SRANDMEMBER", "s")) 337 ok(t, err) 338 assert(t, el == "aap" || el == "noot" || el == "mies", "srandmember got something") 339 } 340 341 // Positive count 342 { 343 els, err := redis.Strings(c.Do("SRANDMEMBER", "s", 2)) 344 ok(t, err) 345 equals(t, 2, len(els)) 346 } 347 348 // Negative count 349 { 350 els, err := redis.Strings(c.Do("SRANDMEMBER", "s", -2)) 351 ok(t, err) 352 equals(t, 2, len(els)) 353 } 354 355 // a nonexisting key 356 { 357 b, err := c.Do("SRANDMEMBER", "nosuch") 358 ok(t, err) 359 equals(t, nil, b) 360 } 361 362 // Various errors 363 { 364 s.SetAdd("chk", "aap", "noot") 365 s.Set("str", "value") 366 367 _, err = redis.String(c.Do("SRANDMEMBER")) 368 assert(t, err != nil, "SRANDMEMBER error") 369 _, err = redis.String(c.Do("SRANDMEMBER", "chk", "noint")) 370 assert(t, err != nil, "SRANDMEMBER error") 371 _, err = redis.String(c.Do("SRANDMEMBER", "chk", 1, "toomanu")) 372 assert(t, err != nil, "SRANDMEMBER error") 373 374 _, err = c.Do("SRANDMEMBER", "str") 375 assert(t, err != nil, "SRANDMEMBER error") 376 } 377} 378 379// Test SDIFF 380func TestSdiff(t *testing.T) { 381 s, err := Run() 382 ok(t, err) 383 defer s.Close() 384 c, err := redis.Dial("tcp", s.Addr()) 385 ok(t, err) 386 387 s.SetAdd("s1", "aap", "noot", "mies") 388 s.SetAdd("s2", "noot", "mies", "vuur") 389 s.SetAdd("s3", "aap", "mies", "wim") 390 391 // Simple case 392 { 393 els, err := redis.Strings(c.Do("SDIFF", "s1", "s2")) 394 ok(t, err) 395 equals(t, []string{"aap"}, els) 396 } 397 398 // No other set 399 { 400 els, err := redis.Strings(c.Do("SDIFF", "s1")) 401 ok(t, err) 402 sort.Strings(els) 403 equals(t, []string{"aap", "mies", "noot"}, els) 404 } 405 406 // 3 sets 407 { 408 els, err := redis.Strings(c.Do("SDIFF", "s1", "s2", "s3")) 409 ok(t, err) 410 equals(t, []string{}, els) 411 } 412 413 // A nonexisting key 414 { 415 els, err := redis.Strings(c.Do("SDIFF", "s9")) 416 ok(t, err) 417 equals(t, []string{}, els) 418 } 419 420 // Various errors 421 { 422 s.SetAdd("chk", "aap", "noot") 423 s.Set("str", "value") 424 425 _, err = redis.String(c.Do("SDIFF")) 426 assert(t, err != nil, "SDIFF error") 427 _, err = redis.String(c.Do("SDIFF", "str")) 428 assert(t, err != nil, "SDIFF error") 429 _, err = redis.String(c.Do("SDIFF", "chk", "str")) 430 assert(t, err != nil, "SDIFF error") 431 } 432} 433 434// Test SDIFFSTORE 435func TestSdiffstore(t *testing.T) { 436 s, err := Run() 437 ok(t, err) 438 defer s.Close() 439 c, err := redis.Dial("tcp", s.Addr()) 440 ok(t, err) 441 442 s.SetAdd("s1", "aap", "noot", "mies") 443 s.SetAdd("s2", "noot", "mies", "vuur") 444 s.SetAdd("s3", "aap", "mies", "wim") 445 446 // Simple case 447 { 448 i, err := redis.Int(c.Do("SDIFFSTORE", "res", "s1", "s3")) 449 ok(t, err) 450 equals(t, 1, i) 451 s.CheckSet(t, "res", "noot") 452 } 453 454 // Various errors 455 { 456 s.SetAdd("chk", "aap", "noot") 457 s.Set("str", "value") 458 459 _, err = redis.String(c.Do("SDIFFSTORE")) 460 assert(t, err != nil, "SDIFFSTORE error") 461 _, err = redis.String(c.Do("SDIFFSTORE", "t")) 462 assert(t, err != nil, "SDIFFSTORE error") 463 _, err = redis.String(c.Do("SDIFFSTORE", "t", "str")) 464 assert(t, err != nil, "SDIFFSTORE error") 465 } 466} 467 468// Test SINTER 469func TestSinter(t *testing.T) { 470 s, err := Run() 471 ok(t, err) 472 defer s.Close() 473 c, err := redis.Dial("tcp", s.Addr()) 474 ok(t, err) 475 476 s.SetAdd("s1", "aap", "noot", "mies") 477 s.SetAdd("s2", "noot", "mies", "vuur") 478 s.SetAdd("s3", "aap", "mies", "wim") 479 480 // Simple case 481 { 482 els, err := redis.Strings(c.Do("SINTER", "s1", "s2")) 483 ok(t, err) 484 sort.Strings(els) 485 equals(t, []string{"mies", "noot"}, els) 486 } 487 488 // No other set 489 { 490 els, err := redis.Strings(c.Do("SINTER", "s1")) 491 ok(t, err) 492 sort.Strings(els) 493 equals(t, []string{"aap", "mies", "noot"}, els) 494 } 495 496 // 3 sets 497 { 498 els, err := redis.Strings(c.Do("SINTER", "s1", "s2", "s3")) 499 ok(t, err) 500 equals(t, []string{"mies"}, els) 501 } 502 503 // A nonexisting key 504 { 505 els, err := redis.Strings(c.Do("SINTER", "s9")) 506 ok(t, err) 507 equals(t, []string{}, els) 508 } 509 510 // With one of the keys being an empty set, the resulting set is also empty 511 { 512 els, err := redis.Strings(c.Do("SINTER", "s1", "s9")) 513 ok(t, err) 514 equals(t, []string{}, els) 515 } 516 517 // Various errors 518 { 519 s.SetAdd("chk", "aap", "noot") 520 s.Set("str", "value") 521 522 _, err = redis.String(c.Do("SINTER")) 523 assert(t, err != nil, "SINTER error") 524 _, err = redis.String(c.Do("SINTER", "str")) 525 assert(t, err != nil, "SINTER error") 526 _, err = redis.String(c.Do("SINTER", "chk", "str")) 527 assert(t, err != nil, "SINTER error") 528 } 529} 530 531// Test SINTERSTORE 532func TestSinterstore(t *testing.T) { 533 s, err := Run() 534 ok(t, err) 535 defer s.Close() 536 c, err := redis.Dial("tcp", s.Addr()) 537 ok(t, err) 538 539 s.SetAdd("s1", "aap", "noot", "mies") 540 s.SetAdd("s2", "noot", "mies", "vuur") 541 s.SetAdd("s3", "aap", "mies", "wim") 542 543 // Simple case 544 { 545 i, err := redis.Int(c.Do("SINTERSTORE", "res", "s1", "s3")) 546 ok(t, err) 547 equals(t, 2, i) 548 s.CheckSet(t, "res", "aap", "mies") 549 } 550 551 // With one of the keys being an empty set, the resulting set is also empty 552 { 553 i, err := redis.Int(c.Do("SINTERSTORE", "res", "s1", "s9")) 554 ok(t, err) 555 equals(t, 0, i) 556 s.CheckSet(t, "res", []string{}...) 557 } 558 559 // Various errors 560 { 561 s.SetAdd("chk", "aap", "noot") 562 s.Set("str", "value") 563 564 _, err = redis.String(c.Do("SINTERSTORE")) 565 assert(t, err != nil, "SINTERSTORE error") 566 _, err = redis.String(c.Do("SINTERSTORE", "t")) 567 assert(t, err != nil, "SINTERSTORE error") 568 _, err = redis.String(c.Do("SINTERSTORE", "t", "str")) 569 assert(t, err != nil, "SINTERSTORE error") 570 } 571} 572 573// Test SUNION 574func TestSunion(t *testing.T) { 575 s, err := Run() 576 ok(t, err) 577 defer s.Close() 578 c, err := redis.Dial("tcp", s.Addr()) 579 ok(t, err) 580 581 s.SetAdd("s1", "aap", "noot", "mies") 582 s.SetAdd("s2", "noot", "mies", "vuur") 583 s.SetAdd("s3", "aap", "mies", "wim") 584 585 // Simple case 586 { 587 els, err := redis.Strings(c.Do("SUNION", "s1", "s2")) 588 ok(t, err) 589 sort.Strings(els) 590 equals(t, []string{"aap", "mies", "noot", "vuur"}, els) 591 } 592 593 // No other set 594 { 595 els, err := redis.Strings(c.Do("SUNION", "s1")) 596 ok(t, err) 597 sort.Strings(els) 598 equals(t, []string{"aap", "mies", "noot"}, els) 599 } 600 601 // 3 sets 602 { 603 els, err := redis.Strings(c.Do("SUNION", "s1", "s2", "s3")) 604 ok(t, err) 605 sort.Strings(els) 606 equals(t, []string{"aap", "mies", "noot", "vuur", "wim"}, els) 607 } 608 609 // A nonexisting key 610 { 611 els, err := redis.Strings(c.Do("SUNION", "s9")) 612 ok(t, err) 613 equals(t, []string{}, els) 614 } 615 616 // Various errors 617 { 618 s.SetAdd("chk", "aap", "noot") 619 s.Set("str", "value") 620 621 _, err = redis.String(c.Do("SUNION")) 622 assert(t, err != nil, "SUNION error") 623 _, err = redis.String(c.Do("SUNION", "str")) 624 assert(t, err != nil, "SUNION error") 625 _, err = redis.String(c.Do("SUNION", "chk", "str")) 626 assert(t, err != nil, "SUNION error") 627 } 628} 629 630// Test SUNIONSTORE 631func TestSunionstore(t *testing.T) { 632 s, err := Run() 633 ok(t, err) 634 defer s.Close() 635 c, err := redis.Dial("tcp", s.Addr()) 636 ok(t, err) 637 638 s.SetAdd("s1", "aap", "noot", "mies") 639 s.SetAdd("s2", "noot", "mies", "vuur") 640 s.SetAdd("s3", "aap", "mies", "wim") 641 642 // Simple case 643 { 644 i, err := redis.Int(c.Do("SUNIONSTORE", "res", "s1", "s3")) 645 ok(t, err) 646 equals(t, 4, i) 647 s.CheckSet(t, "res", "aap", "mies", "noot", "wim") 648 } 649 650 // Various errors 651 { 652 s.SetAdd("chk", "aap", "noot") 653 s.Set("str", "value") 654 655 _, err = redis.String(c.Do("SUNIONSTORE")) 656 assert(t, err != nil, "SUNIONSTORE error") 657 _, err = redis.String(c.Do("SUNIONSTORE", "t")) 658 assert(t, err != nil, "SUNIONSTORE error") 659 _, err = redis.String(c.Do("SUNIONSTORE", "t", "str")) 660 assert(t, err != nil, "SUNIONSTORE error") 661 } 662} 663 664func TestSscan(t *testing.T) { 665 s, err := Run() 666 ok(t, err) 667 defer s.Close() 668 c, err := redis.Dial("tcp", s.Addr()) 669 ok(t, err) 670 671 // We cheat with sscan. It always returns everything. 672 673 s.SetAdd("set", "value1", "value2") 674 675 // No problem 676 { 677 res, err := redis.Values(c.Do("SSCAN", "set", 0)) 678 ok(t, err) 679 equals(t, 2, len(res)) 680 681 var c int 682 var keys []string 683 _, err = redis.Scan(res, &c, &keys) 684 ok(t, err) 685 equals(t, 0, c) 686 equals(t, []string{"value1", "value2"}, keys) 687 } 688 689 // Invalid cursor 690 { 691 res, err := redis.Values(c.Do("SSCAN", "set", 42)) 692 ok(t, err) 693 equals(t, 2, len(res)) 694 695 var c int 696 var keys []string 697 _, err = redis.Scan(res, &c, &keys) 698 ok(t, err) 699 equals(t, 0, c) 700 equals(t, []string(nil), keys) 701 } 702 703 // COUNT (ignored) 704 { 705 res, err := redis.Values(c.Do("SSCAN", "set", 0, "COUNT", 200)) 706 ok(t, err) 707 equals(t, 2, len(res)) 708 709 var c int 710 var keys []string 711 _, err = redis.Scan(res, &c, &keys) 712 ok(t, err) 713 equals(t, 0, c) 714 equals(t, []string{"value1", "value2"}, keys) 715 } 716 717 // MATCH 718 { 719 s.SetAdd("set", "aap", "noot", "mies") 720 res, err := redis.Values(c.Do("SSCAN", "set", 0, "MATCH", "mi*")) 721 ok(t, err) 722 equals(t, 2, len(res)) 723 724 var c int 725 var keys []string 726 _, err = redis.Scan(res, &c, &keys) 727 ok(t, err) 728 equals(t, 0, c) 729 equals(t, []string{"mies"}, keys) 730 } 731 732 // Wrong usage 733 { 734 _, err := redis.Int(c.Do("SSCAN")) 735 assert(t, err != nil, "do SSCAN error") 736 _, err = redis.Int(c.Do("SSCAN", "set")) 737 assert(t, err != nil, "do SSCAN error") 738 _, err = redis.Int(c.Do("SSCAN", "set", "noint")) 739 assert(t, err != nil, "do SSCAN error") 740 _, err = redis.Int(c.Do("SSCAN", "set", 1, "MATCH")) 741 assert(t, err != nil, "do SSCAN error") 742 _, err = redis.Int(c.Do("SSCAN", "set", 1, "COUNT")) 743 assert(t, err != nil, "do SSCAN error") 744 _, err = redis.Int(c.Do("SSCAN", "set", 1, "COUNT", "noint")) 745 assert(t, err != nil, "do SSCAN error") 746 s.Set("str", "value") 747 _, err = redis.Int(c.Do("SSCAN", "str", 1)) 748 assert(t, err != nil, "do SSCAN error") 749 } 750} 751