diff options
Diffstat (limited to 'src/python/grpcio_tests/tests/unit/framework/interfaces/links')
3 files changed, 0 insertions, 524 deletions
diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/__init__.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/links/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_cases.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_cases.py deleted file mode 100644 index 608e64119e..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_cases.py +++ /dev/null @@ -1,327 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Tests of the links interface of RPC Framework.""" - -# unittest is referenced from specification in this module. -import abc -import unittest # pylint: disable=unused-import - -import six - -from grpc.framework.interfaces.links import links -from tests.unit.framework.common import test_constants -from tests.unit.framework.interfaces.links import test_utilities - - -def at_least_n_payloads_received_predicate(n): - def predicate(ticket_sequence): - payload_count = 0 - for ticket in ticket_sequence: - if ticket.payload is not None: - payload_count += 1 - if n <= payload_count: - return True - else: - return False - return predicate - - -def terminated(ticket_sequence): - return ticket_sequence and ticket_sequence[-1].termination is not None - -_TRANSMISSION_GROUP = 'test.Group' -_TRANSMISSION_METHOD = 'TestMethod' - - -class TransmissionTest(six.with_metaclass(abc.ABCMeta)): - """Tests ticket transmission between two connected links. - - This class must be mixed into a unittest.TestCase that implements the abstract - methods it provides. - """ - - # This is a unittest.TestCase mix-in. - # pylint: disable=invalid-name - - @abc.abstractmethod - def create_transmitting_links(self): - """Creates two connected links for use in this test. - - Returns: - Two links.Links, the first of which will be used on the invocation side - of RPCs and the second of which will be used on the service side of - RPCs. - """ - raise NotImplementedError() - - @abc.abstractmethod - def destroy_transmitting_links(self, invocation_side_link, service_side_link): - """Destroys the two connected links created for this test. - - - Args: - invocation_side_link: The link used on the invocation side of RPCs in - this test. - service_side_link: The link used on the service side of RPCs in this - test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_invocation_initial_metadata(self): - """Creates a value for use as invocation-side initial metadata. - - Returns: - A metadata value appropriate for use as invocation-side initial metadata - or None if invocation-side initial metadata transmission is not - supported by the links under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_invocation_terminal_metadata(self): - """Creates a value for use as invocation-side terminal metadata. - - Returns: - A metadata value appropriate for use as invocation-side terminal - metadata or None if invocation-side terminal metadata transmission is - not supported by the links under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_service_initial_metadata(self): - """Creates a value for use as service-side initial metadata. - - Returns: - A metadata value appropriate for use as service-side initial metadata or - None if service-side initial metadata transmission is not supported by - the links under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_service_terminal_metadata(self): - """Creates a value for use as service-side terminal metadata. - - Returns: - A metadata value appropriate for use as service-side terminal metadata or - None if service-side terminal metadata transmission is not supported by - the links under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_invocation_completion(self): - """Creates values for use as invocation-side code and message. - - Returns: - An invocation-side code value and an invocation-side message value. - Either or both may be None if invocation-side code and/or - invocation-side message transmission is not supported by the links - under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_service_completion(self): - """Creates values for use as service-side code and message. - - Returns: - A service-side code value and a service-side message value. Either or - both may be None if service-side code and/or service-side message - transmission is not supported by the links under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def assertMetadataTransmitted(self, original_metadata, transmitted_metadata): - """Asserts that transmitted_metadata contains original_metadata. - - Args: - original_metadata: A metadata object used in this test. - transmitted_metadata: A metadata object obtained after transmission - through the system under test. - - Raises: - AssertionError: if the transmitted_metadata object does not contain - original_metadata. - """ - raise NotImplementedError() - - def group_and_method(self): - """Returns the group and method used in this test case. - - Returns: - A pair of the group and method used in this test case. - """ - return _TRANSMISSION_GROUP, _TRANSMISSION_METHOD - - def serialize_request(self, request): - """Serializes a request value used in this test case. - - Args: - request: A request value created by this test case. - - Returns: - A bytestring that is the serialization of the given request. - """ - return request - - def deserialize_request(self, serialized_request): - """Deserializes a request value used in this test case. - - Args: - serialized_request: A bytestring that is the serialization of some request - used in this test case. - - Returns: - The request value encoded by the given bytestring. - """ - return serialized_request - - def serialize_response(self, response): - """Serializes a response value used in this test case. - - Args: - response: A response value created by this test case. - - Returns: - A bytestring that is the serialization of the given response. - """ - return response - - def deserialize_response(self, serialized_response): - """Deserializes a response value used in this test case. - - Args: - serialized_response: A bytestring that is the serialization of some - response used in this test case. - - Returns: - The response value encoded by the given bytestring. - """ - return serialized_response - - def _assert_is_valid_metadata_payload_sequence( - self, ticket_sequence, payloads, initial_metadata, terminal_metadata): - initial_metadata_seen = False - seen_payloads = [] - terminal_metadata_seen = False - - for ticket in ticket_sequence: - if ticket.initial_metadata is not None: - self.assertFalse(initial_metadata_seen) - self.assertFalse(seen_payloads) - self.assertFalse(terminal_metadata_seen) - self.assertMetadataTransmitted(initial_metadata, ticket.initial_metadata) - initial_metadata_seen = True - - if ticket.payload is not None: - self.assertFalse(terminal_metadata_seen) - seen_payloads.append(ticket.payload) - - if ticket.terminal_metadata is not None: - self.assertFalse(terminal_metadata_seen) - self.assertMetadataTransmitted(terminal_metadata, ticket.terminal_metadata) - terminal_metadata_seen = True - self.assertSequenceEqual(payloads, seen_payloads) - - def _assert_is_valid_invocation_sequence( - self, ticket_sequence, group, method, payloads, initial_metadata, - terminal_metadata, termination): - self.assertLess(0, len(ticket_sequence)) - self.assertEqual(group, ticket_sequence[0].group) - self.assertEqual(method, ticket_sequence[0].method) - self._assert_is_valid_metadata_payload_sequence( - ticket_sequence, payloads, initial_metadata, terminal_metadata) - self.assertIs(termination, ticket_sequence[-1].termination) - - def _assert_is_valid_service_sequence( - self, ticket_sequence, payloads, initial_metadata, terminal_metadata, - code, message, termination): - self.assertLess(0, len(ticket_sequence)) - self._assert_is_valid_metadata_payload_sequence( - ticket_sequence, payloads, initial_metadata, terminal_metadata) - self.assertEqual(code, ticket_sequence[-1].code) - self.assertEqual(message, ticket_sequence[-1].message) - self.assertIs(termination, ticket_sequence[-1].termination) - - def setUp(self): - self._invocation_link, self._service_link = self.create_transmitting_links() - self._invocation_mate = test_utilities.RecordingLink() - self._service_mate = test_utilities.RecordingLink() - self._invocation_link.join_link(self._invocation_mate) - self._service_link.join_link(self._service_mate) - - def tearDown(self): - self.destroy_transmitting_links(self._invocation_link, self._service_link) - - def testSimplestRoundTrip(self): - """Tests transmission of one ticket in each direction.""" - invocation_operation_id = object() - invocation_payload = b'\x07' * 1023 - timeout = test_constants.LONG_TIMEOUT - invocation_initial_metadata = self.create_invocation_initial_metadata() - invocation_terminal_metadata = self.create_invocation_terminal_metadata() - invocation_code, invocation_message = self.create_invocation_completion() - service_payload = b'\x08' * 1025 - service_initial_metadata = self.create_service_initial_metadata() - service_terminal_metadata = self.create_service_terminal_metadata() - service_code, service_message = self.create_service_completion() - - original_invocation_ticket = links.Ticket( - invocation_operation_id, 0, _TRANSMISSION_GROUP, _TRANSMISSION_METHOD, - links.Ticket.Subscription.FULL, timeout, 0, invocation_initial_metadata, - invocation_payload, invocation_terminal_metadata, invocation_code, - invocation_message, links.Ticket.Termination.COMPLETION, None) - self._invocation_link.accept_ticket(original_invocation_ticket) - - self._service_mate.block_until_tickets_satisfy( - at_least_n_payloads_received_predicate(1)) - service_operation_id = self._service_mate.tickets()[0].operation_id - - self._service_mate.block_until_tickets_satisfy(terminated) - self._assert_is_valid_invocation_sequence( - self._service_mate.tickets(), _TRANSMISSION_GROUP, _TRANSMISSION_METHOD, - (invocation_payload,), invocation_initial_metadata, - invocation_terminal_metadata, links.Ticket.Termination.COMPLETION) - - original_service_ticket = links.Ticket( - service_operation_id, 0, None, None, links.Ticket.Subscription.FULL, - timeout, 0, service_initial_metadata, service_payload, - service_terminal_metadata, service_code, service_message, - links.Ticket.Termination.COMPLETION, None) - self._service_link.accept_ticket(original_service_ticket) - self._invocation_mate.block_until_tickets_satisfy(terminated) - self._assert_is_valid_service_sequence( - self._invocation_mate.tickets(), (service_payload,), - service_initial_metadata, service_terminal_metadata, service_code, - service_message, links.Ticket.Termination.COMPLETION) diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_utilities.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_utilities.py deleted file mode 100644 index 39c7f2fc63..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_utilities.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior appropriate for use in tests.""" - -import logging -import threading -import time - -from grpc.framework.interfaces.links import links -from grpc.framework.interfaces.links import utilities - -# A more-or-less arbitrary limit on the length of raw data values to be logged. -_UNCOMFORTABLY_LONG = 48 - - -def _safe_for_log_ticket(ticket): - """Creates a safe-for-printing-to-the-log ticket for a given ticket. - - Args: - ticket: Any links.Ticket. - - Returns: - A links.Ticket that is as much as can be equal to the given ticket but - possibly features values like the string "<payload of length 972321>" in - place of the actual values of the given ticket. - """ - if isinstance(ticket.payload, (basestring,)): - payload_length = len(ticket.payload) - else: - payload_length = -1 - if payload_length < _UNCOMFORTABLY_LONG: - return ticket - else: - return links.Ticket( - ticket.operation_id, ticket.sequence_number, - ticket.group, ticket.method, ticket.subscription, ticket.timeout, - ticket.allowance, ticket.initial_metadata, - '<payload of length {}>'.format(payload_length), - ticket.terminal_metadata, ticket.code, ticket.message, - ticket.termination, None) - - -class RecordingLink(links.Link): - """A Link that records every ticket passed to it.""" - - def __init__(self): - self._condition = threading.Condition() - self._tickets = [] - - def accept_ticket(self, ticket): - with self._condition: - self._tickets.append(ticket) - self._condition.notify_all() - - def join_link(self, link): - pass - - def block_until_tickets_satisfy(self, predicate): - """Blocks until the received tickets satisfy the given predicate. - - Args: - predicate: A callable that takes a sequence of tickets and returns a - boolean value. - """ - with self._condition: - while not predicate(self._tickets): - self._condition.wait() - - def tickets(self): - """Returns a copy of the list of all tickets received by this Link.""" - with self._condition: - return tuple(self._tickets) - - -class _Pipe(object): - """A conduit that logs all tickets passed through it.""" - - def __init__(self, name): - self._lock = threading.Lock() - self._name = name - self._left_mate = utilities.NULL_LINK - self._right_mate = utilities.NULL_LINK - - def accept_left_to_right_ticket(self, ticket): - with self._lock: - logging.warning( - '%s: moving left to right through %s: %s', time.time(), self._name, - _safe_for_log_ticket(ticket)) - try: - self._right_mate.accept_ticket(ticket) - except Exception as e: # pylint: disable=broad-except - logging.exception(e) - - def accept_right_to_left_ticket(self, ticket): - with self._lock: - logging.warning( - '%s: moving right to left through %s: %s', time.time(), self._name, - _safe_for_log_ticket(ticket)) - try: - self._left_mate.accept_ticket(ticket) - except Exception as e: # pylint: disable=broad-except - logging.exception(e) - - def join_left_mate(self, left_mate): - with self._lock: - self._left_mate = utilities.NULL_LINK if left_mate is None else left_mate - - def join_right_mate(self, right_mate): - with self._lock: - self._right_mate = ( - utilities.NULL_LINK if right_mate is None else right_mate) - - -class _Facade(links.Link): - - def __init__(self, accept, join): - self._accept = accept - self._join = join - - def accept_ticket(self, ticket): - self._accept(ticket) - - def join_link(self, link): - self._join(link) - - -def logging_links(name): - """Creates a conduit that logs all tickets passed through it. - - Args: - name: A name to use for the conduit to identify itself in logging output. - - Returns: - Two links.Links, the first of which is the "left" side of the conduit - and the second of which is the "right" side of the conduit. - """ - pipe = _Pipe(name) - left_facade = _Facade(pipe.accept_left_to_right_ticket, pipe.join_left_mate) - right_facade = _Facade(pipe.accept_right_to_left_ticket, pipe.join_right_mate) - return left_facade, right_facade |