def test_repr(): """Test writer.__repr__ for client and server viewpoint.""" srv = telnetlib3.TelnetWriter(transport=None, protocol=None, server=True) clt = telnetlib3.TelnetWriter(transport=None, protocol=None, client=True) assert repr(srv) == ('<TelnetWriter server ' 'mode:local +lineflow -xon_any +slc_sim>') assert repr(clt) == ('<TelnetWriter client ' 'mode:local +lineflow -xon_any +slc_sim>')
def test_writer_instantiation_safety(): """On instantiation, one of server or client must be specified.""" telnetlib3.TelnetWriter(transport=None, protocol=None, client=True) with pytest.raises(TypeError): # must define at least server=True or client=True telnetlib3.TelnetWriter(transport=None, protocol=None) with pytest.raises(TypeError): # but cannot define both! telnetlib3.TelnetWriter(transport=None, protocol=None, server=True, client=True)
def test_bad_iac(): """Test using writer.iac for something outside of DO/DONT/WILL/WONT.""" from telnetlib3.telopt import NOP writer = telnetlib3.TelnetWriter(transport=None, protocol=None, server=True) with pytest.raises(ValueError): writer.iac(NOP)
def test_illegal_2byte_iac(): """Given an illegal 2byte IAC command, raise ValueError.""" writer = telnetlib3.TelnetWriter(transport=None, protocol=None, server=True) from telnetlib3.telopt import IAC, SGA writer.feed_byte(IAC) with pytest.raises(ValueError): # IAC SGA(b'\x03'): not a legal 2-byte cmd writer.feed_byte(SGA)
def test_sb_interrupted(): """IAC SB gets interrupted by IAC command, reseting and exiting state.""" # when within an SB buffer, all SB protocols we know about remark that # IAC must be escaped -- for example, the NAWS negotiation of a 65535 # by 0 window size should be '\xff\xff\xff\xff\x00\x00' -- so if we # receive an IAC **not** followed by an IAC while within a sub-negotiation # buffer, we are in miscommunication. The remote end is not RFC complaint, # not a telnet server, or is simply fuzzing us. # # instead of awaiting the unlikely SE, and throwing all intermediary bytes # out, we just clear what we have received so far within this so called # 'SB', and exit the sb buffering state. from telnetlib3.telopt import IAC, SB, TM, SE import logging log = logging.getLogger(__name__) log.setLevel(logging.DEBUG) writer = telnetlib3.TelnetWriter(transport=None, protocol=None, server=True, log=log) given = IAC + SB + b"sbdata-\xff\xff-sbdata" sb_expected = b"sbdata-\xff-sbdata" for val in given: writer.feed_byte(bytes([val])) assert b"".join(writer._sb_buffer) == sb_expected writer.feed_byte(IAC) with pytest.raises(ValueError, match="SB unhandled"): # [SB + b's'] unsolicited, writer.feed_byte(SE) # the 'IAC TM' interrupts and ends the SB buffer given = IAC + SB + b"sbdata-" + IAC + TM + b"-sbdata" for val in given: writer.feed_byte(bytes([val])) assert b"".join(writer._sb_buffer) == b"" # so, even if you sent an IAC + SE, that is no longer # legal for this state. writer.feed_byte(b"x") writer.feed_byte(IAC) with pytest.raises(ValueError, match="not a legal 2-byte cmd"): writer.feed_byte(SE)
def test_legal_2byte_iac(): """Nothing special about a 2-byte IAC, test wiring a callback.""" from telnetlib3.telopt import IAC, NOP import threading called = threading.Event() def callback(cmd): assert cmd == NOP called.set() writer = telnetlib3.TelnetWriter(transport=None, protocol=None, server=True) writer.set_iac_callback(cmd=NOP, func=callback) writer.feed_byte(IAC) writer.feed_byte(NOP) assert called.is_set()