Home | History | Annotate | Download | only in test
      1 import builtins
      2 import os
      3 import select
      4 import socket
      5 import unittest
      6 import errno
      7 from errno import EEXIST
      8 
      9 
     10 class SubOSError(OSError):
     11     pass
     12 
     13 class SubOSErrorWithInit(OSError):
     14     def __init__(self, message, bar):
     15         self.bar = bar
     16         super().__init__(message)
     17 
     18 class SubOSErrorWithNew(OSError):
     19     def __new__(cls, message, baz):
     20         self = super().__new__(cls, message)
     21         self.baz = baz
     22         return self
     23 
     24 class SubOSErrorCombinedInitFirst(SubOSErrorWithInit, SubOSErrorWithNew):
     25     pass
     26 
     27 class SubOSErrorCombinedNewFirst(SubOSErrorWithNew, SubOSErrorWithInit):
     28     pass
     29 
     30 class SubOSErrorWithStandaloneInit(OSError):
     31     def __init__(self):
     32         pass
     33 
     34 
     35 class HierarchyTest(unittest.TestCase):
     36 
     37     def test_builtin_errors(self):
     38         self.assertEqual(OSError.__name__, 'OSError')
     39         self.assertIs(IOError, OSError)
     40         self.assertIs(EnvironmentError, OSError)
     41 
     42     def test_socket_errors(self):
     43         self.assertIs(socket.error, IOError)
     44         self.assertIs(socket.gaierror.__base__, OSError)
     45         self.assertIs(socket.herror.__base__, OSError)
     46         self.assertIs(socket.timeout.__base__, OSError)
     47 
     48     def test_select_error(self):
     49         self.assertIs(select.error, OSError)
     50 
     51     # mmap.error is tested in test_mmap
     52 
     53     _pep_map = """
     54         +-- BlockingIOError        EAGAIN, EALREADY, EWOULDBLOCK, EINPROGRESS
     55         +-- ChildProcessError                                          ECHILD
     56         +-- ConnectionError
     57             +-- BrokenPipeError                              EPIPE, ESHUTDOWN
     58             +-- ConnectionAbortedError                           ECONNABORTED
     59             +-- ConnectionRefusedError                           ECONNREFUSED
     60             +-- ConnectionResetError                               ECONNRESET
     61         +-- FileExistsError                                            EEXIST
     62         +-- FileNotFoundError                                          ENOENT
     63         +-- InterruptedError                                            EINTR
     64         +-- IsADirectoryError                                          EISDIR
     65         +-- NotADirectoryError                                        ENOTDIR
     66         +-- PermissionError                                     EACCES, EPERM
     67         +-- ProcessLookupError                                          ESRCH
     68         +-- TimeoutError                                            ETIMEDOUT
     69     """
     70     def _make_map(s):
     71         _map = {}
     72         for line in s.splitlines():
     73             line = line.strip('+- ')
     74             if not line:
     75                 continue
     76             excname, _, errnames = line.partition(' ')
     77             for errname in filter(None, errnames.strip().split(', ')):
     78                 _map[getattr(errno, errname)] = getattr(builtins, excname)
     79         return _map
     80     _map = _make_map(_pep_map)
     81 
     82     def test_errno_mapping(self):
     83         # The OSError constructor maps errnos to subclasses
     84         # A sample test for the basic functionality
     85         e = OSError(EEXIST, "Bad file descriptor")
     86         self.assertIs(type(e), FileExistsError)
     87         # Exhaustive testing
     88         for errcode, exc in self._map.items():
     89             e = OSError(errcode, "Some message")
     90             self.assertIs(type(e), exc)
     91         othercodes = set(errno.errorcode) - set(self._map)
     92         for errcode in othercodes:
     93             e = OSError(errcode, "Some message")
     94             self.assertIs(type(e), OSError)
     95 
     96     def test_try_except(self):
     97         filename = "some_hopefully_non_existing_file"
     98 
     99         # This checks that try .. except checks the concrete exception
    100         # (FileNotFoundError) and not the base type specified when
    101         # PyErr_SetFromErrnoWithFilenameObject was called.
    102         # (it is therefore deliberate that it doesn't use assertRaises)
    103         try:
    104             open(filename)
    105         except FileNotFoundError:
    106             pass
    107         else:
    108             self.fail("should have raised a FileNotFoundError")
    109 
    110         # Another test for PyErr_SetExcFromWindowsErrWithFilenameObject()
    111         self.assertFalse(os.path.exists(filename))
    112         try:
    113             os.unlink(filename)
    114         except FileNotFoundError:
    115             pass
    116         else:
    117             self.fail("should have raised a FileNotFoundError")
    118 
    119 
    120 class AttributesTest(unittest.TestCase):
    121 
    122     def test_windows_error(self):
    123         if os.name == "nt":
    124             self.assertIn('winerror', dir(OSError))
    125         else:
    126             self.assertNotIn('winerror', dir(OSError))
    127 
    128     def test_posix_error(self):
    129         e = OSError(EEXIST, "File already exists", "foo.txt")
    130         self.assertEqual(e.errno, EEXIST)
    131         self.assertEqual(e.args[0], EEXIST)
    132         self.assertEqual(e.strerror, "File already exists")
    133         self.assertEqual(e.filename, "foo.txt")
    134         if os.name == "nt":
    135             self.assertEqual(e.winerror, None)
    136 
    137     @unittest.skipUnless(os.name == "nt", "Windows-specific test")
    138     def test_errno_translation(self):
    139         # ERROR_ALREADY_EXISTS (183) -> EEXIST
    140         e = OSError(0, "File already exists", "foo.txt", 183)
    141         self.assertEqual(e.winerror, 183)
    142         self.assertEqual(e.errno, EEXIST)
    143         self.assertEqual(e.args[0], EEXIST)
    144         self.assertEqual(e.strerror, "File already exists")
    145         self.assertEqual(e.filename, "foo.txt")
    146 
    147     def test_blockingioerror(self):
    148         args = ("a", "b", "c", "d", "e")
    149         for n in range(6):
    150             e = BlockingIOError(*args[:n])
    151             with self.assertRaises(AttributeError):
    152                 e.characters_written
    153         e = BlockingIOError("a", "b", 3)
    154         self.assertEqual(e.characters_written, 3)
    155         e.characters_written = 5
    156         self.assertEqual(e.characters_written, 5)
    157 
    158 
    159 class ExplicitSubclassingTest(unittest.TestCase):
    160 
    161     def test_errno_mapping(self):
    162         # When constructing an OSError subclass, errno mapping isn't done
    163         e = SubOSError(EEXIST, "Bad file descriptor")
    164         self.assertIs(type(e), SubOSError)
    165 
    166     def test_init_overridden(self):
    167         e = SubOSErrorWithInit("some message", "baz")
    168         self.assertEqual(e.bar, "baz")
    169         self.assertEqual(e.args, ("some message",))
    170 
    171     def test_init_kwdargs(self):
    172         e = SubOSErrorWithInit("some message", bar="baz")
    173         self.assertEqual(e.bar, "baz")
    174         self.assertEqual(e.args, ("some message",))
    175 
    176     def test_new_overridden(self):
    177         e = SubOSErrorWithNew("some message", "baz")
    178         self.assertEqual(e.baz, "baz")
    179         self.assertEqual(e.args, ("some message",))
    180 
    181     def test_new_kwdargs(self):
    182         e = SubOSErrorWithNew("some message", baz="baz")
    183         self.assertEqual(e.baz, "baz")
    184         self.assertEqual(e.args, ("some message",))
    185 
    186     def test_init_new_overridden(self):
    187         e = SubOSErrorCombinedInitFirst("some message", "baz")
    188         self.assertEqual(e.bar, "baz")
    189         self.assertEqual(e.baz, "baz")
    190         self.assertEqual(e.args, ("some message",))
    191         e = SubOSErrorCombinedNewFirst("some message", "baz")
    192         self.assertEqual(e.bar, "baz")
    193         self.assertEqual(e.baz, "baz")
    194         self.assertEqual(e.args, ("some message",))
    195 
    196     def test_init_standalone(self):
    197         # __init__ doesn't propagate to OSError.__init__ (see issue #15229)
    198         e = SubOSErrorWithStandaloneInit()
    199         self.assertEqual(e.args, ())
    200         self.assertEqual(str(e), '')
    201 
    202 
    203 if __name__ == "__main__":
    204     unittest.main()
    205