""" Unit tests for testing CORE EMANE networks. """ import os from tempfile import TemporaryFile from typing import Type from xml.etree import ElementTree import pytest from core import utils from core.emane.bypass import EmaneBypassModel from core.emane.commeffect import EmaneCommEffectModel from core.emane.emanemodel import EmaneModel from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.nodes import EmaneNet from core.emane.rfpipe import EmaneRfPipeModel from core.emane.tdma import EmaneTdmaModel from core.emulator.data import IpPrefixes, NodeOptions from core.emulator.session import Session from core.errors import CoreCommandError, CoreError from core.nodes.base import CoreNode _EMANE_MODELS = [ EmaneIeee80211abgModel, EmaneRfPipeModel, EmaneBypassModel, EmaneCommEffectModel, EmaneTdmaModel, ] _DIR = os.path.dirname(os.path.abspath(__file__)) def ping( from_node: CoreNode, to_node: CoreNode, ip_prefixes: IpPrefixes, count: int = 3 ): address = ip_prefixes.ip4_address(to_node.id) try: from_node.cmd(f"ping -c {count} {address}") status = 0 except CoreCommandError as e: status = e.returncode return status class TestEmane: def test_two_emane_interfaces(self, session: Session): """ Test nodes running multiple emane interfaces. :param core.emulator.coreemu.EmuSession session: session for test """ # create emane node for networking the core nodes session.set_location(47.57917, -122.13232, 2.00000, 1.0) options = NodeOptions() options.set_position(80, 50) options.emane = EmaneIeee80211abgModel.name emane_net1 = session.add_node(EmaneNet, options=options) options.emane = EmaneRfPipeModel.name emane_net2 = session.add_node(EmaneNet, options=options) # create nodes options = NodeOptions(model="mdr") options.set_position(150, 150) node1 = session.add_node(CoreNode, options=options) options.set_position(300, 150) node2 = session.add_node(CoreNode, options=options) # create interfaces ip_prefix1 = IpPrefixes("10.0.0.0/24") ip_prefix2 = IpPrefixes("10.0.1.0/24") for i, node in enumerate([node1, node2]): node.setposition(x=150 * (i + 1), y=150) iface_data = ip_prefix1.create_iface(node) session.add_link(node.id, emane_net1.id, iface1_data=iface_data) iface_data = ip_prefix2.create_iface(node) session.add_link(node.id, emane_net2.id, iface1_data=iface_data) # instantiate session session.instantiate() # ping node2 from node1 on both interfaces and check success status = ping(node1, node2, ip_prefix1, count=5) assert not status status = ping(node1, node2, ip_prefix2, count=5) assert not status @pytest.mark.parametrize("model", _EMANE_MODELS) def test_models( self, session: Session, model: Type[EmaneModel], ip_prefixes: IpPrefixes ): """ Test emane models within a basic network. :param core.emulator.coreemu.EmuSession session: session for test :param model: emane model to test :param ip_prefixes: generates ip addresses for nodes """ # create emane node for networking the core nodes session.set_location(47.57917, -122.13232, 2.00000, 1.0) options = NodeOptions() options.set_position(80, 50) emane_network = session.add_node(EmaneNet, options=options) session.emane.set_model(emane_network, model) # configure tdma if model == EmaneTdmaModel: session.emane.set_model_config( emane_network.id, EmaneTdmaModel.name, {"schedule": os.path.join(_DIR, "../../examples/tdma/schedule.xml")}, ) # create nodes options = NodeOptions(model="mdr") options.set_position(150, 150) node1 = session.add_node(CoreNode, options=options) options.set_position(300, 150) node2 = session.add_node(CoreNode, options=options) for i, node in enumerate([node1, node2]): node.setposition(x=150 * (i + 1), y=150) iface_data = ip_prefixes.create_iface(node) session.add_link(node.id, emane_network.id, iface1_data=iface_data) # instantiate session session.instantiate() # ping node2 from node1 and assert success status = ping(node1, node2, ip_prefixes, count=5) assert not status def test_xml_emane( self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes ): """ Test xml client methods for emane. :param session: session for test :param tmpdir: tmpdir to create data in :param ip_prefixes: generates ip addresses for nodes """ # create emane node for networking the core nodes session.set_location(47.57917, -122.13232, 2.00000, 1.0) options = NodeOptions() options.set_position(80, 50) emane_network = session.add_node(EmaneNet, options=options) config_key = "txpower" config_value = "10" session.emane.set_model( emane_network, EmaneIeee80211abgModel, {config_key: config_value} ) # create nodes options = NodeOptions(model="mdr") options.set_position(150, 150) node1 = session.add_node(CoreNode, options=options) options.set_position(300, 150) node2 = session.add_node(CoreNode, options=options) for i, node in enumerate([node1, node2]): node.setposition(x=150 * (i + 1), y=150) iface_data = ip_prefixes.create_iface(node) session.add_link(node.id, emane_network.id, iface1_data=iface_data) # instantiate session session.instantiate() # get ids for nodes emane_id = emane_network.id node1_id = node1.id node2_id = node2.id # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(node1_id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(node2_id, CoreNode) # load saved xml session.open_xml(file_path, start=True) # retrieve configuration we set originally value = str( session.emane.get_config(config_key, emane_id, EmaneIeee80211abgModel.name) ) # verify nodes and configuration were restored assert session.get_node(node1_id, CoreNode) assert session.get_node(node2_id, CoreNode) assert session.get_node(emane_id, EmaneNet) assert value == config_value def test_xml_emane_node_config( self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes ): # create nodes options = NodeOptions(model="mdr", x=50, y=50) node1 = session.add_node(CoreNode, options=options) iface1_data = ip_prefixes.create_iface(node1) node2 = session.add_node(CoreNode, options=options) iface2_data = ip_prefixes.create_iface(node2) # create emane node options = NodeOptions(model=None, emane=EmaneRfPipeModel.name) emane_node = session.add_node(EmaneNet, options=options) # create links session.add_link(node1.id, emane_node.id, iface1_data) session.add_link(node2.id, emane_node.id, iface2_data) # set node specific conifg datarate = "101" session.emane.set_model_config( node1.id, EmaneRfPipeModel.name, {"datarate": datarate} ) # instantiate session session.instantiate() # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(node1.id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(node2.id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(emane_node.id, EmaneNet) # load saved xml session.open_xml(file_path, start=True) # verify nodes have been recreated assert session.get_node(node1.id, CoreNode) assert session.get_node(node2.id, CoreNode) assert session.get_node(emane_node.id, EmaneNet) links = [] for node_id in session.nodes: node = session.nodes[node_id] links += node.links() assert len(links) == 2 config = session.emane.get_model_config(node1.id, EmaneRfPipeModel.name) assert config["datarate"] == datarate def test_xml_emane_interface_config( self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes ): # create nodes options = NodeOptions(model="mdr", x=50, y=50) node1 = session.add_node(CoreNode, options=options) iface1_data = ip_prefixes.create_iface(node1) node2 = session.add_node(CoreNode, options=options) iface2_data = ip_prefixes.create_iface(node2) # create emane node options = NodeOptions(model=None, emane=EmaneRfPipeModel.name) emane_node = session.add_node(EmaneNet, options=options) # create links session.add_link(node1.id, emane_node.id, iface1_data) session.add_link(node2.id, emane_node.id, iface2_data) # set node specific conifg datarate = "101" config_id = utils.iface_config_id(node1.id, iface1_data.id) session.emane.set_model_config( config_id, EmaneRfPipeModel.name, {"datarate": datarate} ) # instantiate session session.instantiate() # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(node1.id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(node2.id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(emane_node.id, EmaneNet) # load saved xml session.open_xml(file_path, start=True) # verify nodes have been recreated assert session.get_node(node1.id, CoreNode) assert session.get_node(node2.id, CoreNode) assert session.get_node(emane_node.id, EmaneNet) links = [] for node_id in session.nodes: node = session.nodes[node_id] links += node.links() assert len(links) == 2 config = session.emane.get_model_config(config_id, EmaneRfPipeModel.name) assert config["datarate"] == datarate