"Fossies" - the Fresh Open Source Software Archive

Member "redis-6.2.5/tests/unit/type/stream.tcl" (21 Jul 2021, 23679 Bytes) of package /linux/misc/redis-6.2.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Tcl/Tk source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "stream.tcl": 6.2.4_vs_6.2.5.

    1 # return value is like strcmp() and similar.
    2 proc streamCompareID {a b} {
    3     if {$a eq $b} {return 0}
    4     lassign [split $a -] a_ms a_seq
    5     lassign [split $b -] b_ms b_seq
    6     if {$a_ms > $b_ms} {return 1}
    7     if {$a_ms < $b_ms} {return -1}
    8     # Same ms case, compare seq.
    9     if {$a_seq > $b_seq} {return 1}
   10     if {$a_seq < $b_seq} {return -1}
   11 }
   12 
   13 # return the ID immediately greater than the specified one.
   14 # Note that this function does not care to handle 'seq' overflow
   15 # since it's a 64 bit value.
   16 proc streamNextID {id} {
   17     lassign [split $id -] ms seq
   18     incr seq
   19     join [list $ms $seq] -
   20 }
   21 
   22 # Generate a random stream entry ID with the ms part between min and max
   23 # and a low sequence number (0 - 999 range), in order to stress test
   24 # XRANGE against a Tcl implementation implementing the same concept
   25 # with Tcl-only code in a linear array.
   26 proc streamRandomID {min_id max_id} {
   27     lassign [split $min_id -] min_ms min_seq
   28     lassign [split $max_id -] max_ms max_seq
   29     set delta [expr {$max_ms-$min_ms+1}]
   30     set ms [expr {$min_ms+[randomInt $delta]}]
   31     set seq [randomInt 1000]
   32     return $ms-$seq
   33 }
   34 
   35 # Tcl-side implementation of XRANGE to perform fuzz testing in the Redis
   36 # XRANGE implementation.
   37 proc streamSimulateXRANGE {items start end} {
   38     set res {}
   39     foreach i $items  {
   40         set this_id [lindex $i 0]
   41         if {[streamCompareID $this_id $start] >= 0} {
   42             if {[streamCompareID $this_id $end] <= 0} {
   43                 lappend res $i
   44             }
   45         }
   46     }
   47     return $res
   48 }
   49 
   50 set content {} ;# Will be populated with Tcl side copy of the stream content.
   51 
   52 start_server {
   53     tags {"stream"}
   54 } {
   55     test {XADD can add entries into a stream that XRANGE can fetch} {
   56         r XADD mystream * item 1 value a
   57         r XADD mystream * item 2 value b
   58         assert_equal 2 [r XLEN mystream]
   59         set items [r XRANGE mystream - +]
   60         assert_equal [lindex $items 0 1] {item 1 value a}
   61         assert_equal [lindex $items 1 1] {item 2 value b}
   62     }
   63 
   64     test {XADD IDs are incremental} {
   65         set id1 [r XADD mystream * item 1 value a]
   66         set id2 [r XADD mystream * item 2 value b]
   67         set id3 [r XADD mystream * item 3 value c]
   68         assert {[streamCompareID $id1 $id2] == -1}
   69         assert {[streamCompareID $id2 $id3] == -1}
   70     }
   71 
   72     test {XADD IDs are incremental when ms is the same as well} {
   73         r multi
   74         r XADD mystream * item 1 value a
   75         r XADD mystream * item 2 value b
   76         r XADD mystream * item 3 value c
   77         lassign [r exec] id1 id2 id3
   78         assert {[streamCompareID $id1 $id2] == -1}
   79         assert {[streamCompareID $id2 $id3] == -1}
   80     }
   81 
   82     test {XADD IDs correctly report an error when overflowing} {
   83         r DEL mystream
   84         r xadd mystream 18446744073709551615-18446744073709551615 a b
   85         assert_error ERR* {r xadd mystream * c d}
   86     }
   87 
   88     test {XADD with MAXLEN option} {
   89         r DEL mystream
   90         for {set j 0} {$j < 1000} {incr j} {
   91             if {rand() < 0.9} {
   92                 r XADD mystream MAXLEN 5 * xitem $j
   93             } else {
   94                 r XADD mystream MAXLEN 5 * yitem $j
   95             }
   96         }
   97         assert {[r xlen mystream] == 5}
   98         set res [r xrange mystream - +]
   99         set expected 995
  100         foreach r $res {
  101             assert {[lindex $r 1 1] == $expected}
  102             incr expected
  103         }
  104     }
  105 
  106     test {XADD with MAXLEN option and the '=' argument} {
  107         r DEL mystream
  108         for {set j 0} {$j < 1000} {incr j} {
  109             if {rand() < 0.9} {
  110                 r XADD mystream MAXLEN = 5 * xitem $j
  111             } else {
  112                 r XADD mystream MAXLEN = 5 * yitem $j
  113             }
  114         }
  115         assert {[r XLEN mystream] == 5}
  116     }
  117 
  118     test {XADD with MAXLEN option and the '~' argument} {
  119         r DEL mystream
  120         for {set j 0} {$j < 1000} {incr j} {
  121             if {rand() < 0.9} {
  122                 r XADD mystream MAXLEN ~ 555 * xitem $j
  123             } else {
  124                 r XADD mystream MAXLEN ~ 555 * yitem $j
  125             }
  126         }
  127         assert {[r XLEN mystream] == 600}
  128     }
  129 
  130     test {XADD with NOMKSTREAM option} {
  131         r DEL mystream
  132         assert_equal "" [r XADD mystream NOMKSTREAM * item 1 value a]
  133         assert_equal 0 [r EXISTS mystream]
  134         r XADD mystream * item 1 value a
  135         r XADD mystream NOMKSTREAM * item 2 value b
  136         assert_equal 2 [r XLEN mystream]
  137         set items [r XRANGE mystream - +]
  138         assert_equal [lindex $items 0 1] {item 1 value a}
  139         assert_equal [lindex $items 1 1] {item 2 value b}
  140     }
  141 
  142     test {XADD with MINID option} {
  143         r DEL mystream
  144         for {set j 1} {$j < 1001} {incr j} {
  145             set minid 1000
  146             if {$j >= 5} {
  147                 set minid [expr {$j-5}]
  148             }
  149             if {rand() < 0.9} {
  150                 r XADD mystream MINID $minid $j xitem $j
  151             } else {
  152                 r XADD mystream MINID $minid $j yitem $j
  153             }
  154         }
  155         assert {[r xlen mystream] == 6}
  156         set res [r xrange mystream - +]
  157         set expected 995
  158         foreach r $res {
  159             assert {[lindex $r 1 1] == $expected}
  160             incr expected
  161         }
  162     }
  163 
  164     test {XTRIM with MINID option} {
  165         r DEL mystream
  166         r XADD mystream 1-0 f v
  167         r XADD mystream 2-0 f v
  168         r XADD mystream 3-0 f v
  169         r XADD mystream 4-0 f v
  170         r XADD mystream 5-0 f v
  171         r XTRIM mystream MINID = 3-0
  172         assert_equal [r XRANGE mystream - +] {{3-0 {f v}} {4-0 {f v}} {5-0 {f v}}}
  173     }
  174 
  175     test {XADD mass insertion and XLEN} {
  176         r DEL mystream
  177         r multi
  178         for {set j 0} {$j < 10000} {incr j} {
  179             # From time to time insert a field with a different set
  180             # of fields in order to stress the stream compression code.
  181             if {rand() < 0.9} {
  182                 r XADD mystream * item $j
  183             } else {
  184                 r XADD mystream * item $j otherfield foo
  185             }
  186         }
  187         r exec
  188 
  189         set items [r XRANGE mystream - +]
  190         for {set j 0} {$j < 10000} {incr j} {
  191             assert {[lrange [lindex $items $j 1] 0 1] eq [list item $j]}
  192         }
  193         assert {[r xlen mystream] == $j}
  194     }
  195 
  196     test {XADD with ID 0-0} {
  197         r DEL otherstream
  198         catch {r XADD otherstream 0-0 k v} err
  199         assert {[r EXISTS otherstream] == 0}
  200     }
  201 
  202     test {XADD with LIMIT delete entries no more than limit} {
  203         r del yourstream
  204         for {set j 0} {$j < 3} {incr j} {
  205             r XADD yourstream * xitem v
  206         }
  207         r XADD yourstream MAXLEN ~ 0 limit 1 * xitem v
  208         assert {[r XLEN yourstream] == 4}
  209     }
  210 
  211     test {XRANGE COUNT works as expected} {
  212         assert {[llength [r xrange mystream - + COUNT 10]] == 10}
  213     }
  214 
  215     test {XREVRANGE COUNT works as expected} {
  216         assert {[llength [r xrevrange mystream + - COUNT 10]] == 10}
  217     }
  218 
  219     test {XRANGE can be used to iterate the whole stream} {
  220         set last_id "-"
  221         set j 0
  222         while 1 {
  223             set elements [r xrange mystream $last_id + COUNT 100]
  224             if {[llength $elements] == 0} break
  225             foreach e $elements {
  226                 assert {[lrange [lindex $e 1] 0 1] eq [list item $j]}
  227                 incr j;
  228             }
  229             set last_id [streamNextID [lindex $elements end 0]]
  230         }
  231         assert {$j == 10000}
  232     }
  233 
  234     test {XREVRANGE returns the reverse of XRANGE} {
  235         assert {[r xrange mystream - +] == [lreverse [r xrevrange mystream + -]]}
  236     }
  237 
  238     test {XRANGE exclusive ranges} {
  239         set ids {0-1 0-18446744073709551615 1-0 42-0 42-42
  240                  18446744073709551615-18446744073709551614
  241                  18446744073709551615-18446744073709551615}
  242         set total [llength $ids]
  243         r multi
  244         r DEL vipstream
  245         foreach id $ids {
  246             r XADD vipstream $id foo bar
  247         }
  248         r exec
  249         assert {[llength [r xrange vipstream - +]] == $total}
  250         assert {[llength [r xrange vipstream ([lindex $ids 0] +]] == $total-1}
  251         assert {[llength [r xrange vipstream - ([lindex $ids $total-1]]] == $total-1}
  252         assert {[llength [r xrange vipstream (0-1 (1-0]] == 1}
  253         assert {[llength [r xrange vipstream (1-0 (42-42]] == 1}
  254         catch {r xrange vipstream (- +} e
  255         assert_match {ERR*} $e
  256         catch {r xrange vipstream - (+} e
  257         assert_match {ERR*} $e
  258         catch {r xrange vipstream (18446744073709551615-18446744073709551615 +} e
  259         assert_match {ERR*} $e
  260         catch {r xrange vipstream - (0-0} e
  261         assert_match {ERR*} $e
  262     }
  263 
  264     test {XREAD with non empty stream} {
  265         set res [r XREAD COUNT 1 STREAMS mystream 0-0]
  266         assert {[lrange [lindex $res 0 1 0 1] 0 1] eq {item 0}}
  267     }
  268 
  269     test {Non blocking XREAD with empty streams} {
  270         set res [r XREAD STREAMS s1 s2 0-0 0-0]
  271         assert {$res eq {}}
  272     }
  273 
  274     test {XREAD with non empty second stream} {
  275         set res [r XREAD COUNT 1 STREAMS nostream mystream 0-0 0-0]
  276         assert {[lindex $res 0 0] eq {mystream}}
  277         assert {[lrange [lindex $res 0 1 0 1] 0 1] eq {item 0}}
  278     }
  279 
  280     test {Blocking XREAD waiting new data} {
  281         r XADD s2 * old abcd1234
  282         set rd [redis_deferring_client]
  283         $rd XREAD BLOCK 20000 STREAMS s1 s2 s3 $ $ $
  284         r XADD s2 * new abcd1234
  285         set res [$rd read]
  286         assert {[lindex $res 0 0] eq {s2}}
  287         assert {[lindex $res 0 1 0 1] eq {new abcd1234}}
  288     }
  289 
  290     test {Blocking XREAD waiting old data} {
  291         set rd [redis_deferring_client]
  292         $rd XREAD BLOCK 20000 STREAMS s1 s2 s3 $ 0-0 $
  293         r XADD s2 * foo abcd1234
  294         set res [$rd read]
  295         assert {[lindex $res 0 0] eq {s2}}
  296         assert {[lindex $res 0 1 0 1] eq {old abcd1234}}
  297     }
  298 
  299     test {Blocking XREAD will not reply with an empty array} {
  300         r del s1
  301         r XADD s1 666 f v
  302         r XADD s1 667 f2 v2
  303         r XDEL s1 667
  304         set rd [redis_deferring_client]
  305         $rd XREAD BLOCK 10 STREAMS s1 666
  306         after 20
  307         assert {[$rd read] == {}} ;# before the fix, client didn't even block, but was served synchronously with {s1 {}}
  308     }
  309 
  310     test "XREAD: XADD + DEL should not awake client" {
  311         set rd [redis_deferring_client]
  312         r del s1
  313         $rd XREAD BLOCK 20000 STREAMS s1 $
  314         r multi
  315         r XADD s1 * old abcd1234
  316         r DEL s1
  317         r exec
  318         r XADD s1 * new abcd1234
  319         set res [$rd read]
  320         assert {[lindex $res 0 0] eq {s1}}
  321         assert {[lindex $res 0 1 0 1] eq {new abcd1234}}
  322     }
  323 
  324     test "XREAD: XADD + DEL + LPUSH should not awake client" {
  325         set rd [redis_deferring_client]
  326         r del s1
  327         $rd XREAD BLOCK 20000 STREAMS s1 $
  328         r multi
  329         r XADD s1 * old abcd1234
  330         r DEL s1
  331         r LPUSH s1 foo bar
  332         r exec
  333         r DEL s1
  334         r XADD s1 * new abcd1234
  335         set res [$rd read]
  336         assert {[lindex $res 0 0] eq {s1}}
  337         assert {[lindex $res 0 1 0 1] eq {new abcd1234}}
  338     }
  339 
  340     test {XREAD with same stream name multiple times should work} {
  341         r XADD s2 * old abcd1234
  342         set rd [redis_deferring_client]
  343         $rd XREAD BLOCK 20000 STREAMS s2 s2 s2 $ $ $
  344         r XADD s2 * new abcd1234
  345         set res [$rd read]
  346         assert {[lindex $res 0 0] eq {s2}}
  347         assert {[lindex $res 0 1 0 1] eq {new abcd1234}}
  348     }
  349 
  350     test {XREAD + multiple XADD inside transaction} {
  351         r XADD s2 * old abcd1234
  352         set rd [redis_deferring_client]
  353         $rd XREAD BLOCK 20000 STREAMS s2 s2 s2 $ $ $
  354         r MULTI
  355         r XADD s2 * field one
  356         r XADD s2 * field two
  357         r XADD s2 * field three
  358         r EXEC
  359         set res [$rd read]
  360         assert {[lindex $res 0 0] eq {s2}}
  361         assert {[lindex $res 0 1 0 1] eq {field one}}
  362         assert {[lindex $res 0 1 1 1] eq {field two}}
  363     }
  364 
  365     test {XDEL basic test} {
  366         r del somestream
  367         r xadd somestream * foo value0
  368         set id [r xadd somestream * foo value1]
  369         r xadd somestream * foo value2
  370         r xdel somestream $id
  371         assert {[r xlen somestream] == 2}
  372         set result [r xrange somestream - +]
  373         assert {[lindex $result 0 1 1] eq {value0}}
  374         assert {[lindex $result 1 1 1] eq {value2}}
  375     }
  376 
  377     # Here the idea is to check the consistency of the stream data structure
  378     # as we remove all the elements down to zero elements.
  379     test {XDEL fuzz test} {
  380         r del somestream
  381         set ids {}
  382         set x 0; # Length of the stream
  383         while 1 {
  384             lappend ids [r xadd somestream * item $x]
  385             incr x
  386             # Add enough elements to have a few radix tree nodes inside the stream.
  387             if {[dict get [r xinfo stream somestream] radix-tree-keys] > 20} break
  388         }
  389 
  390         # Now remove all the elements till we reach an empty stream
  391         # and after every deletion, check that the stream is sane enough
  392         # to report the right number of elements with XRANGE: this will also
  393         # force accessing the whole data structure to check sanity.
  394         assert {[r xlen somestream] == $x}
  395 
  396         # We want to remove elements in random order to really test the
  397         # implementation in a better way.
  398         set ids [lshuffle $ids]
  399         foreach id $ids {
  400             assert {[r xdel somestream $id] == 1}
  401             incr x -1
  402             assert {[r xlen somestream] == $x}
  403             # The test would be too slow calling XRANGE for every iteration.
  404             # Do it every 100 removal.
  405             if {$x % 100 == 0} {
  406                 set res [r xrange somestream - +]
  407                 assert {[llength $res] == $x}
  408             }
  409         }
  410     }
  411 
  412     test {XRANGE fuzzing} {
  413         set low_id [lindex $items 0 0]
  414         set high_id [lindex $items end 0]
  415         for {set j 0} {$j < 100} {incr j} {
  416             set start [streamRandomID $low_id $high_id]
  417             set end [streamRandomID $low_id $high_id]
  418             set range [r xrange mystream $start $end]
  419             set tcl_range [streamSimulateXRANGE $items $start $end]
  420             if {$range ne $tcl_range} {
  421                 puts "*** WARNING *** - XRANGE fuzzing mismatch: $start - $end"
  422                 puts "---"
  423                 puts "XRANGE: '$range'"
  424                 puts "---"
  425                 puts "TCL: '$tcl_range'"
  426                 puts "---"
  427                 fail "XRANGE fuzzing failed, check logs for details"
  428             }
  429         }
  430     }
  431 
  432     test {XREVRANGE regression test for issue #5006} {
  433         # Add non compressed entries
  434         r xadd teststream 1234567891230 key1 value1
  435         r xadd teststream 1234567891240 key2 value2
  436         r xadd teststream 1234567891250 key3 value3
  437 
  438         # Add SAMEFIELD compressed entries
  439         r xadd teststream2 1234567891230 key1 value1
  440         r xadd teststream2 1234567891240 key1 value2
  441         r xadd teststream2 1234567891250 key1 value3
  442 
  443         assert_equal [r xrevrange teststream 1234567891245 -] {{1234567891240-0 {key2 value2}} {1234567891230-0 {key1 value1}}}
  444 
  445         assert_equal [r xrevrange teststream2 1234567891245 -] {{1234567891240-0 {key1 value2}} {1234567891230-0 {key1 value1}}}
  446     }
  447 
  448     test {XREAD streamID edge (no-blocking)} {
  449         r del x
  450         r XADD x 1-1 f v
  451         r XADD x 1-18446744073709551615 f v
  452         r XADD x 2-1 f v
  453         set res [r XREAD BLOCK 0 STREAMS x 1-18446744073709551615]
  454         assert {[lindex $res 0 1 0] == {2-1 {f v}}}
  455     }
  456 
  457     test {XREAD streamID edge (blocking)} {
  458         r del x
  459         set rd [redis_deferring_client]
  460         $rd XREAD BLOCK 0 STREAMS x 1-18446744073709551615
  461         r XADD x 1-1 f v
  462         r XADD x 1-18446744073709551615 f v
  463         r XADD x 2-1 f v
  464         set res [$rd read]
  465         assert {[lindex $res 0 1 0] == {2-1 {f v}}}
  466     }
  467 
  468     test {XADD streamID edge} {
  469         r del x
  470         r XADD x 2577343934890-18446744073709551615 f v ;# we need the timestamp to be in the future
  471         r XADD x * f2 v2
  472         assert_equal [r XRANGE x - +] {{2577343934890-18446744073709551615 {f v}} {2577343934891-0 {f2 v2}}}
  473     }
  474 
  475     test {XTRIM with MAXLEN option basic test} {
  476         r DEL mystream
  477         for {set j 0} {$j < 1000} {incr j} {
  478             if {rand() < 0.9} {
  479                 r XADD mystream * xitem $j
  480             } else {
  481                 r XADD mystream * yitem $j
  482             }
  483         }
  484         r XTRIM mystream MAXLEN 666
  485         assert {[r XLEN mystream] == 666}
  486         r XTRIM mystream MAXLEN = 555
  487         assert {[r XLEN mystream] == 555}
  488         r XTRIM mystream MAXLEN ~ 444
  489         assert {[r XLEN mystream] == 500}
  490         r XTRIM mystream MAXLEN ~ 400
  491         assert {[r XLEN mystream] == 400}
  492     }
  493 
  494     test {XADD with LIMIT consecutive calls} {
  495         r del mystream
  496         r config set stream-node-max-entries 10
  497         for {set j 0} {$j < 100} {incr j} {
  498             r XADD mystream * xitem v
  499         }
  500         r XADD mystream MAXLEN ~ 55 LIMIT 30 * xitem v
  501         assert {[r xlen mystream] == 71}
  502         r XADD mystream MAXLEN ~ 55 LIMIT 30 * xitem v
  503         assert {[r xlen mystream] == 62}
  504         r config set stream-node-max-entries 100
  505     }
  506 
  507     test {XTRIM with ~ is limited} {
  508         r del mystream
  509         r config set stream-node-max-entries 1
  510         for {set j 0} {$j < 102} {incr j} {
  511             r XADD mystream * xitem v
  512         }
  513         r XTRIM mystream MAXLEN ~ 1
  514         assert {[r xlen mystream] == 2}
  515         r config set stream-node-max-entries 100
  516     }
  517 
  518     test {XTRIM without ~ is not limited} {
  519         r del mystream
  520         r config set stream-node-max-entries 1
  521         for {set j 0} {$j < 102} {incr j} {
  522             r XADD mystream * xitem v
  523         }
  524         r XTRIM mystream MAXLEN 1
  525         assert {[r xlen mystream] == 1}
  526         r config set stream-node-max-entries 100
  527     }
  528 
  529     test {XTRIM without ~ and with LIMIT} {
  530         r del mystream
  531         r config set stream-node-max-entries 1
  532         for {set j 0} {$j < 102} {incr j} {
  533             r XADD mystream * xitem v
  534         }
  535         assert_error ERR* {r XTRIM mystream MAXLEN 1 LIMIT 30}
  536     }
  537 
  538     test {XTRIM with LIMIT delete entries no more than limit} {
  539         r del mystream
  540         r config set stream-node-max-entries 2
  541         for {set j 0} {$j < 3} {incr j} {
  542             r XADD mystream * xitem v
  543         }
  544         assert {[r XTRIM mystream MAXLEN ~ 0 LIMIT 1] == 0}
  545         assert {[r XTRIM mystream MAXLEN ~ 0 LIMIT 2] == 2}
  546     }
  547 }
  548 
  549 start_server {tags {"stream"} overrides {appendonly yes}} {
  550     test {XADD with MAXLEN > xlen can propagate correctly} {
  551         for {set j 0} {$j < 100} {incr j} {
  552             r XADD mystream * xitem v
  553         }
  554         r XADD mystream MAXLEN 200 * xitem v
  555         incr j
  556         assert {[r xlen mystream] == $j}
  557         r debug loadaof
  558         r XADD mystream * xitem v
  559         incr j
  560         assert {[r xlen mystream] == $j}
  561     }
  562 }
  563 
  564 start_server {tags {"stream"} overrides {appendonly yes}} {
  565     test {XADD with MINID > lastid can propagate correctly} {
  566         for {set j 0} {$j < 100} {incr j} {
  567             set id [expr {$j+1}]
  568             r XADD mystream $id xitem v
  569         }
  570         r XADD mystream MINID 1 * xitem v
  571         incr j
  572         assert {[r xlen mystream] == $j}
  573         r debug loadaof
  574         r XADD mystream * xitem v
  575         incr j
  576         assert {[r xlen mystream] == $j}
  577     }
  578 }
  579 
  580 start_server {tags {"stream"} overrides {appendonly yes}} {
  581     test {XADD with ~ MAXLEN can propagate correctly} {
  582         for {set j 0} {$j < 100} {incr j} {
  583             r XADD mystream * xitem v
  584         }
  585         r XADD mystream MAXLEN ~ $j * xitem v
  586         incr j
  587         assert {[r xlen mystream] == $j}
  588         r config set stream-node-max-entries 1
  589         r debug loadaof
  590         r XADD mystream * xitem v
  591         incr j
  592         assert {[r xlen mystream] == $j}
  593     }
  594 }
  595 
  596 start_server {tags {"stream"} overrides {appendonly yes stream-node-max-entries 10}} {
  597     test {XADD with ~ MAXLEN and LIMIT can propagate correctly} {
  598         for {set j 0} {$j < 100} {incr j} {
  599             r XADD mystream * xitem v
  600         }
  601         r XADD mystream MAXLEN ~ 55 LIMIT 30 * xitem v
  602         assert {[r xlen mystream] == 71}
  603         r config set stream-node-max-entries 1
  604         r debug loadaof
  605         r XADD mystream * xitem v
  606         assert {[r xlen mystream] == 72}
  607     }
  608 }
  609 
  610 start_server {tags {"stream"} overrides {appendonly yes}} {
  611     test {XADD with ~ MINID can propagate correctly} {
  612         for {set j 0} {$j < 100} {incr j} {
  613             set id [expr {$j+1}]
  614             r XADD mystream $id xitem v
  615         }
  616         r XADD mystream MINID ~ $j * xitem v
  617         incr j
  618         assert {[r xlen mystream] == $j}
  619         r config set stream-node-max-entries 1
  620         r debug loadaof
  621         r XADD mystream * xitem v
  622         incr j
  623         assert {[r xlen mystream] == $j}
  624     }
  625 }
  626 
  627 start_server {tags {"stream"} overrides {appendonly yes stream-node-max-entries 10}} {
  628     test {XADD with ~ MINID and LIMIT can propagate correctly} {
  629         for {set j 0} {$j < 100} {incr j} {
  630             set id [expr {$j+1}]
  631             r XADD mystream $id xitem v
  632         }
  633         r XADD mystream MINID ~ 55 LIMIT 30 * xitem v
  634         assert {[r xlen mystream] == 71}
  635         r config set stream-node-max-entries 1
  636         r debug loadaof
  637         r XADD mystream * xitem v
  638         assert {[r xlen mystream] == 72}
  639     }
  640 }
  641 
  642 start_server {tags {"stream"} overrides {appendonly yes stream-node-max-entries 10}} {
  643     test {XTRIM with ~ MAXLEN can propagate correctly} {
  644         for {set j 0} {$j < 100} {incr j} {
  645             r XADD mystream * xitem v
  646         }
  647         r XTRIM mystream MAXLEN ~ 85
  648         assert {[r xlen mystream] == 90}
  649         r config set stream-node-max-entries 1
  650         r debug loadaof
  651         r XADD mystream * xitem v
  652         incr j
  653         assert {[r xlen mystream] == 91}
  654     }
  655 }
  656 
  657 start_server {tags {"stream xsetid"}} {
  658     test {XADD can CREATE an empty stream} {
  659         r XADD mystream MAXLEN 0 * a b
  660         assert {[dict get [r xinfo stream mystream] length] == 0}
  661     }
  662 
  663     test {XSETID can set a specific ID} {
  664         r XSETID mystream "200-0"
  665         assert {[dict get [r xinfo stream mystream] last-generated-id] == "200-0"}
  666     }
  667 
  668     test {XSETID cannot SETID with smaller ID} {
  669         r XADD mystream * a b
  670         catch {r XSETID mystream "1-1"} err
  671         r XADD mystream MAXLEN 0 * a b
  672         set err
  673     } {ERR*smaller*}
  674 
  675     test {XSETID cannot SETID on non-existent key} {
  676         catch {r XSETID stream 1-1} err
  677         set _ $err
  678     } {ERR no such key}
  679 }
  680 
  681 start_server {tags {"stream"} overrides {appendonly yes aof-use-rdb-preamble no}} {
  682     test {Empty stream can be rewrite into AOF correctly} {
  683         r XADD mystream MAXLEN 0 * a b
  684         assert {[dict get [r xinfo stream mystream] length] == 0}
  685         r bgrewriteaof
  686         waitForBgrewriteaof r
  687         r debug loadaof
  688         assert {[dict get [r xinfo stream mystream] length] == 0}
  689     }
  690 
  691     test {Stream can be rewrite into AOF correctly after XDEL lastid} {
  692         r XSETID mystream 0-0
  693         r XADD mystream 1-1 a b
  694         r XADD mystream 2-2 a b
  695         assert {[dict get [r xinfo stream mystream] length] == 2}
  696         r XDEL mystream 2-2
  697         r bgrewriteaof
  698         waitForBgrewriteaof r
  699         r debug loadaof
  700         assert {[dict get [r xinfo stream mystream] length] == 1}
  701         assert {[dict get [r xinfo stream mystream] last-generated-id] == "2-2"}
  702     }
  703 }
  704 
  705 start_server {tags {"stream"}} {
  706     test {XGROUP HELP should not have unexpected options} {
  707         catch {r XGROUP help xxx} e
  708         assert_match "*Unknown subcommand or wrong number of arguments*" $e
  709     }
  710 }