Example #1
0
class ShadowPortArrayTest(TestCase):

    def setUp(self):
        self.array_a = PortArray()
        self.array_a.add_port('a_only')
        self.array_a.add_port('in_both')
        self.array_a.add_port('also_a_only')

        self.array_b = PortArray()
        self.array_b.add_port('b_only')
        self.array_b.add_port('in_both')

    def test_empty_shadow_port_array_can_be_created(self):
        shadow = ShadowPortArray([])
        self.assertEqual([], shadow.get_ports())

    def test_shadow_with_only_one_child(self):
        shadow = ShadowPortArray([self.array_b])
        self.assertItemsEqual(['b_only', 'in_both'], shadow.get_ports())

    def test_shadow_with_multiple_children(self):
        shadow = ShadowPortArray([self.array_a, self.array_b])
        self.assertItemsEqual(['a_only', 'also_a_only', 'b_only', 'in_both'], shadow.get_ports())

    def test_connecting_ports_via_shadow(self):
        shadow = ShadowPortArray([self.array_a, self.array_b])
        shadow.connect_port('in_both', lambda: 'both')
        shadow.connect_port('a_only', lambda: 'a')

        self.assertEqual('a', self.array_a.a_only())
        self.assertEqual('both', self.array_a.in_both())
        self.assertEqual('both', self.array_b.in_both())

        with self.assertRaisesRegexp(DisconnectedPort, 'Port "b_only" has not been connected'):
            self.array_b.b_only()

    def test_disconnecting_ports_via_shadow(self):
        shadow = ShadowPortArray([self.array_a, self.array_b])
        shadow.connect_port('in_both', lambda: 'both')
        shadow.connect_port('a_only', lambda: 'a')
        shadow.connect_port('b_only', lambda: 'b')

        shadow.disconnect_port('in_both')
        shadow.disconnect_port('b_only')

        with self.assertRaisesRegexp(DisconnectedPort, 'Port "in_both" has not been connected'):
            self.array_a.in_both()

        with self.assertRaisesRegexp(DisconnectedPort, 'Port "in_both" has not been connected'):
            self.array_b.in_both()

        with self.assertRaisesRegexp(DisconnectedPort, 'Port "b_only" has not been connected'):
            self.array_b.b_only()

        self.assertEqual('a', self.array_a.a_only())  # this should remain connected

    def test_raises_WiringError_when_connecting_port_to_non_callable(self):
        shadow = ShadowPortArray([self.array_a, self.array_b])
        with self.assertRaisesRegexp(WiringError, 'Cannot connect port to a non-callable object'):
            shadow.connect_port('in_both', None)

    def test_raise_UnknownPort_when_connecting_an_unknown_port(self):
        shadow = ShadowPortArray([self.array_a, self.array_b])
        with self.assertRaisesRegexp(UnknownPort, '"hello" is not a valid port'):
            shadow.connect_port('hello', lambda: 'hello')

    def test_raise_UnknownPort_when_disconnecting_an_unknown_port(self):
        shadow = ShadowPortArray([self.array_a, self.array_b])
        with self.assertRaisesRegexp(UnknownPort, '"hello" is not a valid port'):
            shadow.disconnect_port('hello')

    def test_shadow_does_not_inherit_ignored_ports(self):
        shadow = ShadowPortArray([self.array_a, self.array_b], ignore_ports=['in_both', 'also_a_only', 'fluff'])
        self.assertItemsEqual(['a_only', 'b_only'], shadow.get_ports())
Example #2
0
class PortArrayTests(TestCase):
    def setUp(self):
        self.ports = PortArray()

    def test_empty_array_can_be_instantiated(self):
        self.assertEqual([], self.ports.get_ports())

    def test_adding_port(self):
        self.ports.add_port('hello')
        self.assertItemsEqual(['hello'], self.ports.get_ports())

        self.ports.add_port('world')
        self.assertItemsEqual(['hello', 'world'], self.ports.get_ports())

    def test_newly_added_port_raises_DisconnectedPort_when_called(self):
        self.ports.add_port('hello')
        with self.assertRaisesRegexp(DisconnectedPort, 'Port "hello" has not been connected'):
            self.ports.hello()

    def test_connecting_port_to_plain_function(self):

        def echo(s):
            return s.upper()

        self.ports.add_port('hello')
        self.ports.connect_port('hello', echo)
        self.assertEqual('YOLO', self.ports.hello('yolo'))

    def test_connecting_port_to_lambda_function(self):
        self.ports.add_port('hello')
        self.ports.connect_port('hello', lambda s: s.upper())
        self.assertEqual('YOLO', self.ports.hello('yolo'))

    def test_connecting_port_to_bound_method(self):

        class EchoChamber(object):
            def echo(self, s):
                return s.upper()

        self.ports.add_port('hello')
        self.ports.connect_port('hello', EchoChamber().echo)
        self.assertEqual('YOLO', self.ports.hello('yolo'))

    def test_connecting_port_to_static_method(self):

        class EchoChamber(object):
            @staticmethod
            def echo(s):
                return s.upper()

        self.ports.add_port('hello')
        self.ports.connect_port('hello', EchoChamber.echo)
        self.assertEqual('YOLO', self.ports.hello('yolo'))

    def test_connecting_port_to_class_method(self):

        class EchoChamber(object):
            @classmethod
            def echo(cls, s):
                return s.upper()

        self.ports.add_port('hello')
        self.ports.connect_port('hello', EchoChamber.echo)
        self.assertEqual('YOLO', self.ports.hello('yolo'))

    def test_connecting_port_to_callable_object(self):

        class EchoChamber(object):
            def __call__(self, s):
                return s.upper()

        self.ports.add_port('hello')
        self.ports.connect_port('hello', EchoChamber())
        self.assertEqual('YOLO', self.ports.hello('yolo'))

    def test_raises_WiringError_when_connecting_port_to_non_callable(self):
        self.ports.add_port('hello')
        with self.assertRaisesRegexp(WiringError, 'Cannot connect port to a non-callable object'):
            self.ports.connect_port('hello', None)

    def test_raises_UnknownPort_when_connecting_to_an_unknown_port(self):
        with self.assertRaisesRegexp(UnknownPort, '"hello" is not a valid port'):
            self.ports.connect_port('hello', lambda: None)

    def test_raises_InvalidPortName_when_port_name_does_not_match_constraints(self):
        self.assert_invalid_port_name_pattern('_starts_with_underscore')
        self.assert_invalid_port_name_pattern('has spaces')
        self.assert_invalid_port_name_pattern('9_does_not_start_with_lowercase_char')
        self.assert_invalid_port_name_pattern('A_does_not_start_with_lowercase_char')
        self.assert_invalid_port_name_pattern('not_!_alphanum')
        self.assert_invalid_port_name_pattern('no_-_dashes_please')

        # these should be fine
        self.ports.add_port('has_underscores')
        self.ports.add_port('has_UppErCaSe')
        self.ports.add_port('has_d1g1ts')

    def assert_invalid_port_name_pattern(self, port_name):
        expected_msg = '"{}" does not have required format for port names'.format(port_name)
        with self.assertRaisesRegexp(InvalidPortName, expected_msg):
            self.ports.add_port(port_name)

    def test_raises_InvalidPortName_when_reserved_words_used(self):
        self.assert_raises_when_port_name_is_reserved_word('add_port')
        self.assert_raises_when_port_name_is_reserved_word('get_ports')
        self.assert_raises_when_port_name_is_reserved_word('connect_port')
        self.assert_raises_when_port_name_is_reserved_word('get_needs')
        self.assert_raises_when_port_name_is_reserved_word('get_provides')

        # also pull in all attrs in case we miss something
        port_array_attrs = [a for a in dir(self.ports) if not a.startswith('_')]
        for name in port_array_attrs:
            self.assert_raises_when_port_name_is_reserved_word(name)

    def assert_raises_when_port_name_is_reserved_word(self, port_name):
        expected_msg = '"{}" is a reserved word and cannot be used as port name'.format(port_name)
        with self.assertRaisesRegexp(InvalidPortName, expected_msg):
            self.ports.add_port(port_name)

    def test_disconnect_port(self):
        self.ports.add_port('hello')
        self.ports.connect_port('hello', lambda: None)
        self.ports.disconnect_port('hello')

        with self.assertRaisesRegexp(DisconnectedPort, 'Port "hello" has not been connected'):
            self.ports.hello()

    def test_if_is_fine_to_disconnect_port_that_is_not_connected(self):
        self.ports.add_port('hello')
        self.ports.disconnect_port('hello')

        with self.assertRaisesRegexp(DisconnectedPort, 'Port "hello" has not been connected'):
            self.ports.hello()

    def test_raise_UnknownPort_when_disconnecting_an_unknown_port(self):
        with self.assertRaisesRegexp(UnknownPort, '"hello" is not a valid port'):
            self.ports.disconnect_port('hello')

    def test_replicating_port_array_results_in_array_with_disconnected_ports(self):
        self.ports.add_port('hello')
        self.ports.add_port('world')
        self.ports.connect_port('hello', lambda: None)

        new_ports = PortArray.replicate(self.ports)
        self.assertIsNot(new_ports, self.ports)
        self.assertItemsEqual(['hello', 'world'], new_ports.get_ports())

        # all ports should be disconnected
        with self.assertRaisesRegexp(DisconnectedPort, 'Port "hello" has not been connected'):
            new_ports.hello()
        with self.assertRaisesRegexp(DisconnectedPort, 'Port "world" has not been connected'):
            new_ports.world()

    def test_identification_of_disconnected_port(self):
        self.ports.add_port('hello')
        self.assertTrue(self.ports.is_disconnected_port('hello'))

        self.ports.connect_port('hello', lambda: None)
        self.assertFalse(self.ports.is_disconnected_port('hello'))

        self.ports.disconnect_port('hello')
        self.assertTrue(self.ports.is_disconnected_port('hello'))

    def test_identification_of_disconnected_port_raises_for_unknown_port(self):
        with self.assertRaisesRegexp(UnknownPort, '"boo" is not a valid port'):
            self.ports.is_disconnected_port('boo')