1start_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, 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 {bar foo} [lsort [r smembers myset]] 22 } 23 24 test {SADD, SCARD, SISMEMBER, SMEMBERS basics - intset} { 25 create_set myset {17} 26 assert_encoding intset myset 27 assert_equal 1 [r sadd myset 16] 28 assert_equal 0 [r sadd myset 16] 29 assert_equal 2 [r scard myset] 30 assert_equal 1 [r sismember myset 16] 31 assert_equal 1 [r sismember myset 17] 32 assert_equal 0 [r sismember myset 18] 33 assert_equal {16 17} [lsort [r smembers myset]] 34 } 35 36 test {SADD against non set} { 37 r lpush mylist foo 38 assert_error ERR*kind* {r sadd mylist bar} 39 } 40 41 test "SADD a non-integer against an intset" { 42 create_set myset {1 2 3} 43 assert_encoding intset myset 44 assert_equal 1 [r sadd myset a] 45 assert_encoding hashtable myset 46 } 47 48 test "SADD an integer larger than 64 bits" { 49 create_set myset {213244124402402314402033402} 50 assert_encoding hashtable myset 51 assert_equal 1 [r sismember myset 213244124402402314402033402] 52 } 53 54 test "SADD overflows the maximum allowed integers in an intset" { 55 r del myset 56 for {set i 0} {$i < 512} {incr i} { r sadd myset $i } 57 assert_encoding intset myset 58 assert_equal 1 [r sadd myset 512] 59 assert_encoding hashtable myset 60 } 61 62 test {Variadic SADD} { 63 r del myset 64 assert_equal 3 [r sadd myset a b c] 65 assert_equal 2 [r sadd myset A a b c B] 66 assert_equal [lsort {A a b c B}] [lsort [r smembers myset]] 67 } 68 69 test "Set encoding after DEBUG RELOAD" { 70 r del myintset myhashset mylargeintset 71 for {set i 0} {$i < 100} {incr i} { r sadd myintset $i } 72 for {set i 0} {$i < 1280} {incr i} { r sadd mylargeintset $i } 73 for {set i 0} {$i < 256} {incr i} { r sadd myhashset [format "i%03d" $i] } 74 assert_encoding intset myintset 75 assert_encoding hashtable mylargeintset 76 assert_encoding hashtable myhashset 77 78 r debug reload 79 assert_encoding intset myintset 80 assert_encoding hashtable mylargeintset 81 assert_encoding hashtable myhashset 82 } 83 84 test {SREM basics - regular set} { 85 create_set myset {foo bar ciao} 86 assert_encoding hashtable myset 87 assert_equal 0 [r srem myset qux] 88 assert_equal 1 [r srem myset foo] 89 assert_equal {bar ciao} [lsort [r smembers myset]] 90 } 91 92 test {SREM basics - intset} { 93 create_set myset {3 4 5} 94 assert_encoding intset myset 95 assert_equal 0 [r srem myset 6] 96 assert_equal 1 [r srem myset 4] 97 assert_equal {3 5} [lsort [r smembers myset]] 98 } 99 100 test {SREM with multiple arguments} { 101 r del myset 102 r sadd myset a b c d 103 assert_equal 0 [r srem myset k k k] 104 assert_equal 2 [r srem myset b d x y] 105 lsort [r smembers myset] 106 } {a c} 107 108 test {SREM variadic version with more args needed to destroy the key} { 109 r del myset 110 r sadd myset 1 2 3 111 r srem myset 1 2 3 4 5 6 7 8 112 } {3} 113 114 foreach {type} {hashtable intset} { 115 for {set i 1} {$i <= 5} {incr i} { 116 r del [format "set%d" $i] 117 } 118 for {set i 0} {$i < 200} {incr i} { 119 r sadd set1 $i 120 r sadd set2 [expr $i+195] 121 } 122 foreach i {199 195 1000 2000} { 123 r sadd set3 $i 124 } 125 for {set i 5} {$i < 200} {incr i} { 126 r sadd set4 $i 127 } 128 r sadd set5 0 129 130 # To make sure the sets are encoded as the type we are testing -- also 131 # when the VM is enabled and the values may be swapped in and out 132 # while the tests are running -- an extra element is added to every 133 # set that determines its encoding. 134 set large 200 135 if {$type eq "hashtable"} { 136 set large foo 137 } 138 139 for {set i 1} {$i <= 5} {incr i} { 140 r sadd [format "set%d" $i] $large 141 } 142 143 test "Generated sets must be encoded as $type" { 144 for {set i 1} {$i <= 5} {incr i} { 145 assert_encoding $type [format "set%d" $i] 146 } 147 } 148 149 test "SINTER with two sets - $type" { 150 assert_equal [list 195 196 197 198 199 $large] [lsort [r sinter set1 set2]] 151 } 152 153 test "SINTERSTORE with two sets - $type" { 154 r sinterstore setres set1 set2 155 assert_encoding $type setres 156 assert_equal [list 195 196 197 198 199 $large] [lsort [r smembers setres]] 157 } 158 159 test "SINTERSTORE with two sets, after a DEBUG RELOAD - $type" { 160 r debug reload 161 r sinterstore setres set1 set2 162 assert_encoding $type setres 163 assert_equal [list 195 196 197 198 199 $large] [lsort [r smembers setres]] 164 } 165 166 test "SUNION with two sets - $type" { 167 set expected [lsort -uniq "[r smembers set1] [r smembers set2]"] 168 assert_equal $expected [lsort [r sunion set1 set2]] 169 } 170 171 test "SUNIONSTORE with two sets - $type" { 172 r sunionstore setres set1 set2 173 assert_encoding $type setres 174 set expected [lsort -uniq "[r smembers set1] [r smembers set2]"] 175 assert_equal $expected [lsort [r smembers setres]] 176 } 177 178 test "SINTER against three sets - $type" { 179 assert_equal [list 195 199 $large] [lsort [r sinter set1 set2 set3]] 180 } 181 182 test "SINTERSTORE with three sets - $type" { 183 r sinterstore setres set1 set2 set3 184 assert_equal [list 195 199 $large] [lsort [r smembers setres]] 185 } 186 187 test "SUNION with non existing keys - $type" { 188 set expected [lsort -uniq "[r smembers set1] [r smembers set2]"] 189 assert_equal $expected [lsort [r sunion nokey1 set1 set2 nokey2]] 190 } 191 192 test "SDIFF with two sets - $type" { 193 assert_equal {0 1 2 3 4} [lsort [r sdiff set1 set4]] 194 } 195 196 test "SDIFF with three sets - $type" { 197 assert_equal {1 2 3 4} [lsort [r sdiff set1 set4 set5]] 198 } 199 200 test "SDIFFSTORE with three sets - $type" { 201 r sdiffstore setres set1 set4 set5 202 # The type is determined by type of the first key to diff against. 203 # See the implementation for more information. 204 assert_encoding $type setres 205 assert_equal {1 2 3 4} [lsort [r smembers setres]] 206 } 207 } 208 209 test "SINTER against non-set should throw error" { 210 r set key1 x 211 assert_error "ERR*wrong kind*" {r sinter key1 noset} 212 } 213 214 test "SUNION against non-set should throw error" { 215 r set key1 x 216 assert_error "ERR*wrong kind*" {r sunion key1 noset} 217 } 218 219 test "SINTERSTORE against non existing keys should delete dstkey" { 220 r set setres xxx 221 assert_equal 0 [r sinterstore setres foo111 bar222] 222 assert_equal 0 [r exists setres] 223 } 224 225 test "SUNIONSTORE against non existing keys should delete dstkey" { 226 r set setres xxx 227 assert_equal 0 [r sunionstore setres foo111 bar222] 228 assert_equal 0 [r exists setres] 229 } 230 231 foreach {type contents} {hashtable {a b c} intset {1 2 3}} { 232 test "SPOP basics - $type" { 233 create_set myset $contents 234 assert_encoding $type myset 235 assert_equal $contents [lsort [list [r spop myset] [r spop myset] [r spop myset]]] 236 assert_equal 0 [r scard myset] 237 } 238 239 test "SRANDMEMBER - $type" { 240 create_set myset $contents 241 unset -nocomplain myset 242 array set myset {} 243 for {set i 0} {$i < 100} {incr i} { 244 set myset([r srandmember myset]) 1 245 } 246 assert_equal $contents [lsort [array names myset]] 247 } 248 } 249 250 proc setup_move {} { 251 r del myset3 myset4 252 create_set myset1 {1 a b} 253 create_set myset2 {2 3 4} 254 assert_encoding hashtable myset1 255 assert_encoding intset myset2 256 } 257 258 test "SMOVE basics - from regular set to intset" { 259 # move a non-integer element to an intset should convert encoding 260 setup_move 261 assert_equal 1 [r smove myset1 myset2 a] 262 assert_equal {1 b} [lsort [r smembers myset1]] 263 assert_equal {2 3 4 a} [lsort [r smembers myset2]] 264 assert_encoding hashtable myset2 265 266 # move an integer element should not convert the encoding 267 setup_move 268 assert_equal 1 [r smove myset1 myset2 1] 269 assert_equal {a b} [lsort [r smembers myset1]] 270 assert_equal {1 2 3 4} [lsort [r smembers myset2]] 271 assert_encoding intset myset2 272 } 273 274 test "SMOVE basics - from intset to regular set" { 275 setup_move 276 assert_equal 1 [r smove myset2 myset1 2] 277 assert_equal {1 2 a b} [lsort [r smembers myset1]] 278 assert_equal {3 4} [lsort [r smembers myset2]] 279 } 280 281 test "SMOVE non existing key" { 282 setup_move 283 assert_equal 0 [r smove myset1 myset2 foo] 284 assert_equal {1 a b} [lsort [r smembers myset1]] 285 assert_equal {2 3 4} [lsort [r smembers myset2]] 286 } 287 288 test "SMOVE non existing src set" { 289 setup_move 290 assert_equal 0 [r smove noset myset2 foo] 291 assert_equal {2 3 4} [lsort [r smembers myset2]] 292 } 293 294 test "SMOVE from regular set to non existing destination set" { 295 setup_move 296 assert_equal 1 [r smove myset1 myset3 a] 297 assert_equal {1 b} [lsort [r smembers myset1]] 298 assert_equal {a} [lsort [r smembers myset3]] 299 assert_encoding hashtable myset3 300 } 301 302 test "SMOVE from intset to non existing destination set" { 303 setup_move 304 assert_equal 1 [r smove myset2 myset3 2] 305 assert_equal {3 4} [lsort [r smembers myset2]] 306 assert_equal {2} [lsort [r smembers myset3]] 307 assert_encoding intset myset3 308 } 309 310 test "SMOVE wrong src key type" { 311 r set x 10 312 assert_error "ERR*wrong kind*" {r smove x myset2 foo} 313 } 314 315 test "SMOVE wrong dst key type" { 316 r set x 10 317 assert_error "ERR*wrong kind*" {r smove myset2 x foo} 318 } 319 320 tags {slow} { 321 test {intsets implementation stress testing} { 322 for {set j 0} {$j < 20} {incr j} { 323 unset -nocomplain s 324 array set s {} 325 r del s 326 set len [randomInt 1024] 327 for {set i 0} {$i < $len} {incr i} { 328 randpath { 329 set data [randomInt 65536] 330 } { 331 set data [randomInt 4294967296] 332 } { 333 set data [randomInt 18446744073709551616] 334 } 335 set s($data) {} 336 r sadd s $data 337 } 338 assert_equal [lsort [r smembers s]] [lsort [array names s]] 339 set len [array size s] 340 for {set i 0} {$i < $len} {incr i} { 341 set e [r spop s] 342 if {![info exists s($e)]} { 343 puts "Can't find '$e' on local array" 344 puts "Local array: [lsort [r smembers s]]" 345 puts "Remote array: [lsort [array names s]]" 346 error "exception" 347 } 348 array unset s $e 349 } 350 assert_equal [r scard s] 0 351 assert_equal [array size s] 0 352 } 353 } 354 } 355} 356