diff --git a/tests/support/test.tcl b/tests/support/test.tcl index d2674da1..4caa6ca7 100644 --- a/tests/support/test.tcl +++ b/tests/support/test.tcl @@ -2,7 +2,38 @@ set ::passed 0 set ::failed 0 set ::testnum 0 -proc test {name code okpattern} { +proc assert_match {pattern value} { + if {![string match $pattern $value]} { + puts "!! ERROR\nExpected '$value' to match '$pattern'" + error "assertion" + } +} + +proc assert_equal {expected value} { + if {$expected ne $value} { + puts "!! ERROR\nExpected '$value' to be equal to '$expected'" + error "assertion" + } +} + +proc assert_error {pattern code} { + if {[catch $code error]} { + assert_match $pattern $error + } else { + puts "!! ERROR\nExpected an error but nothing was catched" + error "assertion" + } +} + +proc assert_encoding {enc key} { + assert_match "* encoding:$enc *" [r debug object $key] +} + +proc assert_type {type key} { + assert_equal $type [r type $key] +} + +proc test {name code {okpattern notspecified}} { # abort if tagged with a tag to deny foreach tag $::denytags { if {[lsearch $::tags $tag] >= 0} { @@ -28,16 +59,21 @@ proc test {name code okpattern} { puts -nonewline [format "#%03d %-68s " $::testnum $name] flush stdout if {[catch {set retval [uplevel 1 $code]} error]} { - puts "EXCEPTION" - puts "\nCaught error: $error" - error "exception" - } - if {$okpattern eq $retval || [string match $okpattern $retval]} { - puts "PASSED" - incr ::passed + if {$error eq "assertion"} { + incr ::failed + } else { + puts "EXCEPTION" + puts "\nCaught error: $error" + error "exception" + } } else { - puts "!! ERROR expected\n'$okpattern'\nbut got\n'$retval'" - incr ::failed + if {$okpattern eq "notspecified" || $okpattern eq $retval || [string match $okpattern $retval]} { + puts "PASSED" + incr ::passed + } else { + puts "!! ERROR expected\n'$okpattern'\nbut got\n'$retval'" + incr ::failed + } } if {$::traceleaks} { if {![string match {*0 leaks*} [exec leaks redis-server]]} { diff --git a/tests/test_helper.tcl b/tests/test_helper.tcl index 95508cda..5aa24248 100644 --- a/tests/test_helper.tcl +++ b/tests/test_helper.tcl @@ -73,7 +73,7 @@ proc main {} { execute_tests "integration/aof" # run tests with VM enabled - set ::global_overrides [list [list vm-enabled yes]] + set ::global_overrides {vm-enabled yes} execute_tests "unit/protocol" execute_tests "unit/basic" execute_tests "unit/type/list" diff --git a/tests/unit/type/list.tcl b/tests/unit/type/list.tcl index 2a5d13bd..00c6ddb2 100644 --- a/tests/unit/type/list.tcl +++ b/tests/unit/type/list.tcl @@ -1,221 +1,345 @@ -start_server {tags {"list"}} { - test {Basic LPUSH, RPUSH, LLENGTH, LINDEX} { - set res [r lpush mylist a] - append res [r lpush mylist b] - append res [r rpush mylist c] - append res [r llen mylist] - append res [r rpush anotherlist d] - append res [r lpush anotherlist e] - append res [r llen anotherlist] - append res [r lindex mylist 0] - append res [r lindex mylist 1] - append res [r lindex mylist 2] - append res [r lindex anotherlist 0] - append res [r lindex anotherlist 1] - list $res [r lindex mylist 100] - } {1233122baced {}} +start_server { + tags {"list"} + overrides { + "list-max-ziplist-value" 16 + "list-max-ziplist-entries" 256 + } +} { + test {LPUSH, RPUSH, LLENGTH, LINDEX - ziplist} { + # first lpush then rpush + assert_equal 1 [r lpush myziplist1 a] + assert_equal 2 [r rpush myziplist1 b] + assert_equal 3 [r rpush myziplist1 c] + assert_equal 3 [r llen myziplist1] + assert_equal a [r lindex myziplist1 0] + assert_equal b [r lindex myziplist1 1] + assert_equal c [r lindex myziplist1 2] + assert_encoding ziplist myziplist1 - test {DEL a list} { - r del mylist - r exists mylist - } {0} + # first rpush then lpush + assert_equal 1 [r rpush myziplist2 a] + assert_equal 2 [r lpush myziplist2 b] + assert_equal 3 [r lpush myziplist2 c] + assert_equal 3 [r llen myziplist2] + assert_equal c [r lindex myziplist2 0] + assert_equal b [r lindex myziplist2 1] + assert_equal a [r lindex myziplist2 2] + assert_encoding ziplist myziplist2 + } - test {Create a long list and check every single element with LINDEX} { - set ok 0 - for {set i 0} {$i < 1000} {incr i} { - r rpush mylist $i + test {LPUSH, RPUSH, LLENGTH, LINDEX - regular list} { + # use a string of length 17 to ensure a regular list is used + set large_value "aaaaaaaaaaaaaaaaa" + + # first lpush then rpush + assert_equal 1 [r lpush mylist1 $large_value] + assert_encoding list mylist1 + assert_equal 2 [r rpush mylist1 b] + assert_equal 3 [r rpush mylist1 c] + assert_equal 3 [r llen mylist1] + assert_equal $large_value [r lindex mylist1 0] + assert_equal b [r lindex mylist1 1] + assert_equal c [r lindex mylist1 2] + + # first rpush then lpush + assert_equal 1 [r rpush mylist2 $large_value] + assert_encoding list mylist2 + assert_equal 2 [r lpush mylist2 b] + assert_equal 3 [r lpush mylist2 c] + assert_equal 3 [r llen mylist2] + assert_equal c [r lindex mylist2 0] + assert_equal b [r lindex mylist2 1] + assert_equal $large_value [r lindex mylist2 2] + } + + test {DEL a list - ziplist} { + assert_equal 1 [r del myziplist2] + assert_equal 0 [r exists myziplist2] + assert_equal 0 [r llen myziplist2] + } + + test {DEL a list - regular list} { + assert_equal 1 [r del mylist2] + assert_equal 0 [r exists mylist2] + assert_equal 0 [r llen mylist2] + } + + proc populate_with_numbers {key num} { + for {set i 0} {$i < $num} {incr i} { + r rpush $key $i } - for {set i 0} {$i < 1000} {incr i} { - if {[r lindex mylist $i] eq $i} {incr ok} - if {[r lindex mylist [expr (-$i)-1]] eq [expr 999-$i]} { - incr ok - } - } - format $ok - } {2000} + } - test {Test elements with LINDEX in random access} { - set ok 0 - for {set i 0} {$i < 1000} {incr i} { - set rint [expr int(rand()*1000)] - if {[r lindex mylist $rint] eq $rint} {incr ok} - if {[r lindex mylist [expr (-$rint)-1]] eq [expr 999-$rint]} { - incr ok - } + proc check_numbered_list_consistency {key} { + set len [r llen $key] + for {set i 0} {$i < $len} {incr i} { + assert_equal $i [r lindex $key $i] + assert_equal [expr $len-1-$i] [r lindex $key [expr (-$i)-1]] } - format $ok - } {2000} + } - test {Check if the list is still ok after a DEBUG RELOAD} { + proc check_random_access_consistency {key} { + set len [r llen $key] + for {set i 0} {$i < $len} {incr i} { + set rint [expr int(rand()*$len)] + assert_equal $rint [r lindex $key $rint] + assert_equal [expr $len-1-$rint] [r lindex $key [expr (-$rint)-1]] + } + } + + test {LINDEX consistency test - ziplist} { + populate_with_numbers myziplist 250 + assert_encoding ziplist myziplist + } + + test {LINDEX consistency test - regular list} { + populate_with_numbers mylist 500 + assert_encoding list mylist + check_numbered_list_consistency mylist + } + + test {LINDEX random access - ziplist} { + assert_encoding ziplist myziplist + check_random_access_consistency myziplist + } + + test {LINDEX random access - regular list} { + assert_encoding list mylist + check_random_access_consistency mylist + } + + test {Check if both list encodings are still ok after a DEBUG RELOAD} { r debug reload - set ok 0 - for {set i 0} {$i < 1000} {incr i} { - set rint [expr int(rand()*1000)] - if {[r lindex mylist $rint] eq $rint} {incr ok} - if {[r lindex mylist [expr (-$rint)-1]] eq [expr 999-$rint]} { - incr ok - } - } - format $ok - } {2000} + assert_encoding ziplist myziplist + check_numbered_list_consistency myziplist + assert_encoding list mylist + check_numbered_list_consistency mylist + } test {LLEN against non-list value error} { r del mylist r set mylist foobar - catch {r llen mylist} err - format $err - } {ERR*} + assert_error ERR* {r llen mylist} + } test {LLEN against non existing key} { - r llen not-a-key - } {0} + assert_equal 0 [r llen not-a-key] + } test {LINDEX against non-list value error} { - catch {r lindex mylist 0} err - format $err - } {ERR*} + assert_error ERR* {r lindex mylist 0} + } test {LINDEX against non existing key} { - r lindex not-a-key 10 - } {} + assert_equal "" [r lindex not-a-key 10] + } test {LPUSH against non-list value error} { - catch {r lpush mylist 0} err - format $err - } {ERR*} + assert_error ERR* {r lpush mylist 0} + } test {RPUSH against non-list value error} { - catch {r rpush mylist 0} err - format $err - } {ERR*} + assert_error ERR* {r rpush mylist 0} + } - test {RPOPLPUSH base case} { - r del mylist - r rpush mylist a - r rpush mylist b - r rpush mylist c - r rpush mylist d - set v1 [r rpoplpush mylist newlist] - set v2 [r rpoplpush mylist newlist] - set l1 [r lrange mylist 0 -1] - set l2 [r lrange newlist 0 -1] - list $v1 $v2 $l1 $l2 - } {d c {a b} {c d}} + proc create_ziplist {key entries} { + r del $key + foreach entry $entries { r rpush $key $entry } + assert_match *encoding:ziplist* [r debug object $key] + } - test {RPOPLPUSH with the same list as src and dst} { - r del mylist - r rpush mylist a - r rpush mylist b - r rpush mylist c - set l1 [r lrange mylist 0 -1] - set v [r rpoplpush mylist mylist] - set l2 [r lrange mylist 0 -1] - list $l1 $v $l2 - } {{a b c} c {c a b}} + proc create_regular_list {key entries} { + r del $key + r rpush $key "aaaaaaaaaaaaaaaaa" + foreach entry $entries { r rpush $key $entry } + assert_equal "aaaaaaaaaaaaaaaaa" [r lpop $key] + assert_match *encoding:list* [r debug object $key] + } - test {RPOPLPUSH target list already exists} { - r del mylist - r del newlist - r rpush mylist a - r rpush mylist b - r rpush mylist c - r rpush mylist d - r rpush newlist x - set v1 [r rpoplpush mylist newlist] - set v2 [r rpoplpush mylist newlist] - set l1 [r lrange mylist 0 -1] - set l2 [r lrange newlist 0 -1] - list $v1 $v2 $l1 $l2 - } {d c {a b} {c d x}} + test {RPOPLPUSH base case - ziplist} { + r del mylist1 mylist2 + create_ziplist mylist1 {a b c d} + assert_equal d [r rpoplpush mylist1 mylist2] + assert_equal c [r rpoplpush mylist1 mylist2] + assert_equal {a b} [r lrange mylist1 0 -1] + assert_equal {c d} [r lrange mylist2 0 -1] + assert_encoding ziplist mylist2 + } + + test {RPOPLPUSH base case - regular list} { + r del mylist1 mylist2 + create_regular_list mylist1 {a b c d} + assert_equal d [r rpoplpush mylist1 mylist2] + assert_equal c [r rpoplpush mylist1 mylist2] + assert_equal {a b} [r lrange mylist1 0 -1] + assert_equal {c d} [r lrange mylist2 0 -1] + assert_encoding ziplist mylist2 + } + + test {RPOPLPUSH with the same list as src and dst - ziplist} { + create_ziplist myziplist {a b c} + assert_equal {a b c} [r lrange myziplist 0 -1] + assert_equal c [r rpoplpush myziplist myziplist] + assert_equal {c a b} [r lrange myziplist 0 -1] + } + + test {RPOPLPUSH with the same list as src and dst - regular list} { + create_regular_list mylist {a b c} + assert_equal {a b c} [r lrange mylist 0 -1] + assert_equal c [r rpoplpush mylist mylist] + assert_equal {c a b} [r lrange mylist 0 -1] + } + + test {RPOPLPUSH target list already exists, being a ziplist} { + create_regular_list srclist {a b c d} + create_ziplist dstlist {x} + assert_equal d [r rpoplpush srclist dstlist] + assert_equal c [r rpoplpush srclist dstlist] + assert_equal {a b} [r lrange srclist 0 -1] + assert_equal {c d x} [r lrange dstlist 0 -1] + } + + test {RPOPLPUSH target list already exists, being a regular list} { + create_regular_list srclist {a b c d} + create_regular_list dstlist {x} + assert_equal d [r rpoplpush srclist dstlist] + assert_equal c [r rpoplpush srclist dstlist] + assert_equal {a b} [r lrange srclist 0 -1] + assert_equal {c d x} [r lrange dstlist 0 -1] + } test {RPOPLPUSH against non existing key} { - r del mylist - r del newlist - set v1 [r rpoplpush mylist newlist] - list $v1 [r exists mylist] [r exists newlist] - } {{} 0 0} + r del srclist dstlist + assert_equal {} [r rpoplpush srclist dstlist] + assert_equal 0 [r exists srclist] + assert_equal 0 [r exists dstlist] + } test {RPOPLPUSH against non list src key} { - r del mylist - r del newlist - r set mylist x - catch {r rpoplpush mylist newlist} err - list [r type mylist] [r exists newlist] [string range $err 0 2] - } {string 0 ERR} + r del srclist dstlist + r set srclist x + assert_error ERR* {r rpoplpush srclist dstlist} + assert_type string srclist + assert_equal 0 [r exists newlist] + } test {RPOPLPUSH against non list dst key} { - r del mylist - r del newlist - r rpush mylist a - r rpush mylist b - r rpush mylist c - r rpush mylist d - r set newlist x - catch {r rpoplpush mylist newlist} err - list [r lrange mylist 0 -1] [r type newlist] [string range $err 0 2] - } {{a b c d} string ERR} + create_ziplist srclist {a b c d} + r set dstlist x + assert_error ERR* {r rpoplpush srclist dstlist} + assert_type string dstlist + assert_equal {a b c d} [r lrange srclist 0 -1] + } test {RPOPLPUSH against non existing src key} { - r del mylist - r del newlist - r rpoplpush mylist newlist - } {} - - test {Basic LPOP/RPOP} { - r del mylist - r rpush mylist 1 - r rpush mylist 2 - r lpush mylist 0 - list [r lpop mylist] [r rpop mylist] [r lpop mylist] [r llen mylist] - } [list 0 2 1 0] - - test {LPOP/RPOP against empty list} { - r lpop mylist + r del srclist dstlist + assert_equal {} [r rpoplpush srclist dstlist] } {} - test {LPOP against non list value} { + test {Basic LPOP/RPOP - ziplist} { + create_ziplist myziplist {0 1 2} + assert_equal 0 [r lpop myziplist] + assert_equal 2 [r rpop myziplist] + assert_equal 1 [r lpop myziplist] + assert_equal 0 [r llen myziplist] + + # pop on empty list + assert_equal {} [r lpop myziplist] + assert_equal {} [r rpop myziplist] + } + + test {Basic LPOP/RPOP - regular list} { + create_regular_list mylist {0 1 2} + assert_equal 0 [r lpop mylist] + assert_equal 2 [r rpop mylist] + assert_equal 1 [r lpop mylist] + assert_equal 0 [r llen mylist] + + # pop on empty list + assert_equal {} [r lpop mylist] + assert_equal {} [r rpop mylist] + } + + test {LPOP/RPOP against non list value} { r set notalist foo - catch {r lpop notalist} err - format $err - } {ERR*kind*} + assert_error ERR*kind* {r lpop notalist} + assert_error ERR*kind* {r rpop notalist} + } - test {Mass LPUSH/LPOP} { - set sum 0 - for {set i 0} {$i < 1000} {incr i} { + test {Mass RPOP/LPOP - ziplist} { + r del mylist + set sum1 0 + for {set i 0} {$i < 250} {incr i} { r lpush mylist $i - incr sum $i + incr sum1 $i } + assert_encoding ziplist mylist set sum2 0 - for {set i 0} {$i < 500} {incr i} { + for {set i 0} {$i < 125} {incr i} { incr sum2 [r lpop mylist] incr sum2 [r rpop mylist] } - expr $sum == $sum2 - } {1} + assert_equal $sum1 $sum2 + } - test {LRANGE basics} { - for {set i 0} {$i < 10} {incr i} { - r rpush mylist $i + test {Mass RPOP/LPOP - regular list} { + r del mylist + set sum1 0 + for {set i 0} {$i < 500} {incr i} { + r lpush mylist $i + incr sum1 $i } - list [r lrange mylist 1 -2] \ - [r lrange mylist -3 -1] \ - [r lrange mylist 4 4] - } {{1 2 3 4 5 6 7 8} {7 8 9} 4} + assert_encoding list mylist + set sum2 0 + for {set i 0} {$i < 250} {incr i} { + incr sum2 [r lpop mylist] + incr sum2 [r rpop mylist] + } + assert_equal $sum1 $sum2 + } - test {LRANGE inverted indexes} { - r lrange mylist 6 2 - } {} + test {LRANGE basics - ziplist} { + create_ziplist mylist {0 1 2 3 4 5 6 7 8 9} + assert_equal {1 2 3 4 5 6 7 8} [r lrange mylist 1 -2] + assert_equal {7 8 9} [r lrange mylist -3 -1] + assert_equal {4} [r lrange mylist 4 4] + } - test {LRANGE out of range indexes including the full list} { - r lrange mylist -1000 1000 - } {0 1 2 3 4 5 6 7 8 9} + test {LRANGE basics - ziplist} { + create_regular_list mylist {0 1 2 3 4 5 6 7 8 9} + assert_equal {1 2 3 4 5 6 7 8} [r lrange mylist 1 -2] + assert_equal {7 8 9} [r lrange mylist -3 -1] + assert_equal {4} [r lrange mylist 4 4] + } + + test {LRANGE inverted indexes - ziplist} { + create_ziplist mylist {0 1 2 3 4 5 6 7 8 9} + assert_equal {} [r lrange mylist 6 2] + } + + test {LRANGE inverted indexes - regular list} { + create_regular_list mylist {0 1 2 3 4 5 6 7 8 9} + assert_equal {} [r lrange mylist 6 2] + } + + test {LRANGE out of range indexes including the full list - ziplist} { + create_ziplist mylist {1 2 3} + assert_equal {1 2 3} [r lrange mylist -1000 1000] + } + + test {LRANGE out of range indexes including the full list - regular list} { + create_regular_list mylist {1 2 3} + assert_equal {1 2 3} [r lrange mylist -1000 1000] + } test {LRANGE against non existing key} { - r lrange nosuchkey 0 1 - } {} + assert_equal {} [r lrange nosuchkey 0 1] + } - test {LTRIM basics} { + test {LTRIM basics - ziplist} { r del mylist + r lpush mylist "aaa" + assert_encoding ziplist mylist for {set i 0} {$i < 100} {incr i} { r lpush mylist $i r ltrim mylist 0 4 @@ -223,106 +347,114 @@ start_server {tags {"list"}} { r lrange mylist 0 -1 } {99 98 97 96 95} - test {LTRIM stress testing} { + test {LTRIM basics - regular list} { + r del mylist + r lpush mylist "aaaaaaaaaaaaaaaaa" + assert_encoding list mylist + for {set i 0} {$i < 100} {incr i} { + r lpush mylist $i + r ltrim mylist 0 4 + } + r lrange mylist 0 -1 + } {99 98 97 96 95} + + test {LTRIM stress testing - ziplist} { set mylist {} - set err {} for {set i 0} {$i < 20} {incr i} { lappend mylist $i } for {set j 0} {$j < 100} {incr j} { - # Fill the list - r del mylist - for {set i 0} {$i < 20} {incr i} { - r rpush mylist $i - } + create_ziplist mylist $mylist # Trim at random set a [randomInt 20] set b [randomInt 20] r ltrim mylist $a $b - if {[r lrange mylist 0 -1] ne [lrange $mylist $a $b]} { - set err "[r lrange mylist 0 -1] != [lrange $mylist $a $b]" - break - } + assert_equal [lrange $mylist $a $b] [r lrange mylist 0 -1] } - set _ $err - } {} + } - test {LSET} { - r del mylist - foreach x {99 98 97 96 95} { - r rpush mylist $x + test {LTRIM stress testing - regular list} { + set mylist {} + for {set i 0} {$i < 20} {incr i} { + lappend mylist $i } + + for {set j 0} {$j < 100} {incr j} { + create_regular_list mylist $mylist + # Trim at random + set a [randomInt 20] + set b [randomInt 20] + r ltrim mylist $a $b + assert_equal [lrange $mylist $a $b] [r lrange mylist 0 -1] + } + } + + test {LSET - ziplist} { + create_ziplist mylist {99 98 97 96 95} r lset mylist 1 foo r lset mylist -1 bar - r lrange mylist 0 -1 - } {99 foo 97 96 bar} + assert_equal {99 foo 97 96 bar} [r lrange mylist 0 -1] + } - test {LSET out of range index} { - catch {r lset mylist 10 foo} err - format $err - } {ERR*range*} + test {LSET out of range index - ziplist} { + assert_error ERR*range* {r lset mylist 10 foo} + } + + test {LSET - regular list} { + create_regular_list mylist {99 98 97 96 95} + r lset mylist 1 foo + r lset mylist -1 bar + assert_equal {99 foo 97 96 bar} [r lrange mylist 0 -1] + } + + test {LSET out of range index - regular list} { + assert_error ERR*range* {r lset mylist 10 foo} + } test {LSET against non existing key} { - catch {r lset nosuchkey 10 foo} err - format $err - } {ERR*key*} + assert_error ERR*key* {r lset nosuchkey 10 foo} + } test {LSET against non list value} { r set nolist foobar - catch {r lset nolist 0 foo} err - format $err - } {ERR*value*} - - test {LREM, remove all the occurrences} { - r flushdb - r rpush mylist foo - r rpush mylist bar - r rpush mylist foobar - r rpush mylist foobared - r rpush mylist zap - r rpush mylist bar - r rpush mylist test - r rpush mylist foo - set res [r lrem mylist 0 bar] - list [r lrange mylist 0 -1] $res - } {{foo foobar foobared zap test foo} 2} + assert_error ERR*value* {r lset nolist 0 foo} + } - test {LREM, remove the first occurrence} { - set res [r lrem mylist 1 foo] - list [r lrange mylist 0 -1] $res - } {{foobar foobared zap test foo} 1} + foreach type {ziplist regular_list} { + set formatted_type [string map {"_" " "} $type] - test {LREM, remove non existing element} { - set res [r lrem mylist 1 nosuchelement] - list [r lrange mylist 0 -1] $res - } {{foobar foobared zap test foo} 0} + test "LREM remove all the occurrences - $formatted_type" { + create_$type mylist {foo bar foobar foobared zap bar test foo} + assert_equal 2 [r lrem mylist 0 bar] + assert_equal {foo foobar foobared zap test foo} [r lrange mylist 0 -1] + } - test {LREM, starting from tail with negative count} { - r flushdb - r rpush mylist foo - r rpush mylist bar - r rpush mylist foobar - r rpush mylist foobared - r rpush mylist zap - r rpush mylist bar - r rpush mylist test - r rpush mylist foo - r rpush mylist foo - set res [r lrem mylist -1 bar] - list [r lrange mylist 0 -1] $res - } {{foo bar foobar foobared zap test foo foo} 1} + test "LREM remove the first occurrence - $formatted_type" { + assert_equal 1 [r lrem mylist 1 foo] + assert_equal {foobar foobared zap test foo} [r lrange mylist 0 -1] + } - test {LREM, starting from tail with negative count (2)} { - set res [r lrem mylist -2 foo] - list [r lrange mylist 0 -1] $res - } {{foo bar foobar foobared zap test} 2} + test "LREM remove non existing element - $formatted_type" { + assert_equal 0 [r lrem mylist 1 nosuchelement] + assert_equal {foobar foobared zap test foo} [r lrange mylist 0 -1] + } - test {LREM, deleting objects that may be encoded as integers} { - r lpush myotherlist 1 - r lpush myotherlist 2 - r lpush myotherlist 3 - r lrem myotherlist 1 2 - r llen myotherlist - } {2} + test "LREM starting from tail with negative count - $formatted_type" { + create_$type mylist {foo bar foobar foobared zap bar test foo foo} + assert_equal 1 [r lrem mylist -1 bar] + assert_equal {foo bar foobar foobared zap test foo foo} [r lrange mylist 0 -1] + } + + test "LREM starting from tail with negative count (2) - $formatted_type" { + assert_equal 2 [r lrem mylist -2 foo] + assert_equal {foo bar foobar foobared zap test} [r lrange mylist 0 -1] + } + + test "LREM deleting objects that may be int encoded - $formatted_type" { + create_$type myotherlist {1 2 3} + assert_equal 1 [r lrem myotherlist 1 2] + assert_equal 2 [r llen myotherlist] + } + } }