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