#!/usr/bin/python 

import sys
import copy
from collections import OrderedDict
from trex import CTRexScenario
sys.path.append(CTRexScenario.scripts_path)
from dpdk_setup_ports import ConfigCreator, DpdkSetup
sys.path.remove(CTRexScenario.scripts_path)
from nose.tools import assert_raises
import yaml

class CompareLinesDiff(Exception): pass
class CompareLinesNumDiff(Exception): pass
class CompareTypeErr(Exception): pass

def compare_lines(golden, output):
    if type(golden) is not str:
        raise CompareTypeErr('Type of golden should be str, got: %s' % type(golden))
    if type(output) is not str:
        raise CompareTypeErr('Type of output should be str, got: %s' % type(output))
    golden_lines = golden.strip().splitlines()
    output_lines = output.strip().splitlines()
    if len(golden_lines) != len(output_lines):
        raise CompareLinesNumDiff('Number of lines on golden is: %s, in output: %s\nGolden:\n%s\nGenerated:\n%s\n' % (len(golden_lines), len(output_lines), golden, output))
    for line_num, (golden_line, output_line) in enumerate(zip(golden_lines, output_lines)):
        if golden_line != output_line:
            raise CompareLinesDiff('Produced YAML differs from golden at line %s.\nGolden: %s <-> Output: %s' % (line_num + 1, golden_line, output_line))

def create_config(cpu_topology, interfaces, *args, **kwargs):
    config = ConfigCreator(cpu_topology, interfaces, *args, **kwargs)
    return config.create_config()

def verify_master_core0(output):
    output_yaml = yaml.safe_load(output)
    assert type(output_yaml) is list, 'Generated YAML should be list'
    assert len(output_yaml) is 1, 'Generated YAML should be list with 1 element'
    output_yaml = output_yaml[0]
    assert 'platform' in output_yaml, 'Generated YAML has no platform section:\n%s' % output
    assert 'master_thread_id' in output_yaml['platform'], 'Generated YAML does not specify master thread id:\n%s' % output
    assert output_yaml['platform']['master_thread_id'] is 0, 'Master thread id should be 0 in generated YAML, got:%s' % output_yaml['platform']['master_thread_id']

class TRexCfgCreator_Test:

    def test_vm_cfg(self):
        cpu_topology = {0: OrderedDict([i, [i]] for i in range(5))}
        interfaces = [{'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 1968,
  'Device_str': 'VMXNET3 Ethernet Controller',
  'Driver_str': 'vmxnet3',
  'Interface': 'ens192',
  'Interface_argv': '0b:00.0',
  'Module_str': 'igb_uio,vfio-pci,uio_pci_generic',
  'NUMA': -1,
  'PhySlot': '192',
  'PhySlot_str': '192',
  'ProgIf': '01',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '07b0',
  'SDevice_str': 'VMXNET3 Ethernet Controller',
  'SVendor': '15ad',
  'SVendor_str': 'VMware',
  'Slot': '0000:0b:00.0',
  'Slot_str': '0b:00.0',
  'Vendor': 5549,
  'Vendor_str': 'VMware',
  'dest_mac': '00:0c:29:92:f1:ca',
  'src_mac': '00:0c:29:92:f1:d4',
  'loopback_dest': True},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 1968,
  'Device_str': 'VMXNET3 Ethernet Controller',
  'Driver_str': 'vmxnet3',
  'Interface': 'ens160',
  'Interface_argv': '03:00.0',
  'Module_str': 'igb_uio,vfio-pci,uio_pci_generic',
  'NUMA': -1,
  'PhySlot': '160',
  'PhySlot_str': '160',
  'ProgIf': '01',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '07b0',
  'SDevice_str': 'VMXNET3 Ethernet Controller',
  'SVendor': '15ad',
  'SVendor_str': 'VMware',
  'Slot': '0000:03:00.0',
  'Slot_str': '03:00.0',
  'Vendor': 5549,
  'Vendor_str': 'VMware',
  'dest_mac': '00:0c:29:92:f1:d4',
  'src_mac': '00:0c:29:92:f1:ca'}]
        golden = '''
### Config file generated by dpdk_setup_ports.py ###

- port_limit: 2
  version: 2
  interfaces: ['0b:00.0', '03:00.0']
  port_info:
      - dest_mac: 00:0c:29:92:f1:ca # MAC OF LOOPBACK TO IT'S DUAL INTERFACE
        src_mac:  00:0c:29:92:f1:d4
      - dest_mac: 00:0c:29:92:f1:d4
        src_mac:  00:0c:29:92:f1:ca

  platform:
      master_thread_id: 0
      latency_thread_id: 1
      dual_if:
        - socket: 0
          threads: [2,3,4]
'''
        output = create_config(cpu_topology, interfaces)
        verify_master_core0(output)
        compare_lines(golden, output)
        with assert_raises(CompareLinesNumDiff):
            compare_lines('1' + golden, output)
        output = create_config(cpu_topology, interfaces, exclude_lcores = [0])
        with assert_raises(AssertionError):
            verify_master_core0(output)
        output = create_config(cpu_topology, interfaces, include_lcores = [1,2,3,4])
        with assert_raises(AssertionError):
            verify_master_core0(output)
        output = create_config(cpu_topology, interfaces, include_lcores = [0,2,3,4])
        verify_master_core0(output)
        output = create_config(cpu_topology, interfaces, include_lcores = [0,2,3,4], exclude_lcores = [0])
        with assert_raises(AssertionError):
            verify_master_core0(output)

    def test_trex08_cfg(self):
        cpu_topology = OrderedDict([(0, OrderedDict([(0, [0, 16]), (1, [1, 17]), (2, [2, 18]), (3, [3, 19]), (4, [4, 20]), (5, [5, 21]), (6, [6, 22]), (7, [7, 23])])), (1, OrderedDict([(0, [8, 24]), (1, [9, 25]), (2, [10, 26]), (3, [11, 27]), (4, [12, 28]), (5, [13, 29]), (6, [14, 30]), (7, [15, 31])]))])
        interfaces = [{'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:02:00.0',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-1',
  'PhySlot_str': '0-1',
  'ProgIf': '01',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0002',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:02:00.0',
  'Slot_str': '02:00.0',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '02:00:02:00:00:00',
  'src_mac': '01:00:01:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:02:00.1',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-1',
  'PhySlot_str': '0-1',
  'ProgIf': '01',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0000',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:02:00.1',
  'Slot_str': '02:00.1',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '01:00:01:00:00:00',
  'src_mac': '02:00:02:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:84:00.0',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 1,
  'PhySlot': '0-8',
  'PhySlot_str': '0-8',
  'ProgIf': '20',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0002',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:84:00.0',
  'Slot_str': '84:00.0',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '04:00:04:00:00:00',
  'src_mac': '03:00:03:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:84:00.1',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 1,
  'PhySlot': '0-8',
  'PhySlot_str': '0-8',
  'ProgIf': '20',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0000',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:84:00.1',
  'Slot_str': '84:00.1',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '03:00:03:00:00:00',
  'src_mac': '04:00:04:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '05:00.0',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-3',
  'PhySlot_str': '0-3',
  'ProgIf': '01',
  'Rev': '02',
  'Rev_str': '02',
  'SDevice': '0000',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:05:00.0',
  'Slot_str': '05:00.0',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '06:00:06:00:00:00',
  'src_mac': '05:00:05:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '05:00.1',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-3',
  'PhySlot_str': '0-3',
  'ProgIf': '01',
  'Rev': '02',
  'Rev_str': '02',
  'SDevice': '0000',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:05:00.1',
  'Slot_str': '05:00.1',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '05:00:05:00:00:00',
  'src_mac': '06:00:06:00:00:00'}]
        golden = '''
### Config file generated by dpdk_setup_ports.py ###

- port_limit: 6
  version: 2
  interfaces: ['02:00.0', '02:00.1', '84:00.0', '84:00.1', '05:00.0', '05:00.1']
  port_bandwidth_gb: 40
  port_info:
      - dest_mac: 02:00:02:00:00:00
        src_mac:  01:00:01:00:00:00
      - dest_mac: 01:00:01:00:00:00
        src_mac:  02:00:02:00:00:00

      - dest_mac: 04:00:04:00:00:00
        src_mac:  03:00:03:00:00:00
      - dest_mac: 03:00:03:00:00:00
        src_mac:  04:00:04:00:00:00

      - dest_mac: 06:00:06:00:00:00
        src_mac:  05:00:05:00:00:00
      - dest_mac: 05:00:05:00:00:00
        src_mac:  06:00:06:00:00:00

  platform:
      master_thread_id: 0
      latency_thread_id: 12
      dual_if:
        - socket: 0
          threads: [1,2,3,16,17,18,19]

        - socket: 1
          threads: [8,9,10,11,24,25,26]

        - socket: 0
          threads: [4,5,6,7,20,21,22]
'''
        output = create_config(cpu_topology, interfaces)
        verify_master_core0(output)
        compare_lines(golden, output)

        interfaces = [{'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:02:00.0',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-1',
  'PhySlot_str': '0-1',
  'ProgIf': '01',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0002',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:02:00.0',
  'Slot_str': '02:00.0',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '02:00:02:00:00:00',
  'src_mac': '01:00:01:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:02:00.1',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-1',
  'PhySlot_str': '0-1',
  'ProgIf': '01',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0000',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:02:00.1',
  'Slot_str': '02:00.1',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '01:00:01:00:00:00',
  'src_mac': '02:00:02:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:84:00.0',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 1,
  'PhySlot': '0-8',
  'PhySlot_str': '0-8',
  'ProgIf': '20',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0002',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:84:00.0',
  'Slot_str': '84:00.0',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '04:00:04:00:00:00',
  'src_mac': '03:00:03:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:84:00.1',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 1,
  'PhySlot': '0-8',
  'PhySlot_str': '0-8',
  'ProgIf': '20',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0000',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:84:00.1',
  'Slot_str': '84:00.1',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '03:00:03:00:00:00',
  'src_mac': '04:00:04:00:00:00'}]
        golden = '''
### Config file generated by dpdk_setup_ports.py ###

- port_limit: 4
  version: 2
  interfaces: ['02:00.0', '02:00.1', '84:00.0', '84:00.1']
  port_bandwidth_gb: 40
  port_info:
      - dest_mac: 02:00:02:00:00:00
        src_mac:  01:00:01:00:00:00
      - dest_mac: 01:00:01:00:00:00
        src_mac:  02:00:02:00:00:00

      - dest_mac: 04:00:04:00:00:00
        src_mac:  03:00:03:00:00:00
      - dest_mac: 03:00:03:00:00:00
        src_mac:  04:00:04:00:00:00

  platform:
      master_thread_id: 0
      latency_thread_id: 31
      dual_if:
        - socket: 0
          threads: [1,2,3,4,5,6,7,16,17,18,19,20,21,22,23]

        - socket: 1
          threads: [8,9,10,11,12,13,14,15,24,25,26,27,28,29,30]
'''
        output = create_config(cpu_topology, interfaces)
        verify_master_core0(output)
        compare_lines(golden, output)

        interfaces = [{'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:02:00.0',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-1',
  'PhySlot_str': '0-1',
  'ProgIf': '01',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0002',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:02:00.0',
  'Slot_str': '02:00.0',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '02:00:02:00:00:00',
  'src_mac': '01:00:01:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:02:00.1',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-1',
  'PhySlot_str': '0-1',
  'ProgIf': '01',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0000',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:02:00.1',
  'Slot_str': '02:00.1',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '01:00:01:00:00:00',
  'src_mac': '02:00:02:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '05:00.0',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-3',
  'PhySlot_str': '0-3',
  'ProgIf': '01',
  'Rev': '02',
  'Rev_str': '02',
  'SDevice': '0000',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:05:00.0',
  'Slot_str': '05:00.0',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '04:00:04:00:00:00',
  'src_mac': '03:00:03:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '05:00.1',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-3',
  'PhySlot_str': '0-3',
  'ProgIf': '01',
  'Rev': '02',
  'Rev_str': '02',
  'SDevice': '0000',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:05:00.1',
  'Slot_str': '05:00.1',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '03:00:03:00:00:00',
  'src_mac': '04:00:04:00:00:00'}]
        golden = '''
### Config file generated by dpdk_setup_ports.py ###

- port_limit: 4
  version: 2
  interfaces: ['02:00.0', '02:00.1', '05:00.0', '05:00.1']
  port_bandwidth_gb: 40
  port_info:
      - dest_mac: 02:00:02:00:00:00
        src_mac:  01:00:01:00:00:00
      - dest_mac: 01:00:01:00:00:00
        src_mac:  02:00:02:00:00:00

      - dest_mac: 04:00:04:00:00:00
        src_mac:  03:00:03:00:00:00
      - dest_mac: 03:00:03:00:00:00
        src_mac:  04:00:04:00:00:00

  platform:
      master_thread_id: 0
      latency_thread_id: 8
      dual_if:
        - socket: 0
          threads: [1,2,3,16,17,18,19]

        - socket: 0
          threads: [4,5,6,7,20,21,22]
'''
        output = create_config(cpu_topology, interfaces)
        verify_master_core0(output)
        compare_lines(golden, output)

    def test_cfg_negative(self):
        cpu_topology = OrderedDict([(0, OrderedDict([(0, [0, 16]), (1, [1, 17]), (2, [2, 18]), (3, [3, 19]), (4, [4, 20]), (5, [5, 21]), (6, [6, 22]), (7, [7, 23])])), (1, OrderedDict([(0, [8, 24]), (1, [9, 25]), (2, [10, 26]), (3, [11, 27]), (4, [12, 28]), (5, [13, 29]), (6, [14, 30]), (7, [15, 31])]))])
        interfaces = [{'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:02:00.0',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-1',
  'PhySlot_str': '0-1',
  'ProgIf': '01',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0002',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:02:00.0',
  'Slot_str': '02:00.0',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '02:00:02:00:00:00',
  'src_mac': '01:00:01:00:00:00'},
 {'Active': '',
  'Class': '0200',
  'Class_str': 'Ethernet controller',
  'Device': 5507,
  'Device_str': 'Ethernet Controller XL710 for 40GbE QSFP+',
  'Driver_str': 'igb_uio',
  'Interface': '',
  'Interface_argv': '0000:02:00.1',
  'Module_str': 'vfio-pci,uio_pci_generic',
  'NUMA': 0,
  'PhySlot': '0-1',
  'PhySlot_str': '0-1',
  'ProgIf': '01',
  'Rev': '01',
  'Rev_str': '01',
  'SDevice': '0000',
  'SDevice_str': 'Ethernet Converged Network Adapter XL710-Q2',
  'SVendor': '8086',
  'SVendor_str': 'Intel Corporation',
  'Slot': '0000:02:00.1',
  'Slot_str': '02:00.1',
  'Vendor': 32902,
  'Vendor_str': 'Intel Corporation',
  'dest_mac': '01:00:01:00:00:00',
  'src_mac': '02:00:02:00:00:00'}]
        # types errors
        with assert_raises(AssertionError):
            create_config(None, None)
        with assert_raises(AssertionError):
            create_config(cpu_topology, None)
        with assert_raises(AssertionError):
            create_config(None, interfaces)
        with assert_raises(AssertionError):
            create_config(cpu_topology, [])
        with assert_raises(AssertionError):
            create_config({}, interfaces)
        with assert_raises(AssertionError):
            create_config({}, [])
        # not enough cores at NUMA 0
        with assert_raises(DpdkSetup):
            create_config({0:{0:[]}, 1:{0:[1,2,3,4,5,6,7]}}, interfaces)
        with assert_raises(DpdkSetup):
            create_config({0:{0:[1]}, 1:{0:[3]}}, interfaces)
        with assert_raises(DpdkSetup):
            create_config({0:{0:[1,2]}}, interfaces)
        # no NUMA 0 info, NICs at NUMA 0
        cpu_topo1 = copy.deepcopy(cpu_topology)
        del cpu_topo1[0]
        with assert_raises(KeyError):
            create_config(cpu_topo1, interfaces)
        int1 = copy.deepcopy(interfaces)
        for interface in int1:
            interface['NUMA'] = 1
        # now should work, as interfaces use NUMA 1
        create_config(cpu_topo1, int1)
        int2 = copy.deepcopy(interfaces)
        int2[1]['NUMA'] = 1
        # interfaces on different NUMAs
        with assert_raises(DpdkSetup):
            create_config(cpu_topology, int2)


    def test_inner_comparator(self):
        compare_lines('', '')
        compare_lines('one\ntwo', 'one\ntwo')
        with assert_raises(CompareLinesNumDiff):
            compare_lines('one\ntwo', 'one\ntwo\nthree')
        with assert_raises(CompareLinesDiff):
            compare_lines('one\ntwo', 'one\ntwo1')
        with assert_raises(CompareLinesDiff):
            compare_lines('one\ntwo', 'one\nthree')
        with assert_raises(CompareTypeErr):
            compare_lines(None, 'one\nthree')
        with assert_raises(CompareTypeErr):
            compare_lines('one\ntwo', None)
        with assert_raises(CompareTypeErr):
            compare_lines(None, None)

    @classmethod
    def tearDownClass(cls):
        if CTRexScenario.scripts_path in sys.path:
            sys.path.remove(CTRexScenario.scripts_path)
        del sys.modules['dpdk_setup_ports']