def test_remove_contact_node(): graph = ContactGraph() identifier1 = ContactIdentifier(from_node='a', to_node='b', from_time=0.0, to_time=10.0, datarate=1000.0, delay=0.0) graph.add_contact_node(identifier1) identifier2 = ContactIdentifier(from_node='b', to_node='c', from_time=10.0, to_time=20.0, datarate=1000.0, delay=0.0) graph.add_contact_node(identifier2) assert len(graph.graph) == 2 identifier_false = ('a', 'b', 0.0, 10.0, 1000.0, 0.0) # Check if exception is thrown if invalid identifier is used with pytest.raises(ValueError): graph.remove_contact_node(identifier_false) assert len(graph.graph) == 2 graph.remove_contact_node(identifier2) # Assert that node was removed properly and both the successor and # predecessor lists are empty assert len(graph.graph) == 1 assert not graph.graph[identifier1][0] assert not graph.graph[identifier1][1]
def test_reinitialize(): graph = ContactGraph() identifier1 = ContactIdentifier(from_node='a', to_node='b', from_time=0.0, to_time=10.0, datarate=1000.0, delay=0.0) graph.add_contact_node(identifier1) identifier2 = ContactIdentifier(from_node='b', to_node='c', from_time=10.0, to_time=20.0, datarate=1000.0, delay=0.0) graph.add_contact_node(identifier2) assert len(graph.graph) == 2 graph.reinitialize() # Assert that all contacts related to 'b' were removed and the graph is # empty assert len(graph.graph) == 0
def test_create_empty_graph(): graph = ContactGraph() assert type(graph) == ContactGraph assert type(graph.graph) == OrderedDict assert not graph.graph
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 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_add_contact_node(): graph = ContactGraph() identifier = ('a', 'b', 0.0, 10.0, 1000.0, 0.0) # Check if exception is thrown if invalid identifier is used with pytest.raises(ValueError): graph.add_contact_node(identifier) identifier1 = ContactIdentifier(from_node='a', to_node='b', from_time=0.0, to_time=10.0, datarate=1000.0, delay=0.0) graph.add_contact_node(identifier1) assert len(graph.graph) == 1 identifier2 = ContactIdentifier(from_node='b', to_node='c', from_time=10.0, to_time=20.0, datarate=1000.0, delay=0.0) graph.add_contact_node(identifier2) identifier3 = ContactIdentifier(from_node='d', to_node='c', from_time=10.0, to_time=20.0, datarate=1000.0, delay=0.0) graph.add_contact_node(identifier3) # Check that the added nodes are properly connected # (predecessors and successors) assert len(graph.graph) == 3 assert identifier2 in graph.graph[identifier1][0] assert len(graph.graph[identifier1][0]) == 1 assert len(graph.graph[identifier1][1]) == 0 assert identifier1 in graph.graph[identifier2][1] assert len(graph.graph[identifier2][1]) == 1 assert len(graph.graph[identifier2][0]) == 0 assert len(graph.graph[identifier3][0]) == 0 assert len(graph.graph[identifier3][1]) == 0
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(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 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_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_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 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 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_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