def test_get_groundstations(): # Create contact plan object cp = ContactPlan(1000.1, 42.42) # Add nodes cp.plan['nodes'].append('gs12') cp.plan['nodes'].append('sat1') cp.plan['nodes'].append('groundstation3') # Check that only matching nodes are returned assert cp.get_groundstations() == ['gs12'] assert cp.get_groundstations('groundstation') == ['groundstation3']
def test_load_route_list_anchoring_first_contact(mod): """Test function that tests the route-finding capabilities, in particular the correct behaviour when the anchoring mechanism is involved and the limiting contact is the first contact of the route. """ # First, create an contact plan that is then converted to the contact graph # representation and later processed by load_route_list # The following topology is tested in this test case: # +---+ # | 5 | # [0:100]+--+---+--+[0:100] # | | # +-+-+ +-+-+ # | 3 | | 4 | # +-+-+ +-+-+ # | | # [0:100]+--+---+--+[0:100] # | 2 | # +-+-+ # | # |[30:70] # | # +-+-+ # | 1 | # +---+ contact_plan = ContactPlan(1000, 0) # Add contacts contact_plan.add_contact('node1', 'node2', 30, 70) contact_plan.add_contact('node2', 'node3', 0, 100) contact_plan.add_contact('node2', 'node4', 0, 100) contact_plan.add_contact('node3', 'node5', 0, 100) contact_plan.add_contact('node4', 'node5', 0, 100) # Generate contact graph representation contact_graph = ContactGraph(contact_plan) # Now generate a route list for possible routes from node1 to node4 route_list_node15 = mod.load_route_list(contact_graph, 'node1', 'node5', 0) # Make sure that only route is found (as both possible routes run through # the identical first limiting contact and thus only one route suffices) assert len(route_list_node15) == 1 # Check that the route is correct route = route_list_node15[0] assert route[0] == [('node1', 'node2', 30, 70, 1000, 0), ('node2', 'node3', 0, 100, 1000, 0), ('node3', 'node5', 0, 100, 1000, 0)] \ or route[0] == [('node1', 'node2', 30, 70, 1000, 0), ('node2', 'node4', 0, 100, 1000, 0), ('node4', 'node5', 0, 100, 1000, 0)] assert route.edt == 30 assert route.capacity == 40000 assert route.to_time == 70
def test_verify_capacity_calculation_consistency(): """Test function that verifies that the capacity calculations in CGR and the Contact object correspond to each other. """ # The following topology is tested in this test case: # +---+ # | 2 | # +-+-+ # | # [30:90]| # | # +-+-+ # | 1 | # +---+ # Create contact plan and add single contact contact_plan = ContactPlan(1, 20) contact_plan.add_contact('node1', 'node2', 30000, 90000) # Generate contact graph representation contact_graph = ContactGraph(contact_plan) # Create Simulation Environment (dummy, simulation will not be # executed) env = QSim() # Create a Contact object that represents the one edge of the contact # graph and should have the same capacity value calculated as the CGR # functions contact = Contact(30000, 90000, 1, 'node1', 'node2', delay=20) # Now generate possible routes route_list_node12 = cgr.load_route_list(contact_graph, 'node1', 'node2', 0) # There should be only one possible route assert len(route_list_node12) == 1 assert route_list_node12[0].edt == 30000 assert route_list_node12[0].capacity == 60000 assert route_list_node12[0].to_time == 90000 assert route_list_node12[0].transmission_plan == ([('node1', 'node2', 30000, 90000, 1, 20)]) # Verify that the capacities that were calculated are equal (as no packet # has been enqueue yet, the capacity value can be checked) assert contact.capacity == route_list_node12[0].capacity
def test_create_contactplan_object(): # Create contact plan object cp = ContactPlan(1000.1, 42.42) # Verify that both the datarate and the delay are properly set assert cp.default_datarate == 1000.1 assert cp.default_delay == 42.42 # Verify that plan object was initialized properly assert type(cp.plan) is OrderedDict assert type(cp.plan['nodes']) is list assert type(cp.plan['contacts']) is list # Create contact plan object cp = ContactPlan(100, 2) # Verify that both the datarate and the delay are properly set assert cp.default_datarate == 100.0 assert cp.default_delay == 2.0
def test_get_outbound_contacts_of_node(): # Create contact plan object cp = ContactPlan(1000.1, 42.42) # Add nodes and contacts (both resulting in adding nodes to set) cp.add_node('testnode1') cp.add_contact('testnode2', 'testnode3', 0.0, 1.0) cp.add_contact('testnode2', 'testnode3', 0.0, 1.0) cp.add_contact('testnode2', 'testnode3', 10.0, 11.0, bidirectional=False) # Verify that all contacts are returned properly assert cp.get_outbound_contacts_of_node('testnode1') == [] assert cp.get_outbound_contacts_of_node('testnode2') == [ ('testnode2', 'testnode3', 0.0, 1.0, 1000.1, 42.42), ('testnode2', 'testnode3', 0.0, 1.0, 1000.1, 42.42), ('testnode2', 'testnode3', 10.0, 11.0, 1000.1, 42.42) ] assert cp.get_outbound_contacts_of_node('testnode3') == [ ('testnode3', 'testnode2', 0.0, 1.0, 1000.1, 42.42), ('testnode3', 'testnode2', 0.0, 1.0, 1000.1, 42.42) ]
def test_get_nodes(): # Create contact plan object cp = ContactPlan(1000.1, 42.42) # Add nodes and contacts (both resulting in adding nodes to set) cp.add_node('testnode1') cp.add_contact('testnode2', 'testnode3', 0.0, 1.0) # Verify that all nodes were added properly assert cp.get_nodes() == ['testnode1', 'testnode2', 'testnode3']
def run_simulation(algorithm, source_list, destination_list): """Performs a simulation with a certain algorithm.""" # Create simulation environment simulator = Simulator() # Generate contact plan from provided json file contact_plan = ContactPlan(1, 100, "tests/resources/tvg_g10_s10.json") # Convert contact plan to contact graph contact_graph = ContactGraph(contact_plan) # Create monitoring instance monitor = ReceptionMonitor(simulator.env) simulator.register_monitor(monitor) # Generate contact objects and register them for planned_contact in contact_plan.get_contacts(): contact = Contact(planned_contact.from_time, planned_contact.to_time, planned_contact.datarate, planned_contact.from_node, planned_contact.to_node, planned_contact.delay) simulator.register_contact(contact) # Generate node objects and register them for planned_node in contact_plan.get_nodes(): contact_list = contact_plan.get_outbound_contacts_of_node(planned_node) contact_dict = simulator.get_contact_dict(contact_list) SimpleCGRNode(planned_node, contact_dict, algorithm, contact_graph, simulator, []) # Generate packet generator(s) and register them generator = BatchPacketGenerator(200, 10000, source_list, destination_list, [10.0]) simulator.register_generator(generator) # Run the simulation simulator.run_simulation(48000000) # Return the monitored results return monitor.packet_dict
def test_clear(): # Create contact plan object cp = ContactPlan(1000.1, 42.42) # Add nodes and contacts (both resulting in adding nodes to set) cp.add_node('testnode1') cp.add_contact('testnode2', 'testnode3', 0.0, 1.0) cp.clear() assert cp.plan['nodes'] == list() assert cp.plan['contacts'] == [] assert cp.default_delay == 42.42 assert cp.default_datarate == 1000.1
def test_load_route_list_unavailable_route(mod): """Test function that tests that no route is found. """ # First, create an contact plan that is then converted to the contact graph # representation and later processed by load_route_list # The following topology is tested in this test case: # +---+ +---+ +---+ +---+ # | 1 +---------+ 2 +---------+ 3 +---------+ 4 | # +---+ 35:40 +---+ 20:40 +---+ 20:25 +---+ contact_plan = ContactPlan(1000, 0) contact_plan.add_contact('node1', 'node2', 35, 40) contact_plan.add_contact('node2', 'node3', 20, 40) contact_plan.add_contact('node3', 'node4', 20, 25) # Generate contact graph representation contact_graph = ContactGraph(contact_plan) # Now generate a route list for possible routes from node1 to node4 route_list_node14 = mod.load_route_list(contact_graph, 'node1', 'node4', 0) # Make sure that two routes were found assert len(route_list_node14) == 0
def generate_test_graph(remove_edge26=False): """Helper function to generate a contact graph for many testcases.""" # The following topology is tested in this test case: # +---+ # | 8 | # [0:100]+--+---+--+[30:90] # | | # +-+-+ +-+-+ # | 6 | | 7 | # +-+-+ +-+-+ # | | # | | # [10:40]| |[40:80] # | | # | | # +-+-+ +-+-+ # | 2 | | 3 | # +-+-+ +-+-+ # | | # [30:90]+--+---+--+[0:100] # | 1 | # +---+ contact_plan = ContactPlan(1000, 0) # Create list of all nodes contact_plan.add_contact('node1', 'node2', 30, 90) contact_plan.add_contact('node1', 'node3', 0, 100) contact_plan.add_contact('node3', 'node7', 40, 80) contact_plan.add_contact('node6', 'node8', 0, 100) contact_plan.add_contact('node7', 'node8', 30, 90) # Only add edge between node2 and node6 if required if not remove_edge26: contact_plan.add_contact('node2', 'node6', 10, 40) # Generate contact graph representation contact_graph = ContactGraph(contact_plan) return contact_graph
def main(): """Simulate basic scenario.""" # Create simulation environment simulator = Simulator() # Generate empy contact plan contact_plan = ContactPlan(1, 50) # Add a single contact from node_a to node_b from 0s to 10s to the plan contact_plan.add_contact('node_a', 'node_b', 0, 10000) # Convert contact plan to contact graph contact_graph = ContactGraph(contact_plan) # Generate contact objects and register them for planned_contact in contact_plan.get_contacts(): # Create a Contact simulation object based on the ContactPlan # information contact = Contact(planned_contact.from_time, planned_contact.to_time, planned_contact.datarate, planned_contact.from_node, planned_contact.to_node, planned_contact.delay) # Register the contact as a generator object in the simulation # environment simulator.register_contact(contact) # Generate node objects and register them for planned_node in contact_plan.get_nodes(): # Generate contact list of node contact_list = contact_plan.get_outbound_contacts_of_node(planned_node) # Create a dict that maps the contact identifiers to Contact simulation # objects contact_dict = simulator.get_contact_dict(contact_list) # Create a node simulation object SimpleCGRNode(planned_node, contact_dict, cgr_basic.cgr, contact_graph, simulator, []) # Generate packet generator(s) and register them generator = BatchPacketGenerator( 1, # Create one packet 1000, # Packet Size: 1000 Bytes ['node_a'], # From 'node_a' ['node_b'], # To 'node_b' [0]) # At simulation time 0s # Register the generator as a generator object in the simulation # environment simulator.register_generator(generator) # Run the simulation for 20 seconds (20000 ms) simulator.run_simulation(20000)
def test_load_route_list_no_route(mod): """Test function that tests the route-finding capabilities of the load_route_list function and tests that no route is found if contacts on route do not add up. """ # First, create an contact plan that is then converted to the contact graph # representation and later processed by load_route_list # The following topology is tested in this test case: # +---+ # | 5 | # [20;30]+--+---+--+[70:80] # | | # +-+-+ +-+-+ # | 3 | | 4 | # +-+-+ +-+-+ # | | # [10;20]+--+---+--+[40:50] # | 2 | # +-+-+ # | # |[50:60] # | # +-+-+ # | 1 | # +---+ contact_plan = ContactPlan(1000, 0) # Add contacts contact_plan.add_contact('node1', 'node2', 50, 60) contact_plan.add_contact('node2', 'node3', 10, 20) contact_plan.add_contact('node2', 'node4', 40, 50) contact_plan.add_contact('node3', 'node5', 20, 30) contact_plan.add_contact('node4', 'node5', 70, 80) # Generate contact graph representation contact_graph = ContactGraph(contact_plan) # Now generate a route list for possible routes from node1 to node4 route_list_node15 = mod.load_route_list(contact_graph, 'node1', 'node5', 0) # Make sure that two routes were found assert len(route_list_node15) == 0
def test_load_route_list(mod): """Test function that tests the route-finding capabilities of the load_route_list function and tests the correctness. """ # First, create an contact plan that is then converted to the contact graph # representation and later processed by load_route_list # The following topology is tested in this test case: # +---+ # | 4 | # [20;30]+--+---+--+[70:80] # | | # +-+-+ +-+-+ # | 2 | | 3 | # +-+-+ +-+-+ # | | # [10;20]+--+---+--+[40:50] # | 1 | # +---+ contact_plan = ContactPlan(1000, 0) contact_plan.add_contact('node1', 'node2', 10, 20) contact_plan.add_contact('node1', 'node3', 40, 50) contact_plan.add_contact('node2', 'node4', 20, 30) contact_plan.add_contact('node3', 'node4', 70, 80) # Generate contact graph representation contact_graph = ContactGraph(contact_plan) # Now generate a route list for possible routes from node1 to node4 route_list_node14 = mod.load_route_list(contact_graph, 'node1', 'node4', 0) # Make sure that two routes were found assert len(route_list_node14) == 2 # Assert characteristics of the found routes route1 = route_list_node14[0] assert route1.transmission_plan == ([('node1', 'node2', 10, 20, 1000, 0), ('node2', 'node4', 20, 30, 1000, 0)]) assert route1.edt == 20 assert route1.capacity == 10000 assert route1.to_time == 20 route2 = route_list_node14[1] assert route2.transmission_plan == ([('node1', 'node3', 40, 50, 1000, 0), ('node3', 'node4', 70, 80, 1000, 0)]) assert route2.edt == 70 assert route2.capacity == 10000 assert route2.to_time == 50
def test_add_node(): # Create contact plan object cp = ContactPlan(1000.1, 42.42) # Add node cp.add_node('testnode') # Check that new node is in node set assert 'testnode' in cp.plan['nodes'] assert len(cp.plan['nodes']) == 1 # Add node again cp.add_node('testnode') # Check that new node is in the set only once assert 'testnode' in cp.plan['nodes'] assert len(cp.plan['nodes']) == 1
def test_create_from_contact_plan(): plan = ContactPlan(1000, 0) plan.add_contact('a', 'b', 0.0, 10.0, 1000.0, 0.0, bidirectional=False) plan.add_contact('b', 'c', 0.0, 30.0, 1000.0, 0.0, bidirectional=False) plan.add_contact('a', 'c', 20.0, 30.0, 1000.0, 0.0, bidirectional=False) # Check if exception is thrown if invalid identifier is used with pytest.raises(ValueError): graph = ContactGraph([]) graph = ContactGraph(plan) assert len(graph.graph) == 6 id1 = ContactIdentifier('a', 'b', 0.0, 10.0, 1000.0, 0.0) id2 = ContactIdentifier('b', 'c', 0.0, 30.0, 1000.0, 0.0) id3 = ContactIdentifier('a', 'c', 20.0, 30.0, 1000.0, 0.0) assert id2 in graph.graph[id1][0] assert id1 in graph.graph[id2][1] assert len(graph.graph[id1][0]) == 2 assert len(graph.graph[id1][1]) == 1 assert len(graph.graph[id2][0]) == 1 assert len(graph.graph[id2][1]) == 2 assert len(graph.graph[id3][0]) == 1 assert len(graph.graph[id3][1]) == 1 # Verify number of root node vertices assert len(graph.graph[('a', 'a', 0, math.inf, math.inf, 0)][0]) == 2 assert len(graph.graph[('b', 'b', 0, math.inf, math.inf, 0)][0]) == 1 assert len(graph.graph[('c', 'c', 0, math.inf, math.inf, 0)][0]) == 0 # Verify that vertice list of contact nodes contains vertices to correct # terminal nodes assert ('a', 'a', 0, math.inf, math.inf, 0) in graph.graph[id1][1] assert ('b', 'b', 0, math.inf, math.inf, 0) in graph.graph[id1][0] assert ('b', 'b', 0, math.inf, math.inf, 0) in graph.graph[id2][1] assert ('c', 'c', 0, math.inf, math.inf, 0) in graph.graph[id2][0] assert ('a', 'a', 0, math.inf, math.inf, 0) in graph.graph[id3][1] assert ('c', 'c', 0, math.inf, math.inf, 0) in graph.graph[id3][0]
def test_load_route_list(): # Create contact plan object cp = ContactPlan(1, 42) # Check if exception is thrown if file does not exist with pytest.raises(FileNotFoundError): cp = ContactPlan(1, 42, 'tests/resources/not_existing_file.json') # Check if exception is thrown if invalid file is loaded with pytest.raises(ValidationError): cp = ContactPlan(1, 42, 'tests/resources/tvg_invalid_file.json') # Load a valid contact plan from the file cp = ContactPlan(1, 42, 'tests/resources/tvg_valid_file.json') assert ['node1', 'node2', 'node3'] == cp.plan['nodes'] assert ('node1', 'node2', 0, 10000, 1, 42) in cp.plan['contacts'] assert ('node2', 'node1', 0, 10000, 1, 42) in cp.plan['contacts'] assert ('node1', 'node2', 20000, 30000, 1, 42) in cp.plan['contacts'] assert ('node2', 'node1', 20000, 30000, 1, 42) in cp.plan['contacts'] assert ('node2', 'node3', 30000, 40000, 1, 42) in cp.plan['contacts'] assert ('node3', 'node2', 30000, 40000, 1, 42) in cp.plan['contacts'] # Load a valid contact plan with custom datarate and delay from the file cp2 = ContactPlan(1, 100, 'tests/resources/tvg_valid_file.json') assert ['node1', 'node2', 'node3'] == cp2.plan['nodes'] assert ('node1', 'node2', 0, 10000, 1, 100) in cp2.plan['contacts'] assert ('node2', 'node1', 0, 10000, 1, 100) in cp2.plan['contacts'] assert ('node1', 'node2', 20000, 30000, 1, 100) in cp2.plan['contacts'] assert ('node2', 'node1', 20000, 30000, 1, 100) in cp2.plan['contacts'] assert ('node2', 'node3', 30000, 40000, 1, 100) in cp2.plan['contacts'] assert ('node3', 'node2', 30000, 40000, 1, 100) in cp2.plan['contacts'] # Load a valid contact plan with custom datarate and delay from the file cp3 = ContactPlan(1, 42, 'tests/resources/03_tvg.json') assert 'NANOSATC-BR1' in cp3.plan['nodes'] assert 'gs0' in cp3.plan['nodes'] assert 'gs1' in cp3.plan['nodes']
def test_add_contact(): # Create contact plan object cp = ContactPlan(1000.1, 42.42) # Add contact to cp object cp.add_contact('node1', 'node2', 0.0, 12.2) # Verify that the two contacts (with the default datarate and default delay) were added properly assert ('node1', 'node2', 0.0, 12.2, 1000.1, 42.42) in cp.plan['contacts'] assert ('node2', 'node1', 0.0, 12.2, 1000.1, 42.42) in cp.plan['contacts'] assert len(cp.plan['contacts']) == 2 # Add unidirectional contact cp.add_contact('node3', 'node4', 0.1, 13.4, bidirectional=False) # Verify that the one contact was added properly assert ('node3', 'node4', 0.1, 13.4, 1000.1, 42.42) in cp.plan['contacts'] assert len(cp.plan['contacts']) == 3 # Use specific values for datarate and delay cp.add_contact('node1', 'node2', 0.0, 12.2, delay=4.2) cp.add_contact('node1', 'node2', 0.0, 12.2, datarate=1004.2) cp.add_contact('node1', 'node2', 0.0, 12.2, delay=12.4, datarate=1004.2) cp.add_contact('node5', 'node6', 0.0, 12.2, delay=4.2, bidirectional=False) # Check that the added contacts are part of the cp assert ('node1', 'node2', 0.0, 12.2, 1000.1, 42.42) in cp.plan['contacts'] assert ('node2', 'node1', 0.0, 12.2, 1000.1, 42.42) in cp.plan['contacts'] assert ('node1', 'node2', 0.0, 12.2, 1004.2, 42.42) in cp.plan['contacts'] assert ('node2', 'node1', 0.0, 12.2, 1004.2, 42.42) in cp.plan['contacts'] assert ('node5', 'node6', 0.0, 12.2, 1000.1, 4.2) in cp.plan['contacts'] assert ('node6', 'node5', 0.0, 12.2, 1000.1, 4.2) not in cp.plan['contacts'] # Check if all nodes were properly added to the contactplan node list assert ['node1', 'node2', 'node3', 'node4', 'node5', 'node6'] == cp.plan['nodes']
def test_cgr_base_no_route(mod): # First, create an contact plan that is then converted to the contact # graph representation and later processed by cgr() # The following topology is tested in this test case: # +---+ +---+ +---+ +---+ # | 1 +---------+ 2 +---------+ 3 +---------+ 4 | # +---+ 35:40 +---+ 20:40 +---+ 20:25 +---+ contact_plan = ContactPlan(1000, 0) contact_plan.add_contact('node1', 'node2', 35, 40) contact_plan.add_contact('node2', 'node3', 20, 40) contact_plan.add_contact('node3', 'node4', 20, 25) # Generate contact graph representation contact_graph = ContactGraph(contact_plan) # Route bundle from node1 to node 8 with size 1 and no deadline bundle = Packet('node1', 'node4', 1, math.inf) # Create empty route_list dictionary so route list for destination will be # regenerated route_list = dict() # Create contact list object contact_list = dict() # Create limbo list limbo = list() # Create Simulation Environment (dummy, will not be run) env = QSim() contact_list[('node1', 'node2', 35, 40, 1000, 0)] = Contact( 35, 40, 1000, 'node1', 'node2', debug=True) contact_list[('node2', 'node3', 20, 40, 1000, 0)] = Contact( 20, 40, 1000, 'node2', 'node3', debug=True) contact_list[('node3', 'node4', 20, 25, 1000, 0)] = Contact( 20, 25, 1000, 'node3', 'node4', debug=True) contact_list[('node1', 'node1', 0, math.inf, 1000, 0)] = Contact( 0, math.inf, 1000, 'node1', 'node1', debug=True) # Add dummy simulator to the contacts dummy = DummySimulator() contact_list[('node1', 'node2', 35, 40, 1000, 0)].register_simulator(dummy) contact_list[('node2', 'node3', 20, 40, 1000, 0)].register_simulator(dummy) contact_list[('node3', 'node4', 20, 25, 1000, 0)].register_simulator(dummy) contact_list[('node1', 'node1', 0, math.inf, 1000, 0)] \ .register_simulator(dummy) # Now run cgr for the bundle (with current time set to 0) mod.cgr(bundle, 'node1', contact_graph, route_list, contact_list, 0, limbo) # Make sure that the bundle is enqueue for the correct contact assert len(limbo) == 1 assert len(contact_list[('node1', 'node2', 35, 40, 1000, 0)] \ .packet_queue) == 0 assert len(contact_list[('node2', 'node3', 20, 40, 1000, 0)] \ .packet_queue) == 0 assert len(contact_list[('node3', 'node4', 20, 25, 1000, 0)] \ .packet_queue) == 0 assert len(contact_list[('node1', 'node1', 0, math.inf, 1000, 0)] \ .packet_queue) == 0