fake_redis_node.tcl 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. # A fake Redis node for replaying predefined/expected traffic with a client.
  2. #
  3. # Usage: tclsh fake_redis_node.tcl PORT COMMAND REPLY [ COMMAND REPLY [ ... ] ]
  4. #
  5. # Commands are given as space-separated strings, e.g. "GET foo", and replies as
  6. # RESP-encoded replies minus the trailing \r\n, e.g. "+OK".
  7. set port [lindex $argv 0];
  8. set expected_traffic [lrange $argv 1 end];
  9. # Reads and parses a command from a socket and returns it as a space-separated
  10. # string, e.g. "set foo bar".
  11. proc read_command {sock} {
  12. set char [read $sock 1]
  13. switch $char {
  14. * {
  15. set numargs [gets $sock]
  16. set result {}
  17. for {set i 0} {$i<$numargs} {incr i} {
  18. read $sock 1; # dollar sign
  19. set len [gets $sock]
  20. set str [read $sock $len]
  21. gets $sock; # trailing \r\n
  22. lappend result $str
  23. }
  24. return $result
  25. }
  26. {} {
  27. # EOF
  28. return {}
  29. }
  30. default {
  31. # Non-RESP command
  32. set rest [gets $sock]
  33. return "$char$rest"
  34. }
  35. }
  36. }
  37. proc accept {sock host port} {
  38. global expected_traffic
  39. foreach {expect_cmd reply} $expected_traffic {
  40. if {[eof $sock]} {break}
  41. set cmd [read_command $sock]
  42. if {[string equal -nocase $cmd $expect_cmd]} {
  43. puts $sock $reply
  44. flush $sock
  45. } else {
  46. puts $sock "-ERR unexpected command $cmd"
  47. break
  48. }
  49. }
  50. close $sock
  51. }
  52. socket -server accept $port
  53. after 5000 set done timeout
  54. vwait done