22
33import errno
44import http .client
5+ import io
56import logging
67import socket
78import time
1415import pytest
1516
1617from jaraco .text import trim , unwrap
18+ from OpenSSL .SSL import SysCallError
1719
1820import cheroot .server
1921from cheroot ._compat import IS_CI , IS_MACOS , IS_PYPY , IS_WINDOWS
@@ -1645,8 +1647,6 @@ class TestBufferedWriter:
16451647
16461648 def test_close_is_idempotent (self ):
16471649 """Test that close() can be called multiple times safely."""
1648- import io
1649-
16501650 raw_buffer = io .BytesIO ()
16511651 buffered_writer = BufferedWriter (raw_buffer )
16521652
@@ -1658,8 +1658,6 @@ def test_close_is_idempotent(self):
16581658
16591659 def test_close_handles_already_closed_buffer (self ):
16601660 """Test that close() handles already closed underlying buffer."""
1661- import io
1662-
16631661 raw_buffer = io .BytesIO ()
16641662 buffered_writer = BufferedWriter (raw_buffer )
16651663
@@ -1668,3 +1666,46 @@ def test_close_handles_already_closed_buffer(self):
16681666
16691667 # This should not raise an exception
16701668 buffered_writer .close ()
1669+
1670+ def test_close_handles_os_error_ebadf (self , mocker ):
1671+ """Test that close() handles OSError with EBADF errno gracefully."""
1672+ raw_buffer = io .BytesIO ()
1673+ buffered_writer = BufferedWriter (raw_buffer )
1674+
1675+ # Mock super().close() to raise OSError with EBADF
1676+ mock_super = mocker .patch ('cheroot.makefile.super' )
1677+ mock_super .return_value .close .side_effect = OSError (
1678+ errno .EBADF ,
1679+ 'Bad file descriptor' ,
1680+ )
1681+
1682+ # Should handle EBADF gracefully (no exception raised)
1683+ buffered_writer .close ()
1684+
1685+ def test_close_handles_os_error_enotconn (self , mocker ):
1686+ """Test that close() handles OSError with ENOTCONN errno gracefully."""
1687+ raw_buffer = io .BytesIO ()
1688+ buffered_writer = BufferedWriter (raw_buffer )
1689+
1690+ # Mock super().close() to raise OSError with ENOTCONN
1691+ mock_super = mocker .patch ('cheroot.makefile.super' )
1692+ mock_super .return_value .close .side_effect = OSError (
1693+ errno .ENOTCONN ,
1694+ 'Socket is not connected' ,
1695+ )
1696+
1697+ # Should handle ENOTCONN gracefully (no exception raised)
1698+ buffered_writer .close ()
1699+
1700+ def test_close_handles_syscall_error (self , mocker ):
1701+ """Test that close() handles SysCallError with expected errno codes."""
1702+ raw_buffer = io .BytesIO ()
1703+ buffered_writer = BufferedWriter (raw_buffer )
1704+
1705+ mock_super = mocker .patch ('cheroot.makefile.super' )
1706+ mock_super .return_value .close .side_effect = SysCallError (
1707+ errno .EBADF ,
1708+ ) # args[0] will be errno.EBADF
1709+
1710+ # Should handle gracefully
1711+ buffered_writer .close ()
0 commit comments