From 53cbf66caf40c44f081336061a8082b08c8f3a28 Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Wed, 19 May 2010 14:33:39 +0200 Subject: [PATCH] initial tests for AOF (and small changes to server.tcl to support these) --- tests/integration/aof.tcl | 80 +++++++++++++++++++++++++++++++++++++++ tests/support/server.tcl | 65 ++++++++++++++++++------------- tests/support/util.tcl | 8 ++++ tests/test_helper.tcl | 1 + 4 files changed, 128 insertions(+), 26 deletions(-) create mode 100644 tests/integration/aof.tcl diff --git a/tests/integration/aof.tcl b/tests/integration/aof.tcl new file mode 100644 index 00000000..0d933449 --- /dev/null +++ b/tests/integration/aof.tcl @@ -0,0 +1,80 @@ +set defaults [list [list appendonly yes] [list appendfilename appendonly.aof]] +set server_path [tmpdir server.aof] +set aof_path "$server_path/appendonly.aof" + +proc append_to_aof {str} { + upvar fp fp + puts -nonewline $fp $str +} + +proc create_aof {code} { + upvar fp fp aof_path aof_path + set fp [open $aof_path w+] + uplevel 1 $code + close $fp +} + +proc start_server_aof {overrides code} { + upvar defaults defaults srv srv server_path server_path + set _defaults $defaults + set srv [start_server default.conf [lappend _defaults $overrides]] + uplevel 1 $code + kill_server $srv +} + +## Test the server doesn't start when the AOF contains an unfinished MULTI +create_aof { + append_to_aof [formatCommand set foo hello] + append_to_aof [formatCommand multi] + append_to_aof [formatCommand set bar world] +} + +start_server_aof [list dir $server_path] { + test {Unfinished MULTI: Server should not have been started} { + is_alive $srv + } {0} + + test {Unfinished MULTI: Server should have logged an error} { + exec cat [dict get $srv stdout] | tail -n1 + } {*Unexpected end of file reading the append only file*} +} + +## Test that the server exits when the AOF contains a short read +create_aof { + append_to_aof [formatCommand set foo hello] + append_to_aof [string range [formatCommand set bar world] 0 end-1] +} + +start_server_aof [list dir $server_path] { + test {Short read: Server should not have been started} { + is_alive $srv + } {0} + + test {Short read: Server should have logged an error} { + exec cat [dict get $srv stdout] | tail -n1 + } {*Bad file format reading the append only file*} +} + +## Test that redis-check-aof indeed sees this AOF is not valid +test {Short read: Utility should confirm the AOF is not valid} { + catch { + exec ./redis-check-aof $aof_path + } str + set _ $str +} {*not valid*} + +test {Short read: Utility should be able to fix the AOF} { + exec echo y | ./redis-check-aof --fix $aof_path +} {*Successfully truncated AOF*} + +## Test that the server can be started using the truncated AOF +start_server_aof [list dir $server_path] { + test {Fixed AOF: Server should have been started} { + is_alive $srv + } {1} + + test {Fixed AOF: Keyspace should contain values that were parsable} { + set client [redis [dict get $srv host] [dict get $srv port]] + list [$client get foo] [$client get bar] + } {hello {}} +} diff --git a/tests/support/server.tcl b/tests/support/server.tcl index 40f21925..8664b9a4 100644 --- a/tests/support/server.tcl +++ b/tests/support/server.tcl @@ -8,6 +8,8 @@ proc error_and_quit {config_file error} { } proc kill_server config { + # nevermind if its already dead + if {![is_alive $config]} { return } set pid [dict get $config pid] # check for leaks @@ -20,16 +22,24 @@ proc kill_server config { } # kill server and wait for the process to be totally exited - exec kill $pid - while 1 { - # with a non-zero exit status, the process is gone - if {[catch {exec ps -p $pid | grep redis-server} result]} { - break + while {[is_alive $config]} { + if {[incr wait 10] % 1000 == 0} { + puts "Waiting for process $pid to exit..." } + exec kill $pid after 10 } } +proc is_alive config { + set pid [dict get $config pid] + if {[catch {exec ps -p $pid} err]} { + return 0 + } else { + return 1 + } +} + proc start_server {filename overrides {code undefined}} { set data [split [exec cat "tests/assets/$filename"] "\n"] set config {} @@ -74,33 +84,14 @@ proc start_server {filename overrides {code undefined}} { error_and_quit $config_file [exec cat $stderr] } - set line [exec head -n1 $stdout] - if {[string match {*already in use*} $line]} { - error_and_quit $config_file $line - } - - while 1 { - # check that the server actually started and is ready for connections - if {[exec cat $stdout | grep "ready to accept" | wc -l] > 0} { - break - } - after 10 - } - # find out the pid regexp {^\[(\d+)\]} [exec head -n1 $stdout] _ pid - # create the client object + # setup properties to be able to initialize a client object set host $::host set port $::port if {[dict exists $config bind]} { set host [dict get $config bind] } if {[dict exists $config port]} { set port [dict get $config port] } - set client [redis $host $port] - - # select the right db when we don't have to authenticate - if {![dict exists $config requirepass]} { - $client select 9 - } # setup config dict dict set srv "config" $config_file @@ -109,9 +100,31 @@ proc start_server {filename overrides {code undefined}} { dict set srv "port" $port dict set srv "stdout" $stdout dict set srv "stderr" $stderr - dict set srv "client" $client + # if a block of code is supplied, we wait for the server to become + # available, create a client object and kill the server afterwards if {$code ne "undefined"} { + set line [exec head -n1 $stdout] + if {[string match {*already in use*} $line]} { + error_and_quit $config_file $line + } + + while 1 { + # check that the server actually started and is ready for connections + if {[exec cat $stdout | grep "ready to accept" | wc -l] > 0} { + break + } + after 10 + } + + set client [redis $host $port] + dict set srv "client" $client + + # select the right db when we don't have to authenticate + if {![dict exists $config requirepass]} { + $client select 9 + } + # append the server to the stack lappend ::servers $srv diff --git a/tests/support/util.tcl b/tests/support/util.tcl index 09a5804c..36bc90d9 100644 --- a/tests/support/util.tcl +++ b/tests/support/util.tcl @@ -188,3 +188,11 @@ proc createComplexDataset {r ops} { } } } + +proc formatCommand {args} { + set cmd "*[llength $args]\r\n" + foreach a $args { + append cmd "$[string length $a]\r\n$a\r\n" + } + set _ $cmd +} diff --git a/tests/test_helper.tcl b/tests/test_helper.tcl index f9830e85..e5f2ed77 100644 --- a/tests/test_helper.tcl +++ b/tests/test_helper.tcl @@ -61,6 +61,7 @@ proc main {} { execute_tests "unit/expire" execute_tests "unit/other" execute_tests "integration/replication" + execute_tests "integration/aof" puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed" if {$::failed > 0} { -- 2.45.2