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