]> git.saurik.com Git - redis.git/blob - tests/unit/type/list.tcl
81eabd3a92f54dfa88ae6df17954cf962a486f20
[redis.git] / tests / unit / type / list.tcl
1 start_server {
2 tags {"list"}
3 overrides {
4 "list-max-ziplist-value" 16
5 "list-max-ziplist-entries" 256
6 }
7 } {
8 test {LPUSH, RPUSH, LLENGTH, LINDEX - ziplist} {
9 # first lpush then rpush
10 assert_equal 1 [r lpush myziplist1 a]
11 assert_equal 2 [r rpush myziplist1 b]
12 assert_equal 3 [r rpush myziplist1 c]
13 assert_equal 3 [r llen myziplist1]
14 assert_equal a [r lindex myziplist1 0]
15 assert_equal b [r lindex myziplist1 1]
16 assert_equal c [r lindex myziplist1 2]
17 assert_encoding ziplist myziplist1
18
19 # first rpush then lpush
20 assert_equal 1 [r rpush myziplist2 a]
21 assert_equal 2 [r lpush myziplist2 b]
22 assert_equal 3 [r lpush myziplist2 c]
23 assert_equal 3 [r llen myziplist2]
24 assert_equal c [r lindex myziplist2 0]
25 assert_equal b [r lindex myziplist2 1]
26 assert_equal a [r lindex myziplist2 2]
27 assert_encoding ziplist myziplist2
28 }
29
30 test {LPUSH, RPUSH, LLENGTH, LINDEX - regular list} {
31 # use a string of length 17 to ensure a regular list is used
32 set large_value "aaaaaaaaaaaaaaaaa"
33
34 # first lpush then rpush
35 assert_equal 1 [r lpush mylist1 $large_value]
36 assert_encoding list mylist1
37 assert_equal 2 [r rpush mylist1 b]
38 assert_equal 3 [r rpush mylist1 c]
39 assert_equal 3 [r llen mylist1]
40 assert_equal $large_value [r lindex mylist1 0]
41 assert_equal b [r lindex mylist1 1]
42 assert_equal c [r lindex mylist1 2]
43
44 # first rpush then lpush
45 assert_equal 1 [r rpush mylist2 $large_value]
46 assert_encoding list mylist2
47 assert_equal 2 [r lpush mylist2 b]
48 assert_equal 3 [r lpush mylist2 c]
49 assert_equal 3 [r llen mylist2]
50 assert_equal c [r lindex mylist2 0]
51 assert_equal b [r lindex mylist2 1]
52 assert_equal $large_value [r lindex mylist2 2]
53 }
54
55 test {LPUSHX, RPUSHX, LPUSHXAFTER, RPUSHXAFTER - ziplist} {
56 r del xlist
57 assert_equal 0 [r lpushx xlist a]
58 assert_equal 0 [r rpushx xlist a]
59 assert_equal 1 [r rpush xlist b]
60 assert_equal 2 [r rpush xlist c]
61 assert_equal 3 [r rpushx xlist d]
62 assert_equal 4 [r lpushx xlist a]
63 assert_encoding ziplist xlist
64 assert_equal {a b c d} [r lrange xlist 0 10]
65
66 assert_equal 5 [r linsert xlist before c zz]
67 assert_equal {a b zz c d} [r lrange xlist 0 10]
68 assert_equal 6 [r linsert xlist after c yy]
69 assert_equal {a b zz c yy d} [r lrange xlist 0 10]
70 assert_equal 7 [r linsert xlist after d dd]
71 assert_equal 7 [r linsert xlist after bad ddd]
72 assert_equal {a b zz c yy d dd} [r lrange xlist 0 10]
73 assert_equal 8 [r linsert xlist before a aa]
74 assert_equal 8 [r linsert xlist before bad aaa]
75 assert_equal {aa a b zz c yy d dd} [r lrange xlist 0 10]
76 assert_equal 9 [r linsert xlist before aa 42]
77 assert_equal 42 [r lrange xlist 0 0]
78 }
79
80 test {LPUSHX, RPUSHX, LPUSHXAFTER, RPUSHXAFTER - regular list} {
81 set large_value "aaaaaaaaaaaaaaaaa"
82
83 r del xlist
84 assert_equal 0 [r lpushx xlist a]
85 assert_equal 0 [r rpushx xlist a]
86 assert_equal 1 [r rpush xlist $large_value]
87 assert_equal 2 [r rpush xlist c]
88 assert_equal 3 [r rpushx xlist d]
89 assert_equal 4 [r lpushx xlist a]
90 assert_encoding list xlist
91 assert_equal {a aaaaaaaaaaaaaaaaa c d} [r lrange xlist 0 10]
92
93 assert_equal 5 [r linsert xlist before c zz]
94 assert_equal {a aaaaaaaaaaaaaaaaa zz c d} [r lrange xlist 0 10]
95 assert_equal 6 [r linsert xlist after c yy]
96 assert_equal {a aaaaaaaaaaaaaaaaa zz c yy d} [r lrange xlist 0 10]
97 assert_equal 7 [r linsert xlist after d dd]
98 assert_equal 7 [r linsert xlist after bad ddd]
99 assert_equal {a aaaaaaaaaaaaaaaaa zz c yy d dd} [r lrange xlist 0 10]
100 assert_equal 8 [r linsert xlist before a aa]
101 assert_equal 8 [r linsert xlist before bad aaa]
102 assert_equal {aa a aaaaaaaaaaaaaaaaa zz c yy d dd} [r lrange xlist 0 10]
103 assert_equal 9 [r linsert xlist before aa 42]
104 assert_equal 42 [r lrange xlist 0 0]
105 }
106
107 test {DEL a list - ziplist} {
108 assert_equal 1 [r del myziplist2]
109 assert_equal 0 [r exists myziplist2]
110 assert_equal 0 [r llen myziplist2]
111 }
112
113 test {DEL a list - regular list} {
114 assert_equal 1 [r del mylist2]
115 assert_equal 0 [r exists mylist2]
116 assert_equal 0 [r llen mylist2]
117 }
118
119 proc create_ziplist {key entries} {
120 r del $key
121 foreach entry $entries { r rpush $key $entry }
122 assert_encoding ziplist $key
123 }
124
125 proc create_list {key entries} {
126 r del $key
127 r rpush $key "aaaaaaaaaaaaaaaaa"
128 foreach entry $entries { r rpush $key $entry }
129 assert_equal "aaaaaaaaaaaaaaaaa" [r lpop $key]
130 assert_encoding list $key
131 }
132
133 foreach {type num} {ziplist 250 list 500} {
134 proc check_numbered_list_consistency {key} {
135 set len [r llen $key]
136 for {set i 0} {$i < $len} {incr i} {
137 assert_equal $i [r lindex $key $i]
138 assert_equal [expr $len-1-$i] [r lindex $key [expr (-$i)-1]]
139 }
140 }
141
142 proc check_random_access_consistency {key} {
143 set len [r llen $key]
144 for {set i 0} {$i < $len} {incr i} {
145 set rint [expr int(rand()*$len)]
146 assert_equal $rint [r lindex $key $rint]
147 assert_equal [expr $len-1-$rint] [r lindex $key [expr (-$rint)-1]]
148 }
149 }
150
151 test "LINDEX consistency test - $type" {
152 r del mylist
153 for {set i 0} {$i < $num} {incr i} {
154 r rpush mylist $i
155 }
156 assert_encoding $type mylist
157 check_numbered_list_consistency mylist
158 }
159
160 test "LINDEX random access - $type" {
161 assert_encoding $type mylist
162 check_random_access_consistency mylist
163 }
164
165 test "Check if list is still ok after a DEBUG RELOAD - $type" {
166 r debug reload
167 assert_encoding $type mylist
168 check_numbered_list_consistency mylist
169 check_random_access_consistency mylist
170 }
171 }
172
173 test {LLEN against non-list value error} {
174 r del mylist
175 r set mylist foobar
176 assert_error ERR* {r llen mylist}
177 }
178
179 test {LLEN against non existing key} {
180 assert_equal 0 [r llen not-a-key]
181 }
182
183 test {LINDEX against non-list value error} {
184 assert_error ERR* {r lindex mylist 0}
185 }
186
187 test {LINDEX against non existing key} {
188 assert_equal "" [r lindex not-a-key 10]
189 }
190
191 test {LPUSH against non-list value error} {
192 assert_error ERR* {r lpush mylist 0}
193 }
194
195 test {RPUSH against non-list value error} {
196 assert_error ERR* {r rpush mylist 0}
197 }
198
199 foreach type {ziplist list} {
200 test "RPOPLPUSH base case - $type" {
201 r del mylist1 mylist2
202 create_$type mylist1 {a b c d}
203 assert_equal d [r rpoplpush mylist1 mylist2]
204 assert_equal c [r rpoplpush mylist1 mylist2]
205 assert_equal {a b} [r lrange mylist1 0 -1]
206 assert_equal {c d} [r lrange mylist2 0 -1]
207 assert_encoding ziplist mylist2
208 }
209
210 test "RPOPLPUSH with the same list as src and dst - $type" {
211 create_$type mylist {a b c}
212 assert_equal {a b c} [r lrange mylist 0 -1]
213 assert_equal c [r rpoplpush mylist mylist]
214 assert_equal {c a b} [r lrange mylist 0 -1]
215 }
216
217 foreach othertype {ziplist list} {
218 test "RPOPLPUSH with $type source and existing target $othertype" {
219 create_$type srclist {a b c d}
220 create_$othertype dstlist {x}
221 assert_equal d [r rpoplpush srclist dstlist]
222 assert_equal c [r rpoplpush srclist dstlist]
223 assert_equal {a b} [r lrange srclist 0 -1]
224 assert_equal {c d x} [r lrange dstlist 0 -1]
225 }
226 }
227 }
228
229 test {RPOPLPUSH against non existing key} {
230 r del srclist dstlist
231 assert_equal {} [r rpoplpush srclist dstlist]
232 assert_equal 0 [r exists srclist]
233 assert_equal 0 [r exists dstlist]
234 }
235
236 test {RPOPLPUSH against non list src key} {
237 r del srclist dstlist
238 r set srclist x
239 assert_error ERR* {r rpoplpush srclist dstlist}
240 assert_type string srclist
241 assert_equal 0 [r exists newlist]
242 }
243
244 test {RPOPLPUSH against non list dst key} {
245 create_ziplist srclist {a b c d}
246 r set dstlist x
247 assert_error ERR* {r rpoplpush srclist dstlist}
248 assert_type string dstlist
249 assert_equal {a b c d} [r lrange srclist 0 -1]
250 }
251
252 test {RPOPLPUSH against non existing src key} {
253 r del srclist dstlist
254 assert_equal {} [r rpoplpush srclist dstlist]
255 } {}
256
257 foreach type {ziplist list} {
258 test "Basic LPOP/RPOP - $type" {
259 create_$type mylist {0 1 2}
260 assert_equal 0 [r lpop mylist]
261 assert_equal 2 [r rpop mylist]
262 assert_equal 1 [r lpop mylist]
263 assert_equal 0 [r llen mylist]
264
265 # pop on empty list
266 assert_equal {} [r lpop mylist]
267 assert_equal {} [r rpop mylist]
268 }
269 }
270
271 test {LPOP/RPOP against non list value} {
272 r set notalist foo
273 assert_error ERR*kind* {r lpop notalist}
274 assert_error ERR*kind* {r rpop notalist}
275 }
276
277 foreach {type num} {ziplist 250 list 500} {
278 test "Mass RPOP/LPOP - $type" {
279 r del mylist
280 set sum1 0
281 for {set i 0} {$i < $num} {incr i} {
282 r lpush mylist $i
283 incr sum1 $i
284 }
285 assert_encoding $type mylist
286 set sum2 0
287 for {set i 0} {$i < [expr $num/2]} {incr i} {
288 incr sum2 [r lpop mylist]
289 incr sum2 [r rpop mylist]
290 }
291 assert_equal $sum1 $sum2
292 }
293 }
294
295 foreach type {ziplist list} {
296 test "LRANGE basics - $type" {
297 create_$type mylist {0 1 2 3 4 5 6 7 8 9}
298 assert_equal {1 2 3 4 5 6 7 8} [r lrange mylist 1 -2]
299 assert_equal {7 8 9} [r lrange mylist -3 -1]
300 assert_equal {4} [r lrange mylist 4 4]
301 }
302
303 test "LRANGE inverted indexes - $type" {
304 create_$type mylist {0 1 2 3 4 5 6 7 8 9}
305 assert_equal {} [r lrange mylist 6 2]
306 }
307
308 test "LRANGE out of range indexes including the full list - $type" {
309 create_$type mylist {1 2 3}
310 assert_equal {1 2 3} [r lrange mylist -1000 1000]
311 }
312 }
313
314 test {LRANGE against non existing key} {
315 assert_equal {} [r lrange nosuchkey 0 1]
316 }
317
318 foreach type {ziplist list} {
319 test "LTRIM basics - $type" {
320 create_$type mylist "foo"
321 for {set i 0} {$i < 100} {incr i} {
322 r lpush mylist $i
323 r ltrim mylist 0 4
324 }
325 r lrange mylist 0 -1
326 } {99 98 97 96 95}
327
328 test "LTRIM stress testing - $type" {
329 set mylist {}
330 for {set i 0} {$i < 20} {incr i} {
331 lappend mylist $i
332 }
333
334 for {set j 0} {$j < 100} {incr j} {
335 create_$type mylist $mylist
336
337 # Trim at random
338 set a [randomInt 20]
339 set b [randomInt 20]
340 r ltrim mylist $a $b
341 assert_equal [lrange $mylist $a $b] [r lrange mylist 0 -1]
342 }
343 }
344
345 }
346
347 foreach type {ziplist list} {
348 test "LSET - $type" {
349 create_$type mylist {99 98 97 96 95}
350 r lset mylist 1 foo
351 r lset mylist -1 bar
352 assert_equal {99 foo 97 96 bar} [r lrange mylist 0 -1]
353 }
354
355 test "LSET out of range index - $type" {
356 assert_error ERR*range* {r lset mylist 10 foo}
357 }
358 }
359
360 test {LSET against non existing key} {
361 assert_error ERR*key* {r lset nosuchkey 10 foo}
362 }
363
364 test {LSET against non list value} {
365 r set nolist foobar
366 assert_error ERR*value* {r lset nolist 0 foo}
367 }
368
369 foreach type {ziplist list} {
370 test "LREM remove all the occurrences - $type" {
371 create_$type mylist {foo bar foobar foobared zap bar test foo}
372 assert_equal 2 [r lrem mylist 0 bar]
373 assert_equal {foo foobar foobared zap test foo} [r lrange mylist 0 -1]
374 }
375
376 test "LREM remove the first occurrence - $type" {
377 assert_equal 1 [r lrem mylist 1 foo]
378 assert_equal {foobar foobared zap test foo} [r lrange mylist 0 -1]
379 }
380
381 test "LREM remove non existing element - $type" {
382 assert_equal 0 [r lrem mylist 1 nosuchelement]
383 assert_equal {foobar foobared zap test foo} [r lrange mylist 0 -1]
384 }
385
386 test "LREM starting from tail with negative count - $type" {
387 create_$type mylist {foo bar foobar foobared zap bar test foo foo}
388 assert_equal 1 [r lrem mylist -1 bar]
389 assert_equal {foo bar foobar foobared zap test foo foo} [r lrange mylist 0 -1]
390 }
391
392 test "LREM starting from tail with negative count (2) - $type" {
393 assert_equal 2 [r lrem mylist -2 foo]
394 assert_equal {foo bar foobar foobared zap test} [r lrange mylist 0 -1]
395 }
396
397 test "LREM deleting objects that may be int encoded - $type" {
398 create_$type myotherlist {1 2 3}
399 assert_equal 1 [r lrem myotherlist 1 2]
400 assert_equal 2 [r llen myotherlist]
401 }
402 }
403 }