4 "set-max-intset-entries" 512
7 proc create_set
{key entries
} {
9 foreach entry $entries { r sadd
$key $entry }
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
]]
24 test
{SADD
, SCARD
, SISMEMBER
, SMEMBERS basics
- intset
} {
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
]]
36 test
{SADD against non
set} {
38 assert_error WRONGTYPE
* {r sadd mylist bar
}
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
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]
54 test
"SADD overflows the maximum allowed integers in an intset" {
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
62 test
{Variadic SADD
} {
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
]]
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
79 assert_encoding intset myintset
80 assert_encoding hashtable mylargeintset
81 assert_encoding hashtable myhashset
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
]]
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
]]
100 test
{SREM with multiple arguments
} {
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
]
108 test
{SREM variadic version with more args needed to
destroy the key
} {
111 r srem myset
1 2 3 4 5 6 7 8
114 foreach {type
} {hashtable intset
} {
115 for {set i
1} {$i <= 5} {incr i
} {
116 r del
[format "set%d" $i]
118 for {set i
0} {$i < 200} {incr i
} {
120 r sadd set2
[expr $i+195]
122 foreach i
{199 195 1000 2000} {
125 for {set i
5} {$i < 200} {incr i
} {
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.
135 if {$type eq
"hashtable"} {
139 for {set i
1} {$i <= 5} {incr i
} {
140 r sadd
[format "set%d" $i] $large
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]
149 test
"SINTER with two sets - $type" {
150 assert_equal
[list 195 196 197 198 199 $large] [lsort [r sinter set1 set2
]]
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
]]
159 test
"SINTERSTORE with two sets, after a DEBUG RELOAD - $type" {
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
]]
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
]]
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
]]
178 test
"SINTER against three sets - $type" {
179 assert_equal
[list 195 199 $large] [lsort [r sinter set1 set2 set3
]]
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
]]
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
]]
192 test
"SDIFF with two sets - $type" {
193 assert_equal
{0 1 2 3 4} [lsort [r sdiff set1 set4
]]
196 test
"SDIFF with three sets - $type" {
197 assert_equal
{1 2 3 4} [lsort [r sdiff set1 set4 set5
]]
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
]]
209 test
"SDIFF with first set empty" {
213 r sdiff set1 set2 set3
216 test
"SINTER against non-set should throw error" {
218 assert_error
"WRONGTYPE*" {r sinter key1 noset
}
221 test
"SUNION against non-set should throw error" {
223 assert_error
"WRONGTYPE*" {r sunion key1 noset
}
226 test
"SINTER should handle non existing key as empty" {
230 r sinter set1 set2 set3
233 test
"SINTER with same integer elements but different encoding" {
238 assert_encoding intset set1
239 assert_encoding hashtable set2
240 lsort [r sinter set1 set2
]
243 test
"SINTERSTORE against non existing keys should delete dstkey" {
245 assert_equal
0 [r sinterstore setres foo111 bar222
]
246 assert_equal
0 [r exists setres
]
249 test
"SUNIONSTORE against non existing keys should delete dstkey" {
251 assert_equal
0 [r sunionstore setres foo111 bar222
]
252 assert_equal
0 [r exists setres
]
255 foreach {type contents
} {hashtable
{a b c
} intset
{1 2 3}} {
256 test
"SPOP basics - $type" {
257 create_set myset
$contents
258 assert_encoding
$type myset
259 assert_equal
$contents [lsort [list [r spop myset
] [r spop myset
] [r spop myset
]]]
260 assert_equal
0 [r scard myset
]
263 test
"SRANDMEMBER - $type" {
264 create_set myset
$contents
265 unset -nocomplain myset
267 for {set i
0} {$i < 100} {incr i
} {
268 set myset
([r srandmember myset
]) 1
270 assert_equal
$contents [lsort [array names myset
]]
274 test
"SRANDMEMBER with <count> against non existing key" {
275 r srandmember nonexisting_key
100
278 foreach {type contents
} {
280 1 5 10 50 125 50000 33959417 4775547 65434162
281 12098459 427716 483706 2726473884 72615637475
282 MARY PATRICIA LINDA BARBARA ELIZABETH JENNIFER MARIA
283 SUSAN MARGARET DOROTHY LISA NANCY KAREN BETTY HELEN
284 SANDRA DONNA CAROL RUTH SHARON MICHELLE LAURA SARAH
285 KIMBERLY DEBORAH JESSICA SHIRLEY CYNTHIA ANGELA MELISSA
286 BRENDA AMY ANNA REBECCA VIRGINIA KATHLEEN
289 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
290 20 21 22 23 24 25 26 27 28 29
291 30 31 32 33 34 35 36 37 38 39
292 40 41 42 43 44 45 46 47 48 49
295 test
"SRANDMEMBER with <count> - $type" {
296 create_set myset
$contents
297 unset -nocomplain myset
299 foreach ele
[r smembers myset
] {
302 assert_equal
[lsort $contents] [lsort [array names myset
]]
304 # Make sure that a count of 0 is handled correctly.
305 assert_equal
[r srandmember myset
0] {}
307 # We'll stress different parts of the code, see the implementation
308 # of SRANDMEMBER for more information, but basically there are
309 # four different code paths.
311 # PATH 1: Use negative count.
313 # 1) Check that it returns repeated elements.
314 set res
[r srandmember myset
-100]
315 assert_equal
[llength $res] 100
317 # 2) Check that all the elements actually belong to the
320 assert
{[info exists myset
($ele)]}
323 # 3) Check that eventually all the elements are returned.
324 unset -nocomplain auxset
326 while {$iterations != 0} {
328 set res
[r srandmember myset
-10]
332 if {[lsort [array names myset
]] eq
333 [lsort [array names auxset
]]} {
337 assert
{$iterations != 0}
339 # PATH 2: positive count (unique behavior) with requested size
340 # equal or greater than set size.
341 foreach size
{50 100} {
342 set res
[r srandmember myset
$size]
343 assert_equal
[llength $res] 50
344 assert_equal
[lsort $res] [lsort [array names myset
]]
347 # PATH 3: Ask almost as elements as there are in the set.
348 # In this case the implementation will duplicate the original
349 # set and will remove random elements up to the requested size.
351 # PATH 4: Ask a number of elements definitely smaller than
354 # We can test both the code paths just changing the size but
355 # using the same code.
357 foreach size
{45 5} {
358 set res
[r srandmember myset
$size]
359 assert_equal
[llength $res] $size
361 # 1) Check that all the elements actually belong to the
364 assert
{[info exists myset
($ele)]}
367 # 2) Check that eventually all the elements are returned.
368 unset -nocomplain auxset
370 while {$iterations != 0} {
372 set res
[r srandmember myset
-10]
376 if {[lsort [array names myset
]] eq
377 [lsort [array names auxset
]]} {
381 assert
{$iterations != 0}
388 create_set myset1
{1 a b
}
389 create_set myset2
{2 3 4}
390 assert_encoding hashtable myset1
391 assert_encoding intset myset2
394 test
"SMOVE basics - from regular set to intset" {
395 # move a non-integer element to an intset should convert encoding
397 assert_equal
1 [r smove myset1 myset2 a
]
398 assert_equal
{1 b
} [lsort [r smembers myset1
]]
399 assert_equal
{2 3 4 a
} [lsort [r smembers myset2
]]
400 assert_encoding hashtable myset2
402 # move an integer element should not convert the encoding
404 assert_equal
1 [r smove myset1 myset2
1]
405 assert_equal
{a b
} [lsort [r smembers myset1
]]
406 assert_equal
{1 2 3 4} [lsort [r smembers myset2
]]
407 assert_encoding intset myset2
410 test
"SMOVE basics - from intset to regular set" {
412 assert_equal
1 [r smove myset2 myset1
2]
413 assert_equal
{1 2 a b
} [lsort [r smembers myset1
]]
414 assert_equal
{3 4} [lsort [r smembers myset2
]]
417 test
"SMOVE non existing key" {
419 assert_equal
0 [r smove myset1 myset2 foo
]
420 assert_equal
{1 a b
} [lsort [r smembers myset1
]]
421 assert_equal
{2 3 4} [lsort [r smembers myset2
]]
424 test
"SMOVE non existing src set" {
426 assert_equal
0 [r smove noset myset2 foo
]
427 assert_equal
{2 3 4} [lsort [r smembers myset2
]]
430 test
"SMOVE from regular set to non existing destination set" {
432 assert_equal
1 [r smove myset1 myset3 a
]
433 assert_equal
{1 b
} [lsort [r smembers myset1
]]
434 assert_equal
{a
} [lsort [r smembers myset3
]]
435 assert_encoding hashtable myset3
438 test
"SMOVE from intset to non existing destination set" {
440 assert_equal
1 [r smove myset2 myset3
2]
441 assert_equal
{3 4} [lsort [r smembers myset2
]]
442 assert_equal
{2} [lsort [r smembers myset3
]]
443 assert_encoding intset myset3
446 test
"SMOVE wrong src key type" {
448 assert_error
"WRONGTYPE*" {r smove x myset2 foo
}
451 test
"SMOVE wrong dst key type" {
453 assert_error
"WRONGTYPE*" {r smove myset2 x foo
}
456 test
"SMOVE with identical source and destination" {
460 lsort [r smembers
set]
464 test
{intsets implementation stress testing
} {
465 for {set j
0} {$j < 20} {incr j
} {
469 set len
[randomInt
1024]
470 for {set i
0} {$i < $len} {incr i
} {
472 set data
[randomInt
65536]
474 set data
[randomInt
4294967296]
476 set data
[randomInt
18446744073709551616]
481 assert_equal
[lsort [r smembers s
]] [lsort [array names s
]]
482 set len
[array size s
]
483 for {set i
0} {$i < $len} {incr i
} {
485 if {![info exists s
($e)]} {
486 puts "Can't find '$e' on local array"
487 puts "Local array: [lsort [r smembers s]]"
488 puts "Remote array: [lsort [array names s]]"
493 assert_equal
[r scard s
] 0
494 assert_equal
[array size s
] 0