# A fake Redis node for replaying predefined/expected traffic with a client. # # Usage: tclsh fake_redis_node.tcl PORT COMMAND REPLY [ COMMAND REPLY [ ... ] ] # # Commands are given as space-separated strings, e.g. "GET foo", and replies as # RESP-encoded replies minus the trailing \r\n, e.g. "+OK". set port [lindex $argv 0]; set expected_traffic [lrange $argv 1 end]; # Reads and parses a command from a socket and returns it as a space-separated # string, e.g. "set foo bar". proc read_command {sock} { set char [read $sock 1] switch $char { * { set numargs [gets $sock] set result {} for {set i 0} {$i<$numargs} {incr i} { read $sock 1; # dollar sign set len [gets $sock] set str [read $sock $len] gets $sock; # trailing \r\n lappend result $str } return $result } {} { # EOF return {} } default { # Non-RESP command set rest [gets $sock] return "$char$rest" } } } proc accept {sock host port} { global expected_traffic foreach {expect_cmd reply} $expected_traffic { if {[eof $sock]} {break} set cmd [read_command $sock] if {[string equal -nocase $cmd $expect_cmd]} { puts $sock $reply flush $sock } else { puts $sock "-ERR unexpected command $cmd" break } } close $sock } socket -server accept $port after 5000 set done timeout vwait done