@@ -65,6 +65,50 @@ def test_proxy_bidirectional() -> None:
6565 remote_server .close ()
6666
6767
68+ def test_proxy_pending_data () -> None :
69+ """Test that _proxy forwards pending SSL data correctly."""
70+ local_client , local_server = socket .socketpair ()
71+ remote_client , remote_server = socket .socketpair ()
72+
73+ class MockSSLSocket :
74+ def __init__ (self , sock : socket .socket ) -> None :
75+ self ._sock = sock
76+ self ._pending_calls = [12 , 0 ] # "pending data" is 12 bytes
77+
78+ def pending (self ) -> int :
79+ if self ._pending_calls :
80+ return self ._pending_calls .pop (0 )
81+ return 0
82+
83+ def recv (self , bufsize : int , flags : int = 0 ) -> bytes :
84+ return self ._sock .recv (bufsize , flags )
85+
86+ def __getattr__ (self , name : str ) -> Any :
87+ return getattr (self ._sock , name )
88+
89+ wrapped_remote = MockSSLSocket (remote_client )
90+
91+ # Pre-populate the socket with data that will be read by forward_pending
92+ remote_server .sendall (b"pending data" )
93+
94+ # Start proxy in background
95+ proxy_thread = threading .Thread (
96+ target = _proxy , args = (local_server , wrapped_remote ), daemon = True
97+ )
98+ proxy_thread .start ()
99+
100+ # Verify that local_client receives the pending data immediately
101+ assert local_client .recv (1024 ) == b"pending data"
102+
103+ # Clean up
104+ local_client .close ()
105+ proxy_thread .join (timeout = 2.0 )
106+
107+ local_server .close ()
108+ remote_client .close ()
109+ remote_server .close ()
110+
111+
68112@patch ("psycopg.connect" )
69113def test_connect_wrapper (mock_psycopg_connect : MagicMock ) -> None :
70114 """Test connect wrapper creates temp socket and calls psycopg.connect with correct arguments."""
0 commit comments