Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 1 | import socket |
| 2 | import threading |
| 3 | import telnetlib |
| 4 | import time |
Jack Diederich | 1c8f38c | 2009-04-10 05:33:26 +0000 | [diff] [blame] | 5 | import queue |
Jack Diederich | 36596a3 | 2009-07-26 22:23:04 +0000 | [diff] [blame] | 6 | import sys |
| 7 | import io |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 8 | |
| 9 | from unittest import TestCase |
Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 10 | from test import support |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 11 | |
Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 12 | HOST = support.HOST |
Jack Diederich | 1c8f38c | 2009-04-10 05:33:26 +0000 | [diff] [blame] | 13 | EOF_sigil = object() |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 14 | |
Mark Dickinson | 3a22b4f | 2009-10-26 22:48:32 +0000 | [diff] [blame] | 15 | def server(evt, serv, dataq=None, test_done=None): |
| 16 | """ Open a tcp server in four steps |
Jack Diederich | 1c8f38c | 2009-04-10 05:33:26 +0000 | [diff] [blame] | 17 | 1) set evt to true to let the parent know we are ready |
| 18 | 2) [optional] if is not False, write the list of data from dataq.get() |
| 19 | to the socket. |
Mark Dickinson | 3a22b4f | 2009-10-26 22:48:32 +0000 | [diff] [blame] | 20 | 3) [optional] if test_done is not None, it's an event; wait |
| 21 | for parent to set test_done before closing connection |
| 22 | 4) set evt to true to let the parent know we're done |
Jack Diederich | 1c8f38c | 2009-04-10 05:33:26 +0000 | [diff] [blame] | 23 | """ |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 24 | serv.listen(5) |
Christian Heimes | af98da1 | 2008-01-27 15:18:18 +0000 | [diff] [blame] | 25 | evt.set() |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 26 | try: |
| 27 | conn, addr = serv.accept() |
Jack Diederich | 1c8f38c | 2009-04-10 05:33:26 +0000 | [diff] [blame] | 28 | if dataq: |
| 29 | data = b'' |
| 30 | new_data = dataq.get(True, 0.5) |
| 31 | dataq.task_done() |
| 32 | for item in new_data: |
| 33 | if item == EOF_sigil: |
| 34 | break |
| 35 | if type(item) in [int, float]: |
| 36 | time.sleep(item) |
| 37 | else: |
| 38 | data += item |
| 39 | written = conn.send(data) |
| 40 | data = data[written:] |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 41 | except socket.timeout: |
| 42 | pass |
| 43 | finally: |
Mark Dickinson | 3a22b4f | 2009-10-26 22:48:32 +0000 | [diff] [blame] | 44 | if test_done is not None: |
| 45 | test_done.wait() |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 46 | serv.close() |
| 47 | evt.set() |
| 48 | |
| 49 | class GeneralTests(TestCase): |
| 50 | |
| 51 | def setUp(self): |
| 52 | self.evt = threading.Event() |
Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 53 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 54 | self.sock.settimeout(3) |
Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 55 | self.port = support.bind_port(self.sock) |
Jack Diederich | 1c8f38c | 2009-04-10 05:33:26 +0000 | [diff] [blame] | 56 | self.thread = threading.Thread(target=server, args=(self.evt,self.sock)) |
| 57 | self.thread.start() |
Christian Heimes | af98da1 | 2008-01-27 15:18:18 +0000 | [diff] [blame] | 58 | self.evt.wait() |
| 59 | self.evt.clear() |
| 60 | time.sleep(.1) |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 61 | |
| 62 | def tearDown(self): |
| 63 | self.evt.wait() |
Jack Diederich | 1c8f38c | 2009-04-10 05:33:26 +0000 | [diff] [blame] | 64 | self.thread.join() |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 65 | |
| 66 | def testBasic(self): |
| 67 | # connects |
Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 68 | telnet = telnetlib.Telnet(HOST, self.port) |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 69 | telnet.sock.close() |
| 70 | |
| 71 | def testTimeoutDefault(self): |
Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 72 | self.assertTrue(socket.getdefaulttimeout() is None) |
| 73 | socket.setdefaulttimeout(30) |
| 74 | try: |
| 75 | telnet = telnetlib.Telnet("localhost", self.port) |
| 76 | finally: |
| 77 | socket.setdefaulttimeout(None) |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 78 | self.assertEqual(telnet.sock.gettimeout(), 30) |
| 79 | telnet.sock.close() |
| 80 | |
| 81 | def testTimeoutNone(self): |
| 82 | # None, having other default |
Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 83 | self.assertTrue(socket.getdefaulttimeout() is None) |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 84 | socket.setdefaulttimeout(30) |
| 85 | try: |
Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 86 | telnet = telnetlib.Telnet(HOST, self.port, timeout=None) |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 87 | finally: |
Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 88 | socket.setdefaulttimeout(None) |
| 89 | self.assertTrue(telnet.sock.gettimeout() is None) |
| 90 | telnet.sock.close() |
| 91 | |
| 92 | def testTimeoutValue(self): |
| 93 | telnet = telnetlib.Telnet("localhost", self.port, timeout=30) |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 94 | self.assertEqual(telnet.sock.gettimeout(), 30) |
| 95 | telnet.sock.close() |
| 96 | |
Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 97 | def testTimeoutOpen(self): |
| 98 | telnet = telnetlib.Telnet() |
| 99 | telnet.open("localhost", self.port, timeout=30) |
| 100 | self.assertEqual(telnet.sock.gettimeout(), 30) |
| 101 | telnet.sock.close() |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 102 | |
Jack Diederich | 1c8f38c | 2009-04-10 05:33:26 +0000 | [diff] [blame] | 103 | def _read_setUp(self): |
| 104 | self.evt = threading.Event() |
| 105 | self.dataq = queue.Queue() |
| 106 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 107 | self.sock.settimeout(3) |
| 108 | self.port = support.bind_port(self.sock) |
| 109 | self.thread = threading.Thread(target=server, args=(self.evt,self.sock, self.dataq)) |
| 110 | self.thread.start() |
| 111 | self.evt.wait() |
| 112 | self.evt.clear() |
| 113 | time.sleep(.1) |
| 114 | |
| 115 | def _read_tearDown(self): |
| 116 | self.evt.wait() |
| 117 | self.thread.join() |
| 118 | |
| 119 | class ReadTests(TestCase): |
| 120 | setUp = _read_setUp |
| 121 | tearDown = _read_tearDown |
| 122 | |
| 123 | # use a similar approach to testing timeouts as test_timeout.py |
| 124 | # these will never pass 100% but make the fuzz big enough that it is rare |
| 125 | block_long = 0.6 |
| 126 | block_short = 0.3 |
| 127 | def test_read_until_A(self): |
| 128 | """ |
| 129 | read_until(expected, [timeout]) |
| 130 | Read until the expected string has been seen, or a timeout is |
| 131 | hit (default is no timeout); may block. |
| 132 | """ |
| 133 | want = [b'x' * 10, b'match', b'y' * 10, EOF_sigil] |
| 134 | self.dataq.put(want) |
| 135 | telnet = telnetlib.Telnet(HOST, self.port) |
| 136 | self.dataq.join() |
| 137 | data = telnet.read_until(b'match') |
| 138 | self.assertEqual(data, b''.join(want[:-2])) |
| 139 | |
| 140 | def test_read_until_B(self): |
| 141 | # test the timeout - it does NOT raise socket.timeout |
| 142 | want = [b'hello', self.block_long, b'not seen', EOF_sigil] |
| 143 | self.dataq.put(want) |
| 144 | telnet = telnetlib.Telnet(HOST, self.port) |
| 145 | self.dataq.join() |
| 146 | data = telnet.read_until(b'not seen', self.block_short) |
| 147 | self.assertEqual(data, want[0]) |
| 148 | self.assertEqual(telnet.read_all(), b'not seen') |
| 149 | |
| 150 | def test_read_all_A(self): |
| 151 | """ |
| 152 | read_all() |
| 153 | Read all data until EOF; may block. |
| 154 | """ |
| 155 | want = [b'x' * 500, b'y' * 500, b'z' * 500, EOF_sigil] |
| 156 | self.dataq.put(want) |
| 157 | telnet = telnetlib.Telnet(HOST, self.port) |
| 158 | self.dataq.join() |
| 159 | data = telnet.read_all() |
| 160 | self.assertEqual(data, b''.join(want[:-1])) |
| 161 | return |
| 162 | |
| 163 | def _test_blocking(self, func): |
| 164 | self.dataq.put([self.block_long, EOF_sigil]) |
| 165 | self.dataq.join() |
| 166 | start = time.time() |
| 167 | data = func() |
| 168 | self.assertTrue(self.block_short <= time.time() - start) |
| 169 | |
| 170 | def test_read_all_B(self): |
| 171 | self._test_blocking(telnetlib.Telnet(HOST, self.port).read_all) |
| 172 | |
| 173 | def test_read_all_C(self): |
| 174 | self.dataq.put([EOF_sigil]) |
| 175 | telnet = telnetlib.Telnet(HOST, self.port) |
| 176 | self.dataq.join() |
| 177 | telnet.read_all() |
| 178 | telnet.read_all() # shouldn't raise |
| 179 | |
| 180 | def test_read_some_A(self): |
| 181 | """ |
| 182 | read_some() |
| 183 | Read at least one byte or EOF; may block. |
| 184 | """ |
| 185 | # test 'at least one byte' |
| 186 | want = [b'x' * 500, EOF_sigil] |
| 187 | self.dataq.put(want) |
| 188 | telnet = telnetlib.Telnet(HOST, self.port) |
| 189 | self.dataq.join() |
| 190 | data = telnet.read_all() |
| 191 | self.assertTrue(len(data) >= 1) |
| 192 | |
| 193 | def test_read_some_B(self): |
| 194 | # test EOF |
| 195 | self.dataq.put([EOF_sigil]) |
| 196 | telnet = telnetlib.Telnet(HOST, self.port) |
| 197 | self.dataq.join() |
| 198 | self.assertEqual(b'', telnet.read_some()) |
| 199 | |
| 200 | def test_read_some_C(self): |
| 201 | self._test_blocking(telnetlib.Telnet(HOST, self.port).read_some) |
| 202 | |
| 203 | def _test_read_any_eager_A(self, func_name): |
| 204 | """ |
| 205 | read_very_eager() |
| 206 | Read all data available already queued or on the socket, |
| 207 | without blocking. |
| 208 | """ |
| 209 | want = [self.block_long, b'x' * 100, b'y' * 100, EOF_sigil] |
| 210 | expects = want[1] + want[2] |
| 211 | self.dataq.put(want) |
| 212 | telnet = telnetlib.Telnet(HOST, self.port) |
| 213 | self.dataq.join() |
| 214 | func = getattr(telnet, func_name) |
| 215 | data = b'' |
| 216 | while True: |
| 217 | try: |
| 218 | data += func() |
| 219 | self.assertTrue(expects.startswith(data)) |
| 220 | except EOFError: |
| 221 | break |
| 222 | self.assertEqual(expects, data) |
| 223 | |
| 224 | def _test_read_any_eager_B(self, func_name): |
| 225 | # test EOF |
| 226 | self.dataq.put([EOF_sigil]) |
| 227 | telnet = telnetlib.Telnet(HOST, self.port) |
| 228 | self.dataq.join() |
| 229 | time.sleep(self.block_short) |
| 230 | func = getattr(telnet, func_name) |
| 231 | self.assertRaises(EOFError, func) |
| 232 | |
| 233 | # read_eager and read_very_eager make the same gaurantees |
| 234 | # (they behave differently but we only test the gaurantees) |
| 235 | def test_read_very_eager_A(self): |
| 236 | self._test_read_any_eager_A('read_very_eager') |
| 237 | def test_read_very_eager_B(self): |
| 238 | self._test_read_any_eager_B('read_very_eager') |
| 239 | def test_read_eager_A(self): |
| 240 | self._test_read_any_eager_A('read_eager') |
| 241 | def test_read_eager_B(self): |
| 242 | self._test_read_any_eager_B('read_eager') |
| 243 | # NB -- we need to test the IAC block which is mentioned in the docstring |
| 244 | # but not in the module docs |
| 245 | |
| 246 | def _test_read_any_lazy_B(self, func_name): |
| 247 | self.dataq.put([EOF_sigil]) |
| 248 | telnet = telnetlib.Telnet(HOST, self.port) |
| 249 | self.dataq.join() |
| 250 | func = getattr(telnet, func_name) |
| 251 | telnet.fill_rawq() |
| 252 | self.assertRaises(EOFError, func) |
| 253 | |
| 254 | def test_read_lazy_A(self): |
| 255 | want = [b'x' * 100, EOF_sigil] |
| 256 | self.dataq.put(want) |
| 257 | telnet = telnetlib.Telnet(HOST, self.port) |
| 258 | self.dataq.join() |
| 259 | time.sleep(self.block_short) |
| 260 | self.assertEqual(b'', telnet.read_lazy()) |
| 261 | data = b'' |
| 262 | while True: |
| 263 | try: |
| 264 | read_data = telnet.read_lazy() |
| 265 | data += read_data |
| 266 | if not read_data: |
| 267 | telnet.fill_rawq() |
| 268 | except EOFError: |
| 269 | break |
| 270 | self.assertTrue(want[0].startswith(data)) |
| 271 | self.assertEqual(data, want[0]) |
| 272 | |
| 273 | def test_read_lazy_B(self): |
| 274 | self._test_read_any_lazy_B('read_lazy') |
| 275 | |
| 276 | def test_read_very_lazy_A(self): |
| 277 | want = [b'x' * 100, EOF_sigil] |
| 278 | self.dataq.put(want) |
| 279 | telnet = telnetlib.Telnet(HOST, self.port) |
| 280 | self.dataq.join() |
| 281 | time.sleep(self.block_short) |
| 282 | self.assertEqual(b'', telnet.read_very_lazy()) |
| 283 | data = b'' |
| 284 | while True: |
| 285 | try: |
| 286 | read_data = telnet.read_very_lazy() |
| 287 | except EOFError: |
| 288 | break |
| 289 | data += read_data |
| 290 | if not read_data: |
| 291 | telnet.fill_rawq() |
| 292 | self.assertEqual(b'', telnet.cookedq) |
| 293 | telnet.process_rawq() |
| 294 | self.assertTrue(want[0].startswith(data)) |
| 295 | self.assertEqual(data, want[0]) |
| 296 | |
| 297 | def test_read_very_lazy_B(self): |
| 298 | self._test_read_any_lazy_B('read_very_lazy') |
| 299 | |
| 300 | class nego_collector(object): |
| 301 | def __init__(self, sb_getter=None): |
| 302 | self.seen = b'' |
| 303 | self.sb_getter = sb_getter |
| 304 | self.sb_seen = b'' |
| 305 | |
| 306 | def do_nego(self, sock, cmd, opt): |
| 307 | self.seen += cmd + opt |
| 308 | if cmd == tl.SE and self.sb_getter: |
| 309 | sb_data = self.sb_getter() |
| 310 | self.sb_seen += sb_data |
| 311 | |
Jack Diederich | f31f7bb | 2009-09-03 20:37:58 +0000 | [diff] [blame] | 312 | class SocketProxy(object): |
| 313 | ''' a socket proxy that re-defines sendall() ''' |
| 314 | def __init__(self, real_sock): |
| 315 | self.socket = real_sock |
| 316 | self._raw_sent = b'' |
| 317 | def __getattr__(self, k): |
| 318 | return getattr(self.socket, k) |
| 319 | def sendall(self, data): |
| 320 | self._raw_sent += data |
| 321 | self.socket.sendall(data) |
| 322 | |
| 323 | class TelnetSockSendall(telnetlib.Telnet): |
| 324 | def open(self, *args, **opts): |
| 325 | telnetlib.Telnet.open(self, *args, **opts) |
| 326 | self.sock = SocketProxy(self.sock) |
| 327 | |
| 328 | class WriteTests(TestCase): |
| 329 | '''The only thing that write does is replace each tl.IAC for |
| 330 | tl.IAC+tl.IAC''' |
Mark Dickinson | 3a22b4f | 2009-10-26 22:48:32 +0000 | [diff] [blame] | 331 | def setUp(self): |
| 332 | self.evt = threading.Event() |
| 333 | self.test_done = threading.Event() |
| 334 | self.dataq = queue.Queue() |
| 335 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 336 | self.sock.settimeout(3) |
| 337 | self.port = support.bind_port(self.sock) |
| 338 | self.thread = threading.Thread(target=server, args=( |
| 339 | self.evt, self.sock, self.dataq, self.test_done)) |
| 340 | self.thread.start() |
| 341 | self.evt.wait() |
| 342 | self.evt.clear() |
| 343 | time.sleep(.1) |
| 344 | |
| 345 | def tearDown(self): |
| 346 | self.test_done.set() |
| 347 | self.evt.wait() |
| 348 | self.thread.join() |
Jack Diederich | f31f7bb | 2009-09-03 20:37:58 +0000 | [diff] [blame] | 349 | |
| 350 | def _test_write(self, data): |
| 351 | self.telnet.sock._raw_sent = b'' |
| 352 | self.telnet.write(data) |
| 353 | after_write = self.telnet.sock._raw_sent |
| 354 | self.assertEqual(data.replace(tl.IAC,tl.IAC+tl.IAC), |
| 355 | after_write) |
| 356 | |
| 357 | def test_write(self): |
| 358 | self.telnet = TelnetSockSendall() |
| 359 | data_sample = [b'data sample without IAC', |
| 360 | b'data sample with' + tl.IAC + b' one IAC', |
| 361 | b'a few' + tl.IAC + tl.IAC + b' iacs' + tl.IAC, |
| 362 | tl.IAC, |
| 363 | b''] |
| 364 | self.telnet.open(HOST, self.port) |
| 365 | for d in data_sample: |
| 366 | self.dataq.put([b'']) |
| 367 | self._test_write(d) |
| 368 | self.telnet.close() |
| 369 | |
Jack Diederich | 1c8f38c | 2009-04-10 05:33:26 +0000 | [diff] [blame] | 370 | tl = telnetlib |
Jack Diederich | 36596a3 | 2009-07-26 22:23:04 +0000 | [diff] [blame] | 371 | |
| 372 | class TelnetDebuglevel(tl.Telnet): |
| 373 | ''' Telnet-alike that captures messages written to stdout when |
| 374 | debuglevel > 0 |
| 375 | ''' |
| 376 | _messages = '' |
| 377 | def msg(self, msg, *args): |
| 378 | orig_stdout = sys.stdout |
| 379 | sys.stdout = fake_stdout = io.StringIO() |
| 380 | tl.Telnet.msg(self, msg, *args) |
| 381 | self._messages += fake_stdout.getvalue() |
| 382 | sys.stdout = orig_stdout |
| 383 | return |
| 384 | |
Jack Diederich | 1c8f38c | 2009-04-10 05:33:26 +0000 | [diff] [blame] | 385 | class OptionTests(TestCase): |
| 386 | setUp = _read_setUp |
| 387 | tearDown = _read_tearDown |
| 388 | # RFC 854 commands |
| 389 | cmds = [tl.AO, tl.AYT, tl.BRK, tl.EC, tl.EL, tl.GA, tl.IP, tl.NOP] |
| 390 | |
| 391 | def _test_command(self, data): |
| 392 | """ helper for testing IAC + cmd """ |
| 393 | self.setUp() |
| 394 | self.dataq.put(data) |
| 395 | telnet = telnetlib.Telnet(HOST, self.port) |
| 396 | self.dataq.join() |
| 397 | nego = nego_collector() |
| 398 | telnet.set_option_negotiation_callback(nego.do_nego) |
| 399 | txt = telnet.read_all() |
| 400 | cmd = nego.seen |
| 401 | self.assertTrue(len(cmd) > 0) # we expect at least one command |
| 402 | self.assertTrue(cmd[:1] in self.cmds) |
| 403 | self.assertEqual(cmd[1:2], tl.NOOPT) |
| 404 | self.assertEqual(len(b''.join(data[:-1])), len(txt + cmd)) |
| 405 | nego.sb_getter = None # break the nego => telnet cycle |
| 406 | self.tearDown() |
| 407 | |
| 408 | def test_IAC_commands(self): |
| 409 | # reset our setup |
| 410 | self.dataq.put([EOF_sigil]) |
| 411 | telnet = telnetlib.Telnet(HOST, self.port) |
| 412 | self.dataq.join() |
| 413 | self.tearDown() |
| 414 | |
| 415 | for cmd in self.cmds: |
| 416 | self._test_command([tl.IAC, cmd, EOF_sigil]) |
| 417 | self._test_command([b'x' * 100, tl.IAC, cmd, b'y'*100, EOF_sigil]) |
| 418 | self._test_command([b'x' * 10, tl.IAC, cmd, b'y'*10, EOF_sigil]) |
| 419 | # all at once |
| 420 | self._test_command([tl.IAC + cmd for (cmd) in self.cmds] + [EOF_sigil]) |
| 421 | self.assertEqual(b'', telnet.read_sb_data()) |
| 422 | |
| 423 | def test_SB_commands(self): |
| 424 | # RFC 855, subnegotiations portion |
| 425 | send = [tl.IAC + tl.SB + tl.IAC + tl.SE, |
| 426 | tl.IAC + tl.SB + tl.IAC + tl.IAC + tl.IAC + tl.SE, |
| 427 | tl.IAC + tl.SB + tl.IAC + tl.IAC + b'aa' + tl.IAC + tl.SE, |
| 428 | tl.IAC + tl.SB + b'bb' + tl.IAC + tl.IAC + tl.IAC + tl.SE, |
| 429 | tl.IAC + tl.SB + b'cc' + tl.IAC + tl.IAC + b'dd' + tl.IAC + tl.SE, |
| 430 | EOF_sigil, |
| 431 | ] |
| 432 | self.dataq.put(send) |
| 433 | telnet = telnetlib.Telnet(HOST, self.port) |
| 434 | self.dataq.join() |
| 435 | nego = nego_collector(telnet.read_sb_data) |
| 436 | telnet.set_option_negotiation_callback(nego.do_nego) |
| 437 | txt = telnet.read_all() |
| 438 | self.assertEqual(txt, b'') |
| 439 | want_sb_data = tl.IAC + tl.IAC + b'aabb' + tl.IAC + b'cc' + tl.IAC + b'dd' |
| 440 | self.assertEqual(nego.sb_seen, want_sb_data) |
| 441 | self.assertEqual(b'', telnet.read_sb_data()) |
| 442 | nego.sb_getter = None # break the nego => telnet cycle |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 443 | |
Jack Diederich | 36596a3 | 2009-07-26 22:23:04 +0000 | [diff] [blame] | 444 | def _test_debuglevel(self, data, expected_msg): |
| 445 | """ helper for testing debuglevel messages """ |
| 446 | self.setUp() |
Jack Diederich | f31f7bb | 2009-09-03 20:37:58 +0000 | [diff] [blame] | 447 | self.dataq.put(data + [EOF_sigil]) |
Jack Diederich | 36596a3 | 2009-07-26 22:23:04 +0000 | [diff] [blame] | 448 | telnet = TelnetDebuglevel(HOST, self.port) |
| 449 | telnet.set_debuglevel(1) |
| 450 | self.dataq.join() |
| 451 | txt = telnet.read_all() |
| 452 | self.assertTrue(expected_msg in telnet._messages, |
| 453 | msg=(telnet._messages, expected_msg)) |
Jack Diederich | f31f7bb | 2009-09-03 20:37:58 +0000 | [diff] [blame] | 454 | telnet.close() |
Jack Diederich | 36596a3 | 2009-07-26 22:23:04 +0000 | [diff] [blame] | 455 | self.tearDown() |
| 456 | |
Jack Diederich | f31f7bb | 2009-09-03 20:37:58 +0000 | [diff] [blame] | 457 | def test_debuglevel_reads(self): |
Jack Diederich | 36596a3 | 2009-07-26 22:23:04 +0000 | [diff] [blame] | 458 | # test all the various places that self.msg(...) is called |
| 459 | given_a_expect_b = [ |
| 460 | # Telnet.fill_rawq |
| 461 | (b'a', ": recv b''\n"), |
| 462 | # Telnet.process_rawq |
| 463 | (tl.IAC + bytes([88]), ": IAC 88 not recognized\n"), |
| 464 | (tl.IAC + tl.DO + bytes([1]), ": IAC DO 1\n"), |
| 465 | (tl.IAC + tl.DONT + bytes([1]), ": IAC DONT 1\n"), |
| 466 | (tl.IAC + tl.WILL + bytes([1]), ": IAC WILL 1\n"), |
| 467 | (tl.IAC + tl.WONT + bytes([1]), ": IAC WONT 1\n"), |
Jack Diederich | 36596a3 | 2009-07-26 22:23:04 +0000 | [diff] [blame] | 468 | ] |
| 469 | for a, b in given_a_expect_b: |
| 470 | self._test_debuglevel([a, EOF_sigil], b) |
| 471 | return |
| 472 | |
Jack Diederich | f31f7bb | 2009-09-03 20:37:58 +0000 | [diff] [blame] | 473 | def test_debuglevel_write(self): |
| 474 | self.setUp() |
| 475 | telnet = TelnetDebuglevel(HOST, self.port) |
| 476 | telnet.set_debuglevel(1) |
| 477 | self.dataq.put([b'', EOF_sigil]) |
| 478 | self.dataq.join() |
| 479 | telnet.write(b'xxx') |
| 480 | expected = "send b'xxx'\n" |
| 481 | self.assertTrue(expected in telnet._messages, |
| 482 | msg=(telnet._messages, expected)) |
| 483 | telnet.close() |
| 484 | self.tearDown() |
| 485 | |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 486 | def test_main(verbose=None): |
Jack Diederich | f31f7bb | 2009-09-03 20:37:58 +0000 | [diff] [blame] | 487 | support.run_unittest(GeneralTests, ReadTests, WriteTests, OptionTests) |
Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 488 | |
| 489 | if __name__ == '__main__': |
| 490 | test_main() |