]> git.saurik.com Git - redis.git/blob - tests/unit/type/set.tcl
a1b655ef8891abb6b0cf54f3d862080056120d0a
[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 overflows the maximum allowed integers in an intset" {
49 r del myset
50 for {set i 0} {$i < 512} {incr i} { r sadd myset $i }
51 assert_encoding intset myset
52 assert_equal 1 [r sadd myset 512]
53 assert_encoding hashtable myset
54 }
55
56 test "Set encoding after DEBUG RELOAD" {
57 r del myintset myhashset mylargeintset
58 for {set i 0} {$i < 100} {incr i} { r sadd myintset $i }
59 for {set i 0} {$i < 1280} {incr i} { r sadd mylargeintset $i }
60 for {set i 0} {$i < 256} {incr i} { r sadd myhashset [format "i%03d" $i] }
61 assert_encoding intset myintset
62 assert_encoding hashtable mylargeintset
63 assert_encoding hashtable myhashset
64
65 r debug reload
66 assert_encoding intset myintset
67 assert_encoding hashtable mylargeintset
68 assert_encoding hashtable myhashset
69 }
70
71 test {SREM basics - regular set} {
72 create_set myset {foo bar ciao}
73 assert_encoding hashtable myset
74 assert_equal 0 [r srem myset qux]
75 assert_equal 1 [r srem myset foo]
76 assert_equal {bar ciao} [lsort [r smembers myset]]
77 }
78
79 test {SREM basics - intset} {
80 create_set myset {3 4 5}
81 assert_encoding intset myset
82 assert_equal 0 [r srem myset 6]
83 assert_equal 1 [r srem myset 4]
84 assert_equal {3 5} [lsort [r smembers myset]]
85 }
86
87 foreach {type} {hashtable intset} {
88 for {set i 1} {$i <= 5} {incr i} {
89 r del [format "set%d" $i]
90 }
91 for {set i 0} {$i < 200} {incr i} {
92 r sadd set1 $i
93 r sadd set2 [expr $i+195]
94 }
95 foreach i {199 195 1000 2000} {
96 r sadd set3 $i
97 }
98 for {set i 5} {$i < 200} {incr i} {
99 r sadd set4 $i
100 }
101 r sadd set5 0
102
103 # it is possible that a hashtable encoded only contains integers,
104 # because it is converted from an intset to a hashtable when a
105 # non-integer element is added and then removed.
106 if {$type eq "hashtable"} {
107 for {set i 1} {$i <= 5} {incr i} {
108 r sadd [format "set%d" $i] foo
109 r srem [format "set%d" $i] foo
110 }
111 }
112
113 test "Generated sets must be encoded as $type" {
114 for {set i 1} {$i <= 5} {incr i} {
115 assert_encoding $type [format "set%d" $i]
116 }
117 }
118
119 test "SINTER with two sets - $type" {
120 assert_equal {195 196 197 198 199} [lsort [r sinter set1 set2]]
121 }
122
123 test "SINTERSTORE with two sets - $type" {
124 r sinterstore setres set1 set2
125 assert_encoding intset setres
126 assert_equal {195 196 197 198 199} [lsort [r smembers setres]]
127 }
128
129 test "SINTERSTORE with two sets, after a DEBUG RELOAD - $type" {
130 r debug reload
131 r sinterstore setres set1 set2
132 assert_encoding intset setres
133 assert_equal {195 196 197 198 199} [lsort [r smembers setres]]
134 }
135
136 test "SUNION with two sets - $type" {
137 set expected [lsort -uniq "[r smembers set1] [r smembers set2]"]
138 assert_equal $expected [lsort [r sunion set1 set2]]
139 }
140
141 test "SUNIONSTORE with two sets - $type" {
142 r sunionstore setres set1 set2
143 assert_encoding intset setres
144 set expected [lsort -uniq "[r smembers set1] [r smembers set2]"]
145 assert_equal $expected [lsort [r smembers setres]]
146 }
147
148 test "SINTER against three sets - $type" {
149 assert_equal {195 199} [lsort [r sinter set1 set2 set3]]
150 }
151
152 test "SINTERSTORE with three sets - $type" {
153 r sinterstore setres set1 set2 set3
154 assert_equal {195 199} [r smembers setres]
155 }
156
157 test "SUNION with non existing keys - $type" {
158 set expected [lsort -uniq "[r smembers set1] [r smembers set2]"]
159 assert_equal $expected [lsort [r sunion nokey1 set1 set2 nokey2]]
160 }
161
162 test "SDIFF with two sets - $type" {
163 assert_equal {0 1 2 3 4} [lsort [r sdiff set1 set4]]
164 }
165
166 test "SDIFF with three sets - $type" {
167 assert_equal {1 2 3 4} [lsort [r sdiff set1 set4 set5]]
168 }
169
170 test "SDIFFSTORE with three sets - $type" {
171 r sdiffstore setres set1 set4 set5
172 assert_encoding intset setres
173 assert_equal {1 2 3 4} [lsort [r smembers setres]]
174 }
175 }
176
177 test "SINTER against non-set should throw error" {
178 r set key1 x
179 assert_error "ERR*wrong kind*" {r sinter key1 noset}
180 }
181
182 test "SUNION against non-set should throw error" {
183 r set key1 x
184 assert_error "ERR*wrong kind*" {r sunion key1 noset}
185 }
186
187 test "SINTERSTORE against non existing keys should delete dstkey" {
188 r set setres xxx
189 assert_equal 0 [r sinterstore setres foo111 bar222]
190 assert_equal 0 [r exists setres]
191 }
192
193 test "SUNIONSTORE against non existing keys should delete dstkey" {
194 r set setres xxx
195 assert_equal 0 [r sunionstore setres foo111 bar222]
196 assert_equal 0 [r exists setres]
197 }
198
199 foreach {type contents} {hashtable {a b c} intset {1 2 3}} {
200 test "SPOP basics - $type" {
201 create_set myset $contents
202 assert_encoding $type myset
203 assert_equal $contents [lsort [list [r spop myset] [r spop myset] [r spop myset]]]
204 assert_equal 0 [r scard myset]
205 }
206
207 test "SRANDMEMBER - $type" {
208 create_set myset $contents
209 unset -nocomplain myset
210 array set myset {}
211 for {set i 0} {$i < 100} {incr i} {
212 set myset([r srandmember myset]) 1
213 }
214 assert_equal $contents [lsort [array names myset]]
215 }
216 }
217
218 proc setup_move {} {
219 r del myset3 myset4
220 create_set myset1 {1 a b}
221 create_set myset2 {2 3 4}
222 assert_encoding hashtable myset1
223 assert_encoding intset myset2
224 }
225
226 test "SMOVE basics - from regular set to intset" {
227 # move a non-integer element to an intset should convert encoding
228 setup_move
229 assert_equal 1 [r smove myset1 myset2 a]
230 assert_equal {1 b} [lsort [r smembers myset1]]
231 assert_equal {2 3 4 a} [lsort [r smembers myset2]]
232 assert_encoding hashtable myset2
233
234 # move an integer element should not convert the encoding
235 setup_move
236 assert_equal 1 [r smove myset1 myset2 1]
237 assert_equal {a b} [lsort [r smembers myset1]]
238 assert_equal {1 2 3 4} [lsort [r smembers myset2]]
239 assert_encoding intset myset2
240 }
241
242 test "SMOVE basics - from intset to regular set" {
243 setup_move
244 assert_equal 1 [r smove myset2 myset1 2]
245 assert_equal {1 2 a b} [lsort [r smembers myset1]]
246 assert_equal {3 4} [lsort [r smembers myset2]]
247 }
248
249 test "SMOVE non existing key" {
250 setup_move
251 assert_equal 0 [r smove myset1 myset2 foo]
252 assert_equal {1 a b} [lsort [r smembers myset1]]
253 assert_equal {2 3 4} [lsort [r smembers myset2]]
254 }
255
256 test "SMOVE non existing src set" {
257 setup_move
258 assert_equal 0 [r smove noset myset2 foo]
259 assert_equal {2 3 4} [lsort [r smembers myset2]]
260 }
261
262 test "SMOVE from regular set to non existing destination set" {
263 setup_move
264 assert_equal 1 [r smove myset1 myset3 a]
265 assert_equal {1 b} [lsort [r smembers myset1]]
266 assert_equal {a} [lsort [r smembers myset3]]
267 assert_encoding hashtable myset3
268 }
269
270 test "SMOVE from intset to non existing destination set" {
271 setup_move
272 assert_equal 1 [r smove myset2 myset3 2]
273 assert_equal {3 4} [lsort [r smembers myset2]]
274 assert_equal {2} [lsort [r smembers myset3]]
275 assert_encoding intset myset3
276 }
277
278 test "SMOVE wrong src key type" {
279 r set x 10
280 assert_error "ERR*wrong kind*" {r smove x myset2 foo}
281 }
282
283 test "SMOVE wrong dst key type" {
284 r set x 10
285 assert_error "ERR*wrong kind*" {r smove myset2 x foo}
286 }
287 }