@@ -688,6 +688,63 @@ def test_connection_pool_closed_while_request_in_flight():
688688
689689
690690
691+ def test_connection_pool_with_idle_broken_connection ():
692+ """
693+ Pool gives a new connection when an idle connection gets readable (ie broken) while in the pool.
694+ """
695+
696+ class MockStream (httpcore .MockStream ):
697+ def __init__ (self , buffer : typing .List [bytes ]):
698+ super ().__init__ (buffer )
699+ self .mock_is_readable = False
700+
701+ def get_extra_info (self , info : str ) -> typing .Any :
702+ if info == "is_readable" :
703+ return self .mock_is_readable
704+ return super ().get_extra_info (info ) # pragma: nocover
705+
706+ class MockBackend (httpcore .MockBackend ):
707+ def connect_tcp (
708+ self , * args : typing .Any , ** kwargs : typing .Any
709+ ) -> MockStream :
710+ return MockStream (list (self ._buffer ))
711+
712+ network_backend = MockBackend (
713+ [
714+ b"HTTP/1.1 200 OK\r \n " ,
715+ b"Content-Type: plain/text\r \n " ,
716+ b"Content-Length: 13\r \n " ,
717+ b"\r \n " ,
718+ b"Hello, world!" ,
719+ b"HTTP/1.1 200 OK\r \n " ,
720+ b"Content-Type: plain/text\r \n " ,
721+ b"Content-Length: 13\r \n " ,
722+ b"\r \n " ,
723+ b"Hello, world!" ,
724+ ]
725+ )
726+ with httpcore .ConnectionPool (
727+ network_backend = network_backend , max_connections = 1
728+ ) as pool :
729+ pool .request ("GET" , "https://example.com/" )
730+ assert len (pool .connections ) == 1
731+ conn = pool .connections [0 ]
732+ pool .request ("GET" , "https://example.com/" )
733+ assert len (pool .connections ) == 1
734+ assert conn is pool .connections [0 ], "Should reuse connection"
735+
736+ # Simulate network breakage
737+ assert conn .is_idle ()
738+ conn ._connection ._network_stream .mock_is_readable = True # type: ignore[attr-defined]
739+
740+ pool .request ("GET" , "https://example.com/" )
741+ assert len (pool .connections ) == 1
742+ new_conn = pool .connections [0 ]
743+ assert new_conn is not conn , "Should be a new connection"
744+ assert not new_conn ._connection ._network_stream .mock_is_readable # type: ignore[attr-defined]
745+
746+
747+
691748def test_connection_pool_timeout ():
692749 """
693750 Ensure that exceeding max_connections can cause a request to timeout.
0 commit comments