blob: 251e0be0a8fb580fa0b6a294a6657c9b04ceb3de [file] [log] [blame]
Brett Cannonbf364092006-03-01 04:25:17 +00001import unittest
2import __builtin__
3import exceptions
4import warnings
5from test.test_support import run_unittest
6import os
7from platform import system as platform_system
8
9class ExceptionClassTests(unittest.TestCase):
10
11 """Tests for anything relating to exception objects themselves (e.g.,
12 inheritance hierarchy)"""
13
14 def test_builtins_new_style(self):
15 self.failUnless(issubclass(Exception, object))
16
17 def verify_instance_interface(self, ins):
18 for attr in ("args", "message", "__str__", "__unicode__", "__repr__",
19 "__getitem__"):
20 self.failUnless(hasattr(ins, attr), "%s missing %s attribute" %
21 (ins.__class__.__name__, attr))
22
23 def test_inheritance(self):
24 # Make sure the inheritance hierarchy matches the documentation
25 exc_set = set(x for x in dir(exceptions) if not x.startswith('_'))
26 inheritance_tree = open(os.path.join(os.path.split(__file__)[0],
27 'exception_hierarchy.txt'))
28 try:
29 superclass_name = inheritance_tree.readline().rstrip()
30 try:
31 last_exc = getattr(__builtin__, superclass_name)
32 except AttributeError:
33 self.fail("base class %s not a built-in" % superclass_name)
34 self.failUnless(superclass_name in exc_set)
35 exc_set.discard(superclass_name)
36 superclasses = [] # Loop will insert base exception
37 last_depth = 0
38 for exc_line in inheritance_tree:
39 exc_line = exc_line.rstrip()
40 depth = exc_line.rindex('-')
41 exc_name = exc_line[depth+2:] # Slice past space
42 if '(' in exc_name:
43 paren_index = exc_name.index('(')
44 platform_name = exc_name[paren_index+1:-1]
Brett Cannon6b4ed742006-03-01 06:10:48 +000045 exc_name = exc_name[:paren_index-1] # Slice off space
Brett Cannonbf364092006-03-01 04:25:17 +000046 if platform_system() != platform_name:
47 exc_set.discard(exc_name)
48 continue
49 if '[' in exc_name:
50 left_bracket = exc_name.index('[')
51 exc_name = exc_name[:left_bracket-1] # cover space
52 try:
53 exc = getattr(__builtin__, exc_name)
54 except AttributeError:
55 self.fail("%s not a built-in exception" % exc_name)
56 if last_depth < depth:
57 superclasses.append((last_depth, last_exc))
58 elif last_depth > depth:
59 while superclasses[-1][0] >= depth:
60 superclasses.pop()
61 self.failUnless(issubclass(exc, superclasses[-1][1]),
62 "%s is not a subclass of %s" % (exc.__name__,
63 superclasses[-1][1].__name__))
64 try: # Some exceptions require arguments; just skip them
65 self.verify_instance_interface(exc())
66 except TypeError:
67 pass
68 self.failUnless(exc_name in exc_set)
69 exc_set.discard(exc_name)
70 last_exc = exc
71 last_depth = depth
72 finally:
73 inheritance_tree.close()
74 self.failUnlessEqual(len(exc_set), 0, "%s not accounted for" % exc_set)
75
76 interface_tests = ("length", "args", "message", "str", "unicode", "repr",
77 "indexing")
78
79 def interface_test_driver(self, results):
80 for test_name, (given, expected) in zip(self.interface_tests, results):
81 self.failUnlessEqual(given, expected, "%s: %s != %s" % (test_name,
82 given, expected))
83
84 def test_interface_single_arg(self):
85 # Make sure interface works properly when given a single argument
86 arg = "spam"
87 exc = Exception(arg)
88 results = ([len(exc.args), 1], [exc.args[0], arg], [exc.message, arg],
89 [str(exc), str(arg)], [unicode(exc), unicode(arg)],
90 [repr(exc), exc.__class__.__name__ + repr(exc.args)], [exc[0], arg])
91 self.interface_test_driver(results)
92
93 def test_interface_multi_arg(self):
94 # Make sure interface correct when multiple arguments given
95 arg_count = 3
96 args = tuple(range(arg_count))
97 exc = Exception(*args)
98 results = ([len(exc.args), arg_count], [exc.args, args],
99 [exc.message, ''], [str(exc), str(args)],
100 [unicode(exc), unicode(args)],
101 [repr(exc), exc.__class__.__name__ + repr(exc.args)],
102 [exc[-1], args[-1]])
103 self.interface_test_driver(results)
104
105 def test_interface_no_arg(self):
106 # Make sure that with no args that interface is correct
107 exc = Exception()
108 results = ([len(exc.args), 0], [exc.args, tuple()], [exc.message, ''],
109 [str(exc), ''], [unicode(exc), u''],
110 [repr(exc), exc.__class__.__name__ + '()'], [True, True])
111 self.interface_test_driver(results)
112
113class UsageTests(unittest.TestCase):
114
115 """Test usage of exceptions"""
116
117 def setUp(self):
118 self._filters = warnings.filters[:]
119
120 def tearDown(self):
121 warnings.filters = self._filters[:]
122
123 def test_raise_classic(self):
124 class ClassicClass:
125 pass
126 try:
127 raise ClassicClass
128 except ClassicClass:
129 pass
130 except:
131 self.fail("unable to raise classic class")
132 try:
133 raise ClassicClass()
134 except ClassicClass:
135 pass
136 except:
137 self.fail("unable to raise class class instance")
138
139 def test_raise_new_style_non_exception(self):
140 class NewStyleClass(object):
141 pass
142 try:
143 raise NewStyleClass
144 except TypeError:
145 pass
146 except:
147 self.fail("unable to raise new-style class")
148 try:
149 raise NewStyleClass()
150 except TypeError:
151 pass
152 except:
153 self.fail("unable to raise new-style class instance")
154
155 def test_raise_string(self):
156 warnings.resetwarnings()
157 warnings.filterwarnings("error")
158 try:
159 raise "spam"
160 except DeprecationWarning:
161 pass
162 except:
163 self.fail("raising a string did not cause a DeprecationWarning")
164
165 def test_catch_string(self):
166 # Test will be pertinent when catching exceptions raises a
167 # DeprecationWarning
168 warnings.filterwarnings("ignore", "raising")
169 str_exc = "spam"
170 try:
171 raise str_exc
172 except str_exc:
173 pass
174 except:
175 self.fail("catching a string exception failed")
176
177def test_main():
178 run_unittest(ExceptionClassTests, UsageTests)
179
180
181
182if __name__ == '__main__':
183 test_main()