def test_in_order_messages_are_handled_in_order(self): """Test that messages received in order are handled in order.""" message_handling_order = [] message_handler = OrderedMessageHandler( subscriber=MockSubscriber(), subscription=self.mock_subscription, message_handlers={ "test": self._make_order_recording_message_handler(message_handling_order), "finish-test": lambda message: "This is the result.", }, ) with patch( "octue.cloud.pub_sub.service.OrderedMessageHandler._pull_message", new=MockMessagePuller( messages=[ {"type": "test", "message_number": 0}, {"type": "test", "message_number": 1}, {"type": "test", "message_number": 2}, {"type": "finish-test", "message_number": 3}, ] ).pull, ): result = message_handler.handle_messages() self.assertEqual(result, "This is the result.") self.assertEqual(message_handling_order, [0, 1, 2])
def test_error_raised_if_delivery_acknowledgement_not_received_in_time(self): """Test that an error is raised if delivery acknowledgement isn't received before the given acknowledgement timeout. """ message_handler = OrderedMessageHandler(subscriber=MockSubscriber(), subscription=self.mock_subscription) with patch("tests.cloud.pub_sub.mocks.MockSubscriber.pull", return_value=MockPullResponse()): with self.assertRaises(exceptions.QuestionNotDelivered): message_handler.handle_messages(delivery_acknowledgement_timeout=0)
def test_unknown_message_type_raises_warning(self): """Test that unknown message types result in a warning being logged.""" message_handler = OrderedMessageHandler( subscriber=MockSubscriber(), subscription=self.mock_subscription, message_handlers={"finish-test": lambda message: message}, ) with patch("logging.StreamHandler.emit") as mock_emit: message_handler._handle_message({"type": "blah", "message_number": 0}) self.assertIn("Received a message of unknown type", mock_emit.call_args_list[0][0][0].msg)
def test_is_push_subscription(self): """Test that `is_pull_subscription` is `False` and `is_push_subscription` is `True` for a pull subscription.""" push_subscription = Subscription( name="world", topic=self.topic, namespace="hello", project_name=TEST_PROJECT_NAME, subscriber=MockSubscriber(), push_endpoint="https://example.com/endpoint", ) self.assertTrue(push_subscription.is_push_subscription) self.assertFalse(push_subscription.is_pull_subscription)
def test_namespace_only_in_name_once(self): """Test that the subscription's namespace only appears in its name once, even if it is repeated.""" self.assertEqual(self.subscription.name, "hello.world") subscription_with_repeated_namespace = Subscription( name="hello.world", topic=self.topic, namespace="hello", project_name=TEST_PROJECT_NAME, subscriber=MockSubscriber(), ) self.assertEqual(subscription_with_repeated_namespace.name, "hello.world")
def setUpClass(cls): """Set up the test class with a mock subscription. :return None: """ service = MockService(backend=BACKEND) mock_topic = MockTopic(name="world", namespace="hello", service=service) cls.mock_subscription = MockSubscription( name="world", topic=mock_topic, namespace="hello", project_name=TEST_PROJECT_NAME, subscriber=MockSubscriber(), )
def test_error_raised_if_attempting_to_wait_for_answer_from_push_subscription( self): """Test that an error is raised if attempting to wait for an answer from a push subscription.""" service = Service(backend=BACKEND) mock_subscription = MockSubscription( name="world", topic=MockTopic(name="world", namespace="hello", service=service), namespace="hello", project_name=TEST_PROJECT_NAME, subscriber=MockSubscriber(), push_endpoint="https://example.com/endpoint", ) with self.assertRaises(exceptions.PushSubscriptionCannotBePulled): service.wait_for_answer(subscription=mock_subscription)
def test_timeout(self): """Test that a TimeoutError is raised if message handling takes longer than the given timeout.""" message_handler = OrderedMessageHandler( subscriber=MockSubscriber(), subscription=self.mock_subscription, message_handlers={ "test": self._make_order_recording_message_handler([]), "finish-test": lambda message: message, }, ) with patch( "octue.cloud.pub_sub.service.OrderedMessageHandler._pull_message", new=MockMessagePuller(messages=[{"type": "test", "message_number": 0}]).pull, ): with self.assertRaises(TimeoutError): message_handler.handle_messages(timeout=0)
def test_timeout_error_raised_if_no_messages_received_when_waiting(self): """Test that a TimeoutError is raised if no messages are received while waiting.""" service = Service(backend=BACKEND) mock_topic = MockTopic(name="world", namespace="hello", service=service) mock_subscription = MockSubscription( name="world", topic=mock_topic, namespace="hello", project_name=TEST_PROJECT_NAME, subscriber=MockSubscriber(), ) with patch( "octue.cloud.pub_sub.service.pubsub_v1.SubscriberClient.pull", return_value=MockPullResponse()): with self.assertRaises(TimeoutError): service.wait_for_answer(subscription=mock_subscription, timeout=0.01)
def test_delivery_acknowledgement(self): """Test that a delivery acknowledgement message is handled correctly.""" message_handler = OrderedMessageHandler(subscriber=MockSubscriber(), subscription=self.mock_subscription) self.assertFalse(message_handler.received_delivery_acknowledgement) with patch( "octue.cloud.pub_sub.service.OrderedMessageHandler._pull_message", new=MockMessagePuller( [ { "type": "delivery_acknowledgement", "delivery_time": "2021-11-17 17:33:59.717428", "message_number": 0, }, {"type": "result", "output_values": None, "output_manifest": None, "message_number": 1}, ] ).pull, ): result = message_handler.handle_messages() self.assertTrue(message_handler.received_delivery_acknowledgement) self.assertEqual(result, {"output_values": None, "output_manifest": None})
class TestSubscription(BaseTestCase): service = Service(backend=GCPPubSubBackend(project_name="my-project")) topic = Topic(name="world", namespace="hello", service=service) subscription = Subscription(name="world", topic=topic, namespace="hello", project_name=TEST_PROJECT_NAME, subscriber=MockSubscriber()) def test_namespace_only_in_name_once(self): """Test that the subscription's namespace only appears in its name once, even if it is repeated.""" self.assertEqual(self.subscription.name, "hello.world") subscription_with_repeated_namespace = Subscription( name="hello.world", topic=self.topic, namespace="hello", project_name=TEST_PROJECT_NAME, subscriber=MockSubscriber(), ) self.assertEqual(subscription_with_repeated_namespace.name, "hello.world") def test_repr(self): """Test that Subscriptions are represented correctly.""" self.assertEqual(repr(self.subscription), "<Subscription(hello.world)>") def test_error_raised_when_creating_without_allowing_existing_when_subscription_already_exists( self): """Test that an error is raised when trying to create a subscription that already exists and `allow_existing` is `False`. """ with patch( "tests.cloud.pub_sub.mocks.MockSubscriber.create_subscription", side_effect=google.api_core.exceptions.AlreadyExists(""), ): with self.assertRaises(google.api_core.exceptions.AlreadyExists): self.subscription.create(allow_existing=False) def test_create_with_allow_existing_when_already_exists(self): """Test that trying to create a subscription that already exists when `allow_existing` is `True` results in no error. """ with patch( "tests.cloud.pub_sub.mocks.MockSubscriber.create_subscription", side_effect=google.api_core.exceptions.AlreadyExists(""), ): self.subscription.create(allow_existing=True) def test_create_pull_subscription(self): """Test that creating a pull subscription works properly.""" project_name = os.environ["TEST_PROJECT_NAME"] service = Service(backend=GCPPubSubBackend(project_name=project_name)) topic = Topic(name="my-topic", namespace="tests", service=service) subscription = Subscription( name="world", topic=topic, namespace="hello", project_name=project_name, subscriber=SubscriberClient(credentials=service.credentials), ) with patch("google.pubsub_v1.SubscriberClient.create_subscription", new=MockSubscriptionCreationResponse): response = subscription.create(allow_existing=True) self.assertEqual(response._pb.ack_deadline_seconds, 600) self.assertEqual(response._pb.expiration_policy.ttl.seconds, THIRTY_ONE_DAYS) self.assertEqual(response._pb.message_retention_duration.seconds, 600) self.assertEqual(response._pb.retry_policy.minimum_backoff.seconds, 10) self.assertEqual(response._pb.retry_policy.maximum_backoff.seconds, 600) def test_create_push_subscription(self): """Test that creating a push subscription works properly.""" project_name = os.environ["TEST_PROJECT_NAME"] service = Service(backend=GCPPubSubBackend(project_name=project_name)) topic = Topic(name="my-topic", namespace="tests", service=service) subscription = Subscription( name="world", topic=topic, namespace="hello", project_name=project_name, subscriber=SubscriberClient(credentials=service.credentials), push_endpoint="https://example.com/endpoint", ) with patch("google.pubsub_v1.SubscriberClient.create_subscription", new=MockSubscriptionCreationResponse): response = subscription.create(allow_existing=True) self.assertEqual(response._pb.ack_deadline_seconds, 600) self.assertEqual(response._pb.expiration_policy.ttl.seconds, THIRTY_ONE_DAYS) self.assertEqual(response._pb.message_retention_duration.seconds, 600) self.assertEqual(response._pb.retry_policy.minimum_backoff.seconds, 10) self.assertEqual(response._pb.retry_policy.maximum_backoff.seconds, 600) self.assertEqual(response._pb.push_config.push_endpoint, "https://example.com/endpoint") def test_is_pull_subscription(self): """Test that `is_pull_subscription` is `True` and `is_push_subscription` is `False` for a pull subscription.""" self.assertTrue(self.subscription.is_pull_subscription) self.assertFalse(self.subscription.is_push_subscription) def test_is_push_subscription(self): """Test that `is_pull_subscription` is `False` and `is_push_subscription` is `True` for a pull subscription.""" push_subscription = Subscription( name="world", topic=self.topic, namespace="hello", project_name=TEST_PROJECT_NAME, subscriber=MockSubscriber(), push_endpoint="https://example.com/endpoint", ) self.assertTrue(push_subscription.is_push_subscription) self.assertFalse(push_subscription.is_pull_subscription)