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