def test_DuplicateEntry_exception_raised_when_connecting_already_connected_port_to_a_resource(self): # GIVEN the following mesh # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 |-------->| p1 | | # |______|______| |______|______| # # # [ Resource X ] # m = Mesh() m.add_component('A', needs_ports=['n1']) m.add_component('B', provides_ports=['p1']) m.add_resource('Resource X') m.add_connection('A', 'n1', 'B', 'p1') # WHEN attempting to create the following invalid connections # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 |----+----->| p1 | | # |______|______| | |______|______| # | # INVALID # | # | # +----->[ Resource X ] # # # THEN an InvalidConnection exception is raised self.assertRaises(InvalidConnection, m.add_connection_to_resource, 'A', 'n1', 'Resource X')
def test_DuplicateEntry_exception_raised_when_adding_provides_port_with_same_name(self): # GIVEN a Mesh with existing components that has needs and provides m = Mesh() m.add_component('Component A', needs_ports=['needs 1'], provides_ports=['provides 1']) # WHEN we attempt to add an existing provides port to the component # THEN a DuplicateEntry exception is raised self.assertRaises(DuplicateEntry, m.add_provides_port, 'Component A', 'provides 1')
def test_DuplicateEntry_exception_raised_when_adding_components_with_same_name(self): # GIVEN a Mesh with existing components m = Mesh() m.add_component('Component A') m.add_component('Component Z') # WHEN we attempt to add a component with the same name # THEN a DuplicateEntry exception is raised self.assertRaises(DuplicateEntry, m.add_component, 'Component A')
def test_custom_filters_can_be_injected_into_the_template_renderer(self): # GIVEN an arbitrary mesh m = Mesh() m.add_component('My component') m.add_component('Another component') # WHEN it is rendered using a custom filter template = '{% for c in components %}{{c.name|my_filter}};{% endfor %}' filters = {'my_filter': lambda s: s.replace('o', '0')} out = render(m, template, custom_filters=filters) # THEN the output reflects the rendered mesh with the filtes applied self.assertEqual('My c0mp0nent;An0ther c0mp0nent;', out)
def test_added_component_can_be_retrieved_from_mesh(self): # GIVEN a new Mesh instance m = Mesh() # WHEN I add a component m.add_component('Component A') # THEN that component is represented in the output self.assertEqual({ 'components': [ {'name': 'Component A', 'needs_ports': [], 'provides_ports': []}, ], 'resources': [], 'connections': [], }, m.as_dict())
def test_InvalidComponent_exception_raised_when_highlighting_unknown_component(self): # GIVEN a mesh with the following component and resource # # _____________ # | A | # |-------------| # | | n1 | [ Resource X ] # |______|______| # m = Mesh() m.add_component('A', needs_ports=['n1']) m.add_resource('Resource X') # WHEN unknown component Y # THEN an InvalidComponent exception is raised self.assertRaises(InvalidComponent, m.highlight_component, 'Y')
def test_InvalidResource_exception_raised_when_creating_connections_to_resource_that_does_not_exist(self): # GIVEN a mesh with the following component and resource # # _____________ # | A | # |-------------| # | | n1 | [ Resource X ] # |______|______| # m = Mesh() m.add_component('A', needs_ports=['n1']) m.add_resource('Resource X') # WHEN creating a component between A:n1 and Resource P # THEN an InvalidResource exception is raised self.assertRaises(InvalidResource, m.add_connection_to_resource, 'A', 'n1', 'Resource P')
def test_InvalidPort_exception_raised_when_creating_connections_to_resource_with_invalid_consumer_port(self): # GIVEN a mesh with the following component and resource # # _____________ # | A | # |-------------| # | | n1 | [ Resource X ] # |______|______| # m = Mesh() m.add_component('A', needs_ports=['n1']) m.add_resource('Resource X') # WHEN creating a component between A:nX and Resource X # THEN an InvalidPort exception is raised self.assertRaises(InvalidPort, m.add_connection_to_resource, 'A', 'nX', 'Resource X')
def test_InvalidPort_exception_raised_when_creating_connections_with_invalid_producer_port(self): # GIVEN the following components # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 | | p1 | | # |______|______| |______|______| # m = Mesh() m.add_component('A', needs_ports=['n1']) m.add_component('B', provides_ports=['p1']) # WHEN creating a component between A:n1 and B:n1 # THEN an InvalidPort exception is raised self.assertRaises(InvalidPort, m.add_connection, 'A', 'n1', 'B', 'n1')
def test_components_are_returned_in_the_order_they_were_added(self): # GIVEN a new Mesh instance m = Mesh() # WHEN I add several component m.add_component('Component A') m.add_component('Component Z') m.add_component('Component M') # THEN that component are presented in the order they were added self.assertEqual({ 'components': [ {'name': 'Component A', 'needs_ports': [], 'provides_ports': []}, {'name': 'Component Z', 'needs_ports': [], 'provides_ports': []}, {'name': 'Component M', 'needs_ports': [], 'provides_ports': []}, ], 'resources': [], 'connections': [], }, m.as_dict())
def test_adding_provides_port_when_components_are_created(self): # GIVEN a new Mesh instance m = Mesh() # WHEN I add a component with provides ports m.add_component('Component A', provides_ports=['provides 1', 'provides 2']) # THEN the provides ports are represented in the output self.assertEqual({ 'components': [ { 'name': 'Component A', 'needs_ports': [], 'provides_ports': ['provides 1', 'provides 2'], }, ], 'resources': [], 'connections': [], }, m.as_dict())
def test_resource_can_be_highlighted(self): # GIVEN the following mesh # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 |-------->| p1 | n2 |--------->[ Resource X ] # |______|______| |______|______| # # m = Mesh() m.add_component('A', needs_ports=['n1']) m.add_component('B', needs_ports=['n2'], provides_ports=['p1']) m.add_resource('Resource X') m.add_connection('A', 'n1', 'B', 'p1') m.add_connection_to_resource('B', 'n2', 'Resource X') # WHEN Resource X is highlighted m.highlight_resource('Resource X') # THEN this is reflected in the dict representation self.assertEqual({ 'components': [ {'name': 'A', 'needs_ports': ['n1'], 'provides_ports': []}, {'name': 'B', 'needs_ports': ['n2'], 'provides_ports': ['p1']} ], 'resources': ['Resource X'], 'highlighted_resources': ['Resource X'], 'connections': [ { 'consumer_component': 'A', 'consumer_port': 'n1', 'producer_component': 'B', 'producer_port': 'p1', }, { 'consumer_component': 'B', 'consumer_port': 'n2', 'resource': 'Resource X', }, ], }, m.as_dict())
def test_adding_needs_port_to_existing_component(self): # GIVEN a Mesh with existing component m = Mesh() m.add_component('Component A') # WHEN we add a needs port to the component m.add_needs_port('Component A', 'needs 1') # THEN the needs port is represented in the output self.assertEqual({ 'components': [ { 'name': 'Component A', 'needs_ports': ['needs 1'], 'provides_ports': [] }, ], 'resources': [], 'connections': [], }, m.as_dict())
def test_InvalidResource_exception_raised_when_highlighting_unknown_resource(self): # GIVEN a mesh with the following component and resource # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 |-------->| p1 | n2 |--------->[ Resource X ] # |______|______| |______|______| # # m = Mesh() m.add_component('A', needs_ports=['n1']) m.add_component('B', needs_ports=['n2'], provides_ports=['p1']) m.add_resource('Resource X') m.add_connection('A', 'n1', 'B', 'p1') m.add_connection_to_resource('B', 'n2', 'Resource X') # WHEN unknown resource is highlighted # THEN an InvalidResource exception is raised self.assertRaises(InvalidResource, m.highlight_resource, 'Resource K')
def test_adding_connection_between_two_ports(self): # GIVEN the following components # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 | | p1 | | # |______|______| |______|______| # m = Mesh() m.add_component('A', needs_ports=['n1']) m.add_component('B', provides_ports=['p1']) # WHEN we add a connection between A:n1 and B:p1 m.add_connection('A', 'n1', 'B', 'p1') # THEN we get the following mesh representation # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 | ---> | p1 | | # |______|______| |______|______| # self.assertEqual({ 'components': [ {'name': 'A', 'needs_ports': ['n1'], 'provides_ports': []}, {'name': 'B', 'needs_ports': [], 'provides_ports': ['p1']}, ], 'resources': [], 'connections': [ { 'consumer_component': 'A', 'consumer_port': 'n1', 'producer_component': 'B', 'producer_port': 'p1', }, ], }, m.as_dict())
def test_ports_are_returned_in_the_order_they_were_added(self): # GIVEN a new Mesh instance m = Mesh() # WHEN I add a component with ports in a specific order m.add_component('Component A', needs_ports=['needs 8', 'needs 7'], provides_ports=['provides 8', 'provides 7']) m.add_needs_port('Component A', 'needs 1') m.add_provides_port('Component A', 'provides 1') # THEN the ports are represented in the output in the same order they were entered self.assertEqual({ 'components': [ { 'name': 'Component A', 'needs_ports': ['needs 8', 'needs 7', 'needs 1'], 'provides_ports': ['provides 8', 'provides 7', 'provides 1'], }, ], 'resources': [], 'connections': [], }, m.as_dict())
def test_adding_connection_from_port_to_edge_resource(self): # GIVEN a mesh with the following component and resource # # _____________ # | A | # |-------------| # | | n1 | [ Resource X ] # |______|______| # m = Mesh() m.add_component('A', needs_ports=['n1']) m.add_resource('Resource X') # WHEN we connect A:n1 to Resource X m.add_connection_to_resource('A', 'n1', 'Resource X') # THEN we get the following mesh representation # # _____________ # | A | # |-------------| # | | n1 |--------->[ Resource X ] # |______|______| # self.assertEqual({ 'components': [ {'name': 'A', 'needs_ports': ['n1'], 'provides_ports': []}, ], 'resources': ['Resource X'], 'connections': [ { 'consumer_component': 'A', 'consumer_port': 'n1', 'resource': 'Resource X', }, ], }, m.as_dict())
def test_DuplicateEntry_exception_raised_when_assigning_multiple_connections_to_the_same_needs_port(self): # GIVEN the following mesh # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 |-------->| p1 | | # |______|______| |______|______| # # _____________ # | D | # |-------------| # | pX | | # |______|______| # m = Mesh() m.add_component('A', needs_ports=['n1']) m.add_component('B', provides_ports=['p1']) m.add_component('D', provides_ports=['pX']) m.add_connection('A', 'n1', 'B', 'p1') # WHEN attempting to create the following invalid connections # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 |----+----->| p1 | | # |______|______| | |______|______| # | # INVALID _____________ # | | D | # | |-------------| # +----->| pX | | # |______|______| # # THEN an InvalidConnection exception is raised self.assertRaises(InvalidConnection, m.add_connection, 'A', 'n1', 'D', 'pX')
def test_renderering_the_mesh_as_a_dot_file_to_be_parsed_by_graphviz(self): """ NOTE: This is a very artificial test. We've already tested the mesh building and the rendered in the tests above. All we're doing here is checking that the DOT template can be parsed an applied. Inspecting the output is non trivial and perhaps not worth the while? """ # GIVEN the following mesh # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 |----------->| p1 | | # | |______| |______| | # | | n2 |-----+ +-->| p2 | | # |______|______| | | |______|______| # +- | -+ # | | # _____________ | | _____________ # | C | | | | D | # |-------------| | | |-------------| # | | nX |--+ +---->| pX | | # |______|______| |______|______| # m = Mesh() m.add_component('A', needs_ports=['n1', 'n2']) m.add_component('B', provides_ports=['p1', 'p2']) m.add_component('C', needs_ports=['nX']) m.add_component('D', provides_ports=['pX']) m.add_connection('A', 'n1', 'B', 'p1') m.add_connection('A', 'n2', 'D', 'pX') m.add_connection('C', 'nX', 'B', 'p2') # WHEN the dot representation is rendered # THEN the world does not come to an end ("WHAT??" you say? See docstring above) render_mesh_as_dot(m)
def test_textual_representation_can_be_rendered_for_a_populated_mesh(self): # GIVEN the following mesh # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 |----------->| p1 | | # | |______| |______| nY |----->[ Resource Y ] # | | n2 |-----+ +-->| p2 | | # |______|______| | | |______|______| # +- | -+ # | | # _____________ | | _____________ # | C | | | | D | # |-------------| | | |-------------| # | | nX |--+ +---->| pX | nX |------>[ Resource X ] # |______|______| |______|______| # m = Mesh() m.add_component('A', needs_ports=['n1', 'n2']) m.add_component('B', provides_ports=['p1', 'p2'], needs_ports=['nY']) m.add_component('C', needs_ports=['nX']) m.add_component('D', provides_ports=['pX'], needs_ports=['nX']) m.add_resource('Resource X') m.add_resource('Resource Y') m.add_connection('A', 'n1', 'B', 'p1') m.add_connection('A', 'n2', 'D', 'pX') m.add_connection('C', 'nX', 'B', 'p2') m.add_connection_to_resource('D', 'nX', 'Resource X') m.add_connection_to_resource('B', 'nY', 'Resource Y') # WHEN the textual representation is rendered out = render(m, self.JSON_TEMPLATE) # THEN the rendered output reflects that of the mesh out_data = json.loads(out) self.assertEqual({ 'components': [ {'name': 'A', 'needs_ports': ['n1', 'n2'], 'provides_ports': []}, {'name': 'B', 'needs_ports': ['nY'], 'provides_ports': ['p1', 'p2']}, {'name': 'C', 'needs_ports': ['nX'], 'provides_ports': []}, {'name': 'D', 'needs_ports': ['nX'], 'provides_ports': ['pX']}, ], 'resources': ['Resource X', 'Resource Y'], 'connections': [ { 'consumer_component': 'A', 'consumer_port': 'n1', 'producer_component': 'B', 'producer_port': 'p1', }, { 'consumer_component': 'A', 'consumer_port': 'n2', 'producer_component': 'D', 'producer_port': 'pX', }, { 'consumer_component': 'C', 'consumer_port': 'nX', 'producer_component': 'B', 'producer_port': 'p2', }, { 'consumer_component': 'D', 'consumer_port': 'nX', 'resource': 'Resource X', }, { 'consumer_component': 'B', 'consumer_port': 'nY', 'resource': 'Resource Y', }, ], }, out_data)
def test_multiple_connections_across_components_with_multiple_ports(self): # GIVEN the following components # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 | | p1 | | # | |______| |______| | # | | n2 | | p2 | | # |______|______| |______|______| # # # _____________ _____________ # | C | | D | # |-------------| |-------------| # | | nX | | pX | | # |______|______| |______|______| # m = Mesh() m.add_component('A', needs_ports=['n1', 'n2']) m.add_component('B', provides_ports=['p1', 'p2']) m.add_component('C', needs_ports=['nX']) m.add_component('D', provides_ports=['pX']) # WHEN we add a connection between A:n1 and B:p1 # WHEN we add a connection between C:nX and B:p1 m.add_connection('A', 'n1', 'B', 'p1') m.add_connection('A', 'n2', 'D', 'pX') m.add_connection('C', 'nX', 'B', 'p2') # THEN we get the following mesh representation # # _____________ _____________ # | A | | B | # |-------------| |-------------| # | | n1 |----------->| p1 | | # | |______| |______| | # | | n2 |-----+ +-->| p2 | | # |______|______| | | |______|______| # +- | -+ # | | # _____________ | | _____________ # | C | | | | D | # |-------------| | | |-------------| # | | nX |--+ +---->| pX | | # |______|______| |______|______| # self.assertEqual({ 'components': [ {'name': 'A', 'needs_ports': ['n1', 'n2'], 'provides_ports': []}, {'name': 'B', 'needs_ports': [], 'provides_ports': ['p1', 'p2']}, {'name': 'C', 'needs_ports': ['nX'], 'provides_ports': []}, {'name': 'D', 'needs_ports': [], 'provides_ports': ['pX']}, ], 'resources': [], 'connections': [ { 'consumer_component': 'A', 'consumer_port': 'n1', 'producer_component': 'B', 'producer_port': 'p1', }, { 'consumer_component': 'A', 'consumer_port': 'n2', 'producer_component': 'D', 'producer_port': 'pX', }, { 'consumer_component': 'C', 'consumer_port': 'nX', 'producer_component': 'B', 'producer_port': 'p2', }, ], }, m.as_dict())