@@ -78,23 +78,54 @@ fn args_as_string(args: Vec<Value>) -> String {
7878 output
7979}
8080
81- fn add_to_response < B : BuildHasher > (
81+ pub fn add_to_response < B : BuildHasher > (
8282 response : & mut HashMap < String , String , B > ,
8383 cmd : & redis:: Cmd ,
8484 args : Vec < Value > ,
8585) {
86- response. insert ( cmd_as_string ( cmd) , args_as_string ( args) ) ;
86+ add_to_response_raw ( response, cmd, args_as_string ( args) ) ;
87+ }
88+
89+ pub fn add_to_response_raw < B : BuildHasher > (
90+ response : & mut HashMap < String , String , B > ,
91+ cmd : & redis:: Cmd ,
92+ args : String ,
93+ ) {
94+ response. insert ( cmd_as_string ( cmd) , args) ;
8795}
8896
8997fn setinfo ( responses : & mut HashMap < String , String > ) {
90- // Library sends both lib-name and lib-ver in one go, so we respond to both
91- add_to_response (
92- responses,
98+ // We do raw inserts of command here, because the library sends 3/4 commands in one go
99+ // They always start with HELLO, then optionally SELECT, so we use this to differentiate
100+ let hello = cmd_as_string ( redis:: cmd ( "HELLO" ) . arg ( "3" ) ) ;
101+ let setinfo = cmd_as_string (
93102 redis:: cmd ( "CLIENT" )
94103 . arg ( "SETINFO" )
95104 . arg ( "LIB-NAME" )
96105 . arg ( "redis-rs" ) ,
97- vec ! [ Value :: Okay , Value :: Okay ] ,
106+ ) ;
107+ responses. insert (
108+ [ hello. clone ( ) , setinfo. clone ( ) ] . join ( "" ) ,
109+ args_as_string ( vec ! [
110+ Value :: Map ( vec![ (
111+ Value :: SimpleString ( "server" . into( ) ) ,
112+ Value :: SimpleString ( "redis" . into( ) ) ,
113+ ) ] ) ,
114+ Value :: Okay ,
115+ Value :: Okay ,
116+ ] ) ,
117+ ) ;
118+ responses. insert (
119+ [ hello, cmd_as_string ( redis:: cmd ( "SELECT" ) . arg ( 3 ) ) , setinfo] . join ( "" ) ,
120+ args_as_string ( vec ! [
121+ Value :: Map ( vec![ (
122+ Value :: SimpleString ( "server" . into( ) ) ,
123+ Value :: SimpleString ( "redis" . into( ) ) ,
124+ ) ] ) ,
125+ Value :: Okay ,
126+ Value :: Okay ,
127+ Value :: Okay ,
128+ ] ) ,
98129 ) ;
99130}
100131
@@ -159,10 +190,11 @@ pub fn fake_redis_sentinel_stream(master_name: &str, redis_port: u16) -> HashMap
159190 response
160191}
161192
162- pub ( crate ) async fn fake_redis_internal < H > ( listener : TcpListener , handler : H )
193+ pub ( crate ) async fn fake_redis_internal < H > ( listener : TcpListener , handlers : Vec < H > )
163194where
164- H : Fn ( & [ u8 ] ) -> String + Send + Clone + ' static ,
195+ H : Fn ( & [ u8 ] ) -> String + Send + Clone + ' static + Sync ,
165196{
197+ let mut handler_iter = handlers. iter ( ) . cloned ( ) . cycle ( ) ;
166198 loop {
167199 info ! (
168200 "Waiting for connection on {}" ,
@@ -173,7 +205,7 @@ where
173205 panic ! ( "error" ) ;
174206 } ;
175207 info ! ( "Accepted new connection" ) ;
176- let local_handler = handler . clone ( ) ;
208+ let local_handler = handler_iter . next ( ) . unwrap ( ) ;
177209 background_spawn ! ( "thread" , async move {
178210 loop {
179211 let mut buf = vec![ 0 ; 8192 ] ;
@@ -189,32 +221,38 @@ where
189221 }
190222}
191223
192- async fn fake_redis < B > ( listener : TcpListener , responses : HashMap < String , String , B > )
224+ async fn fake_redis < B > ( listener : TcpListener , all_responses : Vec < HashMap < String , String , B > > )
193225where
194- B : BuildHasher + Clone + Send + ' static ,
226+ B : BuildHasher + Clone + Send + ' static + Sync ,
195227{
196- info ! ( "Responses are: {:?}" , responses) ;
197- let values = responses. clone ( ) ;
198- let inner = move |buf : & [ u8 ] | -> String {
199- let str_buf = str:: from_utf8 ( buf) ;
200- if let Ok ( s) = str_buf {
201- for ( key, value) in & values {
202- if s. starts_with ( key) {
203- info ! ( "Responding to {}" , s. replace( "\r \n " , "\\ r\\ n" ) ) ;
204- return value. clone ( ) ;
228+ let funcs = all_responses
229+ . iter ( )
230+ . map ( |responses| {
231+ info ! ( "Responses are: {:?}" , responses) ;
232+ let values = responses. clone ( ) ;
233+ move |buf : & [ u8 ] | -> String {
234+ let str_buf = String :: from_utf8_lossy ( buf) . into_owned ( ) ;
235+ for ( key, value) in & values {
236+ if str_buf. starts_with ( key) {
237+ info ! ( "Responding to {}" , str_buf. replace( "\r \n " , "\\ r\\ n" ) ) ;
238+ return value. clone ( ) ;
239+ }
205240 }
241+ warn ! (
242+ "Unknown command: {}" ,
243+ str_buf. chars( ) . take( 1000 ) . collect:: <String >( )
244+ ) ;
245+ String :: new ( )
206246 }
207- warn ! ( "Unknown command: {s}" ) ;
208- } else {
209- warn ! ( "Bytes buffer: {:?}" , & buf) ;
210- }
211- String :: new ( )
212- } ;
213- fake_redis_internal ( listener, inner) . await ;
247+ } )
248+ . collect ( ) ;
249+ fake_redis_internal ( listener, funcs) . await ;
214250}
215251
216- pub async fn make_fake_redis_with_responses < B : BuildHasher + Clone + Send + ' static > (
217- responses : HashMap < String , String , B > ,
252+ pub async fn make_fake_redis_with_multiple_responses <
253+ B : BuildHasher + Clone + Send + ' static + Sync ,
254+ > (
255+ responses : Vec < HashMap < String , String , B > > ,
218256) -> u16 {
219257 let listener = TcpListener :: bind ( "127.0.0.1:0" ) . await . unwrap ( ) ;
220258 let port = listener. local_addr ( ) . unwrap ( ) . port ( ) ;
@@ -226,3 +264,9 @@ pub async fn make_fake_redis_with_responses<B: BuildHasher + Clone + Send + 'sta
226264
227265 port
228266}
267+
268+ pub async fn make_fake_redis_with_responses < B : BuildHasher + Clone + Send + ' static + Sync > (
269+ responses : HashMap < String , String , B > ,
270+ ) -> u16 {
271+ make_fake_redis_with_multiple_responses ( vec ! [ responses] ) . await
272+ }
0 commit comments