"Fossies" - the Fresh Open Source Software Archive

Member "redis-6.0.8/tests/integration/aof.tcl" (10 Sep 2020, 9992 Bytes) of package /linux/misc/redis-6.0.8.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 and code folding option. 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 "aof.tcl": 6.0.7_vs_6.0.8.

    1 set defaults { appendonly {yes} appendfilename {appendonly.aof} }
    2 set server_path [tmpdir server.aof]
    3 set aof_path "$server_path/appendonly.aof"
    4 
    5 proc append_to_aof {str} {
    6     upvar fp fp
    7     puts -nonewline $fp $str
    8 }
    9 
   10 proc create_aof {code} {
   11     upvar fp fp aof_path aof_path
   12     set fp [open $aof_path w+]
   13     uplevel 1 $code
   14     close $fp
   15 }
   16 
   17 proc start_server_aof {overrides code} {
   18     upvar defaults defaults srv srv server_path server_path
   19     set config [concat $defaults $overrides]
   20     set srv [start_server [list overrides $config]]
   21     uplevel 1 $code
   22     kill_server $srv
   23 }
   24 
   25 tags {"aof"} {
   26     ## Server can start when aof-load-truncated is set to yes and AOF
   27     ## is truncated, with an incomplete MULTI block.
   28     create_aof {
   29         append_to_aof [formatCommand set foo hello]
   30         append_to_aof [formatCommand multi]
   31         append_to_aof [formatCommand set bar world]
   32     }
   33 
   34     start_server_aof [list dir $server_path aof-load-truncated yes] {
   35         test "Unfinished MULTI: Server should start if load-truncated is yes" {
   36             assert_equal 1 [is_alive $srv]
   37         }
   38     }
   39 
   40     ## Should also start with truncated AOF without incomplete MULTI block.
   41     create_aof {
   42         append_to_aof [formatCommand incr foo]
   43         append_to_aof [formatCommand incr foo]
   44         append_to_aof [formatCommand incr foo]
   45         append_to_aof [formatCommand incr foo]
   46         append_to_aof [formatCommand incr foo]
   47         append_to_aof [string range [formatCommand incr foo] 0 end-1]
   48     }
   49 
   50     start_server_aof [list dir $server_path aof-load-truncated yes] {
   51         test "Short read: Server should start if load-truncated is yes" {
   52             assert_equal 1 [is_alive $srv]
   53         }
   54 
   55         test "Truncated AOF loaded: we expect foo to be equal to 5" {
   56             set client [redis [dict get $srv host] [dict get $srv port] 0 $::tls]
   57             wait_done_loading $client
   58             assert {[$client get foo] eq "5"}
   59         }
   60 
   61         test "Append a new command after loading an incomplete AOF" {
   62             $client incr foo
   63         }
   64     }
   65 
   66     # Now the AOF file is expected to be correct
   67     start_server_aof [list dir $server_path aof-load-truncated yes] {
   68         test "Short read + command: Server should start" {
   69             assert_equal 1 [is_alive $srv]
   70         }
   71 
   72         test "Truncated AOF loaded: we expect foo to be equal to 6 now" {
   73             set client [redis [dict get $srv host] [dict get $srv port] 0 $::tls]
   74             wait_done_loading $client
   75             assert {[$client get foo] eq "6"}
   76         }
   77     }
   78 
   79     ## Test that the server exits when the AOF contains a format error
   80     create_aof {
   81         append_to_aof [formatCommand set foo hello]
   82         append_to_aof "!!!"
   83         append_to_aof [formatCommand set foo hello]
   84     }
   85 
   86     start_server_aof [list dir $server_path aof-load-truncated yes] {
   87         test "Bad format: Server should have logged an error" {
   88             set pattern "*Bad file format reading the append only file*"
   89             set retry 10
   90             while {$retry} {
   91                 set result [exec tail -1 < [dict get $srv stdout]]
   92                 if {[string match $pattern $result]} {
   93                     break
   94                 }
   95                 incr retry -1
   96                 after 1000
   97             }
   98             if {$retry == 0} {
   99                 error "assertion:expected error not found on config file"
  100             }
  101         }
  102     }
  103 
  104     ## Test the server doesn't start when the AOF contains an unfinished MULTI
  105     create_aof {
  106         append_to_aof [formatCommand set foo hello]
  107         append_to_aof [formatCommand multi]
  108         append_to_aof [formatCommand set bar world]
  109     }
  110 
  111     start_server_aof [list dir $server_path aof-load-truncated no] {
  112         test "Unfinished MULTI: Server should have logged an error" {
  113             set pattern "*Unexpected end of file reading the append only file*"
  114             set retry 10
  115             while {$retry} {
  116                 set result [exec tail -1 < [dict get $srv stdout]]
  117                 if {[string match $pattern $result]} {
  118                     break
  119                 }
  120                 incr retry -1
  121                 after 1000
  122             }
  123             if {$retry == 0} {
  124                 error "assertion:expected error not found on config file"
  125             }
  126         }
  127     }
  128 
  129     ## Test that the server exits when the AOF contains a short read
  130     create_aof {
  131         append_to_aof [formatCommand set foo hello]
  132         append_to_aof [string range [formatCommand set bar world] 0 end-1]
  133     }
  134 
  135     start_server_aof [list dir $server_path aof-load-truncated no] {
  136         test "Short read: Server should have logged an error" {
  137             set pattern "*Unexpected end of file reading the append only file*"
  138             set retry 10
  139             while {$retry} {
  140                 set result [exec tail -1 < [dict get $srv stdout]]
  141                 if {[string match $pattern $result]} {
  142                     break
  143                 }
  144                 incr retry -1
  145                 after 1000
  146             }
  147             if {$retry == 0} {
  148                 error "assertion:expected error not found on config file"
  149             }
  150         }
  151     }
  152 
  153     ## Test that redis-check-aof indeed sees this AOF is not valid
  154     test "Short read: Utility should confirm the AOF is not valid" {
  155         catch {
  156             exec src/redis-check-aof $aof_path
  157         } result
  158         assert_match "*not valid*" $result
  159     }
  160 
  161     test "Short read: Utility should be able to fix the AOF" {
  162         set result [exec src/redis-check-aof --fix $aof_path << "y\n"]
  163         assert_match "*Successfully truncated AOF*" $result
  164     }
  165 
  166     ## Test that the server can be started using the truncated AOF
  167     start_server_aof [list dir $server_path aof-load-truncated no] {
  168         test "Fixed AOF: Server should have been started" {
  169             assert_equal 1 [is_alive $srv]
  170         }
  171 
  172         test "Fixed AOF: Keyspace should contain values that were parseable" {
  173             set client [redis [dict get $srv host] [dict get $srv port] 0 $::tls]
  174             wait_done_loading $client
  175             assert_equal "hello" [$client get foo]
  176             assert_equal "" [$client get bar]
  177         }
  178     }
  179 
  180     ## Test that SPOP (that modifies the client's argc/argv) is correctly free'd
  181     create_aof {
  182         append_to_aof [formatCommand sadd set foo]
  183         append_to_aof [formatCommand sadd set bar]
  184         append_to_aof [formatCommand spop set]
  185     }
  186 
  187     start_server_aof [list dir $server_path aof-load-truncated no] {
  188         test "AOF+SPOP: Server should have been started" {
  189             assert_equal 1 [is_alive $srv]
  190         }
  191 
  192         test "AOF+SPOP: Set should have 1 member" {
  193             set client [redis [dict get $srv host] [dict get $srv port] 0 $::tls]
  194             wait_done_loading $client
  195             assert_equal 1 [$client scard set]
  196         }
  197     }
  198 
  199     ## Uses the alsoPropagate() API.
  200     create_aof {
  201         append_to_aof [formatCommand sadd set foo]
  202         append_to_aof [formatCommand sadd set bar]
  203         append_to_aof [formatCommand sadd set gah]
  204         append_to_aof [formatCommand spop set 2]
  205     }
  206 
  207     start_server_aof [list dir $server_path] {
  208         test "AOF+SPOP: Server should have been started" {
  209             assert_equal 1 [is_alive $srv]
  210         }
  211 
  212         test "AOF+SPOP: Set should have 1 member" {
  213             set client [redis [dict get $srv host] [dict get $srv port] 0 $::tls]
  214             wait_done_loading $client
  215             assert_equal 1 [$client scard set]
  216         }
  217     }
  218 
  219     ## Test that EXPIREAT is loaded correctly
  220     create_aof {
  221         append_to_aof [formatCommand rpush list foo]
  222         append_to_aof [formatCommand expireat list 1000]
  223         append_to_aof [formatCommand rpush list bar]
  224     }
  225 
  226     start_server_aof [list dir $server_path aof-load-truncated no] {
  227         test "AOF+EXPIRE: Server should have been started" {
  228             assert_equal 1 [is_alive $srv]
  229         }
  230 
  231         test "AOF+EXPIRE: List should be empty" {
  232             set client [redis [dict get $srv host] [dict get $srv port] 0 $::tls]
  233             wait_done_loading $client
  234             assert_equal 0 [$client llen list]
  235         }
  236     }
  237 
  238     start_server {overrides {appendonly {yes} appendfilename {appendonly.aof}}} {
  239         test {Redis should not try to convert DEL into EXPIREAT for EXPIRE -1} {
  240             r set x 10
  241             r expire x -1
  242         }
  243     }
  244 
  245     start_server {overrides {appendonly {yes} appendfilename {appendonly.aof} appendfsync always}} {
  246         test {AOF fsync always barrier issue} {
  247             set rd [redis_deferring_client]
  248             # Set a sleep when aof is flushed, so that we have a chance to look
  249             # at the aof size and detect if the response of an incr command
  250             # arrives before the data was written (and hopefully fsynced)
  251             # We create a big reply, which will hopefully not have room in the
  252             # socket buffers, and will install a write handler, then we sleep
  253             # a big and issue the incr command, hoping that the last portion of
  254             # the output buffer write, and the processing of the incr will happen
  255             # in the same event loop cycle.
  256             # Since the socket buffers and timing are unpredictable, we fuzz this
  257             # test with slightly different sizes and sleeps a few times.
  258             for {set i 0} {$i < 10} {incr i} {
  259                 r debug aof-flush-sleep 0
  260                 r del x
  261                 r setrange x [expr {int(rand()*5000000)+10000000}] x
  262                 r debug aof-flush-sleep 500000
  263                 set aof [file join [lindex [r config get dir] 1] appendonly.aof]
  264                 set size1 [file size $aof]
  265                 $rd get x
  266                 after [expr {int(rand()*30)}]
  267                 $rd incr new_value
  268                 $rd read
  269                 $rd read
  270                 set size2 [file size $aof]
  271                 assert {$size1 != $size2}
  272             }
  273         }
  274     }
  275 }