"Fossies" - the Fresh Open Source Software Archive

Member "redis-6.2.5/tests/unit/type/set.tcl" (21 Jul 2021, 30507 Bytes) of package /linux/misc/redis-6.2.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Tcl/Tk source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "set.tcl": 6.2.4_vs_6.2.5.

    1 start_server {
    2     tags {"set"}
    3     overrides {
    4         "set-max-intset-entries" 512
    5     }
    6 } {
    7     proc create_set {key entries} {
    8         r del $key
    9         foreach entry $entries { r sadd $key $entry }
   10     }
   11 
   12     test {SADD, SCARD, SISMEMBER, SMISMEMBER, SMEMBERS basics - regular set} {
   13         create_set myset {foo}
   14         assert_encoding hashtable myset
   15         assert_equal 1 [r sadd myset bar]
   16         assert_equal 0 [r sadd myset bar]
   17         assert_equal 2 [r scard myset]
   18         assert_equal 1 [r sismember myset foo]
   19         assert_equal 1 [r sismember myset bar]
   20         assert_equal 0 [r sismember myset bla]
   21         assert_equal {1} [r smismember myset foo]
   22         assert_equal {1 1} [r smismember myset foo bar]
   23         assert_equal {1 0} [r smismember myset foo bla]
   24         assert_equal {0 1} [r smismember myset bla foo]
   25         assert_equal {0} [r smismember myset bla]
   26         assert_equal {bar foo} [lsort [r smembers myset]]
   27     }
   28 
   29     test {SADD, SCARD, SISMEMBER, SMISMEMBER, SMEMBERS basics - intset} {
   30         create_set myset {17}
   31         assert_encoding intset myset
   32         assert_equal 1 [r sadd myset 16]
   33         assert_equal 0 [r sadd myset 16]
   34         assert_equal 2 [r scard myset]
   35         assert_equal 1 [r sismember myset 16]
   36         assert_equal 1 [r sismember myset 17]
   37         assert_equal 0 [r sismember myset 18]
   38         assert_equal {1} [r smismember myset 16]
   39         assert_equal {1 1} [r smismember myset 16 17]
   40         assert_equal {1 0} [r smismember myset 16 18]
   41         assert_equal {0 1} [r smismember myset 18 16]
   42         assert_equal {0} [r smismember myset 18]
   43         assert_equal {16 17} [lsort [r smembers myset]]
   44     }
   45 
   46     test {SMISMEMBER against non set} {
   47         r lpush mylist foo
   48         assert_error WRONGTYPE* {r smismember mylist bar}
   49     }
   50 
   51     test {SMISMEMBER non existing key} {
   52         assert_equal {0} [r smismember myset1 foo]
   53         assert_equal {0 0} [r smismember myset1 foo bar]
   54     }
   55 
   56     test {SMISMEMBER requires one or more members} {
   57         r del zmscoretest
   58         r zadd zmscoretest 10 x
   59         r zadd zmscoretest 20 y
   60         
   61         catch {r smismember zmscoretest} e
   62         assert_match {*ERR*wrong*number*arg*} $e
   63     }
   64 
   65     test {SADD against non set} {
   66         r lpush mylist foo
   67         assert_error WRONGTYPE* {r sadd mylist bar}
   68     }
   69 
   70     test "SADD a non-integer against an intset" {
   71         create_set myset {1 2 3}
   72         assert_encoding intset myset
   73         assert_equal 1 [r sadd myset a]
   74         assert_encoding hashtable myset
   75     }
   76 
   77     test "SADD an integer larger than 64 bits" {
   78         create_set myset {213244124402402314402033402}
   79         assert_encoding hashtable myset
   80         assert_equal 1 [r sismember myset 213244124402402314402033402]
   81         assert_equal {1} [r smismember myset 213244124402402314402033402]
   82     }
   83 
   84     test "SADD overflows the maximum allowed integers in an intset" {
   85         r del myset
   86         for {set i 0} {$i < 512} {incr i} { r sadd myset $i }
   87         assert_encoding intset myset
   88         assert_equal 1 [r sadd myset 512]
   89         assert_encoding hashtable myset
   90     }
   91 
   92     test {Variadic SADD} {
   93         r del myset
   94         assert_equal 3 [r sadd myset a b c]
   95         assert_equal 2 [r sadd myset A a b c B]
   96         assert_equal [lsort {A a b c B}] [lsort [r smembers myset]]
   97     }
   98 
   99     test "Set encoding after DEBUG RELOAD" {
  100         r del myintset myhashset mylargeintset
  101         for {set i 0} {$i <  100} {incr i} { r sadd myintset $i }
  102         for {set i 0} {$i < 1280} {incr i} { r sadd mylargeintset $i }
  103         for {set i 0} {$i <  256} {incr i} { r sadd myhashset [format "i%03d" $i] }
  104         assert_encoding intset myintset
  105         assert_encoding hashtable mylargeintset
  106         assert_encoding hashtable myhashset
  107 
  108         r debug reload
  109         assert_encoding intset myintset
  110         assert_encoding hashtable mylargeintset
  111         assert_encoding hashtable myhashset
  112     }
  113 
  114     test {SREM basics - regular set} {
  115         create_set myset {foo bar ciao}
  116         assert_encoding hashtable myset
  117         assert_equal 0 [r srem myset qux]
  118         assert_equal 1 [r srem myset foo]
  119         assert_equal {bar ciao} [lsort [r smembers myset]]
  120     }
  121 
  122     test {SREM basics - intset} {
  123         create_set myset {3 4 5}
  124         assert_encoding intset myset
  125         assert_equal 0 [r srem myset 6]
  126         assert_equal 1 [r srem myset 4]
  127         assert_equal {3 5} [lsort [r smembers myset]]
  128     }
  129 
  130     test {SREM with multiple arguments} {
  131         r del myset
  132         r sadd myset a b c d
  133         assert_equal 0 [r srem myset k k k]
  134         assert_equal 2 [r srem myset b d x y]
  135         lsort [r smembers myset]
  136     } {a c}
  137 
  138     test {SREM variadic version with more args needed to destroy the key} {
  139         r del myset
  140         r sadd myset 1 2 3
  141         r srem myset 1 2 3 4 5 6 7 8
  142     } {3}
  143 
  144     foreach {type} {hashtable intset} {
  145         for {set i 1} {$i <= 5} {incr i} {
  146             r del [format "set%d" $i]
  147         }
  148         for {set i 0} {$i < 200} {incr i} {
  149             r sadd set1 $i
  150             r sadd set2 [expr $i+195]
  151         }
  152         foreach i {199 195 1000 2000} {
  153             r sadd set3 $i
  154         }
  155         for {set i 5} {$i < 200} {incr i} {
  156             r sadd set4 $i
  157         }
  158         r sadd set5 0
  159 
  160         # To make sure the sets are encoded as the type we are testing -- also
  161         # when the VM is enabled and the values may be swapped in and out
  162         # while the tests are running -- an extra element is added to every
  163         # set that determines its encoding.
  164         set large 200
  165         if {$type eq "hashtable"} {
  166             set large foo
  167         }
  168 
  169         for {set i 1} {$i <= 5} {incr i} {
  170             r sadd [format "set%d" $i] $large
  171         }
  172 
  173         test "Generated sets must be encoded as $type" {
  174             for {set i 1} {$i <= 5} {incr i} {
  175                 assert_encoding $type [format "set%d" $i]
  176             }
  177         }
  178 
  179         test "SINTER with two sets - $type" {
  180             assert_equal [list 195 196 197 198 199 $large] [lsort [r sinter set1 set2]]
  181         }
  182 
  183         test "SINTERSTORE with two sets - $type" {
  184             r sinterstore setres set1 set2
  185             assert_encoding $type setres
  186             assert_equal [list 195 196 197 198 199 $large] [lsort [r smembers setres]]
  187         }
  188 
  189         test "SINTERSTORE with two sets, after a DEBUG RELOAD - $type" {
  190             r debug reload
  191             r sinterstore setres set1 set2
  192             assert_encoding $type setres
  193             assert_equal [list 195 196 197 198 199 $large] [lsort [r smembers setres]]
  194         }
  195 
  196         test "SUNION with two sets - $type" {
  197             set expected [lsort -uniq "[r smembers set1] [r smembers set2]"]
  198             assert_equal $expected [lsort [r sunion set1 set2]]
  199         }
  200 
  201         test "SUNIONSTORE with two sets - $type" {
  202             r sunionstore setres set1 set2
  203             assert_encoding $type setres
  204             set expected [lsort -uniq "[r smembers set1] [r smembers set2]"]
  205             assert_equal $expected [lsort [r smembers setres]]
  206         }
  207 
  208         test "SINTER against three sets - $type" {
  209             assert_equal [list 195 199 $large] [lsort [r sinter set1 set2 set3]]
  210         }
  211 
  212         test "SINTERSTORE with three sets - $type" {
  213             r sinterstore setres set1 set2 set3
  214             assert_equal [list 195 199 $large] [lsort [r smembers setres]]
  215         }
  216 
  217         test "SUNION with non existing keys - $type" {
  218             set expected [lsort -uniq "[r smembers set1] [r smembers set2]"]
  219             assert_equal $expected [lsort [r sunion nokey1 set1 set2 nokey2]]
  220         }
  221 
  222         test "SDIFF with two sets - $type" {
  223             assert_equal {0 1 2 3 4} [lsort [r sdiff set1 set4]]
  224         }
  225 
  226         test "SDIFF with three sets - $type" {
  227             assert_equal {1 2 3 4} [lsort [r sdiff set1 set4 set5]]
  228         }
  229 
  230         test "SDIFFSTORE with three sets - $type" {
  231             r sdiffstore setres set1 set4 set5
  232             # When we start with intsets, we should always end with intsets.
  233             if {$type eq {intset}} {
  234                 assert_encoding intset setres
  235             }
  236             assert_equal {1 2 3 4} [lsort [r smembers setres]]
  237         }
  238     }
  239 
  240     test "SDIFF with first set empty" {
  241         r del set1 set2 set3
  242         r sadd set2 1 2 3 4
  243         r sadd set3 a b c d
  244         r sdiff set1 set2 set3
  245     } {}
  246 
  247     test "SDIFF with same set two times" {
  248         r del set1
  249         r sadd set1 a b c 1 2 3 4 5 6
  250         r sdiff set1 set1
  251     } {}
  252 
  253     test "SDIFF fuzzing" {
  254         for {set j 0} {$j < 100} {incr j} {
  255             unset -nocomplain s
  256             array set s {}
  257             set args {}
  258             set num_sets [expr {[randomInt 10]+1}]
  259             for {set i 0} {$i < $num_sets} {incr i} {
  260                 set num_elements [randomInt 100]
  261                 r del set_$i
  262                 lappend args set_$i
  263                 while {$num_elements} {
  264                     set ele [randomValue]
  265                     r sadd set_$i $ele
  266                     if {$i == 0} {
  267                         set s($ele) x
  268                     } else {
  269                         unset -nocomplain s($ele)
  270                     }
  271                     incr num_elements -1
  272                 }
  273             }
  274             set result [lsort [r sdiff {*}$args]]
  275             assert_equal $result [lsort [array names s]]
  276         }
  277     }
  278 
  279     test "SDIFF against non-set should throw error" {
  280         # with an empty set
  281         r set key1{t} x
  282         assert_error "WRONGTYPE*" {r sdiff key1{t} noset{t}}
  283         # different order
  284         assert_error "WRONGTYPE*" {r sdiff noset{t} key1{t}}
  285 
  286         # with a legal set
  287         r del set1{t}
  288         r sadd set1{t} a b c
  289         assert_error "WRONGTYPE*" {r sdiff key1{t} set1{t}}
  290         # different order
  291         assert_error "WRONGTYPE*" {r sdiff set1{t} key1{t}}
  292     }
  293 
  294     test "SDIFF should handle non existing key as empty" {
  295         r del set1{t} set2{t} set3{t}
  296 
  297         r sadd set1{t} a b c
  298         r sadd set2{t} b c d
  299         assert_equal {a} [lsort [r sdiff set1{t} set2{t} set3{t}]]
  300         assert_equal {} [lsort [r sdiff set3{t} set2{t} set1{t}]]
  301     }
  302 
  303     test "SDIFFSTORE against non-set should throw error" {
  304         r del set1{t} set2{t} set3{t} key1{t}
  305         r set key1{t} x
  306 
  307         # with en empty dstkey
  308         assert_error "WRONGTYPE*" {r SDIFFSTORE set3{t} key1{t} noset{t}}
  309         assert_equal 0 [r exists set3{t}]
  310         assert_error "WRONGTYPE*" {r SDIFFSTORE set3{t} noset{t} key1{t}}
  311         assert_equal 0 [r exists set3{t}]
  312 
  313         # with a legal dstkey
  314         r sadd set1{t} a b c
  315         r sadd set2{t} b c d
  316         r sadd set3{t} e
  317         assert_error "WRONGTYPE*" {r SDIFFSTORE set3{t} key1{t} set1{t} noset{t}}
  318         assert_equal 1 [r exists set3{t}]
  319         assert_equal {e} [lsort [r smembers set3{t}]]
  320 
  321         assert_error "WRONGTYPE*" {r SDIFFSTORE set3{t} set1{t} key1{t} set2{t}}
  322         assert_equal 1 [r exists set3{t}]
  323         assert_equal {e} [lsort [r smembers set3{t}]]
  324     }
  325 
  326     test "SDIFFSTORE should handle non existing key as empty" {
  327         r del set1{t} set2{t} set3{t}
  328 
  329         r set setres{t} xxx
  330         assert_equal 0 [r sdiffstore setres{t} foo111{t} bar222{t}]
  331         assert_equal 0 [r exists setres{t}]
  332 
  333         # with a legal dstkey, should delete dstkey
  334         r sadd set3{t} a b c
  335         assert_equal 0 [r sdiffstore set3{t} set1{t} set2{t}]
  336         assert_equal 0 [r exists set3{t}]
  337 
  338         r sadd set1{t} a b c
  339         assert_equal 3 [r sdiffstore set3{t} set1{t} set2{t}]
  340         assert_equal 1 [r exists set3{t}]
  341         assert_equal {a b c} [lsort [r smembers set3{t}]]
  342 
  343         # with a legal dstkey and empty set2, should delete the dstkey
  344         r sadd set3{t} a b c
  345         assert_equal 0 [r sdiffstore set3{t} set2{t} set1{t}]
  346         assert_equal 0 [r exists set3{t}]
  347     }
  348 
  349     test "SINTER against non-set should throw error" {
  350         r set key1{t} x
  351         assert_error "WRONGTYPE*" {r sinter key1{t} noset{t}}
  352         # different order
  353         assert_error "WRONGTYPE*" {r sinter noset{t} key1{t}}
  354 
  355         r sadd set1{t} a b c
  356         assert_error "WRONGTYPE*" {r sinter key1{t} set1{t}}
  357         # different order
  358         assert_error "WRONGTYPE*" {r sinter set1{t} key1{t}}
  359     }
  360 
  361     test "SINTER should handle non existing key as empty" {
  362         r del set1 set2 set3
  363         r sadd set1 a b c
  364         r sadd set2 b c d
  365         r sinter set1 set2 set3
  366     } {}
  367 
  368     test "SINTER with same integer elements but different encoding" {
  369         r del set1 set2
  370         r sadd set1 1 2 3
  371         r sadd set2 1 2 3 a
  372         r srem set2 a
  373         assert_encoding intset set1
  374         assert_encoding hashtable set2
  375         lsort [r sinter set1 set2]
  376     } {1 2 3}
  377 
  378     test "SINTERSTORE against non-set should throw error" {
  379         r del set1{t} set2{t} set3{t} key1{t}
  380         r set key1{t} x
  381 
  382         # with en empty dstkey
  383         assert_error "WRONGTYPE*" {r sinterstore set3{t} key1{t} noset{t}}
  384         assert_equal 0 [r exists set3{t}]
  385         assert_error "WRONGTYPE*" {r sinterstore set3{t} noset{t} key1{t}}
  386         assert_equal 0 [r exists set3{t}]
  387 
  388         # with a legal dstkey
  389         r sadd set1{t} a b c
  390         r sadd set2{t} b c d
  391         r sadd set3{t} e
  392         assert_error "WRONGTYPE*" {r sinterstore set3{t} key1{t} set2{t} noset{t}}
  393         assert_equal 1 [r exists set3{t}]
  394         assert_equal {e} [lsort [r smembers set3{t}]]
  395 
  396         assert_error "WRONGTYPE*" {r sinterstore set3{t} noset{t} key1{t} set2{t}}
  397         assert_equal 1 [r exists set3{t}]
  398         assert_equal {e} [lsort [r smembers set3{t}]]
  399     }
  400 
  401     test "SINTERSTORE against non existing keys should delete dstkey" {
  402         r del set1{t} set2{t} set3{t}
  403 
  404         r set setres{t} xxx
  405         assert_equal 0 [r sinterstore setres{t} foo111{t} bar222{t}]
  406         assert_equal 0 [r exists setres{t}]
  407 
  408         # with a legal dstkey
  409         r sadd set3{t} a b c
  410         assert_equal 0 [r sinterstore set3{t} set1{t} set2{t}]
  411         assert_equal 0 [r exists set3{t}]
  412 
  413         r sadd set1{t} a b c
  414         assert_equal 0 [r sinterstore set3{t} set1{t} set2{t}]
  415         assert_equal 0 [r exists set3{t}]
  416 
  417         assert_equal 0 [r sinterstore set3{t} set2{t} set1{t}]
  418         assert_equal 0 [r exists set3{t}]
  419     }
  420 
  421     test "SUNION against non-set should throw error" {
  422         r set key1{t} x
  423         assert_error "WRONGTYPE*" {r sunion key1{t} noset{t}}
  424         # different order
  425         assert_error "WRONGTYPE*" {r sunion noset{t} key1{t}}
  426 
  427         r del set1{t}
  428         r sadd set1{t} a b c
  429         assert_error "WRONGTYPE*" {r sunion key1{t} set1{t}}
  430         # different order
  431         assert_error "WRONGTYPE*" {r sunion set1{t} key1{t}}
  432     }
  433 
  434     test "SUNION should handle non existing key as empty" {
  435         r del set1{t} set2{t} set3{t}
  436 
  437         r sadd set1{t} a b c
  438         r sadd set2{t} b c d
  439         assert_equal {a b c d} [lsort [r sunion set1{t} set2{t} set3{t}]]
  440     }
  441 
  442     test "SUNIONSTORE against non-set should throw error" {
  443         r del set1{t} set2{t} set3{t} key1{t}
  444         r set key1{t} x
  445 
  446         # with en empty dstkey
  447         assert_error "WRONGTYPE*" {r sunionstore set3{t} key1{t} noset{t}}
  448         assert_equal 0 [r exists set3{t}]
  449         assert_error "WRONGTYPE*" {r sunionstore set3{t} noset{t} key1{t}}
  450         assert_equal 0 [r exists set3{t}]
  451 
  452         # with a legal dstkey
  453         r sadd set1{t} a b c
  454         r sadd set2{t} b c d
  455         r sadd set3{t} e
  456         assert_error "WRONGTYPE*" {r sunionstore set3{t} key1{t} key2{t} noset{t}}
  457         assert_equal 1 [r exists set3{t}]
  458         assert_equal {e} [lsort [r smembers set3{t}]]
  459 
  460         assert_error "WRONGTYPE*" {r sunionstore set3{t} noset{t} key1{t} key2{t}}
  461         assert_equal 1 [r exists set3{t}]
  462         assert_equal {e} [lsort [r smembers set3{t}]]
  463     }
  464 
  465     test "SUNIONSTORE should handle non existing key as empty" {
  466         r del set1{t} set2{t} set3{t}
  467 
  468         r set setres{t} xxx
  469         assert_equal 0 [r sunionstore setres{t} foo111{t} bar222{t}]
  470         assert_equal 0 [r exists setres{t}]
  471 
  472         # set1 set2 both empty, should delete the dstkey
  473         r sadd set3{t} a b c
  474         assert_equal 0 [r sunionstore set3{t} set1{t} set2{t}]
  475         assert_equal 0 [r exists set3{t}]
  476 
  477         r sadd set1{t} a b c
  478         r sadd set3{t} e f
  479         assert_equal 3 [r sunionstore set3{t} set1{t} set2{t}]
  480         assert_equal 1 [r exists set3{t}]
  481         assert_equal {a b c} [lsort [r smembers set3{t}]]
  482 
  483         r sadd set3{t} d
  484         assert_equal 3 [r sunionstore set3{t} set2{t} set1{t}]
  485         assert_equal 1 [r exists set3{t}]
  486         assert_equal {a b c} [lsort [r smembers set3{t}]]
  487     }
  488 
  489     test "SUNIONSTORE against non existing keys should delete dstkey" {
  490         r set setres xxx
  491         assert_equal 0 [r sunionstore setres foo111 bar222]
  492         assert_equal 0 [r exists setres]
  493     }
  494 
  495     foreach {type contents} {hashtable {a b c} intset {1 2 3}} {
  496         test "SPOP basics - $type" {
  497             create_set myset $contents
  498             assert_encoding $type myset
  499             assert_equal $contents [lsort [list [r spop myset] [r spop myset] [r spop myset]]]
  500             assert_equal 0 [r scard myset]
  501         }
  502 
  503         test "SPOP with <count>=1 - $type" {
  504             create_set myset $contents
  505             assert_encoding $type myset
  506             assert_equal $contents [lsort [list [r spop myset 1] [r spop myset 1] [r spop myset 1]]]
  507             assert_equal 0 [r scard myset]
  508         }
  509 
  510         test "SRANDMEMBER - $type" {
  511             create_set myset $contents
  512             unset -nocomplain myset
  513             array set myset {}
  514             for {set i 0} {$i < 100} {incr i} {
  515                 set myset([r srandmember myset]) 1
  516             }
  517             assert_equal $contents [lsort [array names myset]]
  518         }
  519     }
  520 
  521     foreach {type contents} {
  522         hashtable {a b c d e f g h i j k l m n o p q r s t u v w x y z} 
  523         intset {1 10 11 12 13 14 15 16 17 18 19 2 20 21 22 23 24 25 26 3 4 5 6 7 8 9}
  524     } {
  525         test "SPOP with <count>" {
  526             create_set myset $contents
  527             assert_encoding $type myset
  528             assert_equal $contents [lsort [concat [r spop myset 11] [r spop myset 9] [r spop myset 0] [r spop myset 4] [r spop myset 1] [r spop myset 0] [r spop myset 1] [r spop myset 0]]]
  529             assert_equal 0 [r scard myset]
  530         }
  531     }
  532 
  533     # As seen in intsetRandomMembers
  534     test "SPOP using integers, testing Knuth's and Floyd's algorithm" {
  535         create_set myset {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
  536         assert_encoding intset myset
  537         assert_equal 20 [r scard myset]
  538         r spop myset 1
  539         assert_equal 19 [r scard myset]
  540         r spop myset 2
  541         assert_equal 17 [r scard myset]
  542         r spop myset 3
  543         assert_equal 14 [r scard myset]
  544         r spop myset 10
  545         assert_equal 4 [r scard myset]
  546         r spop myset 10
  547         assert_equal 0 [r scard myset]
  548         r spop myset 1
  549         assert_equal 0 [r scard myset]
  550     } {}
  551 
  552     test "SPOP using integers with Knuth's algorithm" {
  553         r spop nonexisting_key 100
  554     } {}
  555 
  556     test "SPOP new implementation: code path #1" {
  557         set content {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
  558         create_set myset $content
  559         set res [r spop myset 30]
  560         assert {[lsort $content] eq [lsort $res]}
  561     }
  562 
  563     test "SPOP new implementation: code path #2" {
  564         set content {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
  565         create_set myset $content
  566         set res [r spop myset 2]
  567         assert {[llength $res] == 2}
  568         assert {[r scard myset] == 18}
  569         set union [concat [r smembers myset] $res]
  570         assert {[lsort $union] eq [lsort $content]}
  571     }
  572 
  573     test "SPOP new implementation: code path #3" {
  574         set content {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
  575         create_set myset $content
  576         set res [r spop myset 18]
  577         assert {[llength $res] == 18}
  578         assert {[r scard myset] == 2}
  579         set union [concat [r smembers myset] $res]
  580         assert {[lsort $union] eq [lsort $content]}
  581     }
  582 
  583     test "SRANDMEMBER count of 0 is handled correctly" {
  584         r srandmember myset 0
  585     } {}
  586 
  587     test "SRANDMEMBER with <count> against non existing key" {
  588         r srandmember nonexisting_key 100
  589     } {}
  590 
  591     # Make sure we can distinguish between an empty array and a null response
  592     r readraw 1
  593 
  594     test "SRANDMEMBER count of 0 is handled correctly - emptyarray" {
  595         r srandmember myset 0
  596     } {*0}
  597 
  598     test "SRANDMEMBER with <count> against non existing key - emptyarray" {
  599         r srandmember nonexisting_key 100
  600     } {*0}
  601 
  602     r readraw 0
  603 
  604     foreach {type contents} {
  605         hashtable {
  606             1 5 10 50 125 50000 33959417 4775547 65434162
  607             12098459 427716 483706 2726473884 72615637475
  608             MARY PATRICIA LINDA BARBARA ELIZABETH JENNIFER MARIA
  609             SUSAN MARGARET DOROTHY LISA NANCY KAREN BETTY HELEN
  610             SANDRA DONNA CAROL RUTH SHARON MICHELLE LAURA SARAH
  611             KIMBERLY DEBORAH JESSICA SHIRLEY CYNTHIA ANGELA MELISSA
  612             BRENDA AMY ANNA REBECCA VIRGINIA KATHLEEN
  613         }
  614         intset {
  615             0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  616             20 21 22 23 24 25 26 27 28 29
  617             30 31 32 33 34 35 36 37 38 39
  618             40 41 42 43 44 45 46 47 48 49
  619         }
  620     } {
  621         test "SRANDMEMBER with <count> - $type" {
  622             create_set myset $contents
  623             unset -nocomplain myset
  624             array set myset {}
  625             foreach ele [r smembers myset] {
  626                 set myset($ele) 1
  627             }
  628             assert_equal [lsort $contents] [lsort [array names myset]]
  629 
  630             # Make sure that a count of 0 is handled correctly.
  631             assert_equal [r srandmember myset 0] {}
  632 
  633             # We'll stress different parts of the code, see the implementation
  634             # of SRANDMEMBER for more information, but basically there are
  635             # four different code paths.
  636             #
  637             # PATH 1: Use negative count.
  638             #
  639             # 1) Check that it returns repeated elements.
  640             set res [r srandmember myset -100]
  641             assert_equal [llength $res] 100
  642 
  643             # 2) Check that all the elements actually belong to the
  644             # original set.
  645             foreach ele $res {
  646                 assert {[info exists myset($ele)]}
  647             }
  648 
  649             # 3) Check that eventually all the elements are returned.
  650             unset -nocomplain auxset
  651             set iterations 1000
  652             while {$iterations != 0} {
  653                 incr iterations -1
  654                 set res [r srandmember myset -10]
  655                 foreach ele $res {
  656                     set auxset($ele) 1
  657                 }
  658                 if {[lsort [array names myset]] eq
  659                     [lsort [array names auxset]]} {
  660                     break;
  661                 }
  662             }
  663             assert {$iterations != 0}
  664 
  665             # PATH 2: positive count (unique behavior) with requested size
  666             # equal or greater than set size.
  667             foreach size {50 100} {
  668                 set res [r srandmember myset $size]
  669                 assert_equal [llength $res] 50
  670                 assert_equal [lsort $res] [lsort [array names myset]]
  671             }
  672 
  673             # PATH 3: Ask almost as elements as there are in the set.
  674             # In this case the implementation will duplicate the original
  675             # set and will remove random elements up to the requested size.
  676             #
  677             # PATH 4: Ask a number of elements definitely smaller than
  678             # the set size.
  679             #
  680             # We can test both the code paths just changing the size but
  681             # using the same code.
  682 
  683             foreach size {45 5} {
  684                 set res [r srandmember myset $size]
  685                 assert_equal [llength $res] $size
  686 
  687                 # 1) Check that all the elements actually belong to the
  688                 # original set.
  689                 foreach ele $res {
  690                     assert {[info exists myset($ele)]}
  691                 }
  692 
  693                 # 2) Check that eventually all the elements are returned.
  694                 unset -nocomplain auxset
  695                 set iterations 1000
  696                 while {$iterations != 0} {
  697                     incr iterations -1
  698                     set res [r srandmember myset $size]
  699                     foreach ele $res {
  700                         set auxset($ele) 1
  701                     }
  702                     if {[lsort [array names myset]] eq
  703                         [lsort [array names auxset]]} {
  704                         break;
  705                     }
  706                 }
  707                 assert {$iterations != 0}
  708             }
  709         }
  710     }
  711 
  712     foreach {type contents} {
  713         hashtable {
  714             1 5 10 50 125
  715             MARY PATRICIA LINDA BARBARA ELIZABETH
  716         }
  717         intset {
  718             0 1 2 3 4 5 6 7 8 9
  719         }
  720     } {
  721         test "SRANDMEMBER histogram distribution - $type" {
  722             create_set myset $contents
  723             unset -nocomplain myset
  724             array set myset {}
  725             foreach ele [r smembers myset] {
  726                 set myset($ele) 1
  727             }
  728 
  729             # Use negative count (PATH 1).
  730             # df = 9, 40 means 0.00001 probability
  731             set res [r srandmember myset -1000]
  732             assert_lessthan [chi_square_value $res] 40
  733 
  734             # Use positive count (both PATH 3 and PATH 4).
  735             foreach size {8 2} {
  736                 unset -nocomplain allkey
  737                 set iterations [expr {1000 / $size}]
  738                 while {$iterations != 0} {
  739                     incr iterations -1
  740                     set res [r srandmember myset $size]
  741                     foreach ele $res {
  742                         lappend allkey $ele
  743                     }
  744                 }
  745                 # df = 9, 40 means 0.00001 probability
  746                 assert_lessthan [chi_square_value $allkey] 40
  747             }
  748         }
  749     }
  750 
  751     proc setup_move {} {
  752         r del myset3 myset4
  753         create_set myset1 {1 a b}
  754         create_set myset2 {2 3 4}
  755         assert_encoding hashtable myset1
  756         assert_encoding intset myset2
  757     }
  758 
  759     test "SMOVE basics - from regular set to intset" {
  760         # move a non-integer element to an intset should convert encoding
  761         setup_move
  762         assert_equal 1 [r smove myset1 myset2 a]
  763         assert_equal {1 b} [lsort [r smembers myset1]]
  764         assert_equal {2 3 4 a} [lsort [r smembers myset2]]
  765         assert_encoding hashtable myset2
  766 
  767         # move an integer element should not convert the encoding
  768         setup_move
  769         assert_equal 1 [r smove myset1 myset2 1]
  770         assert_equal {a b} [lsort [r smembers myset1]]
  771         assert_equal {1 2 3 4} [lsort [r smembers myset2]]
  772         assert_encoding intset myset2
  773     }
  774 
  775     test "SMOVE basics - from intset to regular set" {
  776         setup_move
  777         assert_equal 1 [r smove myset2 myset1 2]
  778         assert_equal {1 2 a b} [lsort [r smembers myset1]]
  779         assert_equal {3 4} [lsort [r smembers myset2]]
  780     }
  781 
  782     test "SMOVE non existing key" {
  783         setup_move
  784         assert_equal 0 [r smove myset1 myset2 foo]
  785         assert_equal 0 [r smove myset1 myset1 foo]
  786         assert_equal {1 a b} [lsort [r smembers myset1]]
  787         assert_equal {2 3 4} [lsort [r smembers myset2]]
  788     }
  789 
  790     test "SMOVE non existing src set" {
  791         setup_move
  792         assert_equal 0 [r smove noset myset2 foo]
  793         assert_equal {2 3 4} [lsort [r smembers myset2]]
  794     }
  795 
  796     test "SMOVE from regular set to non existing destination set" {
  797         setup_move
  798         assert_equal 1 [r smove myset1 myset3 a]
  799         assert_equal {1 b} [lsort [r smembers myset1]]
  800         assert_equal {a} [lsort [r smembers myset3]]
  801         assert_encoding hashtable myset3
  802     }
  803 
  804     test "SMOVE from intset to non existing destination set" {
  805         setup_move
  806         assert_equal 1 [r smove myset2 myset3 2]
  807         assert_equal {3 4} [lsort [r smembers myset2]]
  808         assert_equal {2} [lsort [r smembers myset3]]
  809         assert_encoding intset myset3
  810     }
  811 
  812     test "SMOVE wrong src key type" {
  813         r set x 10
  814         assert_error "WRONGTYPE*" {r smove x myset2 foo}
  815     }
  816 
  817     test "SMOVE wrong dst key type" {
  818         r set x 10
  819         assert_error "WRONGTYPE*" {r smove myset2 x foo}
  820     }
  821 
  822     test "SMOVE with identical source and destination" {
  823         r del set
  824         r sadd set a b c
  825         r smove set set b
  826         lsort [r smembers set]
  827     } {a b c}
  828 
  829     test "SMOVE only notify dstset when the addition is successful" {
  830         r del srcset{t}
  831         r del dstset{t}
  832 
  833         r sadd srcset{t} a b
  834         r sadd dstset{t} a
  835 
  836         r watch dstset{t}
  837 
  838         r multi
  839         r sadd dstset{t} c
  840 
  841         set r2 [redis_client]
  842         $r2 smove srcset{t} dstset{t} a
  843 
  844         # The dstset is actually unchanged, multi should success
  845         r exec
  846         set res [r scard dstset{t}]
  847         assert_equal $res 2
  848         $r2 close
  849     }
  850 
  851     tags {slow} {
  852         test {intsets implementation stress testing} {
  853             for {set j 0} {$j < 20} {incr j} {
  854                 unset -nocomplain s
  855                 array set s {}
  856                 r del s
  857                 set len [randomInt 1024]
  858                 for {set i 0} {$i < $len} {incr i} {
  859                     randpath {
  860                         set data [randomInt 65536]
  861                     } {
  862                         set data [randomInt 4294967296]
  863                     } {
  864                         set data [randomInt 18446744073709551616]
  865                     }
  866                     set s($data) {}
  867                     r sadd s $data
  868                 }
  869                 assert_equal [lsort [r smembers s]] [lsort [array names s]]
  870                 set len [array size s]
  871                 for {set i 0} {$i < $len} {incr i} {
  872                     set e [r spop s]
  873                     if {![info exists s($e)]} {
  874                         puts "Can't find '$e' on local array"
  875                         puts "Local array: [lsort [r smembers s]]"
  876                         puts "Remote array: [lsort [array names s]]"
  877                         error "exception"
  878                     }
  879                     array unset s $e
  880                 }
  881                 assert_equal [r scard s] 0
  882                 assert_equal [array size s] 0
  883             }
  884         }
  885     }
  886 }