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