@@ -212,6 +212,44 @@ public function testWillRejectAndCloseAutomaticallyWhenAuthCommandReceivesErrorR
212212 ));
213213 }
214214
215+ public function testWillRejectAndCloseAutomaticallyWhenConnectionIsClosedWhileWaitingForAuthCommand ()
216+ {
217+ $ closeHandler = null ;
218+ $ stream = $ this ->getMockBuilder ('React\Socket\ConnectionInterface ' )->getMock ();
219+ $ stream ->expects ($ this ->once ())->method ('write ' )->with ("*2 \r\n$4 \r\nauth \r\n$5 \r\nworld \r\n" );
220+ $ stream ->expects ($ this ->once ())->method ('close ' );
221+ $ stream ->expects ($ this ->exactly (2 ))->method ('on ' )->withConsecutive (
222+ array ('data ' , $ this ->anything ()),
223+ array ('close ' , $ this ->callback (function ($ arg ) use (&$ closeHandler ) {
224+ $ closeHandler = $ arg ;
225+ return true ;
226+ }))
227+ );
228+
229+ $ this ->connector ->expects ($ this ->once ())->method ('connect ' )->willReturn (Promise \resolve ($ stream ));
230+ $ promise = $ this ->factory ->createClient ('redis://:world@localhost ' );
231+
232+ $ this ->assertTrue (is_callable ($ closeHandler ));
233+ $ stream ->expects ($ this ->once ())->method ('isReadable ' )->willReturn (false );
234+ $ stream ->expects ($ this ->once ())->method ('isWritable ' )->willReturn (false );
235+ call_user_func ($ closeHandler );
236+
237+ $ promise ->then (null , $ this ->expectCallableOnceWith (
238+ $ this ->logicalAnd (
239+ $ this ->isInstanceOf ('RuntimeException ' ),
240+ $ this ->callback (function (\Exception $ e ) {
241+ return $ e ->getMessage () === 'Connection to redis://:***@localhost failed during AUTH command: Connection closed by peer (ECONNRESET) ' ;
242+ }),
243+ $ this ->callback (function (\Exception $ e ) {
244+ return $ e ->getCode () === (defined ('SOCKET_ECONNRESET ' ) ? SOCKET_ECONNRESET : 104 );
245+ }),
246+ $ this ->callback (function (\Exception $ e ) {
247+ return $ e ->getPrevious ()->getMessage () === 'Connection closed by peer (ECONNRESET) ' ;
248+ })
249+ )
250+ ));
251+ }
252+
215253 public function testWillWriteSelectCommandIfRedisUnixUriContainsDbQueryParameter ()
216254 {
217255 $ stream = $ this ->getMockBuilder ('React\Socket\ConnectionInterface ' )->getMock ();
@@ -279,6 +317,80 @@ public function testWillRejectAndCloseAutomaticallyWhenSelectCommandReceivesErro
279317 ));
280318 }
281319
320+ public function testWillRejectAndCloseAutomaticallyWhenSelectCommandReceivesAuthErrorResponseIfRedisUriContainsPath ()
321+ {
322+ $ dataHandler = null ;
323+ $ stream = $ this ->getMockBuilder ('React\Socket\ConnectionInterface ' )->getMock ();
324+ $ stream ->expects ($ this ->once ())->method ('write ' )->with ("*2 \r\n$6 \r\nselect \r\n$3 \r\n123 \r\n" );
325+ $ stream ->expects ($ this ->once ())->method ('close ' );
326+ $ stream ->expects ($ this ->exactly (2 ))->method ('on ' )->withConsecutive (
327+ array ('data ' , $ this ->callback (function ($ arg ) use (&$ dataHandler ) {
328+ $ dataHandler = $ arg ;
329+ return true ;
330+ })),
331+ array ('close ' , $ this ->anything ())
332+ );
333+
334+ $ this ->connector ->expects ($ this ->once ())->method ('connect ' )->willReturn (Promise \resolve ($ stream ));
335+ $ promise = $ this ->factory ->createClient ('redis://localhost/123 ' );
336+
337+ $ this ->assertTrue (is_callable ($ dataHandler ));
338+ $ dataHandler ("-NOAUTH Authentication required. \r\n" );
339+
340+ $ promise ->then (null , $ this ->expectCallableOnceWith (
341+ $ this ->logicalAnd (
342+ $ this ->isInstanceOf ('RuntimeException ' ),
343+ $ this ->callback (function (\Exception $ e ) {
344+ return $ e ->getMessage () === 'Connection to redis://localhost/123 failed during SELECT command: NOAUTH Authentication required. (EACCES) ' ;
345+ }),
346+ $ this ->callback (function (\Exception $ e ) {
347+ return $ e ->getCode () === (defined ('SOCKET_EACCES ' ) ? SOCKET_EACCES : 13 );
348+ }),
349+ $ this ->callback (function (\Exception $ e ) {
350+ return $ e ->getPrevious ()->getMessage () === 'NOAUTH Authentication required. ' ;
351+ })
352+ )
353+ ));
354+ }
355+
356+ public function testWillRejectAndCloseAutomaticallyWhenConnectionIsClosedWhileWaitingForSelectCommand ()
357+ {
358+ $ closeHandler = null ;
359+ $ stream = $ this ->getMockBuilder ('React\Socket\ConnectionInterface ' )->getMock ();
360+ $ stream ->expects ($ this ->once ())->method ('write ' )->with ("*2 \r\n$6 \r\nselect \r\n$3 \r\n123 \r\n" );
361+ $ stream ->expects ($ this ->once ())->method ('close ' );
362+ $ stream ->expects ($ this ->exactly (2 ))->method ('on ' )->withConsecutive (
363+ array ('data ' , $ this ->anything ()),
364+ array ('close ' , $ this ->callback (function ($ arg ) use (&$ closeHandler ) {
365+ $ closeHandler = $ arg ;
366+ return true ;
367+ }))
368+ );
369+
370+ $ this ->connector ->expects ($ this ->once ())->method ('connect ' )->willReturn (Promise \resolve ($ stream ));
371+ $ promise = $ this ->factory ->createClient ('redis://localhost/123 ' );
372+
373+ $ this ->assertTrue (is_callable ($ closeHandler ));
374+ $ stream ->expects ($ this ->once ())->method ('isReadable ' )->willReturn (false );
375+ $ stream ->expects ($ this ->once ())->method ('isWritable ' )->willReturn (false );
376+ call_user_func ($ closeHandler );
377+
378+ $ promise ->then (null , $ this ->expectCallableOnceWith (
379+ $ this ->logicalAnd (
380+ $ this ->isInstanceOf ('RuntimeException ' ),
381+ $ this ->callback (function (\Exception $ e ) {
382+ return $ e ->getMessage () === 'Connection to redis://localhost/123 failed during SELECT command: Connection closed by peer (ECONNRESET) ' ;
383+ }),
384+ $ this ->callback (function (\Exception $ e ) {
385+ return $ e ->getCode () === (defined ('SOCKET_ECONNRESET ' ) ? SOCKET_ECONNRESET : 104 );
386+ }),
387+ $ this ->callback (function (\Exception $ e ) {
388+ return $ e ->getPrevious ()->getMessage () === 'Connection closed by peer (ECONNRESET) ' ;
389+ })
390+ )
391+ ));
392+ }
393+
282394 public function testWillRejectIfConnectorRejects ()
283395 {
284396 $ this ->connector ->expects ($ this ->once ())->method ('connect ' )->with ('127.0.0.1:2 ' )->willReturn (Promise \reject (new \RuntimeException ('Foo ' , 42 )));
0 commit comments