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