"""
<Program Name>
  z_test_state_machine.repy

<Started>
  February 8, 2009

<Author>
  Richard Jordan

<Purpose>
  To test that all of TcpStateMachine's functions work
  together.

  Passes quietly
"""
include state_machine.repy
include test_packet_sender.repy

def test_passive():
  # passive
  mycontext['sm'].state = mycontext['sm'].STATE_CLOSED
  mycontext['sm'].listen()
  mycontext['tps'].send("SYN")
  mycontext['tps'].send("ACK")
  mycontext['tps'].send("ACK")
  mycontext['tps'].send("PSH")
  assert mycontext['sm'].state == mycontext['sm'].STATE_ESTAB
  mycontext['tps'].send("FIN")
  mycontext['sm'].close()  
  mycontext['tps'].send("ACK")
  assert mycontext['sm'].state == mycontext['sm'].STATE_CLOSED

def test_passive_pshack():
  # passive
  mycontext['sm'].state = mycontext['sm'].STATE_CLOSED
  mycontext['sm'].listen()
  mycontext['tps'].send("SYN")
  mycontext['tps'].send("PSH")
  assert mycontext['sm'].state == mycontext['sm'].STATE_ESTAB
  mycontext['tps'].send("FIN")
  mycontext['sm'].close()  
  mycontext['tps'].send("ACK")
  assert mycontext['sm'].state == mycontext['sm'].STATE_CLOSED

def test_active():
  # active
  mycontext['sm'].state = mycontext['sm'].STATE_CLOSED
  mycontext['sm'].connect()
  mycontext['tps'].send("SYNACK")
  assert mycontext['sm'].state == mycontext['sm'].STATE_ESTAB
  mycontext['sm'].close()
  mycontext['tps'].send("ACK")
  mycontext['tps'].send("FIN")
  assert mycontext['sm'].state == mycontext['sm'].STATE_TIME_WAIT
  mycontext['sm'].timeout_close()
  assert mycontext['sm'].state == mycontext['sm'].STATE_CLOSED

def test_active_loopback():
  # active
  mycontext['sm'].state = mycontext['sm'].STATE_CLOSED
  mycontext['sm'].connect()
  mycontext['tps'].send("SYN")
  mycontext['tps'].send("ACK")
  assert mycontext['sm'].state == mycontext['sm'].STATE_ESTAB
  mycontext['sm'].close()
  mycontext['tps'].send("ACK")
  mycontext['tps'].send("FIN")
  assert mycontext['sm'].state == mycontext['sm'].STATE_TIME_WAIT
  mycontext['sm'].timeout_close()
  assert mycontext['sm'].state == mycontext['sm'].STATE_CLOSED 

def test_active_loopback_pshack():
  # active
  mycontext['sm'].state = mycontext['sm'].STATE_CLOSED
  mycontext['sm'].connect()
  mycontext['tps'].send("SYN")
  mycontext['tps'].send("PSH")
  assert mycontext['sm'].state == mycontext['sm'].STATE_ESTAB
  mycontext['sm'].close()
  mycontext['tps'].send("ACK")
  mycontext['tps'].send("FIN")
  assert mycontext['sm'].state == mycontext['sm'].STATE_TIME_WAIT
  mycontext['sm'].timeout_close()
  assert mycontext['sm'].state == mycontext['sm'].STATE_CLOSED 

def test_active_finfin():
  # active
  mycontext['sm'].state = mycontext['sm'].STATE_CLOSED
  mycontext['sm'].connect()
  mycontext['tps'].send("SYNACK")
  mycontext['tps'].send("PSH")
  assert mycontext['sm'].state == mycontext['sm'].STATE_ESTAB
  mycontext['sm'].close()
  mycontext['tps'].send("FIN")
  mycontext['tps'].send("ACK")
  assert mycontext['sm'].state == mycontext['sm'].STATE_CLOSED 


####################
# Test Helper Functions
####################
  
# Deliver UDP messages to state machine
def callback(ip, port, mess, ch):
  packet = unpack(mess)
  mycontext['sm'].next(packet)

if callfunc == 'initialize':
  IP = '127.0.0.1' #  getmyip()
  PORT = 12346

  # setup
  ch = recvmess(IP, PORT, callback)
  mycontext['sm'] = TcpStateMachine()
  mycontext['tps'] = TestPacketSender(IP, PORT)
  
  # Run tests
  test_passive()
  test_passive_pshack()
  test_active()
  test_active_loopback()
  test_active_loopback_pshack()
  test_active_finfin()

  # teardown
  stopcomm(ch)
  exitall()
