1"Test run, coverage 49%." 2 3from idlelib import run 4import unittest 5from unittest import mock 6from idlelib.idle_test.mock_idle import Func 7from test.support import captured_output, captured_stderr 8 9import io 10import sys 11 12 13class RunTest(unittest.TestCase): 14 15 def test_print_exception_unhashable(self): 16 class UnhashableException(Exception): 17 def __eq__(self, other): 18 return True 19 20 ex1 = UnhashableException('ex1') 21 ex2 = UnhashableException('ex2') 22 try: 23 raise ex2 from ex1 24 except UnhashableException: 25 try: 26 raise ex1 27 except UnhashableException: 28 with captured_stderr() as output: 29 with mock.patch.object(run, 30 'cleanup_traceback') as ct: 31 ct.side_effect = lambda t, e: t 32 run.print_exception() 33 34 tb = output.getvalue().strip().splitlines() 35 self.assertEqual(11, len(tb)) 36 self.assertIn('UnhashableException: ex2', tb[3]) 37 self.assertIn('UnhashableException: ex1', tb[10]) 38 39 40# StdioFile tests. 41 42class S(str): 43 def __str__(self): 44 return '%s:str' % type(self).__name__ 45 def __unicode__(self): 46 return '%s:unicode' % type(self).__name__ 47 def __len__(self): 48 return 3 49 def __iter__(self): 50 return iter('abc') 51 def __getitem__(self, *args): 52 return '%s:item' % type(self).__name__ 53 def __getslice__(self, *args): 54 return '%s:slice' % type(self).__name__ 55 56 57class MockShell: 58 def __init__(self): 59 self.reset() 60 def write(self, *args): 61 self.written.append(args) 62 def readline(self): 63 return self.lines.pop() 64 def close(self): 65 pass 66 def reset(self): 67 self.written = [] 68 def push(self, lines): 69 self.lines = list(lines)[::-1] 70 71 72class StdInputFilesTest(unittest.TestCase): 73 74 def test_misc(self): 75 shell = MockShell() 76 f = run.StdInputFile(shell, 'stdin') 77 self.assertIsInstance(f, io.TextIOBase) 78 self.assertEqual(f.encoding, 'utf-8') 79 self.assertEqual(f.errors, 'strict') 80 self.assertIsNone(f.newlines) 81 self.assertEqual(f.name, '<stdin>') 82 self.assertFalse(f.closed) 83 self.assertTrue(f.isatty()) 84 self.assertTrue(f.readable()) 85 self.assertFalse(f.writable()) 86 self.assertFalse(f.seekable()) 87 88 def test_unsupported(self): 89 shell = MockShell() 90 f = run.StdInputFile(shell, 'stdin') 91 self.assertRaises(OSError, f.fileno) 92 self.assertRaises(OSError, f.tell) 93 self.assertRaises(OSError, f.seek, 0) 94 self.assertRaises(OSError, f.write, 'x') 95 self.assertRaises(OSError, f.writelines, ['x']) 96 97 def test_read(self): 98 shell = MockShell() 99 f = run.StdInputFile(shell, 'stdin') 100 shell.push(['one\n', 'two\n', '']) 101 self.assertEqual(f.read(), 'one\ntwo\n') 102 shell.push(['one\n', 'two\n', '']) 103 self.assertEqual(f.read(-1), 'one\ntwo\n') 104 shell.push(['one\n', 'two\n', '']) 105 self.assertEqual(f.read(None), 'one\ntwo\n') 106 shell.push(['one\n', 'two\n', 'three\n', '']) 107 self.assertEqual(f.read(2), 'on') 108 self.assertEqual(f.read(3), 'e\nt') 109 self.assertEqual(f.read(10), 'wo\nthree\n') 110 111 shell.push(['one\n', 'two\n']) 112 self.assertEqual(f.read(0), '') 113 self.assertRaises(TypeError, f.read, 1.5) 114 self.assertRaises(TypeError, f.read, '1') 115 self.assertRaises(TypeError, f.read, 1, 1) 116 117 def test_readline(self): 118 shell = MockShell() 119 f = run.StdInputFile(shell, 'stdin') 120 shell.push(['one\n', 'two\n', 'three\n', 'four\n']) 121 self.assertEqual(f.readline(), 'one\n') 122 self.assertEqual(f.readline(-1), 'two\n') 123 self.assertEqual(f.readline(None), 'three\n') 124 shell.push(['one\ntwo\n']) 125 self.assertEqual(f.readline(), 'one\n') 126 self.assertEqual(f.readline(), 'two\n') 127 shell.push(['one', 'two', 'three']) 128 self.assertEqual(f.readline(), 'one') 129 self.assertEqual(f.readline(), 'two') 130 shell.push(['one\n', 'two\n', 'three\n']) 131 self.assertEqual(f.readline(2), 'on') 132 self.assertEqual(f.readline(1), 'e') 133 self.assertEqual(f.readline(1), '\n') 134 self.assertEqual(f.readline(10), 'two\n') 135 136 shell.push(['one\n', 'two\n']) 137 self.assertEqual(f.readline(0), '') 138 self.assertRaises(TypeError, f.readlines, 1.5) 139 self.assertRaises(TypeError, f.readlines, '1') 140 self.assertRaises(TypeError, f.readlines, 1, 1) 141 142 def test_readlines(self): 143 shell = MockShell() 144 f = run.StdInputFile(shell, 'stdin') 145 shell.push(['one\n', 'two\n', '']) 146 self.assertEqual(f.readlines(), ['one\n', 'two\n']) 147 shell.push(['one\n', 'two\n', '']) 148 self.assertEqual(f.readlines(-1), ['one\n', 'two\n']) 149 shell.push(['one\n', 'two\n', '']) 150 self.assertEqual(f.readlines(None), ['one\n', 'two\n']) 151 shell.push(['one\n', 'two\n', '']) 152 self.assertEqual(f.readlines(0), ['one\n', 'two\n']) 153 shell.push(['one\n', 'two\n', '']) 154 self.assertEqual(f.readlines(3), ['one\n']) 155 shell.push(['one\n', 'two\n', '']) 156 self.assertEqual(f.readlines(4), ['one\n', 'two\n']) 157 158 shell.push(['one\n', 'two\n', '']) 159 self.assertRaises(TypeError, f.readlines, 1.5) 160 self.assertRaises(TypeError, f.readlines, '1') 161 self.assertRaises(TypeError, f.readlines, 1, 1) 162 163 def test_close(self): 164 shell = MockShell() 165 f = run.StdInputFile(shell, 'stdin') 166 shell.push(['one\n', 'two\n', '']) 167 self.assertFalse(f.closed) 168 self.assertEqual(f.readline(), 'one\n') 169 f.close() 170 self.assertFalse(f.closed) 171 self.assertEqual(f.readline(), 'two\n') 172 self.assertRaises(TypeError, f.close, 1) 173 174 175class StdOutputFilesTest(unittest.TestCase): 176 177 def test_misc(self): 178 shell = MockShell() 179 f = run.StdOutputFile(shell, 'stdout') 180 self.assertIsInstance(f, io.TextIOBase) 181 self.assertEqual(f.encoding, 'utf-8') 182 self.assertEqual(f.errors, 'strict') 183 self.assertIsNone(f.newlines) 184 self.assertEqual(f.name, '<stdout>') 185 self.assertFalse(f.closed) 186 self.assertTrue(f.isatty()) 187 self.assertFalse(f.readable()) 188 self.assertTrue(f.writable()) 189 self.assertFalse(f.seekable()) 190 191 def test_unsupported(self): 192 shell = MockShell() 193 f = run.StdOutputFile(shell, 'stdout') 194 self.assertRaises(OSError, f.fileno) 195 self.assertRaises(OSError, f.tell) 196 self.assertRaises(OSError, f.seek, 0) 197 self.assertRaises(OSError, f.read, 0) 198 self.assertRaises(OSError, f.readline, 0) 199 200 def test_write(self): 201 shell = MockShell() 202 f = run.StdOutputFile(shell, 'stdout') 203 f.write('test') 204 self.assertEqual(shell.written, [('test', 'stdout')]) 205 shell.reset() 206 f.write('t\xe8\u015b\U0001d599') 207 self.assertEqual(shell.written, [('t\xe8\u015b\U0001d599', 'stdout')]) 208 shell.reset() 209 210 f.write(S('t\xe8\u015b\U0001d599')) 211 self.assertEqual(shell.written, [('t\xe8\u015b\U0001d599', 'stdout')]) 212 self.assertEqual(type(shell.written[0][0]), str) 213 shell.reset() 214 215 self.assertRaises(TypeError, f.write) 216 self.assertEqual(shell.written, []) 217 self.assertRaises(TypeError, f.write, b'test') 218 self.assertRaises(TypeError, f.write, 123) 219 self.assertEqual(shell.written, []) 220 self.assertRaises(TypeError, f.write, 'test', 'spam') 221 self.assertEqual(shell.written, []) 222 223 def test_write_stderr_nonencodable(self): 224 shell = MockShell() 225 f = run.StdOutputFile(shell, 'stderr', 'iso-8859-15', 'backslashreplace') 226 f.write('t\xe8\u015b\U0001d599\xa4') 227 self.assertEqual(shell.written, [('t\xe8\\u015b\\U0001d599\\xa4', 'stderr')]) 228 shell.reset() 229 230 f.write(S('t\xe8\u015b\U0001d599\xa4')) 231 self.assertEqual(shell.written, [('t\xe8\\u015b\\U0001d599\\xa4', 'stderr')]) 232 self.assertEqual(type(shell.written[0][0]), str) 233 shell.reset() 234 235 self.assertRaises(TypeError, f.write) 236 self.assertEqual(shell.written, []) 237 self.assertRaises(TypeError, f.write, b'test') 238 self.assertRaises(TypeError, f.write, 123) 239 self.assertEqual(shell.written, []) 240 self.assertRaises(TypeError, f.write, 'test', 'spam') 241 self.assertEqual(shell.written, []) 242 243 def test_writelines(self): 244 shell = MockShell() 245 f = run.StdOutputFile(shell, 'stdout') 246 f.writelines([]) 247 self.assertEqual(shell.written, []) 248 shell.reset() 249 f.writelines(['one\n', 'two']) 250 self.assertEqual(shell.written, 251 [('one\n', 'stdout'), ('two', 'stdout')]) 252 shell.reset() 253 f.writelines(['on\xe8\n', 'tw\xf2']) 254 self.assertEqual(shell.written, 255 [('on\xe8\n', 'stdout'), ('tw\xf2', 'stdout')]) 256 shell.reset() 257 258 f.writelines([S('t\xe8st')]) 259 self.assertEqual(shell.written, [('t\xe8st', 'stdout')]) 260 self.assertEqual(type(shell.written[0][0]), str) 261 shell.reset() 262 263 self.assertRaises(TypeError, f.writelines) 264 self.assertEqual(shell.written, []) 265 self.assertRaises(TypeError, f.writelines, 123) 266 self.assertEqual(shell.written, []) 267 self.assertRaises(TypeError, f.writelines, [b'test']) 268 self.assertRaises(TypeError, f.writelines, [123]) 269 self.assertEqual(shell.written, []) 270 self.assertRaises(TypeError, f.writelines, [], []) 271 self.assertEqual(shell.written, []) 272 273 def test_close(self): 274 shell = MockShell() 275 f = run.StdOutputFile(shell, 'stdout') 276 self.assertFalse(f.closed) 277 f.write('test') 278 f.close() 279 self.assertTrue(f.closed) 280 self.assertRaises(ValueError, f.write, 'x') 281 self.assertEqual(shell.written, [('test', 'stdout')]) 282 f.close() 283 self.assertRaises(TypeError, f.close, 1) 284 285 286class RecursionLimitTest(unittest.TestCase): 287 # Test (un)install_recursionlimit_wrappers and fixdoc. 288 289 def test_bad_setrecursionlimit_calls(self): 290 run.install_recursionlimit_wrappers() 291 self.addCleanup(run.uninstall_recursionlimit_wrappers) 292 f = sys.setrecursionlimit 293 self.assertRaises(TypeError, f, limit=100) 294 self.assertRaises(TypeError, f, 100, 1000) 295 self.assertRaises(ValueError, f, 0) 296 297 def test_roundtrip(self): 298 run.install_recursionlimit_wrappers() 299 self.addCleanup(run.uninstall_recursionlimit_wrappers) 300 301 # Check that setting the recursion limit works. 302 orig_reclimit = sys.getrecursionlimit() 303 self.addCleanup(sys.setrecursionlimit, orig_reclimit) 304 sys.setrecursionlimit(orig_reclimit + 3) 305 306 # Check that the new limit is returned by sys.getrecursionlimit(). 307 new_reclimit = sys.getrecursionlimit() 308 self.assertEqual(new_reclimit, orig_reclimit + 3) 309 310 def test_default_recursion_limit_preserved(self): 311 orig_reclimit = sys.getrecursionlimit() 312 run.install_recursionlimit_wrappers() 313 self.addCleanup(run.uninstall_recursionlimit_wrappers) 314 new_reclimit = sys.getrecursionlimit() 315 self.assertEqual(new_reclimit, orig_reclimit) 316 317 def test_fixdoc(self): 318 # Put here until better place for miscellaneous test. 319 def func(): "docstring" 320 run.fixdoc(func, "more") 321 self.assertEqual(func.__doc__, "docstring\n\nmore") 322 func.__doc__ = None 323 run.fixdoc(func, "more") 324 self.assertEqual(func.__doc__, "more") 325 326 327class HandleErrorTest(unittest.TestCase): 328 # Method of MyRPCServer 329 def test_fatal_error(self): 330 eq = self.assertEqual 331 with captured_output('__stderr__') as err,\ 332 mock.patch('idlelib.run.thread.interrupt_main', 333 new_callable=Func) as func: 334 try: 335 raise EOFError 336 except EOFError: 337 run.MyRPCServer.handle_error(None, 'abc', '123') 338 eq(run.exit_now, True) 339 run.exit_now = False 340 eq(err.getvalue(), '') 341 342 try: 343 raise IndexError 344 except IndexError: 345 run.MyRPCServer.handle_error(None, 'abc', '123') 346 eq(run.quitting, True) 347 run.quitting = False 348 msg = err.getvalue() 349 self.assertIn('abc', msg) 350 self.assertIn('123', msg) 351 self.assertIn('IndexError', msg) 352 eq(func.called, 2) 353 354if __name__ == '__main__': 355 unittest.main(verbosity=2) 356