]> git.saurik.com Git - redis.git/blob - tests/unit/type/list.tcl
616abd21a04972a1fbf5d673888bb312daa5d8dc
[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 # We need a value larger than list-max-ziplist-value to make sure
9 # the list has the right encoding when it is swapped in again.
10 array set largevalue {}
11 set largevalue(ziplist) "hello"
12 set largevalue(linkedlist) [string repeat "hello" 4]
13
14 test {LPUSH, RPUSH, LLENGTH, LINDEX - ziplist} {
15 # first lpush then rpush
16 assert_equal 1 [r lpush myziplist1 a]
17 assert_equal 2 [r rpush myziplist1 b]
18 assert_equal 3 [r rpush myziplist1 c]
19 assert_equal 3 [r llen myziplist1]
20 assert_equal a [r lindex myziplist1 0]
21 assert_equal b [r lindex myziplist1 1]
22 assert_equal c [r lindex myziplist1 2]
23 assert_encoding ziplist myziplist1
24
25 # first rpush then lpush
26 assert_equal 1 [r rpush myziplist2 a]
27 assert_equal 2 [r lpush myziplist2 b]
28 assert_equal 3 [r lpush myziplist2 c]
29 assert_equal 3 [r llen myziplist2]
30 assert_equal c [r lindex myziplist2 0]
31 assert_equal b [r lindex myziplist2 1]
32 assert_equal a [r lindex myziplist2 2]
33 assert_encoding ziplist myziplist2
34 }
35
36 test {LPUSH, RPUSH, LLENGTH, LINDEX - regular list} {
37 # first lpush then rpush
38 assert_equal 1 [r lpush mylist1 $largevalue(linkedlist)]
39 assert_encoding linkedlist mylist1
40 assert_equal 2 [r rpush mylist1 b]
41 assert_equal 3 [r rpush mylist1 c]
42 assert_equal 3 [r llen mylist1]
43 assert_equal $largevalue(linkedlist) [r lindex mylist1 0]
44 assert_equal b [r lindex mylist1 1]
45 assert_equal c [r lindex mylist1 2]
46
47 # first rpush then lpush
48 assert_equal 1 [r rpush mylist2 $largevalue(linkedlist)]
49 assert_encoding linkedlist mylist2
50 assert_equal 2 [r lpush mylist2 b]
51 assert_equal 3 [r lpush mylist2 c]
52 assert_equal 3 [r llen mylist2]
53 assert_equal c [r lindex mylist2 0]
54 assert_equal b [r lindex mylist2 1]
55 assert_equal $largevalue(linkedlist) [r lindex mylist2 2]
56 }
57
58 test {Variadic RPUSH/LPUSH} {
59 r del mylist
60 assert_equal 4 [r lpush mylist a b c d]
61 assert_equal 8 [r rpush mylist 0 1 2 3]
62 assert_equal {d c b a 0 1 2 3} [r lrange mylist 0 -1]
63 }
64
65 test {DEL a list - ziplist} {
66 assert_equal 1 [r del myziplist2]
67 assert_equal 0 [r exists myziplist2]
68 assert_equal 0 [r llen myziplist2]
69 }
70
71 test {DEL a list - regular list} {
72 assert_equal 1 [r del mylist2]
73 assert_equal 0 [r exists mylist2]
74 assert_equal 0 [r llen mylist2]
75 }
76
77 proc create_ziplist {key entries} {
78 r del $key
79 foreach entry $entries { r rpush $key $entry }
80 assert_encoding ziplist $key
81 }
82
83 proc create_linkedlist {key entries} {
84 r del $key
85 foreach entry $entries { r rpush $key $entry }
86 assert_encoding linkedlist $key
87 }
88
89 foreach {type large} [array get largevalue] {
90 test "BLPOP, BRPOP: single existing list - $type" {
91 set rd [redis_deferring_client]
92 create_$type blist "a b $large c d"
93
94 $rd blpop blist 1
95 assert_equal {blist a} [$rd read]
96 $rd brpop blist 1
97 assert_equal {blist d} [$rd read]
98
99 $rd blpop blist 1
100 assert_equal {blist b} [$rd read]
101 $rd brpop blist 1
102 assert_equal {blist c} [$rd read]
103 }
104
105 test "BLPOP, BRPOP: multiple existing lists - $type" {
106 set rd [redis_deferring_client]
107 create_$type blist1 "a $large c"
108 create_$type blist2 "d $large f"
109
110 $rd blpop blist1 blist2 1
111 assert_equal {blist1 a} [$rd read]
112 $rd brpop blist1 blist2 1
113 assert_equal {blist1 c} [$rd read]
114 assert_equal 1 [r llen blist1]
115 assert_equal 3 [r llen blist2]
116
117 $rd blpop blist2 blist1 1
118 assert_equal {blist2 d} [$rd read]
119 $rd brpop blist2 blist1 1
120 assert_equal {blist2 f} [$rd read]
121 assert_equal 1 [r llen blist1]
122 assert_equal 1 [r llen blist2]
123 }
124
125 test "BLPOP, BRPOP: second list has an entry - $type" {
126 set rd [redis_deferring_client]
127 r del blist1
128 create_$type blist2 "d $large f"
129
130 $rd blpop blist1 blist2 1
131 assert_equal {blist2 d} [$rd read]
132 $rd brpop blist1 blist2 1
133 assert_equal {blist2 f} [$rd read]
134 assert_equal 0 [r llen blist1]
135 assert_equal 1 [r llen blist2]
136 }
137
138 test "BRPOPLPUSH - $type" {
139 r del target
140
141 set rd [redis_deferring_client]
142 create_$type blist "a b $large c d"
143
144 $rd brpoplpush blist target 1
145 assert_equal d [$rd read]
146
147 assert_equal d [r rpop target]
148 assert_equal "a b $large c" [r lrange blist 0 -1]
149 }
150 }
151
152 test "BLPOP with variadic LPUSH" {
153 set rd [redis_deferring_client]
154 r del blist target
155 $rd blpop blist 0
156 assert_equal 2 [r lpush blist foo bar]
157 assert_equal {blist foo} [$rd read]
158 assert_equal bar [lindex [r lrange blist 0 -1] 0]
159 }
160
161 test "BRPOPLPUSH with zero timeout should block indefinitely" {
162 set rd [redis_deferring_client]
163 r del blist target
164 $rd brpoplpush blist target 0
165 after 1000
166 r rpush blist foo
167 assert_equal foo [$rd read]
168 assert_equal {foo} [r lrange target 0 -1]
169 }
170
171 test "BRPOPLPUSH with a client BLPOPing the target list" {
172 set rd [redis_deferring_client]
173 set rd2 [redis_deferring_client]
174 r del blist target
175 $rd2 blpop target 0
176 $rd brpoplpush blist target 0
177 after 1000
178 r rpush blist foo
179 assert_equal foo [$rd read]
180 assert_equal {target foo} [$rd2 read]
181 assert_equal 0 [r exists target]
182 }
183
184 test "BRPOPLPUSH with wrong source type" {
185 set rd [redis_deferring_client]
186 r del blist target
187 r set blist nolist
188 $rd brpoplpush blist target 1
189 assert_error "ERR*wrong kind*" {$rd read}
190 }
191
192 test "BRPOPLPUSH with wrong destination type" {
193 set rd [redis_deferring_client]
194 r del blist target
195 r set target nolist
196 r lpush blist foo
197 $rd brpoplpush blist target 1
198 assert_error "ERR*wrong kind*" {$rd read}
199
200 set rd [redis_deferring_client]
201 r del blist target
202 r set target nolist
203 $rd brpoplpush blist target 0
204 after 1000
205 r rpush blist foo
206 assert_error "ERR*wrong kind*" {$rd read}
207 assert_equal {foo} [r lrange blist 0 -1]
208 }
209
210 test "BRPOPLPUSH with multiple blocked clients" {
211 set rd1 [redis_deferring_client]
212 set rd2 [redis_deferring_client]
213 r del blist target1 target2
214 r set target1 nolist
215 $rd1 brpoplpush blist target1 0
216 $rd2 brpoplpush blist target2 0
217 r lpush blist foo
218
219 assert_error "ERR*wrong kind*" {$rd1 read}
220 assert_equal {foo} [$rd2 read]
221 assert_equal {foo} [r lrange target2 0 -1]
222 }
223
224 test "Linked BRPOPLPUSH" {
225 set rd1 [redis_deferring_client]
226 set rd2 [redis_deferring_client]
227
228 r del list1 list2 list3
229
230 $rd1 brpoplpush list1 list2 0
231 $rd2 brpoplpush list2 list3 0
232
233 r rpush list1 foo
234
235 assert_equal {} [r lrange list1 0 -1]
236 assert_equal {} [r lrange list2 0 -1]
237 assert_equal {foo} [r lrange list3 0 -1]
238 }
239
240 test "Circular BRPOPLPUSH" {
241 set rd1 [redis_deferring_client]
242 set rd2 [redis_deferring_client]
243
244 r del list1 list2
245
246 $rd1 brpoplpush list1 list2 0
247 $rd2 brpoplpush list2 list1 0
248
249 r rpush list1 foo
250
251 assert_equal {foo} [r lrange list1 0 -1]
252 assert_equal {} [r lrange list2 0 -1]
253 }
254
255 test "Self-referential BRPOPLPUSH" {
256 set rd [redis_deferring_client]
257
258 r del blist
259
260 $rd brpoplpush blist blist 0
261
262 r rpush blist foo
263
264 assert_equal {foo} [r lrange blist 0 -1]
265 }
266
267 test "BRPOPLPUSH inside a transaction" {
268 r del xlist target
269 r lpush xlist foo
270 r lpush xlist bar
271
272 r multi
273 r brpoplpush xlist target 0
274 r brpoplpush xlist target 0
275 r brpoplpush xlist target 0
276 r lrange xlist 0 -1
277 r lrange target 0 -1
278 r exec
279 } {foo bar {} {} {bar foo}}
280
281 test {BRPOPLPUSH timeout} {
282 set rd [redis_deferring_client]
283
284 $rd brpoplpush foo_list bar_list 1
285 after 2000
286 $rd read
287 } {}
288
289 foreach {pop} {BLPOP BRPOP} {
290 test "$pop: with single empty list argument" {
291 set rd [redis_deferring_client]
292 r del blist1
293 $rd $pop blist1 1
294 r rpush blist1 foo
295 assert_equal {blist1 foo} [$rd read]
296 assert_equal 0 [r exists blist1]
297 }
298
299 test "$pop: with negative timeout" {
300 set rd [redis_deferring_client]
301 $rd $pop blist1 -1
302 assert_error "ERR*is negative*" {$rd read}
303 }
304
305 test "$pop: with non-integer timeout" {
306 set rd [redis_deferring_client]
307 $rd $pop blist1 1.1
308 assert_error "ERR*not an integer*" {$rd read}
309 }
310
311 test "$pop: with zero timeout should block indefinitely" {
312 # To test this, use a timeout of 0 and wait a second.
313 # The blocking pop should still be waiting for a push.
314 set rd [redis_deferring_client]
315 $rd $pop blist1 0
316 after 1000
317 r rpush blist1 foo
318 assert_equal {blist1 foo} [$rd read]
319 }
320
321 test "$pop: second argument is not a list" {
322 set rd [redis_deferring_client]
323 r del blist1 blist2
324 r set blist2 nolist
325 $rd $pop blist1 blist2 1
326 assert_error "ERR*wrong kind*" {$rd read}
327 }
328
329 test "$pop: timeout" {
330 set rd [redis_deferring_client]
331 r del blist1 blist2
332 $rd $pop blist1 blist2 1
333 assert_equal {} [$rd read]
334 }
335
336 test "$pop: arguments are empty" {
337 set rd [redis_deferring_client]
338 r del blist1 blist2
339
340 $rd $pop blist1 blist2 1
341 r rpush blist1 foo
342 assert_equal {blist1 foo} [$rd read]
343 assert_equal 0 [r exists blist1]
344 assert_equal 0 [r exists blist2]
345
346 $rd $pop blist1 blist2 1
347 r rpush blist2 foo
348 assert_equal {blist2 foo} [$rd read]
349 assert_equal 0 [r exists blist1]
350 assert_equal 0 [r exists blist2]
351 }
352 }
353
354 test {BLPOP inside a transaction} {
355 r del xlist
356 r lpush xlist foo
357 r lpush xlist bar
358 r multi
359 r blpop xlist 0
360 r blpop xlist 0
361 r blpop xlist 0
362 r exec
363 } {{xlist bar} {xlist foo} {}}
364
365 test {LPUSHX, RPUSHX - generic} {
366 r del xlist
367 assert_equal 0 [r lpushx xlist a]
368 assert_equal 0 [r llen xlist]
369 assert_equal 0 [r rpushx xlist a]
370 assert_equal 0 [r llen xlist]
371 }
372
373 foreach {type large} [array get largevalue] {
374 test "LPUSHX, RPUSHX - $type" {
375 create_$type xlist "$large c"
376 assert_equal 3 [r rpushx xlist d]
377 assert_equal 4 [r lpushx xlist a]
378 assert_equal "a $large c d" [r lrange xlist 0 -1]
379 }
380
381 test "LINSERT - $type" {
382 create_$type xlist "a $large c d"
383 assert_equal 5 [r linsert xlist before c zz]
384 assert_equal "a $large zz c d" [r lrange xlist 0 10]
385 assert_equal 6 [r linsert xlist after c yy]
386 assert_equal "a $large zz c yy d" [r lrange xlist 0 10]
387 assert_equal 7 [r linsert xlist after d dd]
388 assert_equal -1 [r linsert xlist after bad ddd]
389 assert_equal "a $large zz c yy d dd" [r lrange xlist 0 10]
390 assert_equal 8 [r linsert xlist before a aa]
391 assert_equal -1 [r linsert xlist before bad aaa]
392 assert_equal "aa a $large zz c yy d dd" [r lrange xlist 0 10]
393
394 # check inserting integer encoded value
395 assert_equal 9 [r linsert xlist before aa 42]
396 assert_equal 42 [r lrange xlist 0 0]
397 }
398 }
399
400 test {LPUSHX, RPUSHX convert from ziplist to list} {
401 set large $largevalue(linkedlist)
402
403 # convert when a large value is pushed
404 create_ziplist xlist a
405 assert_equal 2 [r rpushx xlist $large]
406 assert_encoding linkedlist xlist
407 create_ziplist xlist a
408 assert_equal 2 [r lpushx xlist $large]
409 assert_encoding linkedlist xlist
410
411 # convert when the length threshold is exceeded
412 create_ziplist xlist [lrepeat 256 a]
413 assert_equal 257 [r rpushx xlist b]
414 assert_encoding linkedlist xlist
415 create_ziplist xlist [lrepeat 256 a]
416 assert_equal 257 [r lpushx xlist b]
417 assert_encoding linkedlist xlist
418 }
419
420 test {LINSERT convert from ziplist to list} {
421 set large $largevalue(linkedlist)
422
423 # convert when a large value is inserted
424 create_ziplist xlist a
425 assert_equal 2 [r linsert xlist before a $large]
426 assert_encoding linkedlist xlist
427 create_ziplist xlist a
428 assert_equal 2 [r linsert xlist after a $large]
429 assert_encoding linkedlist xlist
430
431 # convert when the length threshold is exceeded
432 create_ziplist xlist [lrepeat 256 a]
433 assert_equal 257 [r linsert xlist before a a]
434 assert_encoding linkedlist xlist
435 create_ziplist xlist [lrepeat 256 a]
436 assert_equal 257 [r linsert xlist after a a]
437 assert_encoding linkedlist xlist
438
439 # don't convert when the value could not be inserted
440 create_ziplist xlist [lrepeat 256 a]
441 assert_equal -1 [r linsert xlist before foo a]
442 assert_encoding ziplist xlist
443 create_ziplist xlist [lrepeat 256 a]
444 assert_equal -1 [r linsert xlist after foo a]
445 assert_encoding ziplist xlist
446 }
447
448 foreach {type num} {ziplist 250 linkedlist 500} {
449 proc check_numbered_list_consistency {key} {
450 set len [r llen $key]
451 for {set i 0} {$i < $len} {incr i} {
452 assert_equal $i [r lindex $key $i]
453 assert_equal [expr $len-1-$i] [r lindex $key [expr (-$i)-1]]
454 }
455 }
456
457 proc check_random_access_consistency {key} {
458 set len [r llen $key]
459 for {set i 0} {$i < $len} {incr i} {
460 set rint [expr int(rand()*$len)]
461 assert_equal $rint [r lindex $key $rint]
462 assert_equal [expr $len-1-$rint] [r lindex $key [expr (-$rint)-1]]
463 }
464 }
465
466 test "LINDEX consistency test - $type" {
467 r del mylist
468 for {set i 0} {$i < $num} {incr i} {
469 r rpush mylist $i
470 }
471 assert_encoding $type mylist
472 check_numbered_list_consistency mylist
473 }
474
475 test "LINDEX random access - $type" {
476 assert_encoding $type mylist
477 check_random_access_consistency mylist
478 }
479
480 test "Check if list is still ok after a DEBUG RELOAD - $type" {
481 r debug reload
482 assert_encoding $type mylist
483 check_numbered_list_consistency mylist
484 check_random_access_consistency mylist
485 }
486 }
487
488 test {LLEN against non-list value error} {
489 r del mylist
490 r set mylist foobar
491 assert_error ERR* {r llen mylist}
492 }
493
494 test {LLEN against non existing key} {
495 assert_equal 0 [r llen not-a-key]
496 }
497
498 test {LINDEX against non-list value error} {
499 assert_error ERR* {r lindex mylist 0}
500 }
501
502 test {LINDEX against non existing key} {
503 assert_equal "" [r lindex not-a-key 10]
504 }
505
506 test {LPUSH against non-list value error} {
507 assert_error ERR* {r lpush mylist 0}
508 }
509
510 test {RPUSH against non-list value error} {
511 assert_error ERR* {r rpush mylist 0}
512 }
513
514 foreach {type large} [array get largevalue] {
515 test "RPOPLPUSH base case - $type" {
516 r del mylist1 mylist2
517 create_$type mylist1 "a $large c d"
518 assert_equal d [r rpoplpush mylist1 mylist2]
519 assert_equal c [r rpoplpush mylist1 mylist2]
520 assert_equal "a $large" [r lrange mylist1 0 -1]
521 assert_equal "c d" [r lrange mylist2 0 -1]
522 assert_encoding ziplist mylist2
523 }
524
525 test "RPOPLPUSH with the same list as src and dst - $type" {
526 create_$type mylist "a $large c"
527 assert_equal "a $large c" [r lrange mylist 0 -1]
528 assert_equal c [r rpoplpush mylist mylist]
529 assert_equal "c a $large" [r lrange mylist 0 -1]
530 }
531
532 foreach {othertype otherlarge} [array get largevalue] {
533 test "RPOPLPUSH with $type source and existing target $othertype" {
534 create_$type srclist "a b c $large"
535 create_$othertype dstlist "$otherlarge"
536 assert_equal $large [r rpoplpush srclist dstlist]
537 assert_equal c [r rpoplpush srclist dstlist]
538 assert_equal "a b" [r lrange srclist 0 -1]
539 assert_equal "c $large $otherlarge" [r lrange dstlist 0 -1]
540
541 # When we rpoplpush'ed a large value, dstlist should be
542 # converted to the same encoding as srclist.
543 if {$type eq "linkedlist"} {
544 assert_encoding linkedlist dstlist
545 }
546 }
547 }
548 }
549
550 test {RPOPLPUSH against non existing key} {
551 r del srclist dstlist
552 assert_equal {} [r rpoplpush srclist dstlist]
553 assert_equal 0 [r exists srclist]
554 assert_equal 0 [r exists dstlist]
555 }
556
557 test {RPOPLPUSH against non list src key} {
558 r del srclist dstlist
559 r set srclist x
560 assert_error ERR* {r rpoplpush srclist dstlist}
561 assert_type string srclist
562 assert_equal 0 [r exists newlist]
563 }
564
565 test {RPOPLPUSH against non list dst key} {
566 create_ziplist srclist {a b c d}
567 r set dstlist x
568 assert_error ERR* {r rpoplpush srclist dstlist}
569 assert_type string dstlist
570 assert_equal {a b c d} [r lrange srclist 0 -1]
571 }
572
573 test {RPOPLPUSH against non existing src key} {
574 r del srclist dstlist
575 assert_equal {} [r rpoplpush srclist dstlist]
576 } {}
577
578 foreach {type large} [array get largevalue] {
579 test "Basic LPOP/RPOP - $type" {
580 create_$type mylist "$large 1 2"
581 assert_equal $large [r lpop mylist]
582 assert_equal 2 [r rpop mylist]
583 assert_equal 1 [r lpop mylist]
584 assert_equal 0 [r llen mylist]
585
586 # pop on empty list
587 assert_equal {} [r lpop mylist]
588 assert_equal {} [r rpop mylist]
589 }
590 }
591
592 test {LPOP/RPOP against non list value} {
593 r set notalist foo
594 assert_error ERR*kind* {r lpop notalist}
595 assert_error ERR*kind* {r rpop notalist}
596 }
597
598 foreach {type num} {ziplist 250 linkedlist 500} {
599 test "Mass RPOP/LPOP - $type" {
600 r del mylist
601 set sum1 0
602 for {set i 0} {$i < $num} {incr i} {
603 r lpush mylist $i
604 incr sum1 $i
605 }
606 assert_encoding $type mylist
607 set sum2 0
608 for {set i 0} {$i < [expr $num/2]} {incr i} {
609 incr sum2 [r lpop mylist]
610 incr sum2 [r rpop mylist]
611 }
612 assert_equal $sum1 $sum2
613 }
614 }
615
616 foreach {type large} [array get largevalue] {
617 test "LRANGE basics - $type" {
618 create_$type mylist "$large 1 2 3 4 5 6 7 8 9"
619 assert_equal {1 2 3 4 5 6 7 8} [r lrange mylist 1 -2]
620 assert_equal {7 8 9} [r lrange mylist -3 -1]
621 assert_equal {4} [r lrange mylist 4 4]
622 }
623
624 test "LRANGE inverted indexes - $type" {
625 create_$type mylist "$large 1 2 3 4 5 6 7 8 9"
626 assert_equal {} [r lrange mylist 6 2]
627 }
628
629 test "LRANGE out of range indexes including the full list - $type" {
630 create_$type mylist "$large 1 2 3"
631 assert_equal "$large 1 2 3" [r lrange mylist -1000 1000]
632 }
633
634 test "LRANGE out of range negative end index - $type" {
635 create_$type mylist "$large 1 2 3"
636 assert_equal $large [r lrange mylist 0 -4]
637 assert_equal {} [r lrange mylist 0 -5]
638 }
639 }
640
641 test {LRANGE against non existing key} {
642 assert_equal {} [r lrange nosuchkey 0 1]
643 }
644
645 foreach {type large} [array get largevalue] {
646 proc trim_list {type min max} {
647 upvar 1 large large
648 r del mylist
649 create_$type mylist "1 2 3 4 $large"
650 r ltrim mylist $min $max
651 r lrange mylist 0 -1
652 }
653
654 test "LTRIM basics - $type" {
655 assert_equal "1" [trim_list $type 0 0]
656 assert_equal "1 2" [trim_list $type 0 1]
657 assert_equal "1 2 3" [trim_list $type 0 2]
658 assert_equal "2 3" [trim_list $type 1 2]
659 assert_equal "2 3 4 $large" [trim_list $type 1 -1]
660 assert_equal "2 3 4" [trim_list $type 1 -2]
661 assert_equal "4 $large" [trim_list $type -2 -1]
662 assert_equal "$large" [trim_list $type -1 -1]
663 assert_equal "1 2 3 4 $large" [trim_list $type -5 -1]
664 assert_equal "1 2 3 4 $large" [trim_list $type -10 10]
665 assert_equal "1 2 3 4 $large" [trim_list $type 0 5]
666 assert_equal "1 2 3 4 $large" [trim_list $type 0 10]
667 }
668
669 test "LTRIM out of range negative end index - $type" {
670 assert_equal {1} [trim_list $type 0 -5]
671 assert_equal {} [trim_list $type 0 -6]
672 }
673
674 tags {"slow"} {
675 test "LTRIM stress testing - $type" {
676 set mylist {}
677 set startlen 32
678 r del mylist
679
680 # Start with the large value to ensure the
681 # right encoding is used.
682 r rpush mylist $large
683 lappend mylist $large
684
685 for {set i 0} {$i < $startlen} {incr i} {
686 set str [randomInt 9223372036854775807]
687 r rpush mylist $str
688 lappend mylist $str
689 }
690
691 for {set i 0} {$i < 1000} {incr i} {
692 set min [expr {int(rand()*$startlen)}]
693 set max [expr {$min+int(rand()*$startlen)}]
694 set mylist [lrange $mylist $min $max]
695 r ltrim mylist $min $max
696 assert_equal $mylist [r lrange mylist 0 -1]
697
698 for {set j [r llen mylist]} {$j < $startlen} {incr j} {
699 set str [randomInt 9223372036854775807]
700 r rpush mylist $str
701 lappend mylist $str
702 }
703 }
704 }
705 }
706 }
707
708 foreach {type large} [array get largevalue] {
709 test "LSET - $type" {
710 create_$type mylist "99 98 $large 96 95"
711 r lset mylist 1 foo
712 r lset mylist -1 bar
713 assert_equal "99 foo $large 96 bar" [r lrange mylist 0 -1]
714 }
715
716 test "LSET out of range index - $type" {
717 assert_error ERR*range* {r lset mylist 10 foo}
718 }
719 }
720
721 test {LSET against non existing key} {
722 assert_error ERR*key* {r lset nosuchkey 10 foo}
723 }
724
725 test {LSET against non list value} {
726 r set nolist foobar
727 assert_error ERR*value* {r lset nolist 0 foo}
728 }
729
730 foreach {type e} [array get largevalue] {
731 test "LREM remove all the occurrences - $type" {
732 create_$type mylist "$e foo bar foobar foobared zap bar test foo"
733 assert_equal 2 [r lrem mylist 0 bar]
734 assert_equal "$e foo foobar foobared zap test foo" [r lrange mylist 0 -1]
735 }
736
737 test "LREM remove the first occurrence - $type" {
738 assert_equal 1 [r lrem mylist 1 foo]
739 assert_equal "$e foobar foobared zap test foo" [r lrange mylist 0 -1]
740 }
741
742 test "LREM remove non existing element - $type" {
743 assert_equal 0 [r lrem mylist 1 nosuchelement]
744 assert_equal "$e foobar foobared zap test foo" [r lrange mylist 0 -1]
745 }
746
747 test "LREM starting from tail with negative count - $type" {
748 create_$type mylist "$e foo bar foobar foobared zap bar test foo foo"
749 assert_equal 1 [r lrem mylist -1 bar]
750 assert_equal "$e foo bar foobar foobared zap test foo foo" [r lrange mylist 0 -1]
751 }
752
753 test "LREM starting from tail with negative count (2) - $type" {
754 assert_equal 2 [r lrem mylist -2 foo]
755 assert_equal "$e foo bar foobar foobared zap test" [r lrange mylist 0 -1]
756 }
757
758 test "LREM deleting objects that may be int encoded - $type" {
759 create_$type myotherlist "$e 1 2 3"
760 assert_equal 1 [r lrem myotherlist 1 2]
761 assert_equal 3 [r llen myotherlist]
762 }
763
764 }
765 }
766
767 start_server {
768 tags {list ziplist}
769 overrides {
770 "list-max-ziplist-value" 200000
771 "list-max-ziplist-entries" 256
772 }
773 } {
774 test {Explicit regression for a list bug} {
775 set mylist {49376042582 {BkG2o\pIC]4YYJa9cJ4GWZalG[4tin;1D2whSkCOW`mX;SFXGyS8sedcff3fQI^tgPCC@^Nu1J6o]meM@Lko]t_jRyo<xSJ1oObDYd`ppZuW6P@fS278YaOx=s6lvdFlMbP0[SbkI^Kr\HBXtuFaA^mDx:yzS4a[skiiPWhT<nNfAf=aQVfclcuwDrfe;iVuKdNvB9kbfq>tK?tH[\EvWqS]b`o2OCtjg:?nUTwdjpcUm]y:pg5q24q7LlCOwQE^}}
776 r del l
777 r rpush l [lindex $mylist 0]
778 r rpush l [lindex $mylist 1]
779 assert_equal [r lindex l 0] [lindex $mylist 0]
780 assert_equal [r lindex l 1] [lindex $mylist 1]
781 }
782
783 tags {slow} {
784 test {ziplist implementation: value encoding and backlink} {
785 for {set j 0} {$j < 100} {incr j} {
786 r del l
787 set l {}
788 for {set i 0} {$i < 200} {incr i} {
789 randpath {
790 set data [string repeat x [randomInt 100000]]
791 } {
792 set data [randomInt 65536]
793 } {
794 set data [randomInt 4294967296]
795 } {
796 set data [randomInt 18446744073709551616]
797 }
798 lappend l $data
799 r rpush l $data
800 }
801 assert_equal [llength $l] [r llen l]
802 # Traverse backward
803 for {set i 199} {$i >= 0} {incr i -1} {
804 if {[lindex $l $i] ne [r lindex l $i]} {
805 assert_equal [lindex $l $i] [r lindex l $i]
806 }
807 }
808 }
809 }
810
811 test {ziplist implementation: encoding stress testing} {
812 for {set j 0} {$j < 200} {incr j} {
813 r del l
814 set l {}
815 set len [randomInt 400]
816 for {set i 0} {$i < $len} {incr i} {
817 set rv [randomValue]
818 randpath {
819 lappend l $rv
820 r rpush l $rv
821 } {
822 set l [concat [list $rv] $l]
823 r lpush l $rv
824 }
825 }
826 assert_equal [llength $l] [r llen l]
827 for {set i 0} {$i < 200} {incr i} {
828 if {[lindex $l $i] ne [r lindex l $i]} {
829 assert_equal [lindex $l $i] [r lindex l $i]
830 }
831 }
832 }
833 }
834 }
835 }