Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

initial tests for AOF (and small changes to server.tcl to support these)

  • Loading branch information...
commit 04c9847701604b6c4e056c928e9e296c253cc252 1 parent d33b131
Pieter Noordhuis pietern authored ngmoco:) committed
80 tests/integration/aof.tcl
... ... @@ -0,0 +1,80 @@
  1 +set defaults [list [list appendonly yes] [list 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 _defaults $defaults
  20 + set srv [start_server default.conf [lappend _defaults $overrides]]
  21 + uplevel 1 $code
  22 + kill_server $srv
  23 +}
  24 +
  25 +## Test the server doesn't start when the AOF contains an unfinished MULTI
  26 +create_aof {
  27 + append_to_aof [formatCommand set foo hello]
  28 + append_to_aof [formatCommand multi]
  29 + append_to_aof [formatCommand set bar world]
  30 +}
  31 +
  32 +start_server_aof [list dir $server_path] {
  33 + test {Unfinished MULTI: Server should not have been started} {
  34 + is_alive $srv
  35 + } {0}
  36 +
  37 + test {Unfinished MULTI: Server should have logged an error} {
  38 + exec cat [dict get $srv stdout] | tail -n1
  39 + } {*Unexpected end of file reading the append only file*}
  40 +}
  41 +
  42 +## Test that the server exits when the AOF contains a short read
  43 +create_aof {
  44 + append_to_aof [formatCommand set foo hello]
  45 + append_to_aof [string range [formatCommand set bar world] 0 end-1]
  46 +}
  47 +
  48 +start_server_aof [list dir $server_path] {
  49 + test {Short read: Server should not have been started} {
  50 + is_alive $srv
  51 + } {0}
  52 +
  53 + test {Short read: Server should have logged an error} {
  54 + exec cat [dict get $srv stdout] | tail -n1
  55 + } {*Bad file format reading the append only file*}
  56 +}
  57 +
  58 +## Test that redis-check-aof indeed sees this AOF is not valid
  59 +test {Short read: Utility should confirm the AOF is not valid} {
  60 + catch {
  61 + exec ./redis-check-aof $aof_path
  62 + } str
  63 + set _ $str
  64 +} {*not valid*}
  65 +
  66 +test {Short read: Utility should be able to fix the AOF} {
  67 + exec echo y | ./redis-check-aof --fix $aof_path
  68 +} {*Successfully truncated AOF*}
  69 +
  70 +## Test that the server can be started using the truncated AOF
  71 +start_server_aof [list dir $server_path] {
  72 + test {Fixed AOF: Server should have been started} {
  73 + is_alive $srv
  74 + } {1}
  75 +
  76 + test {Fixed AOF: Keyspace should contain values that were parsable} {
  77 + set client [redis [dict get $srv host] [dict get $srv port]]
  78 + list [$client get foo] [$client get bar]
  79 + } {hello {}}
  80 +}
65 tests/support/server.tcl
@@ -8,6 +8,8 @@ proc error_and_quit {config_file error} {
8 8 }
9 9
10 10 proc kill_server config {
  11 + # nevermind if its already dead
  12 + if {![is_alive $config]} { return }
11 13 set pid [dict get $config pid]
12 14
13 15 # check for leaks
@@ -20,16 +22,24 @@ proc kill_server config {
20 22 }
21 23
22 24 # kill server and wait for the process to be totally exited
23   - exec kill $pid
24   - while 1 {
25   - # with a non-zero exit status, the process is gone
26   - if {[catch {exec ps -p $pid | grep redis-server} result]} {
27   - break
  25 + while {[is_alive $config]} {
  26 + if {[incr wait 10] % 1000 == 0} {
  27 + puts "Waiting for process $pid to exit..."
28 28 }
  29 + exec kill $pid
29 30 after 10
30 31 }
31 32 }
32 33
  34 +proc is_alive config {
  35 + set pid [dict get $config pid]
  36 + if {[catch {exec ps -p $pid} err]} {
  37 + return 0
  38 + } else {
  39 + return 1
  40 + }
  41 +}
  42 +
33 43 proc start_server {filename overrides {code undefined}} {
34 44 set data [split [exec cat "tests/assets/$filename"] "\n"]
35 45 set config {}
@@ -74,33 +84,14 @@ proc start_server {filename overrides {code undefined}} {
74 84 error_and_quit $config_file [exec cat $stderr]
75 85 }
76 86
77   - set line [exec head -n1 $stdout]
78   - if {[string match {*already in use*} $line]} {
79   - error_and_quit $config_file $line
80   - }
81   -
82   - while 1 {
83   - # check that the server actually started and is ready for connections
84   - if {[exec cat $stdout | grep "ready to accept" | wc -l] > 0} {
85   - break
86   - }
87   - after 10
88   - }
89   -
90 87 # find out the pid
91 88 regexp {^\[(\d+)\]} [exec head -n1 $stdout] _ pid
92 89
93   - # create the client object
  90 + # setup properties to be able to initialize a client object
94 91 set host $::host
95 92 set port $::port
96 93 if {[dict exists $config bind]} { set host [dict get $config bind] }
97 94 if {[dict exists $config port]} { set port [dict get $config port] }
98   - set client [redis $host $port]
99   -
100   - # select the right db when we don't have to authenticate
101   - if {![dict exists $config requirepass]} {
102   - $client select 9
103   - }
104 95
105 96 # setup config dict
106 97 dict set srv "config" $config_file
@@ -109,9 +100,31 @@ proc start_server {filename overrides {code undefined}} {
109 100 dict set srv "port" $port
110 101 dict set srv "stdout" $stdout
111 102 dict set srv "stderr" $stderr
112   - dict set srv "client" $client
113 103
  104 + # if a block of code is supplied, we wait for the server to become
  105 + # available, create a client object and kill the server afterwards
114 106 if {$code ne "undefined"} {
  107 + set line [exec head -n1 $stdout]
  108 + if {[string match {*already in use*} $line]} {
  109 + error_and_quit $config_file $line
  110 + }
  111 +
  112 + while 1 {
  113 + # check that the server actually started and is ready for connections
  114 + if {[exec cat $stdout | grep "ready to accept" | wc -l] > 0} {
  115 + break
  116 + }
  117 + after 10
  118 + }
  119 +
  120 + set client [redis $host $port]
  121 + dict set srv "client" $client
  122 +
  123 + # select the right db when we don't have to authenticate
  124 + if {![dict exists $config requirepass]} {
  125 + $client select 9
  126 + }
  127 +
115 128 # append the server to the stack
116 129 lappend ::servers $srv
117 130
8 tests/support/util.tcl
@@ -188,3 +188,11 @@ proc createComplexDataset {r ops} {
188 188 }
189 189 }
190 190 }
  191 +
  192 +proc formatCommand {args} {
  193 + set cmd "*[llength $args]\r\n"
  194 + foreach a $args {
  195 + append cmd "$[string length $a]\r\n$a\r\n"
  196 + }
  197 + set _ $cmd
  198 +}
1  tests/test_helper.tcl
@@ -61,6 +61,7 @@ proc main {} {
61 61 execute_tests "unit/expire"
62 62 execute_tests "unit/other"
63 63 execute_tests "integration/replication"
  64 + execute_tests "integration/aof"
64 65
65 66 puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed"
66 67 if {$::failed > 0} {

0 comments on commit 04c9847

Please sign in to comment.
Something went wrong with that request. Please try again.