"""These tests fall under Conformance Test-Suite (OF-SWITCH-1.0.0 TestCases).
    Refer Documentation -- Detailed testing methodology 
    <Some of test-cases are directly taken from oftest> """

"Test Suite 2 --> Openflow Protocol messages"


import logging

import unittest
import random

import oftest.controller as controller
import oftest.cstruct as ofp
import oftest.message as message
import oftest.dataplane as dataplane
import oftest.action as action
import oftest.parse as parse
import basic

from oftest.testutils import *
from time import sleep
from FuncUtils import *


of_port_map = None
of_logger = None
of_config = None

def test_set_init(config):
   

    basic.test_set_init(config)

    global of_port_map
    global of_logger
    global of_config

    of_logger = logging.getLogger("Start Openflow_Protocol_Messages Conformance Test-suite")
    of_logger.info("Initializing test set")
    of_port_map = config["port_map"]
    of_config = config


class FeaturesRequest(basic.SimpleProtocol): 

    """Verify Features_Request-Reply is implemented 
    a) Send OFPT_FEATURES_REQUEST
	b) Verify OFPT_FEATURES_REPLY is received without errors"""

    def runTest(self):
        of_logger.info("Running Features_Request test")
        
        of_ports = of_port_map.keys()
        of_ports.sort()
        
        #Clear switch state
        rc = delete_all_flows(self.controller, of_logger)
        self.assertEqual(rc, 0, "Failed to delete all flows")
        
        of_logger.info("Sending Features_Request")
        of_logger.info("Expecting Features_Reply")

        request = message.features_request()
        rv = self.controller.message_send(request)
        self.assertTrue(rv != -1, "Not able to send features request.")
        
        (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FEATURES_REPLY,
                                               timeout=2)
        self.assertTrue(response is not None, 
                        'Did not receive Features Reply')


class ConfigurationRequest(basic.SimpleProtocol):
    
    """Check basic Get Config request is implemented
    a) Send OFPT_GET_CONFIG_REQUEST
    b) Verify OFPT_GET_CONFIG_REPLY is received without errors"""

    def runTest(self):

        of_logger.info("Running Configuration_Request test ")
        
        of_ports = of_port_map.keys()
        of_ports.sort()

        #Clear switch state
        rc = delete_all_flows(self.controller, of_logger)
        self.assertEqual(rc, 0, "Failed to delete all flows")

        of_logger.info("Sending OFPT_GET_CONFIG_REQUEST ")
        of_logger.info("Expecting OFPT_GET_CONFIG_REPLY ")

        request = message.get_config_request()
        rv = self.controller.message_send(request)
        self.assertTrue(rv != -1, " Not able to send get_config request.")
        
        (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
                                               timeout=2)
        self.assertTrue(response is not None, 
                        'Did not receive OFPT_GET_CONFIG_REPLY')

class ModifyStateAdd(basic.SimpleProtocol):
    
    """Check basic Flow Add request is implemented
    a) Send  OFPT_FLOW_MOD , command = OFPFC_ADD 
    c) Send ofp_table_stats request , verify active_count=1 in reply"""

    def runTest(self):

        of_logger.info("Running Modify_State_Add test")

        of_ports = of_port_map.keys()
        of_ports.sort()
        
        #Clear switch state
        rc = delete_all_flows(self.controller,of_logger)
        self.assertEqual(rc, 0, "Failed to delete all flows")

        of_logger.info("Inserting a flow entry")
        of_logger.info("Expecting active_count=1 in table_stats_reply")

        #Insert a flow entry matching on ingress_port
        (Pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)

        # Send Table_Stats_Request and verify flow gets inserted.
        Verify_TableStats(self,active_entries=1)


class ModifyStateDelete(basic.SimpleProtocol):
    
    """Check Basic Flow Delete request is implemented
    a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
    b) Send ofp_table_stats request , verify active_count=1 in reply
    c) Send OFPT_FLOW_MOD, command = OFPFC_DELETE
    c) Send ofp_table_stats request , verify active_count=0 in reply"""

    def runTest(self):

        of_logger.info("Running Modify_State_Delete test")

        of_ports = of_port_map.keys()
        of_ports.sort()

        #Clear switch state
        rc = delete_all_flows(self.controller,of_logger)
        self.assertEqual(rc, 0, "Failed to delete all flows")

        of_logger.info("Inserting a flow entry and then deleting it")
        of_logger.info("Expecting the active_count=0 in table_stats_reply")

        #Insert a flow matching on ingress_port 
        (Pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)

        #Verify Flow inserted.
        Verify_TableStats(self,active_entries=1)

        #Delete the flow 
        NonStrict_Delete(self,match)

        # Send Table_Stats_Request and verify flow deleted.
        Verify_TableStats(self,active_entries=0)

      

class ModifyStateModify(basic.SimpleDataPlane):
    
    """Verify basic Flow Modify request is implemented
    a) Send OFPT_FLOW_MOD, command = OFPFC_ADD, Action A 
    b) Send OFPT_FLOW_MOD, command = OFPFC_MODIFY , with output action A'
    c) Send a packet matching the flow, verify packet implements action A' """

    def runTest(self):

        of_logger.info("Running Modify_State_Modify test")

        of_ports = of_port_map.keys()
        of_ports.sort()

        #Clear switch state
        rc = delete_all_flows(self.controller, of_logger)
        self.assertEqual(rc, 0, "Failed to delete all flows")

        of_logger.info("Inserting a flow entry and then modifying it")
        of_logger.info("Expecting the Test Packet to implement the modified action")

        # Insert a flow matching on ingress_port with action A (output to of_port[1])    
        (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
  
        # Modify the flow action (output to of_port[2])
        Modify_Flow_Action(self,of_ports,match)
        
        # Send the Test Packet and verify action implemented is A' (output to of_port[2])
        SendPacket(self,pkt,of_ports[0],of_ports[2])
                       

class ReadState(basic.SimpleProtocol):
    
    """Test that a basic Read state request (like flow_stats_get request) does not generate an error
    a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
    b) Send ofp_flow_stats request
    b) Verify switch replies without errors"""

    def runTest(self):

        of_logger.info("Running Read_State test")

        of_ports = of_port_map.keys()
        of_ports.sort()

        #Clear switch state
        rc = delete_all_flows(self.controller, of_logger)
        self.assertEqual(rc, 0, "Failed to delete all flows")

        of_logger.info("Inserting a flow entry and then sending flow_stats request")
        of_logger.info("Expecting the a flow_stats_reply without errors")

        # Insert a flow with match on ingress_port
        (pkt,match ) = Wildcard_All_Except_Ingress(self,of_ports)
        
        #Verify Flow_Stats request does not generate errors
        Verify_FlowStats(self,match)
        
class PacketOut(basic.SimpleDataPlane):
    
    """Test packet out function
    a) Send packet out message for each dataplane port.
    b) Verify the packet appears on the appropriate dataplane port"""
    
    def runTest(self):

        of_logger.info("Running Packet_Out test")

        of_ports = of_port_map.keys()
        of_ports.sort()
       
        #Clear Switch state
        rc = delete_all_flows(self.controller, of_logger)
        self.assertEqual(rc, 0, "Failed to delete all flows")

        of_logger.info("Sending a packet-out for each dataplane port")
        of_logger.info("Expecting the packet on appropriate dataplane port")

        for dp_port in of_ports:
            for outpkt, opt in [
                (simple_tcp_packet(), "simple TCP packet"),
                (simple_eth_packet(), "simple Ethernet packet"),
                (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
            
                msg = message.packet_out()
                msg.data = str(outpkt)
                act = action.action_output()
                act.port = dp_port
                self.assertTrue(msg.actions.add(act), 'Could not add action to msg')

                of_logger.info("PacketOut to: " + str(dp_port))
                rv = self.controller.message_send(msg)
                self.assertTrue(rv == 0, "Error sending out message")

                exp_pkt_arg = None
                exp_port = None
                if of_config["relax"]:
                    exp_pkt_arg = outpkt
                    exp_port = dp_port
                (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=2, 
                                                                port_number=exp_port,
                                                                exp_pkt=exp_pkt_arg)
                
                self.assertTrue(pkt is not None, 'Packet not received')
                of_logger.info("PacketOut: got pkt from " + str(of_port))
                if of_port is not None:
                    self.assertEqual(of_port, dp_port, "Unexpected receive port")
                if not dataplane.match_exp_pkt(outpkt, pkt):
                    of_logger.debug("Sent %s" % format_packet(outpkt))
                    of_logger.debug("Resp %s" % format_packet(
                            str(pkt)[:len(str(outpkt))]))
                self.assertEqual(str(outpkt), str(pkt)[:len(str(outpkt))],
                                    'Response packet does not match send packet')

        
class PacketIn(basic.SimpleDataPlane):
    
    """Test basic packet_in function
    a) Send a simple tcp packet to a dataplane port, without any flow-entry 
    b) Verify that a packet_in event is sent to the controller"""
    
    def runTest(self):
        
        of_logger.info("Running Packet_In test")

        of_ports = of_port_map.keys()
        of_ports.sort()
        ingress_port = of_ports[0]

        #Clear Switch state
        rc = delete_all_flows(self.controller, of_logger)
        self.assertEqual(rc, 0, "Failed to delete all flows")
        self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")

        of_logger.info("Sending a Simple tcp packet a dataplane port")
        of_logger.info("Expecting a packet_in event on the control plane")

        # Send  packet on dataplane port and verify packet_in event gets generated.
        pkt = simple_tcp_packet()
        self.dataplane.send(ingress_port, str(pkt))
        of_logger.info("Sending packet to dp port " + str(ingress_port) +
                   ", expecting packet_in on control plane" )
      
        (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_PACKET_IN,
                                               timeout=2)
        self.assertTrue(response is not None, 
                               'Packet in event is not sent to the controller') 


class Hello(basic.SimpleDataPlane):
    
    """Test Hello messages are implemented
    a) Create Hello messages from controller
    b) Verify switch also exchanges hello message -- (Poll the control plane)
    d) Verify the version field in the hello messages is openflow 1.0.0 """

    def runTest(self):
        
        of_logger.info("Running Hello test")

        of_logger.info("Sending Hello")
        of_logger.info("Expecting a Hello on the control plane with version--1.0.0")
        
        #Send Hello message
        request = message.hello()
        (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_HELLO,
                                               timeout=1)
        self.assertTrue(response is not None, 
                               'Switch did not exchange hello message in return') 
        self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.0')



class EchoWithoutBody(basic.SimpleProtocol):
    
    """Test basic echo-reply is implemented
    a)  Send echo-request from the controller side, note echo body is empty here.
    b)  Verify switch responds back with echo-reply with same xid """
    
    def runTest(self):

        of_logger.info("Running Echo_Without_Body test")

        of_logger.info("Sending Echo Request")
        of_logger.info("Expecting a Echo Reply with version--1.0.0 and same xid")

        # Send echo_request
        request = message.echo_request()
        (response, pkt) = self.controller.transact(request)
        self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,'response is not echo_reply')
        self.assertEqual(request.header.xid, response.header.xid,
                         'response xid != request xid')
        self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.1')
        self.assertEqual(len(response.data), 0, 'response data non-empty')


class BarrierRequestReply(basic.SimpleProtocol):

    """ Check basic Barrier request is implemented
    a) Send OFPT_BARRIER_REQUEST
    c) Verify OFPT_BARRIER_REPLY is recieved"""
    
    def runTest(self):

        of_logger.info("Running Barrier_Request_Reply test")

        of_logger.info("Sending Barrier Request")
        of_logger.info("Expecting a Barrier Reply with same xid")

        #Send Barrier Request
        request = message.barrier_request()
        (response, pkt) = self.controller.transact(request)
        self.assertEqual(response.header.type, ofp.OFPT_BARRIER_REPLY,'response is not barrier_reply')
        self.assertEqual(request.header.xid, response.header.xid,
                         'response xid != request xid')





